YD-RP2040 Module
I want to tell you about the rather inexpensive YD-RP2040 module and show some examples of working with it.
Photos and Schematics
Top view:
Bottom view:
The module’s electrical schematic can be found here https://github.com/initdc/YD-RP2040/blob/master/YD-2040-2022-V1.1-SCH.pdf
Differences from the original Raspberry Pi Pico
This board has several key hardware differences from the standard Raspberry Pi Pico module.
Key changes:
- Flash memory: The module can be fitted with a larger Flash memory capacity — 4MB (32Mbit) or even 16MB (128Mbit) instead of the 2MB in the original.
- Voltage regulator: The DC-DC step-down converter is replaced with a cheaper and less efficient linear regulator. This has freed up pin GPIO23, which was used to control the DC-DC converter in the original Pico.
- RGB LED: A WS2812 addressable LED (Neo-pixel) is connected to the freed GPIO23 pin.
Unlike the original Pico, this board has two additional buttons:
- RESET — for a hardware reset of the microcontroller.
- USR — a user button connected to the GPIO24 pin.
Additionally, a separate VREF pin is available for supplying an external reference voltage to the ADC.
The board has two solder jumpers that are open by default:
- VREF: Connects the microcontroller’s VREF pin to the 3.3V power line. If you do not plan to use an external reference voltage, you need to solder this jumper closed.
- R68: By default, the GPIO23 pin is not connected to the RGB LED. To make the LED work, this jumper must be soldered.
BOOTSEL
This button puts the microcontroller into a mode for uploading new firmware via USB.
To enter this mode, press and hold the BOOTSEL button and, while still holding it, press RESET (or simply connect the board to your computer). After this, the microcontroller will appear in your system as a regular flash drive named “RPI-RP2”.
To install the firmware, simply copy a file in the .uf2 format onto this drive.
LED (GPIO25)
Just like the original Raspberry Pi Pico, this board has a built-in LED connected to GPIO25.
Below is a simple C++ code example that makes this LED blink: const uint LED = 25;
gpio_init(LED);
// Set the pin direction to output (GPIO_OUT)
gpio_set_dir(LED, GPIO_OUT);
while (true) {
gpio_put(LED, true);
sleep_ms(500);
gpio_put(LED, false);
sleep_ms(1500);
}
USR Button (GPIO24)
When pressed, this button connects the GPIO24 pin to ground (GND).
This board lacks an external pull-up resistor to VCC, the microcontroller’s internal pull-up resistor must be enabled in software for the GPIO24 to work correctly.
const uint USR_BTN = 24;
gpio_init(USR_BTN);
// Set the pin direction to output (GPIO_OUT)
gpio_set_dir(USR_BTN, GPIO_IN);
// Enable internal pull-up resistor
gpio_pull_up(USR_BTN);
while (true) {
gpio_put(LED, true);
bool state = gpio_get(USR_BTN);
printf("USB button state = %d\n", state);
sleep_ms(500);
}
Setting up the SDK in VSCode
To prepare Visual Studio Code for developing with RP2040 microcontrollers, the easiest method is to install the official extension.
- In the left VSCode sidebar, navigate to the Extensions tab or use the keyboard shortcut (Ctrl+Shift+X on Ubuntu/Arch, or Cmd+Shift+X on macOS).
- In the search bar, start typing “Raspberry Pi Pico”.
- Find the Raspberry Pi extension in the list (it’s usually the first one) and click the Install button.
This extension will help to automatically download and configure the necessary toolchain (SDK, compiler).
After installing the extension, a new tab with a Raspberry Pi icon will appear in the VSCode sidebar. From this tab, you can manage your projects, configure the board, and also compile and upload your code.
Hello World
To start, let’s create a new project from the Raspberry Pi tab. Click on the “New C/C++ Project” option.
Next, the project configuration window will appear.
- In the Board type field, select your board (in our case, a first-generation Pico without WiFi).
- Enable UART.
- It’s also recommended to enable the Console over UART or Console over USB options. This will allow you to output diagnostic messages from the microcontroller.
What does the “Console over USB” option do?
It enables
USB CDC (Communications Device Class) mode, which allows the
microcontroller to create a virtual serial port. You will be able to see
messages from the board directly in the VSCode terminal or any other
serial monitor program.
The code example demonstrates working with two serial ports simultaneously: a virtual one (via USB) and a hardware one (UART1 on GPIO pins 4 and 5).
#include
#include "pico/stdlib.h"
#include "hardware/uart.h"
#define UART_ID uart1
#define BAUD_RATE 115200
#define UART_TX_PIN 4
#define UART_RX_PIN 5
int main()
{
stdio_init_all();
uart_init(UART_ID, BAUD_RATE);
gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART);
gpio_set_function(UART_RX_PIN, GPIO_FUNC_UART);
while (true) {
uint32_t current_time = to_ms_since_boot(get_absolute_time());
printf("Hello, world! Timestamp: %d ms\n", current_time);
uart_puts(UART_ID, "Hello, UART!\n");
sleep_ms(1000);
}
}
To compile the project, you can:
- Click Compile Project in the sidebar.
- Use the keyboard shortcut: Ctrl+Shift+B (for Windows/Linux) or Cmd+Shift+B (for macOS).
You don’t need a separate programmer to upload the compiled firmware (the .uf2 file) to an RP2040 board. This can be done in two ways:
1. Manual Method (Drag-and-Drop)
This method is universal and works just like copying a file.
- Put the board into bootloader mode: Press and hold the BOOTSEL button, and while holding it, press the RESET button (or simply connect the board to USB while holding BOOTSEL).
- Copy the file: A new USB drive named RPI-RP2 will appear in your operating system. Simply drag and drop or copy your .uf2 file from your project’s build folder onto this drive.
- Reboot: After the file has finished copying, the board will automatically reboot and begin running the new program.
Automatic Method (via VSCode)
Raspberry Pi Pico extension lets you automate the compilation and upload process. - Prepare the board: Put it into bootloader mode as described above. - Start the upload: In the Raspberry Pi extension tab, find and click on Run Project (USB).
To see the program’s output, you need to connect to the virtual serial port that the board creates over USB.
In VSCode, there are several plugins for this, or you can use any third-party serial monitor. As a result, we should see:
Hello from USB! Timestamp: 6001 ms
Hello from USB! Timestamp: 7001 ms
Hello from USB! Timestamp: 8001 ms
Hello from USB! Timestamp: 9001 ms
Hello from USB! Timestamp: 10001 ms
USR Button Example
Now, let’s modify the previous example. Instead of continuously printing messages, we will send a string to the console only when the additional USR button (pin GPIO24) is pressed.
To detect the button press, we’ll use the interrupts mechanism. This is an efficient approach that allows the processor to react to external events (like a button press) without wasting resources by constantly polling its state in the main program loop.
#include
#include "pico/stdlib.h"
#include "hardware/gpio.h"
#include "hardware/uart.h"
#define UART_ID uart1
#define BAUD_RATE 115200
#define UART_TX_PIN 4
#define UART_RX_PIN 5
#define USR_BTN 24
uint32_t last_usrbtn_time = 0;
// interrupts handler
void button_callback(uint gpio, uint32_t events) {
if (events & GPIO_IRQ_EDGE_FALL) {
uint32_t current_time = to_ms_since_boot(get_absolute_time());
if (current_time - last_usrbtn_time > 200) {
printf("Hello, world! Timestamp: %d ms\n", current_time);
last_usrbtn_time = current_time;
}
}
}
int main() {
stdio_init_all();
uart_init(UART_ID, BAUD_RATE);
gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART);
gpio_set_function(UART_RX_PIN, GPIO_FUNC_UART);
// button initialization
gpio_init(USR_BTN);
gpio_set_dir(USR_BTN, GPIO_IN);
gpio_pull_up(USR_BTN);
// let's configure interrupt
gpio_set_irq_enabled_with_callback(USR_BTN, GPIO_IRQ_EDGE_FALL, true, &button_callback);
while (true) {
// empty loop
tight_loop_contents();
}
}
Controlling an RGB LED (WS2812) with PIO
By default, the RGB LED on this module is not connected to the microcontroller. To enable this, you need to bridge the R68 jumper with a solder blob.
To control the WS2812 addressable LED, we’ll use PIO (Programmable I/O)—a unique feature of the RP2040 that lets you create custom hardware interfaces. We will use a pre-written PIO program from the official Raspberry Pi examples.
Download the ws2812.pio file from the official Raspberry Pi repository and place it in your project’s directory.
To make the build system aware of the PIO program and to link the necessary libraries, add the following lines to your CMakeLists.txt file:...
# Generates a C header from our .pio program
pico_generate_pio_header(HelloWorld ${CMAKE_CURRENT_LIST_DIR}/ws2812.pio OUTPUT_DIR ${CMAKE_CURRENT_LIST_DIR})
# Link the hardware_pio library to our project
target_link_libraries(HelloWorld pico_stdlib hardware_pio)
Now, let’s combine our previous interrupt-based code with the new functionality for controlling the LED. Each time the USR button is pressed, the LED’s color will change.
Here is the complete code for the main.cpp file:#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/uart.h"
#include "hardware/pio.h"
#include "ws2812.pio.h" // The header file generated from ws2812.pio
#define UART_ID uart1
#define BAUD_RATE 115200
#define UART_TX_PIN 4
#define UART_RX_PIN 5
#define LED 25
#define USR_BTN 24
#define WS2812_PIN 23 // RGB LED pin
// Array of colors in 0x00GGRRBB format (Green, Red, Blue)
uint32_t ws2812Colors[] = {
0x00800000, // Red
0x80000000, // Green
0x00008000, // Blue
0x80808000, // White
0x00000000 // Off
};
uint8_t ws2812ColorIndex = 0;
PIO ws2812pio = pio0;
int ws2812stateMachine = 0; // The PIO State Machine (SM) number
uint32_t last_usrbtn_time = 0;
void button_callback_rgb(uint gpio, uint32_t events) {
if (events & GPIO_IRQ_EDGE_FALL) {
uint32_t current_time = to_ms_since_boot(get_absolute_time());
if (current_time - last_usrbtn_time > 200) {
printf("Hello, world! Timestamp: %d ms\n", current_time);
last_usrbtn_time = current_time;
}
ws2812ColorIndex++;
if (ws2812ColorIndex >= sizeof(ws2812Colors) / sizeof(ws2812Colors[0])) {
ws2812ColorIndex = 0;
}
// Send the new color to the PIO State Machine
pio_sm_put_blocking(ws2812pio, ws2812stateMachine, ws2812Colors[ws2812ColorIndex]);
}
}
int main() {
stdio_init_all();
uart_init(UART_ID, BAUD_RATE);
gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART);
gpio_set_function(UART_RX_PIN, GPIO_FUNC_UART);
gpio_init(LED);
gpio_set_dir(LED, GPIO_OUT);
gpio_init(USR_BTN);
gpio_set_dir(USR_BTN, GPIO_IN);
gpio_pull_up(USR_BTN);
gpio_set_irq_enabled_with_callback(USR_BTN, GPIO_IRQ_EDGE_FALL, true, &button_callback_rgb);
// Find a free PIO state machine and load our program into it
uint offset = pio_add_program(ws2812pio, &ws2812_program);
// Initialize the state machine, specifying the pin, frequency, and other parameters
ws2812_program_init(ws2812pio, ws2812stateMachine, offset, WS2812_PIN, 800000, false);
while (true) {
tight_loop_contents();
}
}
After uploading this firmware, each press of the USR button will change the color of the RGB LED.
Materials, Documentation, and Samples
- Official documentation: https://www.raspberrypi.com/products/raspberry-pi-pico/
- Official examples for working with the microcontroller: https://github.com/raspberrypi/pico-examples/tree/master/blink
- Video on working with the native SDK: https://www.youtube.com/watch?v=3fsbwl_GGVQ
- Schematics for the YD2040 module: https://github.com/initdc/YD-RP2040/blob/master/YD-2040-PIN.png











Comments
Post a Comment