Увеличение частоты и разрядности ШИМ Ардуино.

Вопросы по аппаратной части Ардуино
Эдуард
Администратор
Сообщения: 484
Зарегистрирован: 30 окт 2016, 20:53

Увеличение частоты и разрядности ШИМ Ардуино.

Сообщение Эдуард » 19 ноя 2016, 23:53

По умолчанию в системе Ардуино для всех ШИМ выводов заданы следующие параметры:
    разрешение 8 разрядов (значение ШИМ от 0 до 255);
    частота 488,28 Гц.
Большинство приложений требует гораздо большей частоты. Для некоторых задач надо иметь большую разрядность ШИМ.

Нашел в интернете варианты установок параметров ШИМ до частоты 31 кГц. Подумал, что должен быть вариант с большей частотой.

Частота генераторов большинства плат 16 мГц. Это соответствует периоду 62,5 нс. Это и есть минимальная временная единица дискретности ШИМ Ардуино. При разрядности 8 минимальный период ШИМ должен быть 62,5 нс * 256 = 16 мкс. Что соответствует частоте 62,5 кГц.

Разобрался с регистрами таймера 1 микроконтроллера ATmega328, установил быстродействующий режим ШИМ и добился частоты 62,5 кГц. Чтобы в следующий раз не разбираться с режимами таймера я выписал всевозможные варианты параметров ШИМ для таймера 1.

Для того, чтобы задать нужный режим ШИМ на выводах 9 и 10 необходимо разместить две соответствующие строки в функцию setup().

8 бит, 62 500 Гц

Код: Выделить всё

TCCR1A = TCCR1A & 0xe0 | 1;
TCCR1B = TCCR1B & 0xe0 | 0x09;
8 бит, 7 812,5 Гц

Код: Выделить всё

TCCR1A = TCCR1A & 0xe0 | 1;
TCCR1B = TCCR1B & 0xe0 | 0x0a;
8 бит, 976,56 Гц

Код: Выделить всё

TCCR1A = TCCR1A & 0xe0 | 1;
TCCR1B = TCCR1B & 0xe0 | 0x0b;
8 бит, 244,14 Гц

Код: Выделить всё

TCCR1A = TCCR1A & 0xe0 | 1;
TCCR1B = TCCR1B & 0xe0 | 0x0c;
8 бит, 61,04 Гц

Код: Выделить всё

TCCR1A = TCCR1A & 0xe0 | 1;
TCCR1B = TCCR1B & 0xe0 | 0x0d;
9 бит, 31 250 Гц

Код: Выделить всё

TCCR1A = TCCR1A & 0xe0 | 2;
TCCR1B = TCCR1B & 0xe0 | 0x09;
9 бит, 3 906,25 Гц

Код: Выделить всё

TCCR1A = TCCR1A & 0xe0 | 2;
TCCR1B = TCCR1B & 0xe0 | 0x0a;
9 бит, 488,28 Гц

Код: Выделить всё

TCCR1A = TCCR1A & 0xe0 | 2;
TCCR1B = TCCR1B & 0xe0 | 0x0b;
9 бит, 122,07 Гц

Код: Выделить всё

TCCR1A = TCCR1A & 0xe0 | 2;
TCCR1B = TCCR1B & 0xe0 | 0x0c;
9 бит, 30,52 Гц

Код: Выделить всё

TCCR1A = TCCR1A & 0xe0 | 2;
TCCR1B = TCCR1B & 0xe0 | 0x0d;
10 бит, 15 625 Гц

Код: Выделить всё

TCCR1A = TCCR1A & 0xe0 | 3;
TCCR1B = TCCR1B & 0xe0 | 0x09;
10 бит, 1 953,13 Гц

Код: Выделить всё

TCCR1A = TCCR1A & 0xe0 | 3;
TCCR1B = TCCR1B & 0xe0 | 0x0a;
10 бит, 244,14 Гц

Код: Выделить всё

TCCR1A = TCCR1A & 0xe0 | 3;
TCCR1B = TCCR1B & 0xe0 | 0x0b;
10 бит, 61,04 Гц

Код: Выделить всё

TCCR1A = TCCR1A & 0xe0 | 3;
TCCR1B = TCCR1B & 0xe0 | 0x0c;
10 бит, 15,26 Гц

Код: Выделить всё

TCCR1A = TCCR1A & 0xe0 | 3;
TCCR1B = TCCR1B & 0xe0 | 0x0d;


Следующий скетч формирует на выводе 10 ШИМ с частотой 62,5 кГц и коэффициентом заполнения примерно 30 %.

Код: Выделить всё

void setup() {
  // ШИМ 8 разрядов, 62,5 кГц
  TCCR1A = TCCR1A & 0xe0 | 1;
  TCCR1B = TCCR1B & 0xe0 | 0x09; 
  analogWrite(10,76); // на выводе 10 ШИМ=30%
}
void loop() {
}


Эдуард
Администратор
Сообщения: 484
Зарегистрирован: 30 окт 2016, 20:53

Re: Увеличение частоты и разрядности ШИМ Ардуино.

Сообщение Эдуард » 06 дек 2016, 22:09

На практике выяснилось, что при установке разрядности ШИМ больше 8ми функция analogWrite() не правильно отрабатывает код 255. Например, при 10ти разрядном ШИМ все коды от 0 до 1023 работают правильно, за исключением кода 255. Вместо того чтобы сформировать сигнал скважностью 1/4, вырабатывается статический сигнал уровня лог. 1. Что соответствует коду 1023.

Не знаю причину такого эффекта. Возможно функция analogWrite() воспринимает 255 как максимальное значение и расширяет его на весь диапазон. Может она принимает 255 как знаковое число.

При использовании analogWrite() с ШИМ повышенной разрядности надо исключить код 255. Например:

Код: Выделить всё

if (i == 255) i = 256;

Или использовать прямое обращение к регистрам ШИМ:

Код: Выделить всё

unsigned int pwm;

OCR1AH = (byte)(pwm >> 8);
OCR1AL = (byte)pwm;

Я сам не проверял, но думаю, должно работать.
При 8ми разрядном режиме ШИМ все работает корректно.

Аватара пользователя
БлудныйКот
Сообщения: 45
Зарегистрирован: 29 дек 2016, 16:19

Re: Увеличение частоты и разрядности ШИМ Ардуино.

Сообщение БлудныйКот » 13 янв 2017, 18:12

Полезная табличка.

10 бит, 1 562,5 Гц

Код: Выделить всё

TCCR1A = TCCR1A & 0xe0 | 3;
TCCR1B = TCCR1B & 0xe0 | 0x09;


Частота 15кГц, поправьте.
Мерил осциллографом на меге328

Эдуард
Администратор
Сообщения: 484
Зарегистрирован: 30 окт 2016, 20:53

Re: Увеличение частоты и разрядности ШИМ Ардуино.

Сообщение Эдуард » 13 янв 2017, 19:22

Спасибо. Ошибся, запятую случайно поставил. Частота для этого режима 15 625 Гц.

mihey78
Сообщения: 3
Зарегистрирован: 14 янв 2017, 23:45

Re: Увеличение частоты и разрядности ШИМ Ардуино.

Сообщение mihey78 » 15 янв 2017, 00:11

Что касается неправильной обработки значения 255, то все просто. Функция AnalogWrite(pin,val) из wiring_analog.c начинается так:

pinMode(pin, OUTPUT);
if (val == 0)
{
digitalWrite(pin, LOW);
}
else if (val == 255) // функция в этой строке считает val 8-битным значением.
{
digitalWrite(pin, HIGH);
}
else
{
//тут все остальные варианты (1..254,256..1023)
}

Я не совсем я понимаю указанные в таблице настройки PWM строки:
TCCR1A = TCCR1A & 0xE0 | 1;
TCCR1B = TCCR1B & 0xE0 | 0x09;

то же в бинарном виде:
TCCR1A = TCCR1A & B11100000 | B00000001, что означает:
не изменять три старших бита, остальные обнулить и установить младший бит (только для Timer1 - разрядность)

но:
- при сбросе все биты регистра сброшены в ноль и смысла их маскировать маской 0xE0 нет
- четыре (а не три) старших бита - это управление выходным сигналом (Compare Output Mode for Channel), если они равны нулю, шим не работает, очень важные при настройке биты, надо бы их вручную устанавливать, функция AnalogWrite очень примитивно это делает - только два варианта, да и надо бы проверить , корректно ли.

TCCR1B = TCCR1B & B11100000 | B00001001;
- здесь та же маска сохранения трех старших битов, но бит 5 вообще не используется, а биты 6 и 7 при PWM-mode вроде как не участвуют, один как-то связан с шумоподавлением, другой определяет переключение по фронту/спаду (только для Timer1).

Эдуард
Администратор
Сообщения: 484
Зарегистрирован: 30 окт 2016, 20:53

Re: Увеличение частоты и разрядности ШИМ Ардуино.

Сообщение Эдуард » 15 янв 2017, 01:09

Спасибо за объяснение работы функции analogWrite. Теперь все понятно.
Что касается установки битов режима таймера, то я поступил формально. Изменил только те биты, которые влияют на режим и частоту ШИМ.

UA6EM
Сообщения: 8
Зарегистрирован: 14 мар 2017, 20:43

Re: Увеличение частоты и разрядности ШИМ Ардуино.

Сообщение UA6EM » 14 мар 2017, 21:09

Для ШИМ я использую такой код :

/* Вызываем для изменения скважности) */
void analogWrite16(uint16_t value) { OCR1A = value;}

/* Вызываем в setup() */
void setup16bitPWM () {
pinMode(9,OUTPUT);
TCCR1A=(1<<COM1A1)|(1<<COM1A0)|(1<<WGM11);
TCCR1B=(1<<WGM13)|(1<<WGM12)|(1<<CS10); //mode14 FastPwm
ICR1=1023;
OCR1A=512; //50% default value
}

void setup() {
Serial.begin(9600);
analogReference(INTERNAL);
setup16bitPWM();

}

veron
Сообщения: 1
Зарегистрирован: 04 ноя 2017, 21:56

Re: Увеличение частоты и разрядности ШИМ Ардуино.

Сообщение veron » 04 ноя 2017, 22:07

Подскажите начинающему как можно одновременно изменять частоту от 1Гц до 10000Гц и скважность ШИМ от 0 до 100% на 9 ноге 328p?


Вернуться в «Аппаратное обеспечение»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость