Skip to content

Addressable LEDs

The robot is equipped with 8 configurable LEDs. This topic was covered in detail during the presentation; here is a brief summary. The configured LEDs in the robot consist of three distinct colors (R - Red, G - Green, B - Blue). Each of these LEDs can have its brightness adjusted in 256 steps, allowing for a total of 16 million shades. Accordingly, each LED component is configurable using 8 bits, resulting in a total of 24 bits to configure all LEDs. The LEDs used in the robot are WS2812 type. Each LED comes with 5 connectors: it requires a power supply (VDD, GND), chip power (VCC), and also has a digital input (DI) and a digital output (DO). The color, brightness and also the the driver for the next input in case its connected in cascade mode is controller by an integrated chip inside the LED.


Addressable LED Management

The robot features eight addressable LEDs. While these were covered in detail during the lecture, here is a brief summary. Each LED module consists of three color channels (R – red, G – green, B – blue). The brightness of each channel can be adjusted in 256 discrete steps, allowing for a total of 16 million possible color combinations. This means each LED is controlled using 8 bits per color channel, totaling 24 bits per LED.

The LEDs used in the robot are WS2812-type addressable LEDs. These LEDs do not require external current-limiting resistors, as they integrate built-in current regulators. The wiring configuration of the WS2812, as specified in the datasheet, is shown in the diagram below.

A WS2812 LED


The digital output (DO) of one LED can serve as the digital input (DI) of the next LED, allowing multiple LEDs to be connected in series. This cascading capability enables the control of an entire LED strip using a single data line, as demonstrated in the following diagram.

A WS2812 LEDs in cascade


To simplify usage, the underlying functions handle the transmission of bit patterns automatically. However, for reference, the 24-bit configuration word for a single LED is structured as follows:

  • The color component order is Green-Red-Blue (GRB).
  • The data is transmitted starting from the most significant bit (MSB) of each component.

This format ensures consistent color rendering across the LED chain, as illustrated in the diagram below.

Addressable LED configuration with color encoding


⚡Hands-on tasks

Controlling the 8 Addressable Serial LEDs on the Robot

We will write a program to control the 8 programmable LEDs on the robot using the NeoPixel library. The LEDs should follow this sequence, changing color every second: 🟥 Red → 🟩 Green → 🟦 Blue → ⚪ White At the end of the program, all LEDs should be turned off.

To achieve this, we will use MicroPython's neopixel.py module. Alternatively, the robot's pico_car.py module can also be used for controlling the LEDs (see additional tasks for details).

Info

More details in NeoPixels docs


We will import the necessary modules:

import machine  # Controls hardware
import neopixel  # Handles programmable NeoPixel LEDs
import time  # Provides delay functions

The LED strip is connected to GPIO6 on the microcontroller. The NeoPixel() function initializes it, and the second parameter specifies the number of LEDs (8 in this case).

LED_pin = machine.Pin(6)  # Define GPIO6 as LED control pin
LED_chain = neopixel.NeoPixel(LED_pin, 8)  # Create NeoPixel object for 8 LEDs

The function automatically handles the correct I/O direction, so no additional configuration is needed.

Understanding LED Color Control

Each LED color is controlled using 24-bit values:

  • First 8 bits: Red component
  • Next 8 bits: Green component
  • Last 8 bits: Blue component

For a given LED, the color is stored as a tuple (R, G, B), where:

  • 0 means off
  • 255 means maximum brightness

For example, setting an LED to full red:

LED_chain[i] = (255, 0, 0)  # Full red, no green, no blue

To apply changes, we must write the updated data to the LED strip:

LED_chain.write()

Complete LED Color Sequence Program

import machine
import neopixel
import time

# Initialize LED strip on GPIO6 with 8 LEDs
LED_pin = machine.Pin(6)
LED_chain = neopixel.NeoPixel(LED_pin, 8)

# Define colors (R, G, B)
colors = [(255, 0, 0),  # Red
          (0, 255, 0),  # Green
          (0, 0, 255),  # Blue
          (255, 255, 255)]  # White

# Loop through colors with 1-second delay
for color in colors:
    for i in range(8):  # Apply color to all LEDs
        LED_chain[i] = color
    LED_chain.write()  # Update LED strip
    time.sleep(1)  # Hold for 1 second -> delay

# Turn off all LEDs
for i in range(8):
    LED_chain[i] = (0, 0, 0)  # Set to black (off)
LED_chain.write()

Try testing various configurations of colors! 🚀

How to change the color?

Simulation

The following simulation demonstrates the example program in action. Feel free to modify the code and experiment with different values to see how it affects the output. Try testing various configurations to deepen your understanding! 🚀

Try it in the Online Simulator

How NeoPixel driver can be inmplemented with PIO?

Here is a short article how NeoPixel LEDs could be driven with PIO (Programmable IO) peripheral.


Additional Tasks

Task 1: Experiment with different brightness levels and color combinations.

Task 2: Implement a gradual brightness increase or decrease for the LEDs. Example: Smoothly increase the red component from 0 to 255 in steps of 2, with a 10 ms delay between updates.

for j in range(0, 255, 2):  # Gradually increase brightness
    for i in range(8):
        LED_chain[i] = (j, 0, 0) # Red intensity increases, green and blue stay off
    LED_chain.write()
    time.sleep_ms(10)  # Small delay for smooth transition

🚀 Try modifying the code to create dynamic light effects or animations!

Tip

Try range with decreasing order: range(255, 0, -2)


➡ Next Steps