Где я ошибаюсь в изменении 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 перестает выполняться?
@localmartian, 👍1
Обсуждение1 ответ
Не делайте серийных отпечатков внутри ISR. Никогда. Они требуют прерываний для работы, а внутри ISR прерывания отключены. На некоторое время попытки печати заполнят буфер, который будет опустошен другим ISR, однако, когда этот буфер заполнится, Serial.print заблокируется. И если он блокируется внутри ISR в ожидании прерывания, он блокируется навсегда. Таким образом, он перестает печатать.
Как предложил Jstola в комментарии под вопросом, включите и выключите светодиод или что-то в этом роде.
Я не могу идеально объяснить ваши 7 отпечатков, но многократная печать ВЫСОКИХ и НИЗКИХ значений с соответствующим возвратом каретки/подачей строки после 7 оборотов (7 x 11 = 77) в значительной степени заполнит последовательный буфер размером 64 байта.
Итак, вы отправляете около 77 байт, некоторые из них "убежали" до того, как буфер заполнился, и когда вы заполнили его 64 байтами, он остановился.
Ваши результаты немного изменились бы, если бы вы сделали скорость передачи данных выше, скажем, 115200 бод, которую я всегда использую, но все же вы не должны печатать внутри ISR.
- Arduino непрерывно считывает значение АЦП с помощью прерывания
- 4-битный счетчик вверх и вниз
- Включить и отключить отдельные прерывания
- Управление функцией включения на драйвере микрошагового устройства
- Измерить количество циклов и время цифрового входа
- Проблема прерывания библиотеки MPU6050 Arduino Jeff Rowberg
- генерировать два сдвинутых по фазе ШИМ-импульса, запускаемых внешним сигналом с частотным разделением, с помощью Arduino uno?
- Включение прерывания Timer1 CompareA мгновенно вызывает прерывание?
вспышка светодиода вместо печати ... если вы все еще хотите печатать, не выполняйте печать внутри функции ISR ... установите флаг внутри одного ISR ... снимите флаг внутри другого ISR ... выведите состояние флага внутри функции
loop()
, @jsotolaСпасибо за комментарий, я заметил, что неправильно понимаю математику того, что 1 период приравнивается к микросекунде, и светодиод 100% помог мне увидеть проблему. Мне нужно включить глобальную переменную для подсчета тиков или "оборотов OCR0A", чтобы правильно рассчитать интервалы., @localmartian