Controlling RGB LED with Raspberry Pi Pico W Web Server using MicroPython
Introduction
Controlling RGB LED with Raspberry Pi Pico W Web Server using MicroPython –in this article, I will teach you how to create a web page to control the RGB LED over wifi using Raspberry Pi Pico W, and I will also teach you how to set up the local network web server on Raspberry PI Pico W. so this article will be very helpful to you. as you know the main thing is the internet while make the web-based projects. So, if you’re not familiar with how to connect to Wi-Fi, I recommend you to read my previous article to learn about Wi-Fi connectivity.
Project Overview:
In this project, i will show you how to connect a Raspberry Pi Pico W to a Wi-Fi network and use its onboard LED to indicate the network connectivity status. When the onboard LED blinks it denotes that the Wi-Fi connection is not established. Once the blinking stops it indicates that the Pico W has successfully connected to the Wi-Fi network. Additionally, we will set up a web server on the Raspberry Pi Pico W accessible via a local network IP address through any internet browser.
A web control page will be designed using HTML and CSS. This webpage will feature text view widgets that will display the values of sliders in RGB format, and will also show the names of the sliders, for example, Red, Green, and Blue. To control RGB LED, we will use 3 sliders. Along with this, we will use a button that will send the slider values to the Raspberry Pi Pico W through a Web Server, and the RGB LED will display the light based on the values set on the slider. Initially, we will test this project on a desktop, but later, we will also access the same local network IP address from our mobile to control the RGB LED through the web server using our mobile browser.
Amazon links:
*Please Note: These are affiliate links. I may make a commission if you buy the components through these links. I would appreciate your support in this way!
Raspberry Pi Pico W Overview:
RP2040 Chip Details
At the heart of the Raspberry Pi Pico W lies the RP2040, a custom ARM chip crafted by the Raspberry Foundation. Featuring a dual-core ARM Cortex M0+ processor, it boasts flexibility and power with a clock speed of up to 133 MHz. This positions the Pico W as an effective and adaptable choice for diverse projects.
Wireless Features
The standout feature of the Pico W is its wireless functionality, enabled by the Infineon CYW43439 wireless chip. Offering IEEE 802.11 b/g/n wireless LAN and Bluetooth 5.2 capabilities, it propels the board into a new era of connected and Internet of Things (IoT) applications.
GPIOs and Compatibility
The Raspberry Pi Pico W comes equipped with 40 pins, including 26 versatile GPIOs, all adhering to a 3.3V logic level. Designed for pin-to-pin compatibility with the earlier Pico model, it ensures seamless transition and convenience for upgrades in existing projects. Additionally, it features a 3-Pin header for debugging near the RP2040 Chip, enhancing its functionality.
Raspberry Pi Pico W Specifications:
Specification | Detail |
Microcontroller Chip | RP2040 (by Raspberry Pi) |
Processor | Dual-core ARM Cortex M0+ |
Clock Speed | Up to 133 MHz |
SRAM | 264kB |
Flash Memory | 2MB onboard |
Wireless Interfaces | Single-band 2.4GHz (802.11n) |
Bluetooth | Bluetooth 5.2 |
Wireless Chip | Infineon CYW43439 |
GPIO Pins | 26 multi-function GPIO pins |
Interfaces | 2×SPI, 2×I2C, 2×UART |
Analog-to-Digital Converters | 3×12-bit ADC |
PWM Channels | 16×controllable |
USB Support | USB 1.1 Host and Device |
Power Modes | Low-power sleep and dormant modes |
Additional Features | Temperature sensor, floating-point libraries |
Programmable IO | 8×Programmable IO (PIO) state machines |
PCB Dimensions | 51mm x 21mm x 1mm |
Power Input | USB port or VSYS pin |
Programming Languages | C/C++ and MicroPython |
IDE Support | Thonny IDE, Arduino IDE |
RGB LED Module:
An RGB LED module is an electronic component that combines red, green, and blue (RGB) light-emitting diodes (LEDs) in a single package. By mixing these three colors in different intensities, it can produce a wide spectrum of colors. This versatility makes RGB LEDs popular in various applications, from decorative lighting to display technology.
Pinout of a Typical RGB LED Â Module:
VCC (Power): This is the positive supply voltage pin. It’s typically connected to a power source (like a battery or a power supply unit). The voltage requirements can vary depending on the type of RGB LED, but common values are 5V or 12V.
Red (R), Green (G), and Blue (B) Pins: These are the control pins for each color. By adjusting the voltage or PWM (pulse-width modulation) signal applied to these pins, you can control the intensity of each color. Lowering the voltage or duty cycle dims the light, and increasing it makes the light brighter.
GND (Ground): This is the negative supply voltage pin. It’s connected to the ground of the power source. In some RGB LEDs, especially common anode types, this pin might be labeled as “Common Anode” and connected to VCC instead of ground.
Types of RGB LEDs:
Common Anode: In this type, all the anodes of the LEDs are connected to a common pin (usually the VCC). The individual colors are controlled by connecting the RGB pins to ground, often through a resistor or a microcontroller.
Common Cathode: Here, all the cathodes are connected to a common pin (usually the GND). The colors are controlled by supplying voltage to the RGB pins.
RGB LED Module with Raspberry Pi Pico W Circuit diagram:
As you can see, the circuit is very simple. I have connected the GND pin of the RGB LED module to the GND of the Raspberry Pi Pico W, the blue pin of the RGB LED module to the GPIO16 of the Raspberry Pi Pico W, the green pin of the RGB LED module to the GPIO17 of the Raspberry Pi Pico W, and the Red pin of the RGB LED Module to the GPIO18 of the Raspberry Pi Pico W.
RGB LED with Raspberry Pi Pico W Circuit diagram:
If you’re not using an RGB LED module, then please refer to this circuit diagram. The connections remain the same, except that a 330-ohm resistor is used for current limiting between the LED and the Raspberry Pi Pico W.
Controlling RGB LED with Raspberry Pi Pico Web Server Program:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 |
import network import socket import time import machine # Wi-Fi credentials ssid = 'your_network_name' password = 'your_network_password' # Connect to the Wi-Fi network wlan = network.WLAN(network.STA_IF) wlan.active(True) wlan.connect(ssid, password) # Setup onboard LED for Wi-Fi status status_led = machine.Pin('LED', machine.Pin.OUT) # Setup RGB LED pins red_led = machine.PWM(machine.Pin(18)) green_led = machine.PWM(machine.Pin(17)) blue_led = machine.PWM(machine.Pin(16)) # Initialize PWM red_led.freq(1000) green_led.freq(1000) blue_led.freq(1000) # Function to set RGB LED color def set_rgb_color(r, g, b): red_led.duty_u16(int(r / 255 * 65535)) green_led.duty_u16(int(g / 255 * 65535)) blue_led.duty_u16(int(b / 255 * 65535)) # Function to blink onboard LED def blink_led(): status_led.toggle() time.sleep(0.5) # Initial connection attempt max_attempts = 10 attempts = 0 connected = False while not wlan.isconnected() and attempts < max_attempts: blink_led() attempts += 1 if wlan.isconnected(): print(f"Connected to {ssid} successfully!") print("Network Config:", wlan.ifconfig()) status_led.value(1) connected = True else: print("Failed to connect to WiFi.") status_led.value(0) # Web server setup addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1] s = socket.socket() s.bind(addr) s.listen(1) # HTML and CSS for the control page html = """<!DOCTYPE html> <html> <head> <title>Pico W RGB LED Control</title> <style> body { font-family: 'Arial', sans-serif; text-align: center; margin: 0; padding-top: 30px; background-color: #f4f4f4; color: #333; box-sizing: border-box; } h1 { color: #4a4a4a; margin: 0 0 20px; font-size: 28px; /* Adjusted for better readability */ } p { color: #4a4a4a; font-size: 20px; /* Adjusted for better readability */ margin: 15px 0; } .container { width: 90%; max-width: 600px; /* Max width for larger screens */ margin: 0 auto; } button { font-size: 20px; /* Adjusted for better readability */ padding: 10px 20px; color: white; background-color: #007bff; border: none; border-radius: 5px; cursor: pointer; transition: background-color 0.3s ease; } button:hover { background-color: #0056b3; } button:active { background-color: #004085; } .slider { -webkit-appearance: none; width: 100%; height: 25px; background: #ddd; outline: none; opacity: 0.7; transition: opacity .2s; } .slider:hover { opacity: 1; } .slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 35px; height: 35px; background: #4CAF50; cursor: pointer; } .slider::-moz-range-thumb { width: 35px; height: 35px; background: #4CAF50; cursor: pointer; } @media (max-width: 600px) { h1 { font-size: 24px; } p { font-size: 18px; } button { font-size: 18px; padding: 8px 16px; } .slider::-webkit-slider-thumb, .slider::-moz-range-thumb { width: 25px; height: 25px; } } </style> </head> <body> <div class="container"> <h1>Pico W RGB LED Control</h1> <div> <p>Red: <input type="range" min="0" max="255" class="slider" id="redSlider" oninput="updateSliderValue('red', this.value)"> <span id="redValue">128</span></p> <p>Green: <input type="range" min="0" max="255" class="slider" id="greenSlider" oninput="updateSliderValue('green', this.value)"> <span id="greenValue">128</span></p> <p>Blue: <input type="range" min="0" max="255" class="slider" id="blueSlider" oninput="updateSliderValue('blue', this.value)"> <span id="blueValue">128</span></p> <button onclick="updateLED()">Update LED</button> </div> </div> <script> function updateLED() { var red = document.getElementById('redSlider').value; var green = document.getElementById('greenSlider').value; var blue = document.getElementById('blueSlider').value; var xhr = new XMLHttpRequest(); xhr.open('GET', '/update?r=' + red + '&g=' + green + '&b=' + blue, true); xhr.send(); } function updateSliderValue(color, value) { document.getElementById(color + 'Value').innerText = value; } </script> </body> </html> """ # Function to handle client requests def handle_client(client): request = client.recv(1024).decode() print('Request:', request) response_html = html if 'GET /update' in request: _, params = request.split('?', 1) params = params.split(' ', 1)[0] r, g, b = [int(v.split('=')[1]) for v in params.split('&')] set_rgb_color(r, g, b) client.send('HTTP/1.1 200 OK\n') client.send('Content-Type: text/html\n') client.send('Connection: close\n\n') client.sendall(response_html if 'GET / ' in request else "") client.close() # Main loop while True: if wlan.isconnected(): if not connected: print("Reconnected to WiFi.") status_led.value(1) print("Network Config:", wlan.ifconfig()) connected = True else: if connected: print("Disconnected from WiFi.") connected = False blink_led() # Blink onboard LED if disconnected # Check for client connection s.settimeout(1) # Set a timeout for socket operations try: client, addr = s.accept() print('Connection from', addr) handle_client(client) except OSError: pass # Ignore timeout errors |
File saving in the Raspberry Pi Pico W:
Open your preferred IDE, for example, Thonny IDE or any other IDE you choose. Copy and paste the above program into the IDE.
Then, go to the ‘File‘ menu and select ‘Save‘.
A dialog box titled “Where to Save To” will appear. Here, choose the Raspberry Pi Pico as the destination.
Then Name the file ‘main.py’ and click the ‘OK‘ button to save it.
Once the program saved, just press the ‘Run‘ button or the ‘F5‘ button on the keyboard.
After clicking the Run button, you will be able to see the following output in console.
Simply copy the local IP address and paste it into any web browser. However, ensure that your device is connected to the same network.
After pasting the IP address into your browser, you will see the page design as follows.
Test on Desktop
As you move the sliders, you will observe the changes.
Test on Mobile:
Access the same IP address on mobile
Code Explanation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import network import socket import time import machine # Wi-Fi credentials ssid = 'your_network_name' password = 'your_network_password' # Connect to the Wi-Fi network wlan = network.WLAN(network.STA_IF) wlan.active(True) wlan.connect(ssid, password) |
This section imports the necessary modules and sets up the Wi-Fi credentials. It activates the Wi-Fi interface in station mode and attempts to connect to the specified Wi-Fi network using the given SSID and password.
1 2 3 |
# Setup onboard LED for Wi-Fi status status_led = machine.Pin('LED', machine.Pin.OUT) |
This line sets up the onboard LED of the Raspberry Pi Pico W to indicate Wi-Fi connection status.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# Setup RGB LED pins red_led = machine.PWM(machine.Pin(18)) green_led = machine.PWM(machine.Pin(17)) blue_led = machine.PWM(machine.Pin(16)) # Initialize PWM red_led.freq(1000) green_led.freq(1000) blue_led.freq(1000) |
Here, the code configures the pins connected to the RGB LED as PWM (Pulse Width Modulation) outputs, allowing for the control of brightness for each color component. It also sets a frequency for the PWM signal.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# Function to set RGB LED color def set_rgb_color(r, g, b): Â Â Â red_led.duty_u16(int(r / 255 * 65535)) Â Â Â green_led.duty_u16(int(g / 255 * 65535)) Â Â Â blue_led.duty_u16(int(b / 255 * 65535)) # Function to blink onboard LED def blink_led(): Â Â Â status_led.toggle() Â Â Â time.sleep(0.5) |
Two functions are defined: set_rgb_color to change the color of the RGB LED by adjusting the PWM duty cycle, and blink_led to blink the onboard LED as a status indicator.
1 2 3 4 5 6 7 8 9 10 11 |
# Initial connection attempt max_attempts = 10 attempts = 0 connected = False while not wlan.isconnected() and attempts < max_attempts: Â Â Â # rest code |
This loop attempts to connect to Wi-Fi a specified number of times, blinking the status LED with each attempt.
1 2 3 4 5 6 7 8 9 |
# Web server setup addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1] s = socket.socket() s.bind(addr) s.listen(1) |
The code sets up a simple web server by binding a socket to all available IP addresses on port 80 (HTTP) and listening for incoming connections.
1 2 3 4 5 |
html = """<!DOCTYPE html> # ... rest of the HTML and CSS code ... """ |
A multiline string html contains the HTML and CSS code for the web page, which will be used to control the RGB LED from a web browser.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# Function to handle client requests def handle_client(client):    request = client.recv(1024).decode()    print('Request:', request)    response_html = html    if 'GET /update' in request:        _, params = request.split('?', 1)        params = params.split(' ', 1)[0]        r, g, b = [int(v.split('=')[1]) for v in params.split('&')]        set_rgb_color(r, g, b)    client.send('HTTP/1.1 200 OK\n')    client.send('Content-Type: text/html\n')    client.send('Connection: close\n\n')    client.sendall(response_html if 'GET / ' in request else "")    client.close() |
This function is designed to handle incoming client requests, parse the query parameters, and update the RGB LED color accordingly.
1 2 3 4 5 |
# Main loop while True: Â Â Â # ... |
The main loop continuously checks if the board is still connected to Wi-Fi and listens for incoming client connections to handle them.
1 2 3 4 5 6 7 8 9 10 11 |
try:        client, addr = s.accept()        print('Connection from', addr)        handle_client(client)    except OSError:        pass # Ignore timeout errors |
A try-except block is used to gracefully handle socket timeouts without stopping the program.