Установить ШИМ по периоду? И он переменный?
В другом QA стека я спрашиваю о генерации импульсного сигнала с периодом от 63 мс. до 6,5 мс. Существует популярная библиотека ШИМ, однако она не компилируется, а также, поскольку 63 мс составляет 15,8 Гц, настройка целочисленной частоты в этой библиотеке бесполезна.
Есть ли определенный процесс, который не размахивает пучками благовоний по углам комнаты? В Интернете слишком много «как сделать», однако ни одно из них, похоже, не привело меня к решению.
У меня есть Mega и я использую TIMER5. Это «точно так же, как» TIMER1 в том смысле, что это 16-битный таймер.
@Chris K, 👍2
1 ответ
Я наткнулся на решение методом проб и ошибок, наблюдая за результатами на о'скопе.
Лучшее руководство дал QA Stack Exchange. Настройка не особенно особенная, однако комбинация битов WGM здесь сработала, и я не стал исследовать дальше. Наибольшее значение имеют биты делителя предварительного делителя, три младших значащих бита TCCRxB. 001
означает отсутствие деления или предварительного масштабирования часов.
Все сводилось к 4 регистрам и вызову pinMode()
. В итоге семь строк кода:
#define PULSE_PIN 45
void setup() {
// ВАЖНО: очистить регистры управления таймером/счетчиком
TCCR5A = 0;
TCCR5B = 0;
// Установка регистров управления таймером/счетчиком
TCCR5A = B00101001; // Правильное изменение фазы и частоты ШИМ на OCRA
TCCR5B = B00010010; // биты наименьшего знака устанавливают "несущую частоту" путем деления тактовой частоты процессора
// Наблюдение:
// TCCR5B = B00010010 и OCR5A = 16667 результатов за период 16,70 мс
// означает, что OCR5A — это период в мкс, когда TCCR5B = B00010010
// TCCR5B = B00010001 : OCR5A = 20000 результатов за период = 2,5 мс 399,3 Гц
pinMode(PULSE_PIN, OUTPUT);
}
В скетче я наблюдаю за аналоговым выводом с потенциометром и сопоставляю его размах с эффективным диапазоном оборотов от 950 до 9000 об/мин. Отсюда произвольный диапазон периодов, которые я хочу обрабатывать. Когда loop()
видит изменение АЦП, приведенный ниже код соответствующим образом настраивает ШИМ.
Обратите внимание, что типы данных с плавающей запятой не используются. Приведенные ниже магические числа были выбраны методом проб и ошибок в электронной таблице со значениями, округленными до целых чисел.
void setRpm(){
// Долгий путь к периоду в мкс из оборотов в минуту
// ответ в диапазоне типа данных:
unsigned int rpm = map(pot_adc, 0, 1023, RPM_MIN, RPM_MAX);
unsigned long period = rpm/50;
period = 24000/period;
period = period*50;
// Триггер длится 26°, поэтому PW составляет 26/360 * период.
dwell = period/36;
dwell = dwell*26;
dwell = dwell/10;
// OCR5A - счетчик, до которого считает несущую частоту,
// который устанавливает период/частоту вывода
// означает, что OCR5A — это период в мкс, когда TCCR5B = B00010010
OCR5A = period; // OCR5A — это период в мкс, когда TCCR5B = B00010010
// OCR5B — ширина импульса. Если бы мы использовали float,
// мы могли бы использовать рабочий цикл * период.
OCR5B = dwell;
}
Очевидно, что этот код будет иметь ограничения на диапазон частот, которые он может обрабатывать, но в Интернете есть множество средств для более высокочастотной ШИМ, особенно когда желаемая ШИМ фиксирована и не нуждается в изменении.
Самый полезный способ увидеть регистры управления — это двоичные позиции, а не полагаться на макросы, маски и сдвиг битов. Этот блок комментариев очень помог:
// WGM modes:
// TCCR1A
// Bit 7 6 5 4 3 2 1 0
// Bit Name COM1A1 COM1A0 COM1B1 COM1B0 ----- ----- WGM11 WGM10
// Initial Value 0 0 0 0 0 0 0 0
// changed to 1 1 1 1 0 0 0 1
// TCCR1B
// Bit 7 6 5 4 3 2 1 0
// Bit Name ICNC1 ICES1 ----- WGM13 WGM12 CS12 CS11 CS10
// Initial Value 0 0 0 0 0 0 0 0
// changed to 0 0 0 0 1 0 0 1
// CS12,CS11,CS10 = (0,1,1) = prescaler divide by 64
- Можно ли сгенерировать точный тактовый импульс 15 кГц с помощью ардуино?
- Генерация сигнала частотой 38 кГц без таймеров
- Светодиод Arduino PWM с замиранием в сборке
- Отрегулируйте расчет времени после изменения частоты Timer0
- Как измерить ультразвуковой датчик без импульсного метода?
- Teensy 4.1 / 4.0 Когда использовать контакты FlexPWM и QuadTimer для стробирования светодиодов
- Seeeduino СЯО запись и чтение ШИМ продолжительность (период) с помощью таймеров
- Режимы установки и сброса CTC таймера — как отменить сброс и сброс?
Мне нравится сдвигать биты в группах. Например,
TCCR1A = (0b11 <<COM1A0) | (0b11 <<COM1B0) | (0b01 << WGM10) ;
иTCCR1B = (0b11 <<WGM12)| (0b001 <<CS10)
-- тогда метод проб и ошибок переворачивания битов становится более понятным и самодокументируемым -- Если вы хотите попробовать прескалер /64, это 1-битное редактирование0b011
, @Dave X