Arduino programming guide series

PWM and buffer overflow

What happens if you write a PWM value that is larger than the maximum value that the Arduino's analogWrite() function can accommodate? This is an interesting case of "buffer overflow".

The Arduino Uno is able to produce Pulse Width Modulation signals via pins 3, 5, 6, 9, 10, and 11. With PWM, you can approximate analog output programmatically and do things like fade an LED on and off or control the speed of a motor.

PWM values and register bits

In the Atmega328 (the chip that powers the Arduino Uno), the register that is used by the PWM function has a resolution of 8 bits. This gives you a total of 256 possible "analog" output levels, from 0 to 255.

If you attach an LED to a PWM-capable pin, you can drive it to 256 different brightness levels, from totally off (PWM value "0") to totally on (PWM value "255").

And if you attach a motor, you can drive it to 256 different speed levels.

Why 256? because the register contains 8 bits, and a binary number with 8 bits can be one of 2 ^ 8 = 256.

You can set a PWM value by using the analogWrite(pin, value) instruction.

So, analogWrite(3, 125) would set pin 3 to value 125.

How to overflow the PWM register

Now, here is where it gets interesting.

What happens if we set analogWrite to a value bigger than 255? Say, 256?

Let's think about this for a minute.

If the PWM value is 255, the binary version is 11111111 (total is 8 bits) is stored in the PWM register (feel free to use this calculator for such binary to decimal conversions). A connected LED would light up in maximum brightness.

Let's add 1 to the register, and make the PWM value 256. 

The binary version of 256 is 0000000100000000 (total is 16 bits) since now we need two bytes to represent this value. 

But, the Arduino (in reality, its Atmega328P chip) can only fit the first byte in its PWM register, the one in green. 

The effect of PWM register overflow

The second byte will overflow and "disappear" (the red part).

So, what is actually stored in the PWM register is 00000000. This is decimal "0", which means that your LED is turned off.

In other words, analogWrite(3, 0) and analogWrite(3, 256) would have the exact same effect on an LED or a motor.

Add another "1" to the register, and the PWM value now is 257. 

The binary version of 257 is 0000000100000001The byte in green is stored in the PWM register, and the rest (in red) disappears. In the register now the decimal value "1" is stored.

The lesson to take home is that although you can set the PWM value in analogWrite to any decimal you like, only the first byte of this number will fit in the PWM register. 

The rest will overflow and disappear.

New to the Arduino?

Arduino Step by Step Getting Started is our most popular course for beginners.

This course is packed with high-quality video, mini-projects, and everything you need to learn Arduino from the ground up. We'll help you get started and at every step with top-notch instruction and our super-helpful course discussion space.

Tech Explorations Arduino intermediate level

Done with the basics? Looking for more advanced topics?

Arduino Step by Step Getting Serious is our comprehensive Arduino course for people ready to go to the next level.

Learn about Wi-Fi, BLE and radio, motors (servo, DC and stepper motors with various controllers), LCD, OLED and TFT screens with buttons and touch interfaces, control large loads like relays and lights, and much much MUCH more.


We publish fresh content each week. Read how-to's on Arduino, ESP32, KiCad, Node-RED, drones and more. Listen to interviews. Learn about new tech with our comprehensive reviews. Get discount offers for our courses and books. Interact with our community. One email per week, no spam; unsubscribe at any time

Image
{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}