Точность синхронизации Arduino nano
Как точно можно отсчитывать время Arduino nano? Проект, над которым я работаю, требует двух Arduino nano для синхронной работы. Один Arduino должен активировать реле через 2700 секунд, а второй Arduino должен активировать второе реле через 2700,360 секунд (через 360 миллисекунд)
С приведенным ниже кодом требуемая точность не достигается.
volatile uint32_t ovfCount = 0UL;
volatile uint32_t currentTime = 0UL;
volatile unsigned long time_prev = 0UL;
volatile unsigned long dT = 0UL;
unsigned long delayTime = 2700UL; // Секунды
unsigned long coilActivateTime = 5UL; // секунды
volatile unsigned long _waitTime = delayTime * 1000UL + 360UL;
uint32_t _burnTime = coilActivateTime * 1000UL;
volatile bool coilOn_flag = false;
ISR(INT0_vect) {
EIMSK = 0b00000000;
TCCR1B = B00011100;
PORTB ^= (1<<0);
ovfCount = 0;
TIFR2 = 0;
TCNT2 = 0;
}
ISR(TIMER2_OVF_vect) {
ovfCount++;
}
ISR(TIMER1_OVF_vect) {
//проходить
}
ISR(TIMER1_COMPA_vect) {
//проходить
}
ISR(TIMER1_COMPB_vect) {
uint8_t tcnt2 = TCNT2;
uint32_t ovf_count = ovfCount;
if (bit_is_set(TIFR2, TOV2) && tcnt2 < 128) {
ovf_count++;
}
uint32_t totalCount = ovf_count << 8 | tcnt2; // необработанный счет
// uint32_t currentTime = totalCount * 0,004; // миллисекунда
currentTime = totalCount * 4UL/1000UL; // миллисекунда
if (currentTime >= _waitTime) {
PORTC ^= (1 << 5); // реле Переключатель
TCCR1A = B00000010;
TIMSK1 = B00000101;
PORTB |= (1<<1);
if (coilOn_flag) {
TCCR1B = 0;
PORTB ^= (1 << 1) | (1<<0);
}
coilOn_flag = true;
_waitTime = _burnTime;
ovfCount = 0;
TCNT2 = 0;
}
}
void setup() {
Serial.begin(115200);
/*setting the pin directions*/
DDRB |= (1 << 1) | (1 << 0); // гЛ, рЛ
DDRC |= (1 << 5); // реле
DDRD &= B11111011; // прерывание- прерывание
/* INITIAL STATE SETTING FOR THE PINS */
PORTB &= B11111100; // рЛ, гл
PORTC &= B11011111; // реле
/* 8Bit Timer*/
TCCR2A = 0;
TCCR2B = 0;
TCCR2A = B00000011;
TCCR2B = B00001100;
OCR2A = 250;
TCNT2 = 0;
TIFR2 = 0;
TIMSK2 = B00000001;
/* 16 bit timer */
TCCR1A = 0;
TCCR1B = 0;
TCCR1A = B10000010;
// TCCR1B = B00011100;
TCCR1B = 0;
ICR1 = 62461;
OCR1A = 6206;
OCR1B = 624;
TCNT1 = 0;
TIFR1 = 0;
TIMSK1 = B00000111;
/* External INTERRUPT */
EICRA = 0b00000010;
EIFR = 0;
EIMSK = 0b00000001;
PORTB ^= (1<<0);
}
void loop() {
}
Как исправить код?
@Lawliet, 👍0
Обсуждение1 ответ
Лучший ответ:
Arduino Nano недостаточно точен для вашего приложения, и это не имеет ничего общего с вашим кодом: это аппаратное ограничение. 360 лишние миллисекунды после 2700 секунд — разница всего 133 ppm (частей на миллион). Arduino Nano разгоняется керамический резонатор, и эти источники времени несут типичную погрешность порядка 1000 частей на миллион. Лучшее, что может сделать код, это подсчитать тактовые циклы с идеальной точностью, что делает синхронизацию программного обеспечения как хороша как базовое оборудование, но никогда не лучше.
Некоторые варианты, которые вы можете попробовать:
Наиболее очевидным кажется первый Arduino. отправить триггерный сигнал второму, когда он активирует первый реле. Или пусть второй Arduino определяет состояние этого реле. Затем все, что нужно сделать второму Arduino, — это подождать 360 мс, что это легко сделать с разумной точностью.
Если ардуино не может обмениваться данными, вы можете попробовать чтобы добавить внешние источники времени к ардуино. Некоторые модули RTC могут выводить сигнал частотой 32 768 Гц, который может быть достаточно точным для вашего потребности. Ищите RTC с температурной компенсацией, так как они более точно.
Если вы не можете добавить дополнительное оборудование, попробуйте откалибровать часы ваших Arduino, чтобы компенсировать их относительное дрейф. Имейте в виду, однако, что скорость дрейфа зависит от температуры и беспорядочно блуждает даже при постоянном температура. Сначала прочтите статью Тактовая частота Arduino. точность, автор Joris_VR, чтобы получить представление о точности можно было ожидать от такой калибровки.
- Проблема прерывания библиотеки MPU6050 Arduino Jeff Rowberg
- ATmega328P - проблема с использованием таймера 2 для генерации тона
- Интервальный таймер на Arduino: Сомнения по поводу библиотеки TimerOne
- Проблема с использованием Arduino Mega Timer2 с прерыванием PinChange
- Можно ли отсоединить прерывание на определенное время
- DS3231 с Arduino Nano для точной синхронизации
- Заставить TCNT оставаться ниже OCRxA на ATmega328P
- Эмуляция Arduino Uno с помощью QEMU: прерывания не работают
вы ничего не сказали о требуемой точности двух значений ... вы также не сказали, есть ли что-то не так с кодом, @jsotola
Внутренние часы Arduino не очень хороши для измерения длительных периодов времени с высокой точностью (из-за производственных различий и дрейфа часов в зависимости от температуры). Для этого потребуется RTC (часы реального времени). Хотя: если вам нужна только точность в разнице во времени между активациями двух реле, вы можете запустить второй Arduino от первого, чтобы начать отсчет времени там. Диапазон миллисекунд обычно легко достигается с помощью Arduinos., @chrisl
почему один Arduino не может управлять обоими реле?, @Juraj
оба будут внутри 2 разных систем. Я запускаю часы на обоих одновременно, используя общий сигнал прерывания., @Lawliet