Мистика 2

ardik
Offline
Зарегистрирован: 21.05.2014

Модуль Nano v5 (ATmega328P). Фрагмент скетча:

void loop()
{
   for (int i = 0; i <= 24; i++) {
      digitalWrite(D2,LOW);
      digitalWrite(D2,HIGH);
   }
   delay(500);
}

Проблема: генерируются пачки - вырезки из меандра - по 25 шт. 8 - 10 пачек генерируются нормально. В 9-й, 10-й и иногда в 11-й пачке без видимых причин время выполнения функций сброса (установки) линии D2 увеличивается вдвое. На осциллографе (цифровом) это выглядит как бегущий  (от пачки к пачке) на фоне меандра отрицательный (положительный) импульс удвоенной длительности. Смена модуля не помогла. В чём может быть причина?

tmr
Offline
Зарегистрирован: 19.05.2014

Проверил на Леонардо такой код:

void setup(){
  DDRF = B11111111;
  PORTF = B11111111;
}

void loop(){
  for (int i = 0; i <= 24; i++) {
    PORTF = B00000000;
    __asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t");
    PORTF = B11111111;
  }
  delay(5);
}

Переодически заметна задержка ~6-7мкс посреди пачки импульсов. С чем м.б. связана понятия не имею, может осцилл тупит.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Попробуйте так:

void loop()
{
   cli();
   for (int i = 0; i <= 24; i++) {
      digitalWrite(D2,LOW);
      digitalWrite(D2,HIGH);
   }
   sei();
   delay(500);
}

Жестоко, конечно, но для проверки сгодится. Теперь проверяйте, есть или нет "кривость". Если есть, то странно, если нет, то понятно, что это происходит из-за перываний.

ardik
Offline
Зарегистрирован: 21.05.2014

Огромное спасибо kisofty и tmry! Действительно, дело оказалось в прерываниях. Предложенный вариант скетча работает стабильно: такая посылка опрашивает энкодер типа TPM58S и тот корректно отвечает четырьмя байтами. Два -  позиция в текущем обороте, интервал  от 0 до 1023, и два - номер оборота с момента последнего сброса (или подачи питания), в интервале от 0 до 8195.

Ещё раз ВАМ БОЛЬШОЙ РЕСПЕКТ!

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Нужно всегда помнить, что МК (а мы рассматриваем именно Ардуино) всегда прерывается таймером 0. Разумеется если перрывания не запрещены. Смотрите файл wiring.c, ищите строку "ISR(TIM0_OVF_vect)".