WS2812B LED ring driven from a Pi Zero

I’ve already written about using WS2812B RGB LEDs with the Pixel Cushion, but seeing a set of concentric circle PCBs available got me thinking. I originally used these a sort-of Superhero badge as part of a fancy-dress outfit, but they were crudely mounted onto a plastic disk with cable ties.

A bit of work with 3d software and a 3d printer produced this.

I’ve used a servo extension lead to power and control the LEDs. They’re all daisy-chained as before, starting from one of the outside LEDs and finishing on the final LED in the centre. In total, there are 61 LEDs which means that if they were run at full power, the load on the battery would be rather high (60mA per LED * 61 LEDs = 3.66 Amps). However, I’m limiting the maximum value for each LED so that they’re dimmer. An added advantage is that I can still see if I look directly at the LEDs. The overall effect is rather striking, although the camera used in the video above struggled to focus (perhaps macro might have been better) but it’s easy to see the exposure control kicking in as more LEDs are lit.

The Raspberry Pi power connections are fed directly into the GPIO connector, bypassing a somewhat delicate micro-usb port as well as ensuring that large currents for the LEDs are going to the adjacent 5v pin which is then fed out to the pixel rings.

Files for the clip-together case can be found and 3d printed from the: YouMagine Website

I suppose it would be prudent to add some sort of switch to initiate a shutdown routine, but for the moment I’ve been just pulling the plug.

Advertisements

Lego – Raspberry Pi interface

Lego interface

Lego interface – a L298 H-bridge motor controller with a servo buffer board.

Here’s the current version of my Lego interface for the Raspberry Pi. It uses an L298 H-bridge motor controller (covered in a previous post) combined with another of my 74HC541 buffers to protect the Raspberry Pi when connecting LEDs and servos.

The whole thing runs from a 5v plug-top power supply which is adequate for driving the 4.5v Lego motors along with a bunch of servos.

There’s a bit of scope here for making the whole thing more compact but that’s another step once I’m happy with the design. I need to add input connections so that the Lego creations can be fully interactive.

It would be also interesting to see if I could make this into a Lego case, perhaps with a bunch of plates combined with 1 x 4 x 3 Panels.

Lego and Raspberry Pi working together

In a small way, I consider the Raspberry Pi almost like a Lego brick. On its own, it’s an interesting device, but it becomes more useful when combined with other components. What would be more natural then, than combining it with other Lego devices along with a few of my own devising.

In previous posts, I’ve shown how servos can be used to create some pretty whacky Lego devices, but equally I feel that individual bricks are open to hacking. Note… this is pretty gruesome stuff – drilling, cutting and filing Lego bricks. Even something rather similar to “The Kragle” ends up being used!

Rather than steal my son’s Lego, I’ve been using Bricklink as a place to buy specific parts. I’ll try to list their code numbers here so that they’re easy to find on the Bricklink website. Bricklink serves as a market place for people to sell their bricks.

In a follow-up post, I’ll show the current version of my Lego interface.


Lego LEDs

Lego LED

Lego LED in 2×2 brick

I’ve debated at length in my own head how to wire these. Essentially all the device needs is a resistor and LED to be mounted into some kind of transparent brick, or for the LED to be poking out of the top.

A standard 5mm LED can be fitted inside a 2×2 brick if it’s allowed to shine through the top. This does mean that other bricks can’t be stacked with it, but it is a neat solution. These 2×2 bricks are also available in clear (I bought Trans-clear, Trans-Dark blue, Trans-Green, Trans-Red).

To make this, you will need:

  • 2×2 Brick (Part No:3003)
  • 2×2 Plate (Part No: )
  • 0.1″ Female connector cables
  • LED
  • 100 Ω resistor (1/8 Watt is easier to fit in)

Lego switches

Lego tactile switch

Lego tactile switch

These are easily made with a 6mm tactile switch with a long actuator. A blob of hot glue can be used to keep the whole switch central while the rest of the brick and plate is assembled around it.

The switch is connected to a short cable with 0.1″ Female connectors on the end.

To make this, you will need:

  • 2×2 Brick (Part No:3003)
  • 2×2 Plate (Part No: )
  • 0.1″ Female connector cables
  • 6mm tactile switch
4-way tactile switch

4-way tactile switch on a PCB in a Lego frame

I’ve also had success with using 4 tactile switches on a PCB. The spacing between studs is 8mm, therefore it’s a fairly simple job to create a PCB which matches. I’ve linked one side of each switch to a common line to reduce the amount of cables required.


Servos

Lego large servo

A Large servo in a Lego framework

Connecting servos into a Lego system remains the biggest challenge. I tried a number of ideas before I settled with two possible solutions.

The micro servos seem to work best glued to a tile. It needs to be something that’s compatible with the plastic of both the servo and plate. Hot glue seems to work well here, although I have had success with some solvent-based cements. Polystyrene cement worked well for a bit, but surprisingly I did have on piece fall apart.

Larger servos require a different approach. I build a framework out of bricks and plates and that seemed to work well, but it does mean that right-angle parts are needed to mount it if the axis of rotation needs to be vertical. The egg-drawing robot used a large servo resting on a tile, with some small axles to centre the spindle within the Lego grid system.

To make a framework that supports a servo on its side, I used:

  • 2 bricks – 1 x 6 (Part no: 3009)
  • 1 plate – 1 x 6 (Part no: 3666)
  • 2 plates – 4 x 6 (Part no: 3032)
  • Optional – Bracket – 2 x 2 with 2 holes (Part no: )

All of the pieces need to be stuck together with solvent and then the servo can be linked into this with hot glue. It’s fairly neat, robust and fits into the Lego system well.

The servo actuator needs a little bit of treatment to make it useful. Small servos can use a Technic axle and pin connector (Part no: 3651) and larger servos will need modifying with a pulley (Part no: 4185) along with some small screws. I used PCB pillars to get the spacing just right.

Lego framework with brackets

Large servo in Lego frame

22mm Pulley for actuator

Servo actuator using a pulley

Lego framework

Largeservo and the Lego framework

Small servo

Small servo on Lego tile with actuator

Lego Matrix of Dots printer – snappy title, eh?

Here’s the Egg Drawing robot converted into a simple one-dot dot matrix printer. I’ve borrowed a routine that I used in the Minecraft Relief Maps project and used that to interpret a JPEG file. There are methods which use Pygame, but I’ve stuck with things I know – and can achieve quickly.

The program reads in the image and converts it into a pattern of “#” symbols and spaces using JP2A. For this reason, a decent monochrome image makes a good starting point. Once converted, it’s split into lines and the servos are then made to scan backwards and forwards, putting in a dot wherever JP2A has left a “#”.

I needed to convert between coordinates on the bitmap and the actual positions needed by the servo. This is relatively easy to do once the correct range given by the servos has been found experimentally.

I had a few problems with the pen bouncing, and also the route that the pen takes is really a curve. This would be more suited to drawing bitmaps on eggs, so that’s the next step. Maybe “Egg Minions?”.

import commands
import os
import time

DELAY = 0.002

pen=2
leftright=1
updown=0

def pwm(pin, angle):
#    print("servo[" + str(pin) + "][" + str(angle) + "]")
    cmd = "echo " + str(pin) + "=" + str(angle) + " > /dev/servoblaster"
    os.system(cmd)
    time.sleep(DELAY)

def slow(servo,start,stop):
	difference = start-stop
	servopos = start
	if start<stop:
		step = 1
	else:
		step = -1
	servopos = start
	while servopos != stop:
		pwm(servo,servopos)
		servopos += step

def penup():
    pwm(2,160)

def pendown():
    pwm(2,140)

def dot():
    slow(2,160,140)
    slow(2,140,160)
		
def servo_off():
	pwm(0,0)

def servoY(posY):
    pwm(0,(posY*1.1)+100)

def servoX(posX):
    pwm(1,(posX*1.2)+80)

penup()
time.sleep(0.5)
pwm(1,60)
pwm(0,100)

wr_str = "MonoLogo.jpg"

cmd = 'jp2a --width=20 --height=20  --background=light --chars=" #" '+wr_str # 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)

print "Your picture has been converted to"
print line

yplot=0
xplot=0

for row in list_line: # one row at a time from list_line (the result from figlet)
    slow(1,(xplot*1.2)+60,60)

    print row
    servoY(yplot)
    yplot=yplot+5
    xplot=0
    for letter in row: # work along each row - check each character.
        blockshade=letter
#        print blockshade
        if blockshade=="#":
            servoX(xplot)
            time.sleep(0.5)
            dot()
        xplot = xplot+5
servoY(0)
time.sleep(1)

servo_off()

print("All done!")

Once that’s all running, assuming you have a MonoLogo.jpg file available, the machine will convert and start automatically.

Lego printer image

Simple print out of the Raspberry Pi logo using a Lego dot matrix printer.

Minion bitmap drawn on the egg

Drawing a design on an Egg

The finished egg design

The finished egg – just in time for breakfast.

Relief maps in Minecraft

The UK south-west peninsula.

The UK south-west peninsula.

When automatically generating landscapes in Minecraft, it seems easy to get large flat areas by just using the setBlocks() part of the API, but what I wanted was depth, height and texture. I’d seen methods of using bump maps in 3d software, so I wondered if similar techniques could be used. After a bit of searching I came across the fantastic maps-for-free website which has a whole earth view in relief map format – and free, too! (Permission is granted to copy, distribute and/or modify the relief maps and the water layer under the terms of the GNU Free Documentation license, Version 1.2 or any later version published by the Free Software Foundation.).

UK relief map image

UK Map taken from the relief layer shown on http://www.maps-for-free.com/

I quickly copied a section, converted it into a JPEG file of reasonable dimensions and re-coloured the sea so that it was the darkest area. In order to simply convert this into a file that Python can use, I cheated and used jp2a again. This converts images into a set of ASCII characters. I read this into a Python and convert into a list The python program works its way through the list and using setBlocks() creates a stack of blocks whose height is related to the intensity of the image at that point. What’s really pleasing is how well the final landform came out. It’s possible to see the high lands of Dartmoor and Exmoor, Snowdonia and further North, as well as the flat areas of the Norfolk Broads (forgive me if my geography is a bit dodgy… they did try to sort me out at school!).


from mcpi import minecraft
import commands
mc = minecraft.Minecraft.create()
mc.postToChat("Python is now in control!")

#Output from jp2a: Default is "   ...',;:clodxkO0KXNWM"

#jp2a 18 values
jp2ascale=" ",".","'",",",";",":","c","l","o","d","x","k","O","0","K","X","N","W","M"
mcscale=80,82,79,1,4,98,98,98,98,98,98,98,98,98,14,15,16,17,49,98
blockset=8,82,79,1,4,98,98,98,98,98,98,98,98,98,14,15,16,17,49,98

wr_str = "ukmap.jpg"

cmd = 'jp2a --width=255 --height=255 '+wr_str # 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)

print "Your picture has been converted to"
print line

#list_line="   ...',;:clodxkO0KXNWM","   ...',;:clodxkO0KXNWM","   ...',;:clodxkO0KXNWM","   ...',;:clodxkO0KXNWM"

startx,starty,startz = mc.player.getPos() #get the player's position

startx=128
starty=-1
startz=128

for row in list_line: # one row at a time from list_line (the result from figlet)
    startz=startz-1 # work down from the top
    column=0
    for letter in row: # work along each row - check each character. If it's a "#" then print a block else leave it as air
        
        column = column+1
        blockheight=jp2ascale.index(letter)
        blocktype=blockset[blockheight]
        mc.setBlocks(startx-column,starty,startz,startx-column,starty+blockheight,startz,blocktype)

print("All done!")


Underground bunker

The underground bunker

A snapshot of the underground bunker.

Building overground is great… but what about working underground. Those little secret bunkers left over from the cold war that are being turned into dwellings. Here’s a version for minecraft. There are two important variables that set the depth (it’s still there as tower height as a throwback to the last post) and the width. If you go too low (perhaps only to 5 or less) then the stairs don’t work. The torches get placed in funny positions sometimes or end up scattered on the floor. I think it’s to do with the fact that I haven’t put in facing-directions yet, but I’m not sure.

This could be interesting if started not far from a cliff-edge – you could then tunnel in to meet it somewhere. The bunker position is based on where “Steve” is standing at the moment the script is run.

Edited… some of the indenting went wrong last night!

from mcpi import minecraft
import time
mc = minecraft.Minecraft.create()
 
mc.postToChat("Python is now in control!")
 
def Bunker(x,y,z,height,width):
    y=y-height
    useblock=45
    centre=width/2
    mc.setBlocks(x,y,z,x+width,y+height,z+width,0) #clear the space first
 
    mc.setBlocks(x,y,z,x+width,y+height,z,useblock) #build a wall
    mc.setBlocks(x,y,z,x,y+height,z+width,useblock) #build a wall
    mc.setBlocks(x+width,y,z,x+width,y+height,z+width,useblock) #build a wall
    mc.setBlocks(x,y,z+width,x+width,y+height,z+width,useblock) #build a wall
 
    mc.setBlocks(x,y+height,z,x+width,y+height,z+width,42) #add a lid
    mc.setBlocks(x+3+centre,y+height,z+1,x+1+centre,y+height,z+2,0) #add a hole in the floor
 
    for floorheight in range(int(y)-1,int(y+height)-1,4):
        print "Putting in a floor at ",floorheight
        mc.setBlocks(x,floorheight,z,x+width,floorheight,z+width,17) #add a floor
        mc.setBlocks(x+3+centre,floorheight,z+1,x+1+centre,floorheight,z+2,0) #add a hole in the floor
 
        mc.setBlocks((x+centre)-1,floorheight+2,z,x+1+centre,floorheight+2,z,50) #add torch to front
        mc.setBlocks(x,floorheight+2,(z+centre)-1,x,floorheight+2,z+1+centre,50) #add torch to right side
        mc.setBlocks((x+centre)-1,floorheight+2,z+width,x+1+centre,floorheight+2,z+width,50) #add torch to rear
        mc.setBlocks(x+width,floorheight+2,(z+centre)-1,x+width,floorheight+2,z+1+centre,50) #add torch to left side
 
        for stepheight in range(1,4):
            mc.setBlock(x+stepheight+centre,floorheight+stepheight,z+1,67,0) # add an ascending east step block
            mc.setBlock(x+stepheight+centre,floorheight+stepheight,z+2,67,0) # add an ascending east step block
 
startx,starty,startz = mc.player.getPos() #get the player's position
 
towerheight=60
towerwidth=10
Bunker(startx,starty,startz,towerheight,towerwidth)

Another Minecraft tower (or two)

High rise towers from a Python program

Create two high-rise towers with this simple script

This program creates two towers next to each other. They’re rather sparse, having only four windows, an entrance door and a staircase to the top. It’s possible to walk up the staircase although you’ll get pretty dizzy in the process. I need to edit the program to stop it putting a useless staircase right at the top, but other than this it’s quite effective. Perhaps with a little work it would be possible to populate the minecraft world with a whole range of flats – even maybe using random for different heights and positions. Another refinement would be to clear the space it occupies so that you don’t have to remove the trees and landscape from the placement position.

from mcpi import minecraft
import time
mc = minecraft.Minecraft.create()

mc.postToChat("Python is now in control!")
#mc.setBlocks(-100,0,-100,100,100,100,0)
#mc.setBlocks(-100,1,-100,100,1,100,1)


def Tower(x,y,z,height,width):
    useblock=1
    centre=width/2
    mc.setBlocks(x,y,z,x+width,y+height,z,useblock)
    mc.setBlocks(x,y,z,x,y+height,z+width,useblock)
    mc.setBlocks(x+width,y,z,x+width,y+height,z+width,useblock)
    mc.setBlocks(x,y,z+width,x+width,y+height,z+width,useblock)
    mc.setBlocks(x+centre,y,z,x+1+centre,y+1,z,0) #add doorway to front


    for floorheight in range(int(y)-1,int(y+height),4):
        print "Putting in a floor at ",floorheight
        mc.setBlocks(x,floorheight,z,x+width,floorheight,z+width,useblock) #add a floor
        mc.setBlocks(x+3+centre,floorheight,z+centre,x+1+centre,floorheight,z+1+centre,0) #add a hole in the floor

        mc.setBlocks((x+centre)-1,floorheight+2,z,x+1+centre,floorheight+2,z,102) #add window to front
        mc.setBlocks(x,floorheight+2,(z+centre)-1,x,floorheight+2,z+1+centre,102) #add window to right side
        mc.setBlocks((x+centre)-1,floorheight+2,z+width,x+1+centre,floorheight+2,z+width,102) #add window to rear
        mc.setBlocks(x+width,floorheight+2,(z+centre)-1,x+width,floorheight+2,z+1+centre,102) #add window to left side
        for stepheight in range(1,4):
            mc.setBlock(x+stepheight+(width/2),floorheight+stepheight,z+(width/2),67,0) # add an ascending east step block
            mc.setBlock(x+stepheight+(width/2),floorheight+stepheight,z+1+(width/2),67,0) # add an ascending east step block

startx,starty,startz = mc.player.getPos() #get the player's position

#startx=0
#starty=0
#startz=0

towerheight=60
towerwidth=10
Tower(startx,starty,startz,towerheight,towerwidth)
Tower(startx+20,starty,startz,towerheight,towerwidth)