Development Board for the Raspberry Pi Pico

I’ve been experimenting with the Raspberry Pi Pico for a little while now and I found that I kept coming back to the same issues – sensors need power, servos need power, I2C devices need power and the SCL/SDA connections. While there are plenty of Ground connections, I had to make up Y-leads so that the 3v3 connections went to other devices.

I also wanted to link this board to some handy little servos, piezo elements and LEDs, as well as having a few switches and an OLED display.

A bit of tinkering with Fritzing and I ended up with this board. Actually, this is version 2. The first was missing a few connections and I’d put the switches 90 degrees around, meaning that the connections were permanently short-circuited.

Pico PCB with Laser Cut Front Panel and 3d printed case.

I’m happy to make the files available and I’ve uploaded them to my webspace. I haven’t got my head around the whole CC-BY-SA thing, so use them. I’d love to hear from you if you have success though!

Files for the Raspberry Pi Pico circuit board:

Gerber files for the PCB are here: http://roulson.net/PiPicoPCB/Gerber.zip

STL files for the top and bottom layers of the sandwich are here: http://roulson.net/PiPicoPCB/TopSpacer.STL and here: http://roulson.net/PiPicoPCB/BottomSpacer.STL

DXF files for the top and bottom of the case are here: http://roulson.net/PiPicoPCB/TopAcrylic.DXF and here: http://roulson.net/PiPicoPCB/BottomAcrylic.DXF

You will also need a 128×64 i2c OLED display, a bunch of 0.1″ pin headers, two 5mm LEDs, four 6mm tactile push switches (with fairly long actuator around 12mm) and two 150ohm resistors. On the back is a longer pin header which is handy for a stepper motor controller or H-bridge.

Assembly

At some point I’ll do a little photo-shoot of the board being assembled. Not much to it, although some things need fitting in the right order as other parts cover up the joints.

Programming

Programming of the board seems to work really well using Microblocks, which runs either in a browser or (in my case) as a download to my Raspberry Pi 400. Microblocks is at https://microblocks.fun/

It is also possible to use BIPES or MicroPython directly with the board.

Advertisement

Raspberry Pi Pico

Well.. it has been a long time since the last post here. I’m still using Raspberry Pi computers and in particular I’m writing this on my pi-topCEED.

I recently bought a couple of Raspberry Pi Pico boards. I didn’t know what to expect, particularly as I have no experience of micropython, but the first impressions are very good. I can’t fault the price – it comes in at less than a Pi Nano and for much of the basic control that I wanted, it looks ideal. It supports NeoPixel style LEDs, LED arrays, a little RTC board that I’d acquired a while back and servos. Cheaper than my usual microcontroller go-to IC, with on-board USB socket for power and download.

I’ve used “Thonny” with the add-in for the Pico, and that works fine, but I’m also experimenting with “BIPES” https://bipes.net.br/beta2/ui/ which seems to offer a good range of facilities. I’m having a couple of issues with variables, but I’m sure that it will soon be sorted.

BIPES is a Blockly-type of programming language, which suits anyone who has learnt Scratch, with the advantage that it supports all sorts of inputs and outputs connecting to those rows of holes or pins down the side of the board.

Watch this space for my experiments!

Poundland Universal Remote Control

I’ve been experimenting with the infra-red input commands on the PICAXE for some simple remote control Lego robots. There is an official remote control for the PICAXE – in an eye-catching blue case, but for economy I’ve bought a bunch of Poundland universal remote controls.

They don’t give the same hardwearing impression that the official ones give – the cases are a little more flimsy, but they do seem more than adequate to remote control a PICAXE and can therefore add a whole new dimension to PICAXE circuits. An infra-red receiver is an easy thing to add and it means that one input can effectively pretend to be many switches – all present remotely on the handset.

To program the remote, press and hold the TV remote for 5 seconds. The LED will light at this point. Type in the code 0495. When this is completed, the LED will go out and the remote is ready to use.

The command to receive the remote signals is to use:

irin [100],3,b0

Assuming that you’re using input 3. I often use the 08M2 Picaxe, and this is fine. The value is dumped into byte variable b0.

Often I use the following program:

main:
    irin [100],3,b0
    debug
    goto main

to see the effect of pressing different buttons in the debug window.

I’ve discovered the following codes  (File: PoundlandUniversalRemote as a PDF file):

PoundlandUniversalRemote

Bluedot – Bluetooth and the 4-tronix Initio Robot.

IMG_1595Some time ago, I wrote about Bluedot – and now I’ve used this to control the Initio robot.

Bluedot consists of two parts – an App and some Python code which runs on the Raspberry Pi. The Initio takes a variety of Raspberry Pi’s, but I recently received some PTFA funding to upgrade to a Pi3 for the club robot so that it would more effectively run Scratch.

Setting up Bluedot is easy – I then took the demonstration program from the Bluedot website and added GPIO commands into the mix.

While my preference is to have robots running autonomously, using sensors to find their way around (And the Initio certainly excels at this), having an App control the motors is certainly fun and a very immediate way of creating a remote control vehicle.

From here? Perhaps a Web cam streaming images to a remote monitor… Watch this space!

 

 


from bluedot import BlueDot
from signal import pause

import time, RPi.GPIO as GPIO

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(19, GPIO.OUT)
GPIO.setup(21, GPIO.OUT)
GPIO.setup(24, GPIO.OUT)
GPIO.setup(26, GPIO.OUT)

def dpad(pos):
    if pos.top:
        print("up")
        print("Both Forward")
        GPIO.output (26, 1)
        GPIO.output (21, 1)
        GPIO.output (19, 0)
        GPIO.output (24, 0)

    elif pos.bottom:
        print("down")
        GPIO.output (26, 0)
        GPIO.output (21, 0)
        GPIO.output (19, 1)
        GPIO.output (24, 1)

    elif pos.left:
        print("left")
        GPIO.output (26, 1)
        GPIO.output (21, 0)
        GPIO.output (19, 1)
        GPIO.output (24, 0)

    elif pos.right:
        print("right")
        GPIO.output (26, 0)
        GPIO.output (21, 1)

    elif pos.middle:
        print("fire")
        GPIO.output (19, 0)
        GPIO.output (21, 0)
        GPIO.output (24, 0)
        GPIO.output (26, 0)

bd = BlueDot()
bd.when_pressed = dpad

pause()

Using a Raspberry Pi as a desktop PC replacement.

It started with a glass of water… and our old laptop. We probably wouldn’t have used the laptop at all, but it ran Vista which meant that it supported our old-ish Canon Canoscan LiDE scanner. The scanner is, in my view, gorgeous –  it’s light, slim and produces good scans. Sadly, Windows 7 or Windows 10 drivers are unavailable for the scanner. I’m not binning or replacing perfectly good kit, so we’re keeping it!

Unfortunately, a clumsy accident with the glass of water meant that the laptop doesn’t work any more. Just when I needed to do some scanning.

Back in the early days of Raspberry Pi use, I had some minor success with scanning from the command line, but now I know a bit more. I installed XSane, fixed some permissions with the way it handles writing to a folder (can’t remember what, though), and off I went. No problems. The batch mode is especially good for scanning a bunch of photos. 4 at a time and just walk away.

Pi-top CEED

All this was running on my Pi-top CEED. I’d picked this up as a kickstarted and now I’m so pleased with it. I’ve got a wireless keyboard and mouse, and the Raspberry Pi 3 inside really shifts it along well. It boots faster than our Windows 10 laptop and I’m not having to put up with the sound of a fan. It connects with no problem to our NAS and I’ve also managed to pair it with the shared printer.

So, the question remains, what would I install? I’ve got the following, squeezed on to the 8Gb card:

  • CUPS used to connect to a shared printer connected to our laptop. I’ve done this before and found it easier to share than trying to get the now-deceased Vista laptop sharing the printer.
  • XSane to run the scanner. I can scan individual images or a bunch at a time in batch mode.
  • GIMP loads WAY faster on the Pi-top CEED than it does on the Win Laptop. Very useable for the brief experiments I tried.
  • Open Office of course.
  • Seq24 for making music. Runs on my MIDI setup elsewhere in the house, but the Raspberry Pi 3 is also able to run some software synthesizers too. I’ve installed Rosegarden which seems to work well, but I need the time to learn it. It sure looks full-featured.
  • Audacity seems to run well, although I did have it crash once on a file. Not sure what and I didn’t have the chance to try again.
  • Fritzing is a PCB and breadboard design package. Works well and could be handy although I’ve spent so much time in our school’s PCB package that I’m not ready to leave quite yet.

There’s a few other packages that I’m using, but for the most part these are the ones I’ll need for general office-type productivity. My conclusion is that, for me, the Pi-top CEED is an excellent desktop replacement.

I’ll just move the glass of water out of the way…

Bluedot – Bluetooth Raspberry Pi control

This is something I’ve really been waiting for … a link between a Raspberry Pi and a mobile phone app.

Bluedot consists of two parts – an App and some Python code which runs on the Raspberry Pi. I used a Raspberry Pi Zero W, which is a handy combination of small size and built-in WiFi and Bluetooth.

Setting up Bluedot is easy – just follow the instructions and download the App from the Google App store.

IMG_20170630_094649037_HDR[1]

Bluetooth controlled belt

I’ve been using Bluedot to demonstrate some work for e-Textiles at school. It’s my intention to combine a small Raspberry Pi and power pack into something that can provide a range of patterns and colours controlled from a smart phone. Bluedot has enabled this to happen easily.

Now, here’s where I show my ignorance of Python terminology and correct use of syntax.

As I see it, Bluedot’s documentation points to the library receiving the events and then calling functions depending on what’s been pressed on the smart-phone’s screen.

I wanted to see whether it was possible to display patterns in a background loop and then change these. When I’m doing this with a microcontroller such as the Picaxe, I’d have a main loop reading a variable, in which I had stored the current “state”.  The state would be used to trigger different patterns of outputs. Some where in the main loop I would poll the inputs to see if there’s a change – if there is, I’d change the state variable to a new value. I wasn’t sure if this is the right thing to do within Python, but it has worked for me for at least two hours.

PiZeroPixelController

PiZero controller in 3d printed case.

My demonstration “belt”, which is currently adorning a mannekin, has 34 NeoPixel (WS2812) RGB LEDs connected to a long servo cable. The Pi Zero has a matching connector soldered to the relevant connections and is currently running from a PoundLand USB battery. My program allows the belt colour to be changed to Red, Green, Blue, Purple and random colour sparkles. I’ve used the Pimoroni Unicorn Hat python module to drive the LEDs although I did modify it to allow me to access individual LEDs along the line (Set Single Pixels) rather than relying on figuring out an X/Y matrix.

Overall, I’m pleased. I’m looking forward to some feedback regarding my approach to polling Bluedot rather than relying on events triggering functions. I’m sure there’s a better way but this sort-of suits my understanding as I sit on the fence between different programming languages.

Oh, and by the way, the Glowing Pendant is a ring of LEDs but controlled independently from a Redfern Electronics Crumble Controller.


## Bluetooth control of sparkles ##
from bluedot import BlueDot
from signal import pause
from random import randint
import time
import unicornhat as unicorn

ledno = 34
dim = 150
mode = 0
print("Bluedot Sparkles")

unicorn.set_layout(unicorn.AUTO)
unicorn.rotation(0)
unicorn.brightness(1)
width,height=unicorn.get_shape()

def scroll():
    for led in range(ledno):
        unicorn.setsingle(led,0,0,255)
        unicorn.show()
        time.sleep(0.05)

def allred():
    led = randint(0,ledno)
    red = 255
    unicorn.setsingle(led,red,0,0)
    unicorn.show()
    time.sleep(0.1)
    unicorn.setsingle(led,dim,0,0)
    unicorn.show()
    time.sleep(0.1)

def allgreen():
    led = randint(0,ledno)
    green = 255
    unicorn.setsingle(led,0,green,0)
    unicorn.show()
    time.sleep(0.1)
    unicorn.setsingle(led,0,dim,0)
    unicorn.show()
    time.sleep(0.1)

def allblue():
    led = randint(0,ledno)
    blue = 255
    unicorn.setsingle(led,0,0,blue)
    unicorn.show()
    time.sleep(0.1)
    unicorn.setsingle(led,0,0,dim)
    unicorn.show()
    time.sleep(0.1)

def allpurple():
    led = randint(0,ledno)
    red = 255
    blue = 255
    unicorn.setsingle(led,red,0,blue)
    unicorn.show()
    time.sleep(0.1)
    unicorn.setsingle(led,dim,0,dim)
    unicorn.show()
    time.sleep(0.1)

def alloff():
    for led in range(ledno):
        unicorn.set_pixel(led,0,0,0,0)
        unicorn.set_pixel(led,1,0,0,0)
    unicorn.show()

def randomsparkle():
    x = randint(0, (width-1))
    y = randint(0, (height-1))
    r = randint(0,2)*127
    g = randint(0,2)*127
    b = randint(0,2)*127
    unicorn.set_pixel(x, y, r, g, b)
    unicorn.show()
    time.sleep(0.1)

def dpad(pos):
    global mode
    if pos.top:
        alloff()
        print("up")
        mode = 1
    elif pos.bottom:
        alloff()
        print("down")
        allgreen()
        mode = 2

    elif pos.left:
        alloff()
        print("left")
        mode = 3

    elif pos.right:
        alloff()
        print("right")
        mode = 4

    elif pos.middle:
        alloff()
        mode = 5
        print("fire")

print("Starting bluedot")

scroll()
#alloff()
#scroll()
#allred()
#time.sleep(1)
#allblue()

bd = BlueDot()

while True:
    bd.when_pressed = dpad

#    print(mode)

    if mode == 5:
        randomsparkle()
    if mode == 1:
        allred()
    if mode == 2:
        allblue()
    if mode == 3:
        allgreen()
    if mode == 4:
        allpurple()

pause()

Clock using a Max7219 Matrix Display

I guess many of us find lighting up loads of LEDs to be rather interesting, so when I saw this group of 4 Matrix displays for sale cheaply, I had to pounce and find a use for them later.

There are a number of methods described for running them with the Raspberry Pi but I stumbled on an excellent library which does all of the hard work. The documentation is comprehensive and the examples really show what is possible.

matrixdisplay

Matrix Display resting on a Lego compatible case. The sizes fit perfectly, so I guess a construction brick display device is on the way soon!

I started out with just an 8×8 display originally, not trusting that I’d have any success with a larger module, but soon I got bored and upgraded. Woah… this thing works well, especially once the correct rotation had been added.


#!/usr/bin/env python

import time
from random import randrange

import max7219.led as led
from max7219.font import proportional, SINCLAIR_FONT, TINY_FONT, CP437_FONT
import feedparser

python_wiki_rss_url = "http://open.live.bbc.co.uk/weather/feeds/en/2649808/3dayforecast.rss"

# create matrix device
device = led.matrix(cascaded=4)
device.orientation(90)
print("Created device")

while True:
        print("Getting feed")
        feed = feedparser.parse( python_wiki_rss_url)

        for repeats in range(10):
                print(repeats)
                for items in feed["items"]:

                        msg = items["title"]
                        msg = msg[0:msg.find(",")]
                        print(msg)
                        device.show_message(msg, font=proportional(SINCLAIR_FONT))
                        time.sleep(1)

                        msg = time.asctime()
                        msg= time.strftime("%H:%M")
                        print(msg)
                        device.show_message(msg, font=proportional(SINCLAIR_FONT))
                        time.sleep(10)

I quickly looked up reading RSS feeds as well as strftime for python, and in a short period of time the program above shows a clock for 10 seconds and then parts of the 3 day forecast.

Seq24 on the Pi 3

Yesterday’s Raspberry Jam in Exeter gave an opportunity to briefly demonstrate Seq24 on the Raspberry Pi. I’ve got a Pi-TopCEED desktop and inside this is fitted a small amplifier and speaker. It’s a simple addition but gives me a chance to use sound without trailing wires.

Seq24 is a block-based sequencer. Patterns of notes are entered into blocks and each of these can be triggered with either the mouse or keyboard. As an experiment, I’ve entered parts of Pachelbel’s Canon in D into the blocks so that they can be cued one at a time. I’ve chosen Canon as it’s based on a repeating chord pattern of D, A, Bm, F#m, G, D, G, A over 4 bars.

Any Pi is fast enough to run Seq24 is external MIDI gear, but now that I’ve got a Pi 3 I’ve installed QSynth (which can emulate an external polyphonic sound module and uses SoundFonts) as well as AMSynth, which emulates a classic analogue synthesizer. These both seemed pretty easy to set up once I’d found a GM Sound Font for QSynth.

Cueing different parts of the Canon gives an entirely new mix which certainly adds an interesting perspective on the original music. Hopefully a YouTube clip will appear here soon!

Seq24 Demonstration

Seq24 and two virtual sound generators running on the Pi-TopCEED at Exeter Raspberry Jam.

 

LED cushion… using e-Textiles as a display device

LEDcushion

LED cushion… enough to make your heart skip a beat?

I’ve been experimenting over the Christmas period with WS2812 RGB LEDs. I intend to write up these experiments in another post, but having a bit of free time enabled me to try something a little more ambitious.

Connecting RGB LEDs to the Raspberry Pi has been simplified and they are now supported in ScratchGPIO once the Pimoroni unicornhat software is installed. By wiring together a bunch of these, I was able to create a 25 LED matrix.

Control via ScratchGPIO was a little slower than I needed and in addition I wanted to see if I could write text. I’ve done this in the past using figlet and writing the result to a Minecraft screen as a pile of blocks. It seemed it might be possible. I originally intended to go for a set of 8×8 LEDs (Similar to the Unicorn Hat or the Sense Hat from Pimoroni) but with time running short for a demo, I had to opt for just 5×5. The maths is what stings here… 25 LEDs, 3 pieces of wire between each, two ends to strip, twist and solder = 150 joints. For 8×8 this would be…. well, ouch!

In the video below, I present the results of the first set of experiments. I fully intend to solder up the remaining 39 LEDs to make 8×8, but this will take some time. I’ve mounted the LEDs on cardboard inside the cushion and covered them with bubble wrap. I will eventually use something much softer in the final product.

The controlling program is written in Python and uses a slight modification of the Unicorn Hat module. It took me a little while to find where Python modules are stored but I found it in

Here’s the final program:

#!/usr/bin/env python

import iprpixel as unicorn
import time
import datetime
import random
from mcpi import minecraft
import commands

#print("Here goes")

lookup=[0,1,2,3,4,9,8,7,6,5,10,11,12,13,14,19,18,17,16,15,20,21,22,23,24]
unicorn.brightness(0.6)

#---------------------
#wr_str = raw_input('What would you like to write? ') # ask the user what they'd like to write at the current position
#wr_str = "Hello"

def choosecol():
	colval=random.randint(0,5)
	global r_val, g_val, b_val
#	print "Colour is :",colval
	if colval==0: #red
		r_val=255
		g_val=0
		b_val=0

	if colval==1: #green
		r_val=0
		g_val=255
		b_val=0

	if colval==2: #blue
		r_val=0
		g_val=0
		b_val=255

	if colval==3: #orange/yellow
		r_val=128
		g_val=128
		b_val=0

	if colval==4: #cyan
		r_val=0
		g_val=128
		b_val=128

	if colval==5: #magenta
		r_val=128
		g_val=0
		b_val=128

def sparklefill():
	for led in range(400):
		ledpos = random.randint(0,24)
		r_val = random.randint(64,255)
		g_val = random.randint(64,255)
		b_val = random.randint(64,255)
		unicorn.setapixel(ledpos,r_val,g_val,b_val)
		unicorn.show()
		time.sleep(.05)
	for led in range(400):
		ledpos = random.randint(0,24)
		unicorn.setapixel(ledpos,0,255,255)
		unicorn.show()
		time.sleep(.05)
		unicorn.setapixel(ledpos,0,0,0)
		unicorn.show()
#		time.sleep(.05)

def timestring():

	global figletstring, list_line
#	wr_str= time.strftime('%I:%M %p')
	wr_str= "Time Now : "+time.strftime('%I:%M %p')
	figletstring=str(wr_str).upper()
	cmd = 'figlet -w 400 -f 3x5 '+figletstring # create an operating system command
	line = commands.getoutput( cmd ) # send cmd as a command to the operating system and receive the result.
	list_line = line.rstrip().split('\n') # split the result from 'figlet' into separate lines (right strip new line feeds)

def ipaddress():
	global figletstring, list_line
	figletstring = commands.getoutput( "hostname -I" )
#	print figletstring
	cmd = 'figlet -w 400 -f 3x5 '+figletstring # create an operating system command
	line = commands.getoutput( cmd ) # send cmd as a command to the operating system and receive the result.
	list_line = line.rstrip().split('\n') # split the result from 'figlet' into separate lines (right strip new line feeds)

def heart1():
	global list_line
	list_line = ["     "," # # ","#####","#####"," ### ","  #  "]

def heart2():
	global list_line
	list_line = ["     ","     "," # # "," ### ","  #  ","     "]

def displayleds():
	for startcolumn in range(len(list_line[1])-4):
		column = 0
		rownumber=-1
		time.sleep(0.1)
		for row in list_line: # one row at a time from list_line (the result from figlet)
#			print row, len(row)
			if rownumber>-1 and rownumber<5:
				column=0
#				print "working with row",row,"completed"
				for letter in row[startcolumn:startcolumn+5]: # work along each row - check each character. If it's a '#' then print a block else leave it as air
					if letter == "#":
						unicorn.setapixel(lookup.index(column+(rownumber*5)),r_val,g_val,b_val)
					else:
						unicorn.setapixel(lookup.index(column+(rownumber*5)),0,0,0)
					column = column+1
					unicorn.show()
			rownumber=rownumber+1

def boxdraw():
	global list_line, r_val, g_val, b_val
	for boxes in range(6):
		choosecol()
		list_line = ["     ","     ","     ","  #  ","     ","     ","     "]
		displayleds()
		time.sleep(0.1)
		list_line = ["     ","     "," ###  "," # # "," ### ","     "]
		displayleds()
		time.sleep(0.1)
		list_line = ["     ","#####","#   #","#   #","#   #","#####"]
		displayleds()
		time.sleep(0.1)

def pacman():
	global list_line, r_val, g_val, b_val
	r_val=255
	g_val=255
	b_val=0
	for bite in range(6):
		list_line = ["     "," ### ","#####","#####","#####"," ### ","     "]
		displayleds()
		time.sleep(0.5)
		list_line = ["     "," ### ","#####","##   ","#####"," ### ","     "]
		displayleds()
		time.sleep(0.5)

def smiley():
	global list_line, r_val, g_val, b_val
	for flashface in range(5):
		choosecol()
		list_line = ["     ","## ##","## ##","     ","#   #"," ### ","     "]
		displayleds()
		time.sleep(1)

def spinner():
	global list_line, r_val, g_val, b_val
	for boxes in range(5):
		choosecol()
		for spin in range(4):
			list_line = ["     ","#    "," #   ","  #  ","   # ","    # "]
			displayleds()
			time.sleep(0.01)
			list_line = ["     ","  #  ","  #  ","  #  ","  #  ","  #   "]
			displayleds()
			time.sleep(0.01)
			list_line = ["     ","    #","   # ","  #  "," #   ","#     "]
			displayleds()
			time.sleep(0.01)
			list_line = ["     ","     ","     ","#####","     ","      "]
			displayleds()
			time.sleep(0.01)

def heartbeat():
	global r_val, g_val, b_val
	for hearts in range(10):
		r_val=255
		g_val=0
		b_val=0

		heart1()
		displayleds()
		time.sleep(1)
		heart2()
		displayleds()
		time.sleep(0.25)

for displayip in range(5):
	choosecol()
	boxdraw()
	choosecol()
	ipaddress()
	displayleds()
	time.sleep(1)

while True:
#	pacman()
	smiley()
	spinner()
	boxdraw()
	heartbeat()
	choosecol()
	timestring()
	displayleds()
	time.sleep(1)
	sparklefill()