Tuesday, July 19, 2016

Toy crane controlled from Raspberry Pi Zero with SenseHat using Scratch


Since the micro:bit was launched one of the demos that I kept seeing was the toy crane controlled using the motion sensing in the micro:bit.  The kids loved it and was very interactive.

Since the SenseHat on the Raspberry Pi has the motion sensors built in I thought this would a good project for a Raspberry Jam.

So, off I went to Home Bargains and bought a crane. From the picture, definitely the right age for me.  This crane is normally controlled using two levers on the hand controller. It can rotate and raise/lower the bucket.

Didn't come with the hard hat
First order of business was to figure out the wiring and cut the cable as the final build would be battery powered to work the same as the micro:bit version.


Cut the red wire

From above the wiring is:
VCC - Red wire
GND - Brown wire (not black)

Rotate motor 
Orange and Yellow

Crane lift motor
Blue and Green.

For turning and crane the direction it goes depends on how you wire it up and how your code works so some adjusting may be needed later.

To make sure I had this right I tested by touching Red to Orange and Brown to Yellow. Crane rotated one way. Swapped wires around and crane rotated the other way.
Red to Blue and Brown to Green, Bucket went down. Swapped wires around and bucket went up.

Wiring confirmed and tested.

As the Raspberry Pi isn't designed to control motors directly I needed a small motor controller.
The L9110s looked perfect for the job. Smaller than the L298N that I usually use so would be easier to accommodate in the final box.

L9110s motor controller
The 2 terminal blocks on the left in the image are for the motors.
On the right are the control pins and power.
Top 2 connections are control for Motor A
Bottom 2 connections are control for Motor B
Then in the middle are VCC and GND

NOTE: A really important thing is to make sure when using multiple boards that all the GND lines are tied together so that all the voltages have the same base reference.  Otherwise strange things can happen.

I wired up the motors. Turning uses GPIO 5 and GPIO 6 on the Raspberry Pi and Motor B on the L9110s while lifting uses GPIO 27 and GPIO 17 and Motor A.

Again did some simple code to see if it would work from Scratch. Initially manually moving with the keyboard.  It worked great and I brought it along to the Egham Jam in April 2016.  As the organiser of the Jam I was a bit delinquent in taking pictures so the only one I have is of the crane, bottom left in the booth of the car before I went to the event. I promise the kids loved it and it was a massive hit, really. Actually, I had a different project called ZeroBall that was finished so it took most of my time.

Bottom leftis the crane
There were two technical reason I didn't have it all set up with motion sensing and coded in Scratch for the Jam.

  1. The SenseHat covers all the GPIO pins meaning I couldn't get at the pins to attach the wires for the motor controller.  So, I could get the readings from the SenseHat but couldn't control the motors.
  2. The Scratch at the time had a problem whereby it didn't support AddOn board. 


The first problem was solved with Stacking Headers and great tutorial from Keith's Pi Tutorials even has a video.
Also, a great reference site for Raspberry Pi board pin usage is pinout.xyz.  They have loads of boards listed and this is where I got the details for the pins used on the SenseHat

Stackable Headers. Note the high tech blutac for holding it all in the tub


The second problem of Scratch not working at all with AddOn boards was reported and fixed in the May 2016 Raspbian update.

With the purchase of Stackable Headers from The Pi Hut and a freshly imaged SD card both of these technical problems were overcome and the way forward was sorted for the SenseHat to be used to control the crane.

Since I wanted it to be battery powered the Raspberry Pi Zero was the obvious choice as it is low power. Only thing is Scratch is a GUI program and so I needed a desktop environment to run it (If you can run Scratch code without a GUI I'd love to know, but I suspect it kind of defeats the purpose of a drag and drop interface if you run it from the command line)

To overcome this I used a USB wifi dongle to connect over the network to the PiZero and then on a laptop used RealVNC to get a desktop. Since this was going to be shown at the first Wimbledon Raspberry Jam I didn't know if I would have a wifi network to connect to so I brought my own in the shape of a VoCore. A one inch cubed wireless router running openWRT.  I backed this as a crowdfunding thing a while back and all I've used it for it to create a local wifi hotspot.  At the Jams I can even power it from a powered Raspberry Pi USB port.

Side Notes:
I think the number is the manufacturing order of the original batch and I've never seen one with a number lower than 26.
The VoCore is only the top layer. The rest is an add-on that gives you USB, Ethernet, microUSB power socket and a microSD slot.  IT also has it's own GPIO pins so can be used for embedded projects.

Vocore. Basically, the guts of a wifi router
Obviously, as this was going to be standalone it had to be battery powered. I'd been picking up these 18650 Lithium Ion batteries in Poundworld and thought 4 of these in a case would make a decent power supply for the day.  No idea why when I cracked them open one was pink.  The battery case was from eBay and it all snapped together really easily.
The case has 2 USB ports for power so could power the Raspberry Pi and the VoCore at the same time.

Batteries in their original cases

Batteries in their new case


I mentioned above that all the Grounds need to be tied together.  In this instance I have 3 circuits that need to all have the same GND. Crane, L9110s and Raspberry Pi Zero (The SenseHat is take care of through the Pi Zero)
I tied the Crane GND (Brown wire directly to Pin 39 on the Raspberry Pi, then the GND pin on the L9110s was tied to Pin 6 on the Raspberry Pi.  In this way all 3 had a common GND.

It's good to be aware that in a circuit all GND can usually be treated as the same point. Especially for such low power and low frequency signals.  If this was a high power high frequency circuit then the trace length between the different GND points could case harmonics.  I cannot think of a project using the Pi that I would do where the length of the trace between GND pins would be a problem


So, now I have power, local network, a way to run Scratch so people can see the code and all the bits wired up. Last of all was the actual Scratch code.

From the image you'll see the code isn't very complex.  The main thing I'd to figure out was which one of the sensors I needed to read. It's the Accelerometer.
I believe the range is -4095 to + 4095 on each axis.
When the program is run a base "flat' reading for Lifter and Turning is taken so any movement in the sensor doesn't carry from one person to the next.  This is what the middle block of code does.
The block of code on the right is there if it all goes wrong and I can just press [space] to turn off the motors.

Th middle block is where the magic happens.  It checks if Accelerometer X is 1000 less or 1000 more than the flat reading for Lifter and/or Turning and then activates the appropriate motor to either turn the crane or raise/lower the bucket.

Not shown below is a second costume for the crane that just says "Put Pi on a flat surface" at the start of the calibration.


If you're not up for trying to copy the code from the image you can download the Scratch code from GitHub.

To make it hand held I stuffed all the bits in to a plastic Chinese takeaway box.  You can see the L9110s on the left, wifi dongle on a short microUSD to USB cable and the SenseHat with the Stackable Headers so the wires for the motor controller can could be added.

Finally, here is a boy totally engrossed in playing with the crane at the Wimbledon Jam.  It all ended really well.

Hours of fun transporting monkey from one place to another









Monday, July 18, 2016

Minecraft Pi backup Worlds on exit

My kids love building cities on the Raspberry Pi version of Minecraft.  They're not programming them yet, but they spend hours placing blocks and designing houses, hotels, swimming pools, and other building and gardens.
All of which is great.
Except I also use the Raspberry Pi for programming and other things where due to my fumbling around I end up borking the SD card and have to start again.

That's OK. If you backup all the files in ~/.minecraft/games/com.mojang/ and then put them on the new SD card all is good.  Really simple backup.
Only problem is I keep forgetting this step and delete weeks or months or effort.

Rather than expecting somehow that I will remember in the future I thought it would be a good idea to solve the problem with a bit of code and a little modification to the menu.

The goal is to replace the command that runs minecraft-pi with a command that runs minecraft-pi and then on exit archives the worlds and sends them to an ftp server.
In this way the backup is off the Pi and even if I do reformat it I can get the backup minecraft worlds and just reinstate them.

All this is being done with Raspbian as the OS.

For the ftp server I have OSMC set up on a Raspberry Pi (1) B+ that I use mainly as a media server for a couple of Blu-Ray player and tablets in the house so it is on 24x7.

The code is quite short made up of a python script that does the archiving and ftping of the file and a bash script that runs minecraft-pi and then runs the backup script.
The code is available at https://github.com/winkleink/MinecraftPi_backup

Just copy it into pi user home folder '/home/pi'
If you copy the code somewhere else then you will need to modify the bash script and the files to take it in to account.
Once copied change the file preferences to permit execution. Since you're in the GUI the easiest way to do this is right click on the file and select [Properties].
The go to Permissions and set Execute.  I chose Anyone, but if you're only going to run as user pi then you can select 'Only owner'

Change Execute permissions so this is a program that can be run

You need to do this for the 2 files (minec.sh and ftpzipminecraft.py)

minec.sh is the bash script to run the 2 commands. With the semicolon at the end of the first command it knows to run them in sequence (one after each other) rather than potentially at the same time. No modification is needed unless you save the ftpzipminecraft.py program somewhere other than the pi home folder

minec.sh

#!/bin/bash
minecraft-pi; 
/home/pi/ftpzipminecraft.py

ftpzipminecraft.py runs after minecraft-pi closes and this does the archiving to local file in the pi home folder and then connects to the ftp server and transfers the archive to the server.
You have to change 3 items in the file for it to work.  I've highlighted them in red below.

FTP SERVER NAME/IP ADDRESS
USERNAME
PASSWORD

ftpzipminecraft.py

#!/usr/bin/python3
# Script to backup the MinecraftPi worlds and then upload them to an FTP server
# By Winkleink (July 2016)
# https://github.com/winkleink/MinecraftPi_backup
# MIT Licence
# This is a quick fix so use at your peril
import os
import zipfile
import datetime

import ftplib

now = datetime.datetime.now()
year= str(now.year)
month = str(now.month)
day = str(now.day)
hour = str(now.hour)
minute= str(now.minute)

uploadfile = "minecraft"+year+"-"+month+"-"+day+"-_-"+hour+"-"+minute+".tar.gz"

print(uploadfile)
os.system ("tar zcvf " + uploadfile + " /home/pi/.minecraft/games/com.mojang")

# Enter your FTP Server Name or IP address, Username and Password in the following line
session = ftplib.FTP("FTP SERVER NAME/IP ADDRESS","USERNAME","PASSWORD")
file = open("/home/pi/"+uploadfile, "rb")
session.storbinary("STOR " + uploadfile, file)
file.close()
session.quit()
print("Done")





Once both files are in place and are set to executable we need to modify the menu entry for Minecraft so it runs our new script minec.sh

From the main menu select [Preferences] [Main Menu Editor]


Then on the left select [Games] and pick [Minecraft] and then click [Properties] on the right.


Finally, replace the 'minecraft-pi' command with '/home/pi/minec.sh'


Its not shown here, but so I know it's the one I've changed I modified the Comment to 'Minecraft + Backup' so when I mouse over the menu entry I can see it the one with the backup.

With this little change I will hopefully never lose my kids amazing creations in Minecraft on the Raspberry Pi.