Страница 1 из 1

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

Добавлено: 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() {
}

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ми разрядном режиме ШИМ все работает корректно.

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

Добавлено: 13 янв 2017, 18:12
БлудныйКот
Полезная табличка.

10 бит, 1 562,5 Гц

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

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


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

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

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

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

Добавлено: 15 янв 2017, 00:11
mihey78
Что касается неправильной обработки значения 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).

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

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

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

Добавлено: 14 мар 2017, 21:09
UA6EM
Для ШИМ я использую такой код :

/* Вызываем для изменения скважности) */
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();

}

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

Добавлено: 04 ноя 2017, 22:07
veron
Подскажите начинающему как можно одновременно изменять частоту от 1Гц до 10000Гц и скважность ШИМ от 0 до 100% на 9 ноге 328p?