Увеличьте разрешение PWM-бит

Я хотел бы увеличить разрешение бит PWM для Arduino Uno. На данный момент это 8-бит, который я считаю слишком низким. Возможно ли это, не теряя возможности прерываний и задержек?

Коен

ИЗМЕНИТЬ Эта настройка обеспечивает 16-битный результат

void setupPWM16() {
    DDRB |= _BV(PB1) | _BV(PB2);        /* set pins as outputs */
    TCCR1A = _BV(COM1A1) | _BV(COM1B1)  /* non-inverting PWM */
        | _BV(WGM11);                   /* mode 14: fast PWM, TOP=ICR1 */
    TCCR1B = _BV(WGM13) | _BV(WGM12)
        | _BV(CS11);                    /* prescaler 1 */
    ICR1 = 0xffff;                      /* TOP counter value (freeing OCR1A*/
}
/* Comments about the setup
Changing ICR1 will effect the amount of bits of resolution.
ICR1 = 0xffff; (65535) 16-bit resolution
ICR1 = 0x7FFF; (32767) 15-bit resolution
ICR1 = 0x3FFF; (16383) 14-bit resolution etc....

Changing the prescaler will effect the frequency of the PWM signal.
Frequency[Hz}=CPU/(ICR1+1) where in this case CPU=16 MHz
16-bit PWM will be>>> 16000000/(65535+1)=244,14Hz
*/

/* 16-bit version of analogWrite(). Works only on pins 9 and 10. */
void analogWrite16(uint8_t pin, uint16_t val)
{
    switch (pin) {
        case  9: OCR1A = val; break;
        case 10: OCR1B = val; break;
    }
}
9 голосов | спросил KoenR 17 J0000006Europe/Moscow 2015, 19:10:10

2 ответа


14

Arduino Uno основан на микроконтроллере ATmega382P. Этот чип имеет два 8-битных таймера, каждый два канала PWM и один 16-разрядный таймер, вождение последних двух каналов.

Вы не можете увеличить разрешение 8-разрядных таймеров. Ты можешь, однако, установите 16-разрядный таймер в 16-битном режиме вместо 8-битного режима используемый основной библиотекой Arduino. Это даст вам два 16-битных PWM каналов с пониженной частотой 244 Гц (максимум). Ты будешь вероятно, придется настраивать таймер самостоятельно, и не выиграет от простой в использовании функции analogWrite(). Подробнее см. В разделе на таймере 1 в ATmega328P техническое описание .

Обновление . Ниже приведена реализация 16-разрядного analogWrite(). Это работает только на контактах 9 и 10, так как это единственные контакты, подключенные к 16-разрядный таймер.

 /* Configure digital pins 9 and 10 as 16-bit PWM outputs. */
void setupPWM16() {
    DDRB |= _BV(PB1) | _BV(PB2);        /* set pins as outputs */
    TCCR1A = _BV(COM1A1) | _BV(COM1B1)  /* non-inverting PWM */
        | _BV(WGM11);                   /* mode 14: fast PWM, TOP=ICR1 */
    TCCR1B = _BV(WGM13) | _BV(WGM12)
        | _BV(CS10);                    /* no prescaling */
    ICR1 = 0xffff;                      /* TOP counter value */
}

/* 16-bit version of analogWrite(). Works only on pins 9 and 10. */
void analogWrite16(uint8_t pin, uint16_t val)
{
    switch (pin) {
        case  9: OCR1A = val; break;
        case 10: OCR1B = val; break;
    }
}

Вы можете заметить, что верхняя часть последовательности счетчиков настроена в явном виде. Вы можете изменить это на меньшее значение, чтобы сделать PWM быстрее, за счет уменьшения разрешения.

И вот пример эскиза, иллюстрирующий его использование:

 void setup() {
    setupPWM16();
}

/* Test: send very slow sawtooth waves. */
void loop() {
    static uint16_t i;
    analogWrite16(9, i);
    analogWrite16(10, 0xffff - i);
    i++;
    delay(1);
}
ответил Edgar Bonet 17 J0000006Europe/Moscow 2015, 19:19:22
2

При некоторой калибровке вы можете суммировать выходы двух PWM-каналов с разными весовыми резисторами. В крайнем случае вы могли бы использовать один вывод для обеспечения 8 бит разрешения и масштабирования другого на 1/256-го уровня и добавлять их, чтобы второй канал покрывал один бит диапазона, и вы (опять-таки по-умолчанию) получили 16 бит разрешения. Без огромной заботы и настройки все, что вы получили, было бы беспорядком.
Однако, разделив 2-й канал на 16 или 32, вы можете добавить несколько дополнительных бит разрешения PWM. Просто добавив 2 аналоговых отфильтрованных выхода PWM-каналов, вы добавите дополнительный бит (поскольку диапазон потенциалов удваивается для неизмененного mV /бит).
Понятно (снова) для каждого дополнительного деления на 2 вы получаете дополнительный бит разрешения, но это может быть выполнено только для 4 или 5 или 6 дополнительных бит, с увеличением требований к точности масштабирующих резисторов и более сложной калибровкой и склонностью к ошибкам ,

Краткий пример.
Если один PWM будет уменьшен, чтобы дать значение 0 - 255 мВ с шагом 1 мВ, то суммирование двух PWM с равной амплитудой даст диапазон 0-510 мВ с шагом 1 мВ.
Если один PWM будет уменьшен в 32 раза, то вместо того, чтобы добавить 255 мВ к исходному диапазону ШИМ, он добавит только 8 мВ к верхнему концу (0.256.32 = 8 мВ, но разрешение будет в 0.03125 (1 /32nd ) mV шагов.

Хотя это может быть достигнуто исключительно с суммированием резисторов и фильтрацией RC, использование летнего ОУ значительно улучшит результаты.

Также пульсация PWM может быть отфильтрована с помощью простого RC-фильтра, но использование одного операционного усилителя в качестве буфера (или даже всего одного транзистора в качестве последователя эмиттера) даст вам 3 или 5 полюсов фильтрации нижних частот и намного больше шансов обеспечивая дополнительное разрешение PWM. Я не проверял «фазовую согласованность» выходных сигналов ШИМ, но ожидаю, что они будут двигаться в относительном блокировке, поэтому вы не получите преимущества сглаживания добавления двух некоррелированных сигналов.

При необходимости может быть сделан дополнительный комментарий. Спросите, интересуетесь ли вы.

ответил Russell McMahon 17 J0000006Europe/Moscow 2015, 20:41:04

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132