10bit PWM сбой в работе.

_Quasar_

✩✩✩✩✩✩✩
30 Июл 2021
55
0
Подскажите в чем дело. На мк 328p настроил на 10 и 9 ноге 10bit pwm используя 1 таймер. Далее решил прогнать заполнение от 0 до 1023 и визуально посмотреть на светодиоде. В итоге я получаю странный закономерный глюк в значениях от 200 до 300. Визуально это выглядит как кратковременный яркий всплеск. Заснял это на видео.
Код проекта тоже прикладываю
C++:
const uint8_t PWM_PIN = 10;
const uint8_t TIME = 3;

void setup() {
  TCCR1A = 0b00000011;  // 10bit
  TCCR1B = 0b00000010;  // x8 phase correct
  pinMode(PWM_PIN, OUTPUT);
}

uint32_t tmr = 0;
uint16_t val = 0;
bool dir = true;

void loop() {

  if (millis() - tmr >= TIME) {
    tmr = millis();
    if (dir) val++;                           // увеличиваем яркость
    else val--;                               // уменьшаем
    if (val >= 1023 || val <= 0) dir = !dir;  // разворачиваем
    analogWrite(PWM_PIN, val);
  }

}

Подскажите с чем это может быть связано. Эффект повторяется на 2 доступных мне платах.
Если есть возможность можете сами его повторить.
 

_Quasar_

✩✩✩✩✩✩✩
30 Июл 2021
55
0
Проблема решилась добавлением вот такой строчки в сетапе TCCR1A |=_BV(COM1B1); и выводе напрямую в порт OCR1B = val;
Стандартные методы ядра похоже плохо умеют переварить все что больше 8bit,можно наткнуться на такие баги. Хоро что решил проверить это визуально.
 

bort707

★★★★★★✩
21 Сен 2020
3,166
934
Стандартные методы ядра
Стандартные методы - это какие? Неужели analogWrite() ?

Откройте исходник пакета ардуино и убедитесь, что команда analogWrite() делает ровно то же, что вы придумали в своем "решении":
C++:
case TIMER1B:
                // connect pwm to pin on timer 1, channel B
                sbi(TCCR1A, COM1B1);
                OCR1B = val; // set pwm duty
                break;
 
Изменено:

Bruzzer

★★★✩✩✩✩
23 Май 2020
584
176
@_Quasar_,
Дело в том, что значение 255 в analogWrite выводится не записью в OCRxx, а как digitalWrite(HIGH);
Можно не использовать 255. Заменять его на 254 или 256
 

Sergo_ST

★★★★★★✩
15 Мар 2020
1,055
875
@bort707, В процедуре analogWrite() имеется вот такой кусок кода:
C++:
else if (val == 255)
{
  digitalWrite(pin, HIGH);
}
При использовании разрешения таймера более чем 8 бит установка значения заполнения шим равным 255 заставляет вывод мк перейти в высокий уровень и отключить шим, как и сказал @Bruzzer.