Где я ошибаюсь в изменении Timer0 и прерываний ISR в этом примере?

(Arduino) Здравствуйте, я не знаю, где я ошибаюсь, пожалуйста, посоветуйте.

В конце концов, я хочу запустить биполярный двигатель, ВЫСОКИЙ/НИЗКИЙ, используя Timer0 с прерываниями OCR0A и OCR0B для регулировки интервала шага двигателей и рабочего цикла. В конце концов, я хотел бы сделать то же самое со вторым двигателем и Timer2.

Идея состоит в том, что прерывание в OCR0A запускает шаг LOW, а прерывание в OCR0B-шаг HIGH. Это разбивается на отсчет TCNT от 0 до OCR0B-НИЗКАЯ фаза, а отсчет TCNT от OCR0B до OCR0A-ВЫСОКАЯ фаза. Обе фазы вместе составляют интервал шага двигателя, который будет находиться между TCNT0=0 и OCR0A ISR Clear. Рабочий цикл определяется значением между OCR0B и OCR0A, длительностью ВЫСОКОЙ фазы.

Мой первый тест состоял в том, чтобы использовать Serial.println() для возврата "LOW" или "HIGH" из соответствующих ISR на компьютер, чтобы увидеть, находится ли последовательность шагов в правильном шаблоне AB-AB. Это не так. Последовательность шагов начинается правильно, но после 7(семи) последовательных прерываний OCR0B ISR OCR0B ISR перестает повторяться, в то время как ISR для OCR0A печатается повторно. Ниже приведен код:

 ISR(TIMER0_COMPA_vect) { Serial.println("HIGH");} //end ISR COMPA//

 ISR(TIMER0_COMPB_vect) { Serial.println("LOW"); } //end ISR COMPB//
                        
 int long  SPEED_A  = 200; // OCR0B->OCR0A is HIGH PHASE // trigger LOW  // clear to 0 //

 int long  SPEED_B  = 150; // 0->OCR0B is LOW PHASE      // trigger HIGH
                        
   void setup()
   {  
      noInterrupts();             // disable interrupts
                     
      OCR0A   = SPEED_A;          // interrupt A compare to TCNT0 value each tick // 0-255

      OCR0B   = SPEED_B;          // interrupt B compare to TCNT0 value each tick // 0-255

      TCCR0A  |= ( 1 << COM0A1);  // clear counter on match // OCR0A

      TIMSK0  |= ( 1 << OCIE0A);  // enable timer compare interrupt A

      TIMSK0  |= ( 1 << OCIE0B);  // enable timer compare interrupt B

      interrupts();               // enable interrupts

      Serial.begin(9600);         // serial

   }  //END setup///

 void loop() { } //END loop//

Серийный возврат выглядит следующим образом:

НИЗКИЙ ВЫСОКИЙ НИЗКИЙ ВЫСОКИЙ НИЗКИЙ ВЫСОКИЙ НИЗКИЙ ВЫСОКИЙ НИЗКИЙ ВЫСОКИЙ НИЗКИЙ ВЫСОКИЙ НИЗКИЙ ВЫСОКИЙ ВЫСОКИЙ ВЫСОКИЙ ВЫСОКИЙ ...

Почему ISR для OCR0B перестает выполняться?

, 👍1

Обсуждение

вспышка светодиода вместо печати ... если вы все еще хотите печатать, не выполняйте печать внутри функции ISR ... установите флаг внутри одного ISR ... снимите флаг внутри другого ISR ... выведите состояние флага внутри функции loop() , @jsotola

Спасибо за комментарий, я заметил, что неправильно понимаю математику того, что 1 период приравнивается к микросекунде, и светодиод 100% помог мне увидеть проблему. Мне нужно включить глобальную переменную для подсчета тиков или "оборотов OCR0A", чтобы правильно рассчитать интервалы., @localmartian


1 ответ


5

Не делайте серийных отпечатков внутри ISR. Никогда. Они требуют прерываний для работы, а внутри ISR прерывания отключены. На некоторое время попытки печати заполнят буфер, который будет опустошен другим ISR, однако, когда этот буфер заполнится, Serial.print заблокируется. И если он блокируется внутри ISR в ожидании прерывания, он блокируется навсегда. Таким образом, он перестает печатать.

Как предложил Jstola в комментарии под вопросом, включите и выключите светодиод или что-то в этом роде.

Я не могу идеально объяснить ваши 7 отпечатков, но многократная печать ВЫСОКИХ и НИЗКИХ значений с соответствующим возвратом каретки/подачей строки после 7 оборотов (7 x 11 = 77) в значительной степени заполнит последовательный буфер размером 64 байта.

Итак, вы отправляете около 77 байт, некоторые из них "убежали" до того, как буфер заполнился, и когда вы заполнили его 64 байтами, он остановился.

Ваши результаты немного изменились бы, если бы вы сделали скорость передачи данных выше, скажем, 115200 бод, которую я всегда использую, но все же вы не должны печатать внутри ISR.

,