Я использую Arduino Uno для отправки информации о времени и напряжении через последовательный порт на Python для построения графика. Однако временные интервалы между последовательными метками времени, по-видимому, со временем увеличиваются, что сказывается на моем графике. Это особенно верно, когда скорость передачи данных установлена на 9600, где моя начальная разница во времени может быть 1320 и увеличивается до 16400 после относительно короткого периода времени. Когда эта скорость установлена на максимум 115200 бит / с, изменение происходит медленнее и менее заметно, с 1340 до 1500, даже после относительно долгой отправки. Время указывается в микросекундах.
Я хотел бы знать, могу ли я уменьшить или устранить этот эффект, и если не понимаю, почему он существует. Я читал кое-что о прерываниях и задержках, вызывающих это, но я не совсем понимаю сложность имеющейся электроники и хотел бы знать:
- Могу ли я получить большую точность в сроках?
- Что вызывает это изменение во времени?
Вот что у меня сейчас есть:
#include <eHealth.h>
extern volatile unsigned long timer0_overflow_count;
float fanalog0;
int analog0;
unsigned long time;
byte serialByte;
void setup() {
Serial.begin(9600);
}
void loop() {
while (Serial.available()>0){
serialByte=Serial.read();
if (serialByte=='S'){
while(1){
fanalog0=eHealth.getECG();
// Use the timer0 => 1 tick every 4 us
time=(timer0_overflow_count << 8) + TCNT0;
// Microseconds conversion.
time=(time*4);
//Print in a file for simulation
//Serial.print(time);
//Serial.print(" ");
Serial.print(fanalog0,5);
Serial.print("\n");
if (Serial.available()>0){
serialByte=Serial.read();
if (serialByte=='F') break;
}
}
}
}
}
источник
eHealth.getECG()
? Этот звонок всегда длится одинаковое количество времени?Ответы:
Используйте таймер и ISR (процедуру обработки прерываний), чтобы сделать синхронизацию более точной.
Взгляните на мое доказательство концепции прерывания по времени 1 мс . Идея состоит в том, чтобы в системе было достаточно точное «сердцебиение» в 1 мс, которое можно использовать для запуска других событий. В PoC он используется для мигания светодиода с частотой 1/2 Гц, но имеет доступ к новым переменным
millisecondCounter
иsecondCounter
позволяет запускать события в основном цикле в произвольные (но точно синхронизированные) моменты.источник
loop()
), причем это значение изменяется ISR. Может случиться так, чтоloop()
читается неверное значение (в середине модификации ISR). Я разместил комментарий в вашем блоге об этом.loop()
: мой пример только что получил значение в миллисекундах, сравните его с предыдущим значением чтения и, если разница> 0 (кроме сброса счетчика в 0), отобразите сообщение.Я могу подумать о нескольких вещах, которые могут повлиять на «согласованность» времени последовательной записи:
Это может быть самой очевидной вещью, о которой нужно думать, но на самом деле, чем больше вы печатаете, тем больше вам понадобится справиться с этим.
Решение: напечатайте формат строки в строку известной длины.
в Unix вы можете получить доступ к последовательному порту, используя буферизованный или небуферизованный способ. Использование буферизованного способа в течение длительного времени может немного замедлить его заполнение буфера, обычно это происходит, когда данные поступают быстрее, чем вы их читаете ...
Решение: используйте небуферизованную последовательную линию ( например ,
/dev/cu.usbmodemXXX
вместо Darwin / OSX/dev/tty.usbmodemXXX
)похоже, что вы используете прерывание TC, и AVR имеют приоритеты в обработке прерываний, я не знаю порядок приоритетов для Atmega328, и это не одна из самых документированных функций, поэтому я не знаю насколько безопасен TC0 по сравнению с прерыванием UART.
Решение: посмотрите далее в документации / таблице данных о приоритетах прерываний и при необходимости измените таймер; и / или выполнить тест, не запустив другой таймер.
некоторые драйверы должны усреднять или выполнять некоторые операции над предыдущими значениями, поэтому чем больше измеряемых значений, тем больше буфер и тем больше времени требуется для вычисления значения, пока не будет достигнут максимальный размер буфера.
Решение: посмотрите на исходный код библиотеки, которую вы используете, и либо оптимизируйте ее, удалите калькуляцию, если она есть, или учтите это увеличивающееся время обработки.
но если вы действительно хотите оптимизировать последовательный вывод от Arduino, вам следует избегать использования накладных расходов Arduino ... Но это менее элегантно и удобно в использовании.
Я почти уверен, что есть другие моменты, которые мне не хватает, но это первое, что я хотел бы проверить, прежде чем копать дальше.
НТН
источник
Ваш код включает в себя продолжительность вывода в последующих измерениях. Таким образом, в зависимости от длины вывода вы будете измерять разное время. Это может быть исправлено путем форматирования на вывод фиксированной длины.
Следующая проблема заключается в том, что у ООН очень плохое время. Посмотрите здесь для сравнения различных типов Arduino и отсчета времени DCF77.
Вывод: если вам нужно точное время, возьмите Arduino с кристаллом или отправляйтесь на RTC. Я настоятельно рекомендую RTC DS3231 / DS3232, поскольку они обычно достигают точности 2 промилле из коробки.
источник