Нужны два выхода ШИМ (25 и 30 кГц) на нано

Как создать второй выход с другой частотой?

void setup() {

const byte DRIVEa = 3;  // Таймер 2 "B" выход: OC2B
  pinMode (DRIVEa, OUTPUT);  // драйвер a.

  TCCR2A = _BV (WGM20) | _BV (WGM21) | _BV (COM2B1); // быстрый ШИМ, очистка OC2B при сравнении.
  TCCR2B = _BV (WGM22) | _BV (CS21);         // быстрый ШИМ, предделитель 8.

}

void loop() {

  OCR2A =  ((F_CPU / 8) / 30000) - 1;    // 30 кГц, ноль относительный.
  OCR2B = ((OCR2A + 1) / 2) - 1;      // 50% рабочий цикл.

} 

, 👍-1

Обсуждение

Используете другой таймер? Частота срабатывания таймера зависит от режима и значения TOP. Какие ещё таймеры вы не используете?, @Dave X

Используется только один выход ШИМ, и при необходимости можно подключать другие устройства. В разделе «Секреты ШИМ» я видел, что вывод 11 может быть вторым выходом? Я позаимствовал код выше из другого поста и не понимаю, как он работает., @ted thomas

Добро пожаловать в SE/Arduino! Пожалуйста, ознакомьтесь с [туром], чтобы узнать, как работает этот сайт, а также прочтите раздел «[спросить]» и другие страницы [помощи]. Вы ведь читали руководство и руководство по применению микроконтроллера, не так ли? Пожалуйста, [отредактируйте] свой вопрос, чтобы уточнить, почему они вам не помогли., @the busybee

@tedthomas: https://docs.arduino.cc/tutorials/generic/secrets-of-arduino-pwm/ — хороший пример. https://gammon.com.au/timers очень хорошо объясняет. Вывод 11 также управляется таймером 2, и его ШИМ-регистр OCR2A используется для установки частоты 30 кГц, поэтому это не сработает. Можно ли использовать вывод 10 таймера 1 с соответствующими настройками для TCCR1A, TCCR1B, OCR1A и OCR1B? Пример TimerHelpers на https://gammon.com.au/timers может упростить задачу., @Dave X


2 ответа


0

Попробуйте изменить свой код следующим образом:

void setup() {
  // Таймер 2 - Первый выход (DRIVEa)
  const byte DRIVEa = 3;  // Выход таймера 2 «B»: OC2B (контакт 3 на Arduino UNO)
  pinMode (DRIVEa, OUTPUT);  // драйвер a
  
  TCCR2A = _BV (WGM20) | _BV (WGM21) | _BV (COM2B1); // быстрый ШИМ, очистка OC2B при сравнении
  TCCR2B = _BV (WGM22) | _BV (CS21);                 // быстрый ШИМ, предделитель 8

  // Таймер 1 - Второй выход (DRIVEb)
  const byte DRIVEb = 9;  // Выход таймера 1 «A»: OC1A (контакт 9 на Arduino UNO)
  pinMode (DRIVEb, OUTPUT);  // драйвер b
  
  TCCR1A = _BV(WGM10) | _BV(WGM11) | _BV(COM1A1);  // быстрый ШИМ, очистка OC1A при сравнении
  TCCR1B = _BV(WGM12) | _BV(WGM13) | _BV(CS11);    // быстрый ШИМ, предделитель 8
}

void loop() {
  // Таймер 2 — установка частоты и рабочего цикла для первого выхода (DRIVEa)
  OCR2A = ((F_CPU / 8) / 30000) - 1;    // частота 30 кГц
  OCR2B = ((OCR2A + 1) / 2) - 1;        // 50% рабочий цикл

  // Таймер 1 — установка частоты и рабочего цикла для второго выхода (DRIVEb)
  OCR1A = ((F_CPU / 8) / 10000) - 1;    // частота 10 кГц
  OCR1B = ((OCR1A + 1) / 4) - 1;        // 25% рабочий цикл (например)
}

Таймер 2 используется для генерации первого ШИМ-сигнала (30 кГц) на выводе 3. Таймер 1 используется для генерации второго ШИМ-сигнала (10 кГц) на выводе 9. Предделитель для обоих таймеров установлен на 8 (CS21 и CS11), но частота определяется значениями, установленными вами для OCR2A и OCR1A. Вы можете изменить рабочий цикл Таймера 1, отрегулировав OCR1B.

,

Таймер 2 работает отлично, а вот Таймер 1 — ничего., @ted thomas

Я попробовал это и ничего не получил от Таймера 1. Я заметил, что Таймер 1 использует 0C1"A", тогда как Таймер 2 использует B. и добавление WGM13, @ted thomas

Выход таймера 1 заблокирован на высоком уровне. Думаете, это как-то связано с 8-битной и 16-битной схемой?, @ted thomas

Использовал код для таймеров 0 и 2, и он отлично работает. Мне нужны другие функции таймера 0, поэтому нужно, чтобы работал и таймер 1..., @ted thomas


0

Наконец-то нашёл решение. Никогда не мог заставить Таймер 1 работать как Таймер 2, но этот инструмент

https://dbuezas.github.io/arduino-web-timers/#mcu=ATMEGA328P&timer=1&CompareOutputModeA=toggle&OCR1A=48059&timerMode=FPWM

позволил мне экспериментировать

void setup() {

const byte DRIVEb = 9;  // Таймер 1 "A" выход: OC1A
pinMode (DRIVEb, OUTPUT);  // драйвер b

TCCR1A = _BV (COM1A0) | _BV (WGM11) | _BV (WGM10); // быстрый ШИМ, переключение
TCCR1B = _BV (WGM13)  | _BV (WGM12) | _BV (CS11);   // быстрый ШИМ, предделитель 8
 

const byte DRIVEa = 3;  // Таймер 2 "B" выход: OC2B
pinMode (DRIVEa, OUTPUT);  // драйвер a

TCCR2A = _BV (WGM20) | _BV (WGM21) | _BV (COM2B1); // быстрый ШИМ, очистка OCR2A при сравнении
TCCR2B = _BV (WGM22) | _BV (CS21);                 // быстрый ШИМ, предделитель 8

}

void loop() {

OCR2A =  ((F_CPU / 8) / 30000) - 1;    // 30 кГц, ноль относительно
OCR2B = ((OCR2A + 1) / 2) - 1;         // 50% рабочий цикл

OCR1A = ((F_CPU / 8 ) / 80000) - 1;    // 40 кГц, режим переключения F/2

} 
,