First of all, a shout-out to ‘hippy’ from the UK in the Raspberry Pi forums for the response to ‘Simplest PWM using C’ which this code sample is based upon. This Pico SDK code targets the DPICO_BOARD=pimoroni_tiny2350
void pwm_init_pin(uint8_t pin) {
gpio_set_function(pin, GPIO_FUNC_PWM);
uint slice_num = pwm_gpio_to_slice_num(pin);
pwm_config config = pwm_get_default_config();
pwm_config_set_clkdiv(&config, 4.f);
pwm_init(slice_num, &config, true);
}
void pwm_set_rgb8(uint8_t red, uint8_t green, uint8_t blue) {
pwm_set_gpio_level(TINY2350_LED_R_PIN, red << 8);
pwm_set_gpio_level(TINY2350_LED_G_PIN, green << 8);
pwm_set_gpio_level(TINY2350_LED_B_PIN, blue << 8);
}
void pwm_set_rgb32(uint32_t rgb) {
pwm_set_gpio_level(TINY2350_LED_R_PIN, ((rgb >> 16) & 0xFF) << 8);
pwm_set_gpio_level(TINY2350_LED_G_PIN, ((rgb >> 8) & 0xFF) << 8);
pwm_set_gpio_level(TINY2350_LED_B_PIN, ((rgb >> 0) & 0xFF) << 8);
}
int main() {
pwm_init_pin(TINY2350_LED_R_PIN);
pwm_init_pin(TINY2350_LED_G_PIN);
pwm_init_pin(TINY2350_LED_B_PIN);
while (true) {
pwm_set_rgb8(255, 0, 0); sleep_ms(1000);
pwm_set_rgb8(0, 255, 0); sleep_ms(1000);
pwm_set_rgb8(0, 0, 255); sleep_ms(1000);
pwm_set_rgb32(0xFF0000); sleep_ms(1000);
pwm_set_rgb32(0x00FF00); sleep_ms(1000);
pwm_set_rgb32(0x0000FF); sleep_ms(1000);
pwm_set_rgb32(0xFFFFFF); sleep_ms(5000);
pwm_set_rgb8(255, 255, 0); sleep_ms(1000);
pwm_set_rgb8(0, 255, 255); sleep_ms(1000);
pwm_set_rgb8(255, 0, 255); sleep_ms(1000);
pwm_set_rgb32(0xFFFF00); sleep_ms(1000);
pwm_set_rgb32(0x00FFFF); sleep_ms(1000);
pwm_set_rgb32(0xFF00FF); sleep_ms(1000);
pwm_set_rgb32(0xFFFFFF); sleep_ms(5000);
}
}
My question is this: When I ran the above code on the Tiny 2350, I was expecting (255, 0, 0) to be a perfect red on the onboard RGB LED. But sadly it is not. Instead (0,255,255) is the brilliant red color I was expecting. What did I get wrong here?
neilman
September 12, 2024, 2:00am
2
Could this be a simple case of inverted logic on the RGB LED? (Common anode rather than common cathode)
0,0,0 being white?
1 Like
I can confirm that 0,0,0 is a bright white light, and 255,255,255 is, well… off (aka black?)
Not exactly an elegant solution, but a solution that proves neilman’s observation is correct. This now works as expected:
int main() {
pwm_init_pin(TINY2350_LED_R_PIN);
pwm_init_pin(TINY2350_LED_G_PIN);
pwm_init_pin(TINY2350_LED_B_PIN);
uint8_t red_value, green_value, blue_value;
uint32_t rgb_value;
while (true) {
red_value = 255; green_value = 0; blue_value = 0;
pwm_set_rgb8((255-red_value), (255-green_value), (255-blue_value)); sleep_ms(1000);
red_value = 0; green_value = 255; blue_value = 0;
pwm_set_rgb8((255-red_value), (255-green_value), (255-blue_value)); sleep_ms(1000);
red_value = 0; green_value = 0; blue_value = 255;
pwm_set_rgb8((255-red_value), (255-green_value), (255-blue_value)); sleep_ms(1000);
rgb_value = 0xFF0000;
pwm_set_rgb32(0xFFFFFF-rgb_value); sleep_ms(1000);
rgb_value = 0x00FF00;
pwm_set_rgb32(0xFFFFFF-rgb_value); sleep_ms(1000);
rgb_value = 0x0000FF;
pwm_set_rgb32(0xFFFFFF-rgb_value); sleep_ms(1000);
}
}
That and by more carefully reading the product page…
The RGB LED is connected to GP18-GP20 and active low (so the on/off state will work in the opposite way to the LED on a Raspberry Pi Pico ). You can PWM the pins to dim the LED - check out Tonygo2’s MicroPython example.
as well as the intro that tonygo2 wrote on his MycroPython post titled “Tiny 2040 RGB LED control - Tutorial”…
The RGB LED built into the Tiny 2040 may give you a surprise if you have only used common cathode RGB LEDs in the past. Here low numbers make it brighter and high numbers make it dimmer.
I guess you can say it gave me a surprise. ;-)
I don’t see a link to a schematic but the pinout shows [Active Low] for the RGB LED. So there you go. =)
Same thing, only in Arduino this time…
int TINY2350_LED_R_PIN = 18;
int TINY2350_LED_G_PIN = 19;
int TINY2350_LED_B_PIN = 20;
int red_value,green_value,blue_value;
#define ACTIVE_LOW_RGB YES
void setup () {
pinMode (TINY2350_LED_R_PIN, OUTPUT);
pinMode (TINY2350_LED_G_PIN, OUTPUT);
pinMode (TINY2350_LED_B_PIN, OUTPUT);
}
void analog_set_rgb(int red, int green, int blue) {
#ifdef ACTIVE_LOW_RGB
red=255-red;green=255-green;blue=255-blue;
#endif
analogWrite (TINY2350_LED_R_PIN, red);
analogWrite (TINY2350_LED_G_PIN, green);
analogWrite (TINY2350_LED_B_PIN, blue);
}
void loop () {
red_value = 255; green_value = 0; blue_value = 0;
analog_set_rgb(red_value,green_value,blue_value); delay(1000);
red_value = 0; green_value = 255; blue_value = 0;
analog_set_rgb(red_value,green_value,blue_value); delay(1000);
red_value = 0; green_value = 0; blue_value = 255;
analog_set_rgb(red_value,green_value,blue_value); delay(1000);
}
Same thing, only in CircuitPython this time (yes, you read that correctly, CircuitPython, not MicroPython )…
import time, pwmio, board
TINY2350_LED_R = pwmio.PWMOut(board.LED_R)
TINY2350_LED_B = pwmio.PWMOut(board.LED_B)
TINY2350_LED_G = pwmio.PWMOut(board.LED_G)
def pwm_set_rgb(red, blue, green):
TINY2350_LED_R.duty_cycle = int(65535 -(65535 * red/255))
TINY2350_LED_B.duty_cycle = int(65535 -(65535 * blue/255))
TINY2350_LED_G.duty_cycle = int(65535 -(65535 * green/255))
while True:
pwm_set_rgb(255, 0, 0)
time.sleep(0.5)
pwm_set_rgb(0, 255, 0)
time.sleep(0.5)
pwm_set_rgb(0, 0, 255)
time.sleep(0.5)
NOTE: I had to compile CircuitPython support for the Tiny 2350 manually from source.
cd ./circuitpython/ports/raspberrypi
make BOARD=pimoroni_tiny2350
cp ./build-pimoroni_tiny2350/firmware.uf2 /media/user/RP2350/
Same thing, same approach for direct comparison of different platforms, only in MicroPython this time…
import time, machine
ACTIVE_LOW_RGB = True
TINY2350_LED_R = machine.PWM(machine.Pin(18))
TINY2350_LED_R.freq(1000)
TINY2350_LED_B = machine.PWM(machine.Pin(19))
TINY2350_LED_B.freq(1000)
TINY2350_LED_G = machine.PWM(machine.Pin(20))
TINY2350_LED_G.freq(1000)
def pwm_set_rgb(red, blue, green):
if(ACTIVE_LOW_RGB):
red = 255-red; green = 255-green; blue = 255-blue
TINY2350_LED_R.duty_u16(int((red * 65535) / 255))
TINY2350_LED_B.duty_u16(int((blue * 65535) / 255))
TINY2350_LED_G.duty_u16(int((green * 65535) / 255))
while True:
pwm_set_rgb(255, 0, 0)
time.sleep(0.5)
pwm_set_rgb(0, 255, 0)
time.sleep(0.5)
pwm_set_rgb(0, 0, 255)
time.sleep(0.5)
NOTE: You cannot yet download final binaries from the MicroPython download site , and the MicroPython github repository does not yet seem to contain the source code that supports the Tiny 2350 board. Instead, I had to download a pre-build binary from here…
bablokb
September 17, 2024, 4:02pm
9
You should have a look at the library adafruit_rgbled. No need to do all of this manually. Of course, only works for CircuitPython.
1 Like
I did. That was actually one place I looked to figure all of this out. I just like to simplify the library into the minimal amount of code to get the desired result. It helps when you are trying to reduce the number and size of helper classes used in an implementation.
I was looking to compare the PWM coding techniques of each platform (Pico SDK, Arduino, CircuitPython and MicroPython) and using the onboard RGB LED seemed a good place as any to learn with.
There is also an implementation on MicroPython that Pimoroni authored. It is one of the classes in this module…
import time
from machine import Pin, PWM, ADC
BREAKOUT_GARDEN_I2C_PINS = {"sda": 4, "scl": 5}
PICO_EXPLORER_I2C_PINS = {"sda": 20, "scl": 21}
HEADER_I2C_PINS = {"sda": 20, "scl": 21}
PICOVISION_I2C_PINS = {"sda": 6, "scl": 7}
# Motor and encoder directions
NORMAL_DIR = 0x00
REVERSED_DIR = 0x01
BREAKOUT_GARDEN_SPI_SLOT_FRONT = 0
BREAKOUT_GARDEN_SPI_SLOT_BACK = 1
PICO_EXPLORER_SPI_ONBOARD = 2
class Analog:
def __init__(self, pin, amplifier_gain=1, resistor=0, offset=0):
This file has been truncated. show original