Closed ptorrone closed 3 years ago
houston....we have BLINK! onboard red led on pin #13
sweet!
a thing of beauty
and it's a pretty good episode of SNL too
It's such a pretty board! Does the Neopixel work? There should be a MicroPython PIO example for WS2812
It's such a pretty board! Does the Neopixel work? There should be a MicroPython PIO example for WS2812
testing this today / tonight!
quick qt - i2c testing ... with the default ssd1306 library and an aht20 library we found on github we got a plug-and-play temp+humidity sensor display going over the qwiic/stemma qt connector.
@Wren6991 here ya go!
pio rainbow neopixels - we hacked together the pio ws2812 demo with our 'essential' neopixel example code to show off color fills, chases and of course a rainbow swirl on a 16-led ring.
video (request access to view) https://drive.google.com/file/d/194NbhmR6EZeuDKbQUuf8wp6AHyZ5gA1W/view?usp=sharing
Code for AHT20 + OLED demo:
import framebuf
import time
from machine import Pin, I2C
from ssd1306 import SSD1306_I2C
import aht10 # from https://github.com/vjsyong/AHT10
WIDTH = 128 # oled display width
HEIGHT = 32 # oled display height
i2c = I2C(1, scl=Pin(3), sda=Pin(2), freq=100000) # Init I2C1 on Stemma QT
print("I2C Address : "+hex(i2c.scan()[0]).upper()) # Display device address
print("I2C Configuration: "+str(i2c)) # Display I2C config
oled = SSD1306_I2C(WIDTH, HEIGHT, i2c, addr=0x3C) # Init oled display
aht = aht10.AHT10(i2c)
# Raspberry Pi logo as 32x32 bytearray
buffer = bytearray(b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00|?\x00\x01\x86@\x80\x01\x01\x80\x80\x01\x11\x88\x80\x01\x05\xa0\x80\x00\x83\xc1\x00\x00C\xe3\x00\x00~\xfc\x00\x00L'\x00\x00\x9c\x11\x00\x00\xbf\xfd\x00\x00\xe1\x87\x00\x01\xc1\x83\x80\x02A\x82@\x02A\x82@\x02\xc1\xc2@\x02\xf6>\xc0\x01\xfc=\x80\x01\x18\x18\x80\x01\x88\x10\x80\x00\x8c!\x00\x00\x87\xf1\x00\x00\x7f\xf6\x00\x008\x1c\x00\x00\x0c \x00\x00\x03\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
# Load the raspberry pi logo into the framebuffer (the image is 32x32)
fb = framebuf.FrameBuffer(buffer, 32, 32, framebuf.MONO_HLSB)
# Clear the oled display in case it has junk on it.
oled.fill(0)
# Blit the image from the framebuffer to the oled display
oled.blit(fb, 96, 0)
# Add some text
oled.text("Raspberry Pi",5,5)
oled.text("Pico",5,15)
# Finally update the oled display so the image & text is displayed
oled.show()
time.sleep(2)
while True:
oled.fill(0)
oled.blit(fb, 96, 0)
oled.text("Feather Demo", 5, 5)
oled.text("Hum: %d %%" % aht.humidity(), 5, 15)
oled.text("Temp: %d C" % aht.temperature(), 5, 25)
oled.show()
time.sleep(1)
code for neopixel ring demo
# Example using PIO to drive a set of WS2812 LEDs.
import array, time
from machine import Pin
import rp2
# Configure the number of WS2812 LEDs.
NUM_LEDS = 16
PIN_NUM = 6
brightness = 0.2
@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=24)
def ws2812():
T1 = 2
T2 = 5
T3 = 3
wrap_target()
label("bitloop")
out(x, 1) .side(0) [T3 - 1]
jmp(not_x, "do_zero") .side(1) [T1 - 1]
jmp("bitloop") .side(1) [T2 - 1]
label("do_zero")
nop() .side(0) [T2 - 1]
wrap()
# Create the StateMachine with the ws2812 program, outputting on pin
sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(PIN_NUM))
# Start the StateMachine, it will wait for data on its FIFO.
sm.active(1)
# Display a pattern on the LEDs via an array of LED RGB values.
ar = array.array("I", [0 for _ in range(NUM_LEDS)])
##########################################################################
def pixels_show():
dimmer_ar = array.array("I", [0 for _ in range(NUM_LEDS)])
for i,c in enumerate(ar):
r = int(((c >> 8) & 0xFF) * brightness)
g = int(((c >> 16) & 0xFF) * brightness)
b = int((c & 0xFF) * brightness)
dimmer_ar[i] = (g<<16) + (r<<8) + b
sm.put(dimmer_ar, 8)
time.sleep_ms(10)
def pixels_set(i, color):
ar[i] = (color[1]<<16) + (color[0]<<8) + color[2]
def pixels_fill(color):
for i in range(len(ar)):
pixels_set(i, color)
def color_chase(color, wait):
for i in range(NUM_LEDS):
pixels_set(i, color)
time.sleep(wait)
pixels_show()
time.sleep(0.2)
def wheel(pos):
# Input a value 0 to 255 to get a color value.
# The colours are a transition r - g - b - back to r.
if pos < 0 or pos > 255:
return (0, 0, 0)
if pos < 85:
return (255 - pos * 3, pos * 3, 0)
if pos < 170:
pos -= 85
return (0, 255 - pos * 3, pos * 3)
pos -= 170
return (pos * 3, 0, 255 - pos * 3)
def rainbow_cycle(wait):
for j in range(255):
for i in range(NUM_LEDS):
rc_index = (i * 256 // NUM_LEDS) + j
pixels_set(i, wheel(rc_index & 255))
pixels_show()
time.sleep(wait)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
YELLOW = (255, 150, 0)
GREEN = (0, 255, 0)
CYAN = (0, 255, 255)
BLUE = (0, 0, 255)
PURPLE = (180, 0, 255)
WHITE = (255, 255, 255)
COLORS = (BLACK, RED, YELLOW, GREEN, CYAN, BLUE, PURPLE, WHITE)
print("fills")
for color in COLORS:
pixels_fill(color)
pixels_show()
time.sleep(0.2)
print("chases")
for color in COLORS:
color_chase(color, 0.01)
print("rainbow")
rainbow_cycle(0)
aaaand onboard neopixel is workin'
I liked it so much, I bought the company
aaaand... uart testing - gps modules are a common uart accessory, this demo tests reading/writing from the uart at 9600 baud, verifying the checksum, then displaying the nmea sentence on the oled. we're indoors so there's no data fix but you can see the rtc seconds increment.
We should add you a feather2040.h to pico/boards (in the PicoSDK) when you know what you want; I assume you are still using MicroPython compiled for "pico"
code for gps + oled demo:
# Tests UART read/write with OLED output
import time
import framebuf
from machine import Pin, UART, I2C
from ssd1306 import SSD1306_I2C
i2c = I2C(1, scl=Pin(3), sda=Pin(2), freq=100000) # Init I2C1 on Stemma QT
uart = UART(0, 9600, rx=Pin(1), tx=Pin(0))
oled = SSD1306_I2C(128, 64, i2c, addr=0x3D) # Init 128*64 oled display
# if this succeeds, yuou will only get GPRMC sentences
uart.write(b'$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29\r\n\r\n')
while True:
sentence = uart.readline().decode('utf-8').strip()
if len(sentence) < 7 or sentence[-3] != "*":
continue
# Get included checksum, then calculate it and compare.
expected = int(sentence[-2:], 16)
actual = 0
for i in range(1, len(sentence) - 3):
actual ^= ord(sentence[i])
if actual != expected:
print("Checksum actual %02x expected %02x" % (actual, expected))
continue
print(sentence) # output the response
oled.fill(0)
oled.text("GPS UART Demo", 5, 5)
oled.text(sentence[0:15], 5, 20)
oled.text(sentence[15:30], 5, 35)
oled.text(sentence[30:45], 5, 50)
oled.show()
We should add you a feather2040.h to pico/boards (in the PicoSDK) when you know what you want; I assume you are still using MicroPython compiled for "pico"
hihi yes, please do we could maybe get framebuf
as included at the same time :) we use the same pin convention but it would be nice to have the default I2C, UART and SPI be on the marked pins / connectors. plus some pins aren't exposed (pins 7, 8, 14, 15, 21, 22, 23)
next up is testing both pwm output and analog input - this common 'sweep' demo take an analog input from a potentiometer and sweeps out a mirror image on a standard servo.
code for analog/pwm servo sweep demo:
# Read a potentiometer on AD0 and control a servo pin pin 12
from machine import Pin, PWM, ADC
import time
# Analog input on AD0
adc = ADC(0)
# Construct PWM object for servo on pin 12
pwm = PWM(Pin(12))
# Set the PWM frequency to 50 hz
SERVO_FREQUENCY = 50
pwm.freq(SERVO_FREQUENCY)
min_pulse=500 # in useconds
max_pulse=2500 # in useconds
us_period = 1_000_000/ SERVO_FREQUENCY
min_dutycycle = int(min_pulse*65535/us_period)
max_dutycycle = int(max_pulse*65535/us_period)
print("PWM period %d us, min duty cycle %d, max %d" %
(us_period, min_dutycycle, max_dutycycle))
def map_range(x, in_min, in_max, out_min, out_max):
"""
Maps a number from one range to another.
Note: This implementation handles values < in_min differently than arduino's map function does.
:return: Returns value mapped to new range
:rtype: float
"""
in_range = in_max - in_min
in_delta = x - in_min
if in_range != 0:
mapped = in_delta / in_range
elif in_delta != 0:
mapped = in_delta
else:
mapped = 0.5
mapped *= out_max - out_min
mapped += out_min
if out_min <= out_max:
return max(min(mapped, out_max), out_min)
return min(max(mapped, out_max), out_min)
while True:
ain = adc.read_u16()
print("Analog input %d%%" % (ain * 100 / 65535))
pos = int(map_range(ain, 65535, 0, min_dutycycle, max_dutycycle))
pwm.duty_u16(pos)
time.sleep(0.1)
hihi yes, please do we could maybe get framebuf as included at the same time :) we use the same pin convention but it would be nice to have the default I2C, UART and SPI be on the marked pins / connectors. plus some pins aren't exposed (pins 7, 8, 14, 15, 21, 22, 23)
Copying @dpgeorge, as I'm not sure where we stand on whether we need a separte "board" concept within the rp2 port in MicroPython too (I know there is for other ports)
We can certainly add some default I2C/SPI pins in the SDK header even if the SDK itself doesn't use them (to save extra abstractions)
P.S. I'm sure framebuf
can be added by default; note I also committed @micropthon.native support for ARMv6M since I was looking at MP performance on Pico, and that seemed like a nice to have. Don't know if @dpgeorge plans to include that by default.
Frankly, yeah I suspect we're likely to want more than one MP configuration for RP2040 based boards.
pio rainbow neopixels - we hacked together the pio ws2812 demo with our 'essential' neopixel example code to show off color fills, chases and of course a rainbow swirl on a 16-led ring.
I went ahead and added this one as an example to the Pico Python SDK book.
If you'd like to add the others, see the /pio/neopixel_ring/
and i2c/1306oled/
directories in the pico-micropython-examples repo for how to add a simple README.adoc
. These README.adoc
will get imported into PDF documentation automatically (see Appendix A of the Pico Python SDK). We take pull requests! 😆
and video here (53 secs), request permission to view: https://drive.google.com/file/d/11iIlO1sBB_vOJg6hdqsmVabHDxVo_4lL/view?usp=sharing
RP2040 Feather is plugged into https://www.adafruit.com/product/3315 and running
# Tests SPI and pin interaction with 2.4" TFT Featherwing
import time
from machine import Pin, SPI
from rgb import color565
import ili9341 # http://github.com/adafruit/micropython-adafruit-rgb-display
import framebuf
spi = machine.SPI(0, baudrate=64000000, sck=Pin(18), mosi=Pin(19), miso=Pin(20))
display = ili9341.ILI9341(spi, cs=machine.Pin(9), dc=machine.Pin(10))
w, h = (240, 320) # cache width and height of LCD
# clear out the screen to test color mapping
display.fill(color565(255, 0, 0))
time.sleep(0.1)
display.fill(color565(0, 255, 0))
time.sleep(0.1)
display.fill(color565(0, 0, 255))
time.sleep(0.1)
display.fill(0)
# function to compute Mandelbrot pixels - from 1602cr demo
def in_set(c):
z = 0
for i in range(32):
z = z * z + c
if abs(z) > 100:
return i
return 0
# create the buffer for each line and set SPI parameters
line = bytearray(w * 2)
# draw the Mandelbrot set line-by-line - from 1602cr demo
hh = (h - 1) / 3.2
ww = (w - 1) / 2.4
for v in range(h):
for u in range(w):
c = in_set((v / hh - 2.3) + (u / ww - 1.2) * 1j)
if c < 16:
rgb = c << 12 | c << 6
else:
rgb = 0xF800 | c << 6
line[2 * u] = rgb
line[2 * u + 1] = rgb >> 8
#display.blit_buffer(line, 0, v, w, 1)
display._block(0, v, w-1, v, line) # unsafe version but faster for demo
aand random lines demo...
GFX library adds shapes (lines, rectangles, triangles, etc) to displays
import time
from machine import Pin, SPI
import ili9341 # http://github.com/adafruit/micropython-adafruit-rgb-display
import gfx # https://github.com/adafruit/micropython-adafruit-gfx
import random
spi = machine.SPI(0, baudrate=64000000, sck=Pin(18), mosi=Pin(19), miso=Pin(20))
display = ili9341.ILI9341(spi, cs=machine.Pin(9), dc=machine.Pin(10))
graphics = gfx.GFX(240, 320, display.pixel)
# Now loop forever drawing random lines.
display.fill(0)
while True:
x0 = random.randrange(0, 240)
y0 = random.randrange(0, 320)
x1 = random.randrange(0, 240)
y1 = random.randrange(0, 320)
r = random.randrange(0, 255)
g = random.randrange(0, 255)
b = random.randrange(0, 255)
graphics.line(x0, y0, x1, y1, ili9341.color565(r, g, b))
while waiting for snl to come on, we put together 4 feather rp2040's, handstencilling and then hot air. all 4 enumerate over usb, yay! next up trying out each pin with micropython ... will post some more updates!