Как установить два ШИМ на две разные частоты?
Я использую Arduino Uno, подключенную к двум светодиодам. Один находится на контакте 3, а другой - на контакте 5. Я знаю, что контакт 3 управляется таймером 3, а контакт 5 - таймером 1. Я много раз пробовал иметь две независимые частоты. ШИМ меня особо не волнует, он у меня на 50% (постоянный).
Существуют ресурсы для установки частоты (http://playground.arduino.cc/Main/TimerPWMCheatsheet), но это предопределенные частоты. Мне нужен один ШИМ на 650 Гц, а другой на 850 Гц.
Есть ли рекомендации по решению этой проблемы?
@Tomasero, 👍1
Обсуждение4 ответа
Существует отличная библиотека с функциями для изменения частоты ШИМ на микроконтроллерах Arduino, которая называется библиотека частот arduino-pwm. Надеюсь, это поможет вам.
Аппаратное обеспечение ATMega PWM, лежащее в основе Arduino, в первую очередь поддерживает изменение рабочего цикла; частоты могут быть выбраны только из нескольких фиксированных вариантов. Обычно таймеры запускаются от 0 до 255 или 65 535 и возвращаются к 0, и вы можете выбрать, где в пределах этого полного цикла выход будет включаться и выключаться.
Поскольку вам нужен простой рабочий цикл 50% с точным контролем частоты, функции ШИМ не очень полезны. Что вам нужно, так это управление тоном или частотой. Таймеры ATMega тоже поддерживают это, но это другая функция, чем ШИМ. Для управления частотой таймер будет циклически изменяться от 0 до выбранного вами верхнего предела. Так, например, вы можете сосчитать до 200 вместо 255; или до 201 - так вы получите более точное управление частотой.
В отличие от ШИМ, на ATMega328p, используемом в Uno, вы можете получить только одну частоту на каждый таймер (вы можете получить два выхода ШИМ на каждый таймер - оба на одной частоте). И если вы хотите, чтобы millis() и микросекунды() и delay() продолжали работать, вам не нужно возиться с таймером 0 для управления частотой (вы можете получить ШИМ от таймера 0, если вы принимаете частоты по умолчанию).
Итак, у вас остается два таймера с регулируемой частотой: таймер 1 (разрешение 16 бит) и таймер 2 (разрешение 8 бит).
См. функцию tone() в библиотеке Arduino для примеров одновременного воспроизведения одного тона.
Информацию о нескольких одновременных частотах (на разных контактах) см. в этой библиотеке: https://code.google. com/p/rogue-code/wiki/ToneLibraryDocumentation. У вас может быть два тона одновременно или три, если вам не нужен millis() и т. д.
ЕСЛИ вам нужно уменьшить яркость светодиодов, используйте:
/*PWM signal on most pins is approximately 490 Hz
On the Uno and similar boards, pins 5 and 6
have a frequency of approximately 980 Hz
brightness1, brightness2 = from 0(0v) to 255(5v)
So make eqution to calculate needed frequency*/
//светодиод подключен к:
const int ledPin1 = 5;
const int ledPin2 = 6;
byte brightness1 = 100; // ~2v
byte brightness2 = 200; // ~4в
void setup()
{
// инициализируем ledPin как выход:
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
}
void loop() {
// устанавливаем яркость светодиода:
analogWrite(ledPin1, brightness1);
analogWrite(ledPin2, brightness2);
}
Я рекомендую вам использовать два ШИМ-сигнала с разными рабочими циклами с одинаковой частотой, используя таймер 1 и выходные контакты 9 и 10. Следующий скетч был протестирован и работает очень хорошо.
/* * Este programa genera 2 PWM signals a partir del timer 1. Las dos señales tienen la misma frecuencia (250Hz) * Lo Que varia es el рабочий цикл independiente para cada señal. Продается штифт 9 и другой штифт 10. */ #include <avr/io.h> #include <avr/interrupt.h> недействительная установка () { Серийный.начать(115200); // поместите сюда код установки для однократного запуска: //********* Определения переменных ШИМ ******************************************************* ******** // Зарегистрировать инициализацию, подробнее см. техническое описание. TCCR1A = 0b10100010; //Регистр управления таймером/счетчиком 1 A COM1A1 COM1A0 COM1B1 COM1B0 - - WGM11 WGM10 // COM1A1 COM1A0 COM1B1 COM1B0 // 1 0 1 0 Очистить OC1A/OC1B при сравнении совпадений, установить OC1A/OC1B в BOTTOM (режим без инвертирования) TCCR1B = 0b00011001; //Регистр управления таймером/счетчиком 1 B ICNC1 ICES1 - WGM13 WGM12 CS12 CS11 CS10 // Регистр ICR1 не буферизуется дважды. Использование регистра ICR1 для определения TOP хорошо работает при использовании фиксированных значений TOP. // При использовании ICR1 регистр OCR1A можно использовать для генерации ШИМ-выхода на OC1A. Вот почему я использую WGM 14. // WGM13 WGM12 WGM11 WGM10 // 1 1 1 0 Fast PWM ICR1 - фиксированный TOP, обновление OCR1x внизу. РГМ 14 (таблица 13-4). // ICNC1 равен 0, шумоподавитель захвата ввода отключен // ICES1 равен 0, задний (отрицательный) фронт используется как триггер // CS12 CS11 CS10 // 0 0 1 Нет предварительного масштабирования ТИМСК1 = 0b00000001; // Регистр маски прерывания Таймера/Счетчика1. Разрешено прерывание по переполнению Таймера/Счетчика 1. //значение TOP ставится в ICR1 и равно 64000, это означает, что 16000000/64000 = 250Гц (т.к. без предварительного масштабирования), частота сигналов ШИМ ICR1 = 64000; ДДРБ = 0b00000110; // Установить PB1(DB9) и PB2(DB10) в качестве выходов. прерывания (); } недействительный цикл () { // поместите сюда ваш основной код для многократного запуска: } ISR(TIMER1_OVF_vect) { // меняем рабочий цикл каждый период. OCR1A = 16000;// в OCR1A ставится значение, соответствующее коэффициенту заполнения, выходной контакт OCR1A равен 9. Коэффициент заполнения 25%. 16000 / 64000 = 0,25 OCR1B = 48000;// выходной контакт OCR1B равен 10, рабочий цикл 75%. 48000 / 64000 = 0,75 }
- Как использовать SPI на Arduino?
- Как решить проблему «avrdude: stk500_recv(): programmer is not responding»?
- Как создать несколько запущенных потоков?
- Как подключиться к Arduino с помощью WiFi?
- avrdude ser_open() can't set com-state
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Я закирпичил свой Arduino Uno? Проблемы с загрузкой скетчей на плату
Вы уже смотрели даташит?, @Ignacio Vazquez-Abrams
Поскольку вы уже используете два разных таймера, ключевым моментом является установка правильного режима генерации волны с соответствующим предделителем и TOP для желаемых частот. Посмотрите https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf для ATMEGA328p или https://ww1.microchip.com/downloads/en/devicedoc/atmel- 2549-8-bit-avr-microcontroller-atmega640-1280-1281-2560-2561_datasheet.pdf для ATMEGA2560 для «CS10» и «CS30» для таблиц предварительного делителя. и WGM10 и WGM31 для режимов генерации волн 8,9,10,11,14 или 15., @Dave X