void setup() {
Serial.begin(9600);
setupPWM16();
}
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?
1 Answer 1
You've got two possibilities:
- You can't have full off in "non-inverting PWM" mode
- 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– ElectronSurf2019年12月28日 20:15:15 +00:00Commented Dec 28, 2019 at 20:15
-
1You just have to change
COM1A
/COM1B
(it's in the datasheet) values and compute correct value forOCR1A
/OCR1B
(something like0xFFFFU - val
)KIIV– KIIV2019年12月28日 20:19:14 +00:00Commented Dec 28, 2019 at 20:19