16-битный ШИМ на Nano Every
Мне нужно управлять светодиодной лентой через модуль MOSFET. Для работы в условиях очень слабой освещенности модулю требуется ШИМ высокого разрешения. Как мне установить для моего вывода 16-битное разрешение ШИМ на Arduino Nano Every?
@awado, 👍1
2 ответа
Лучший ответ:
Возможно, что для D5 (TCA0-WO2) + D9 (TCA0-WO0) + D10 (TCA0-WO1) все три из них будут 16-битными, если вы измените верхнее значение TCA0, но вы не сможете использовать аналоговую запись.
р>void setup() {
// период изменения TCA0 (уже настроен и запущен ядром Arduino)
TCA0.SINGLE.PER = 0xFFFF; // меняем верхнее значение с 255 на 65535
// устанавливаем значение ШИМ D9 (канал 0)
TCA0.SINGLE.CMP0 = 0; // Начальное значение
// включаем выход ШИМ (требуется только один раз при настройке)
pinMode(9, OUTPUT); // установка вывода как выход
TCA0.SINGLE.CTRLB |= TCA_SINGLE_CMP0EN_bm; // включаем ШИМ->контакт
// Д5
TCA0.SINGLE.CMP2 = 1; // Начальное значение
pinMode(5, OUTPUT);
TCA0.SINGLE.CTRLB |= TCA_SINGLE_CMP2EN_bm;
// Д10
TCA0.SINGLE.CMP1 = 65530; // Начальное значение
pinMode(10, OUTPUT);
TCA0.SINGLE.CTRLB |= TCA_SINGLE_CMP1EN_bm;
}
и в коде вы будете использовать только TCA0.SINGLE.CMPn = val;
где n равно 0..2
(не проверялось, но должно работать)
РЕДАКТИРОВАТЬ: я забыл, что период будет 3,8 Гц, поэтому вам также нужно будет изменить прескалер TCA0 или использовать меньшую точность, например 10b или около того. Изменение прескаллера приведет к испорчению всех периодов счетчиков TCB, а также периода, используемого для счетчика миллис, поэтому вам также придется изменить его.
EDIT2: для классического UNO/nano это будет выглядеть так:
TCCR1B = 0; // останавливаем таймер
ICR1 = 0xFFFF; // f = 16 МГц / (2*N*ICR1) = 16 МГц / (2*65536) => ~122 Гц
OCR1A = 1; // PB2 -> D9 (значение ШИМ)
TCCR1A = _BV(COM1A1); // включаем выход ШИМ на PB2
TCCR1B = _BV(WGM13) | _BV(CS10); // mode=8 (фаза и частота правильные, ICR1 вверху) и запускаем таймер с предварительным вызовом /1
Ещё раз спасибо за помощь КИЕВ. Я могу подтвердить, что это работает. Это пример ШИМ при слабом освещении для светодиода на контакте 10. Возможно, это поможет другим.
int brightness = 0; // насколько яркий светодиод
int fadeAmount = 1; // на сколько пунктов затухать светодиод
void setup() {
TCA0.SINGLE.PER = 0x4000;
TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV16_gc | 1 << TCA_SINGLE_ENABLE_bp
TCA0.SINGLE.CMP1 = 65530; // Начальное значение
pinMode(10, OUTPUT);
TCA0.SINGLE.CTRLB |= TCA_SINGLE_CMP1EN_bm;
}
void loop() {
// устанавливаем яркость светодиодного вывода:
TCA0.SINGLE.CMP1 = brightness;
// изменяем яркость для следующего прохода цикла:
brightness = brightness + fadeAmount;
// инвертируем направление затухания на концах затухания:
if (brightness <= 0 || brightness >= 64) {
fadeAmount = -fadeAmount;
}
// ждем, чтобы увидеть эффект затемнения
delay(50);
}
- Установите частоту ШИМ на 25 кГц.
- Какова частота PWM-выхода на Arduino
- Управление скоростью вентилятора с помощью библиотеки Arduino PID
- Как устранить шум от вентилятора 12 В с ШИМ-управлением на низкой скорости
- Генерация частоты ШИМ выше 125 кГц с помощью Arduino Uno
- Увеличить разрядность PWM
- Как вывести истинное аналоговое напряжение на выходной контакт
- PWM-вывод Arduino Nano не функционирует
Спасибо за подробный код. Попробую на днях. Я использовал функцию AnalogWrite на Uno, которая записывала uint16_t в OCR1A (контакт 9). Это все еще то же самое?, @awado
Нет, у классического uno/nano (с Atmega328) другие настройки таймера1 - но с другой стороны у него независимый прескалер, так что ничего не сломаешь., @KIIV
@awado добавил изменения для классического uno (pinMode опущен), @KIIV