void setup() {

uint16_t icr = 0xffff;

void loop() {
  analogWrite16(9, 0);
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);                  /* prescaler 1 */
  ICR1 = icr;                         /* TOP counter value (freeing OCR1A*/

/* 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;

Using the code above I can achieve 16 bit PWM signal, but when writing 0 in analogWrite16 it output ~33mV. I know that I can set the PWM pin low but yet again it don't output 0V.

I'm guessing beside the ATMEGA offset the Arduino UNO board it self ground is raised either because it's being fed from USB or the board circuitry and PCB traces resistance. or both?

because ~33mV offset is a lot, is it normal?

How can I make Arduino to start at 0V or at least reduce that 33mV offset to 1-2mV?


You've got two possibilities:

  1. You can't have full off in "non-inverting PWM" mode
  2. You can't have full on in "inverting PWM" mode

In the Arduino core it's solved by turning off the PWM output and setting logical 0 or 1 for corner values.

And if you need full off but you don't need full on, you can use inverted PWM mode.

  • How do I use inverted mode? is there a code that I have to modify? – ElectronSurf Dec 28 '19 at 20:15
  • 1
    You just have to change COM1A/COM1B (it's in the datasheet) values and compute correct value for OCR1A/OCR1B (something like 0xFFFFU - val) – KIIV Dec 28 '19 at 20:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.