one wire using rp2040 using python - Velkurkirankumar/Internship-Projects GitHub Wiki

Controlling WS2812 NeoPixel Ring with Raspberry Pi Pico


Objective

This project demonstrates how to control a WS2812 (NeoPixel) 16-LED round ring using a Raspberry Pi Pico microcontroller. The system allows users to set individual LED colors via a command-line interface.


Introduction

pico micro controller

  • In this project, you will connect a Raspberry Pi Pico to another computer and learn how to program it using MicroPython.

  • A Raspberry Pi Pico is a low-cost microcontroller device. Microcontrollers are tiny computers, but they tend to lack large volume storage and peripheral devices that you can plug in (for example, keyboards or monitors).

  • A Raspberry Pi Pico has GPIO pins, much like a Raspberry Pi computer, which means it can be used to control and receive input from a variety of electronic devices.

  • Raspberry Pi Pico is a low-cost, high-performance microcontroller board with flexible digital interfaces. Key features include:

  • RP2040 microcontroller chip designed by Raspberry Pi in the United Kingdom

  • Dual-core Arm Cortex M0+ processor, flexible clock running up to 133 MHz

  • 264KB of SRAM, and 2MB of on-board flash memory

  • USB 1.1 with device and host support

  • Low-power sleep and dormant modes

  • Drag-and-drop programming using mass storage over USB

  • 26 × multi-function GPIO pins

  • 2 × SPI, 2 × I2C, 2 × UART, 3 × 12-bit ADC, 16 × controllable PWM channels

  • Accurate clock and timer on-chip

  • Temperature sensor

  • Accelerated floating-point libraries on-chip

  • 8 × Programmable I/O (PIO) state machines for custom peripheral support

image

WS2812 Neopixel

  • This Neo pixel ring can be easily programmed to follow a particular pattern or to change the colour pattern.

  • Round and round and round they go! 16 ultra bright smart LED NeoPixels are arranged in a circle with 1.75″ (44.5mm) outer diameter.

  • The rings are ‘chainable’ – connect the output pin of one to the input pin of another.

  • Use only one microcontroller pin to control as many as you can chain together! Each LED is addressable as the driver chip is inside the LED.

  • Each one has ~18mA constant current drive so the color will be very consistent even if the voltage varies, and no external choke resistors are required making the design slim.

  • Power the whole thing with 5VDC (4-7V works) and you’re ready to rock.

  • There is a single data line with a very timing-specific protocol.

  • Since the protocol is very sensitive to timing, it requires a real-time microconroller such as an AVR, Arduino, PIC, mbed, etc.

  • It cannot be used with a Linux-based microcomputer or interpreted microcontroller such as the netduino or Basic Stamp.

  • As it requires hand-tuned assembly it is only for AVR cores but others may have ported this chip driver code so please google around.

  • An 8MHz or faster processor is required.

  • Comes as a single ring with 16 individually addressable RGB LEDs assembled and tested.

Technical details Dimensions:

  • Outer diameter: 44.5mm / 1.8″;
  • Inner diameter: 31.7mm / 1.2″
  • Thickness: 6.7mm / 0.3″
  • As of 7/16/204 we are now shipping with a standard-thickness PCB and we added an extra ground and power breakout
  • Weight: 3.03g

image


Hardware Components

  • Raspberry Pi Pico: Microcontroller for controlling the NeoPixel ring.
  • WS2812 NeoPixel 16-LED Ring: Individually addressable RGB LEDs.
  • Breadboard: Used to make connections without soldering.
  • Connecting Wires: Male-to-female jumper wires to connect components.

Hardware Connections

NeoPixel Pin Pico Pin Description
Data In GPIO 0 Sends control signals for the NeoPixel LEDs.
Ground (GND) GPIO 8 Connects NeoPixel’s ground to Pico’s ground.
5V VBUS (5V) Powers the NeoPixel ring directly from Pico.

Configuration Details

  • GPIO Pin for NeoPixel: GPIO 0 for Data.
  • Power Source: 5V (VBUS) on the Pico.
  • Number of LEDs: 16.

Software Implementation

Programming Language

  • MicroPython: Lightweight Python implementation for microcontrollers.

Core Concepts

  • Programmable I/O (PIO): Generates the timing signals required for WS2812 LEDs.
  • State Machine: Runs the PIO program and outputs signals to NeoPixel LEDs.
  • User Commands: Allows dynamic control of LED colors through a CLI.

Code Overview

1. Importing Libraries

import array
from machine import Pin
import rp2

1. What is array and why is it used?

  • array is a module in Python (specifically MicroPython in this case) that provides an efficient way to store and manipulate homogeneous data types, like numbers. It is especially useful when dealing with large amounts of data, such as the color values of NeoPixels.
Why it is used:
  • In this code, the array module is used to store the color data for the NeoPixel LEDs in a compact and efficient way. Each element of the array represents the color of an individual LED in the GRB (Green, Red, Blue) format. The advantage of using array over lists is that it consumes less memory and performs better when dealing with numeric data. Since NeoPixel control involves a lot of repetitive data (RGB values for many LEDs), array helps manage this data efficiently.

2.What is machine.Pin and why is it used?

  • machine.Pin is a class from the machine module in MicroPython, which provides low-level access to the hardware pins of the microcontroller. It allows you to control the input and output of the GPIO (General Purpose Input/Output) pins.
Why it is used:
  • The Pin class is used to control the specific GPIO pin on the RP2040 (Raspberry Pi Pico) connected to the NeoPixel ring's data line. By using Pin, you can configure the pin as an output pin and send signals to control the NeoPixel LEDs. In this case, the code uses Pin(NEOPIXEL_PIN) to specify the pin that will send the data to the NeoPixel LEDs.

3. What is rp2?

  • rp2 is a module specific to the Raspberry Pi RP2040 (the microcontroller used in the Raspberry Pi Pico) that provides access to the Programmable I/O (PIO) system. The PIO system allows for precise timing and control of external devices, like the NeoPixel LEDs, by generating custom signals.
Why it is used:
  • The rp2 module is used to define and execute a custom PIO program that controls the timing and data output for the WS2812 (NeoPixel) LEDs. NeoPixels require very specific timing to interpret the data correctly, and the rp2 module allows us to generate that timing using a hardware state machine (a feature of the RP2040).

  • array: Efficiently stores color data for the LEDs.
  • Pin: Manages GPIO pins for data transmission and power.
  • rp2: Utilizes PIO for handling WS2812 data signals.

2. Defining Configuration

NEOPIXEL_PIN = 0  # GPIO for NeoPixel data line
NUM_LEDS = 16     # Total number of LEDs

3. PIO Program for WS2812 Timing

  • The PIO assembly generates the required signal to control the WS2812 LEDs:
@rp2.asm_pio(
    sideset_init=rp2.PIO.OUT_LOW,
    autopull=True,
    pull_thresh=24
)
def ws2812():
    wrap_target()
    label("bitloop")
    out(x, 1)               .side(0) [2]
    jmp(not_x, "do_zero")   .side(1) [1]
    jmp("bitloop")          .side(1) [3]
    label("do_zero")
    nop()                   .side(0) [3]
    wrap()

@rp2.asm_pio(...): This is a decorator that defines the PIO program. The parameters inside the decorator configure how the program behaves:

sideset_init=rp2.PIO.OUT_LOW: This sets the initial state of the data line (side-set pin) to LOW. NeoPixels require the data line to be LOW initially before sending any data.

autopull=True: This tells the PIO program to automatically fetch new data from the FIFO (First-In-First-Out) queue when needed.

pull_thresh=24: This tells the PIO program to pull 24 bits of data at a time (each color channel has 8 bits, and there are 3 channels: red, green, and blue).

wrap_target() and wrap(): These define the start and end of the PIO program loop. Everything between wrap_target() and wrap() is repeated continuously to send out the data.

label("bitloop"): This is a label for a loop that processes each bit of the data to be sent to the NeoPixel. The out(x, 1) command sends one bit at a time.

out(x, 1).side(0) [2]: This outputs one bit to the data line and keeps the data line LOW for 2 cycles. This is the timing protocol required by WS2812 LEDs.

jmp(not_x, "do_zero"): If the bit to be sent is 0, it jumps to the "do_zero" label.

jmp("bitloop"): If the bit is 1, it continues the loop and keeps the data line HIGH for 3 cycles.

label("do_zero"): If the bit is 0, this label is executed, and the data line is held LOW for 3 cycles.

nop(): This is a no-op instruction, meaning it does nothing. It is used to hold the data line LOW for a set number of cycles (3 cycles for a 0 bit).

4. State Machine Setup

sm = rp2.StateMachine(
    0,
    ws2812,
    freq=8000000,
    sideset_base=Pin(NEOPIXEL_PIN)
)
sm.active(1)

5. Updating LED Colors

def update_neopixel(led_data):
    array_data = array.array("I", led_data)
    sm.put(array_data, 8)

6. User Command Input

def control_led_by_command():
    led_data = [0] * NUM_LEDS
    while True:
        command = input("Enter LED number and color (e.g., '0 FFA500') or 'exit' to quit: ").strip()
        if command.lower() == "exit":
            print("Exiting...")
            break
        # Process LED commands...

Requirements needed:

  1. USB cable with Micro B.
  2. pico microcontroller.
  3. Jumper wires both male and female wires.
  4. Breadboard.
  5. ws2812 neopixel round ring.
  6. power supply.

Execution Steps

1. Hardware Setup

  • Connect the NeoPixel ring to the Raspberry Pi Pico as per the connection table.
  • Ensure the NeoPixel ring is powered adequately (5V from VBUS).

2. Upload the Code

  • Flash the MicroPython code onto the Pico using tools like Thonny IDE.

3. Run the Program

  • Open a terminal connected to the Pico.
  • Run the script and control the LEDs by entering commands.

4. Control LEDs

Example commands:

  • 0 FFA500: Set LED 0 to orange.
  • exit: Quit the program.

Observations

  • The NeoPixel ring responds instantly to user commands.
  • Colors display accurately due to precise PIO timing.

Enhancements

  • Save States: Retain the last LED configuration after a reset.
  • Dynamic LED Count: Allow users to define the number of LEDs.

Conclusion

This project demonstrates the use of Raspberry Pi Pico and MicroPython to control a WS2812 NeoPixel ring. The implementation highlights efficient use of PIO and state machines for precise timing, making it suitable for building advanced lighting effects. The system can be extended with animations and additional features for dynamic lighting control.