Точность синхронизации 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() {
  
}

Как исправить код?

, 👍0

Обсуждение

вы ничего не сказали о требуемой точности двух значений ... вы также не сказали, есть ли что-то не так с кодом, @jsotola

Внутренние часы Arduino не очень хороши для измерения длительных периодов времени с высокой точностью (из-за производственных различий и дрейфа часов в зависимости от температуры). Для этого потребуется RTC (часы реального времени). Хотя: если вам нужна только точность в разнице во времени между активациями двух реле, вы можете запустить второй Arduino от первого, чтобы начать отсчет времени там. Диапазон миллисекунд обычно легко достигается с помощью Arduinos., @chrisl

почему один Arduino не может управлять обоими реле?, @Juraj

оба будут внутри 2 разных систем. Я запускаю часы на обоих одновременно, используя общий сигнал прерывания., @Lawliet


1 ответ


Лучший ответ:

2

Arduino Nano недостаточно точен для вашего приложения, и это не имеет ничего общего с вашим кодом: это аппаратное ограничение. 360 лишние миллисекунды после 2700 секунд — разница всего 133 ppm (частей на миллион). Arduino Nano разгоняется керамический резонатор, и эти источники времени несут типичную погрешность порядка 1000 частей на миллион. Лучшее, что может сделать код, это подсчитать тактовые циклы с идеальной точностью, что делает синхронизацию программного обеспечения как хороша как базовое оборудование, но никогда не лучше.

Некоторые варианты, которые вы можете попробовать:

  1. Наиболее очевидным кажется первый Arduino. отправить триггерный сигнал второму, когда он активирует первый реле. Или пусть второй Arduino определяет состояние этого реле. Затем все, что нужно сделать второму Arduino, — это подождать 360 мс, что это легко сделать с разумной точностью.

  2. Если ардуино не может обмениваться данными, вы можете попробовать чтобы добавить внешние источники времени к ардуино. Некоторые модули RTC могут выводить сигнал частотой 32 768 Гц, который может быть достаточно точным для вашего потребности. Ищите RTC с температурной компенсацией, так как они более точно.

  3. Если вы не можете добавить дополнительное оборудование, попробуйте откалибровать часы ваших Arduino, чтобы компенсировать их относительное дрейф. Имейте в виду, однако, что скорость дрейфа зависит от температуры и беспорядочно блуждает даже при постоянном температура. Сначала прочтите статью Тактовая частота Arduino. точность, автор Joris_VR, чтобы получить представление о точности можно было ожидать от такой калибровки.

,