Average Ticker

AverageBot Devblog 6 – Code, Paddles & Switches

AverageBot Devblog 6AverageBot is getting a bit top heavy...

Time for another AverageBot #PiWars devblog! It’s been over two weeks since my last update and the competition is just one month away.

If you want to read my full devblog series, select the ‘Pi Wars‘ option in the menu.

Over the last couple of weeks I’ve mostly been concerning myself with code, having pretty much ignored it up to this point. I’ve also been playing with ball-pushing options for the Skittles challenge, program menus, displays, switches, new attachments and lots more.

So, let’s show you my progress…

Python robot code

Coding has been my main focus this week

Code

I put off any real effort on the code for a while, as I simply prefer building things than I do coding them. I’d much rather get my tools out and hit some stuff than mess around fixing those pesky syntax errors!

I’ll share my complete code later this month once it’s complete, but I thought it would be better to show you some snippets and things I learnt this week:

PyGame not Initialising

You may have read in my last devblog that I am now using PyGame and a 2.4Ghz remote to control my robot.

One issue I kept coming across was PyGame not initialising properly. My robot script would start, then it would get to this line and get stuck with no errors:

pygame.init()

I had to press Ctrl+C on my USB connected keyboard to force it to initialise and get past this line, which wouldn’t work at all in the competition environment.

After a bit of digging and some help from Twitter folks, it turned out I was causing this behaviour myself by not closing PyGame down properly when I was exiting my script.

I didn’t have a try/except block in my code (more on that below), so my script would exit without running pygame.quit(), and then something remains in the background and clashes the next time you try to run the PyGame initialisation.

I fixed that by using a…

Try: Except: Block

I hadn’t used these blocks much before, mostly due to a lack of understanding. I’d seen it used here and there, but I have always done things a different (worse) way. This post from RasPi.TV explains it very well:

http://raspi.tv/2013/rpi-gpio-basics-3-how-to-exit-gpio-programs-cleanly-avoid-warnings-and-protect-your-pi

The try/except block puts your main code in once section (the try: section), and your exit/cleanup code in another section (the except: section). All this does is say “run my code in the try section, and if anything goes wrong, run the code in the except section and close the script”.

Simple right? I can’t believe I’ve ignored this very useful option all this time. I’m converted.

I even found that using ‘finally:’ was all I really needed, where you replace ‘except’ for ‘finally’. This option kills your program on any exception or error, and is a bit more of a simple blanket approach.

What does all of this mean to AverageBot? Well, it means I won’t have the PyGame initialisation issue any more, as no matter how I kill the program, it will always run the ‘finally:’ block – which includes pygame.quit().

Menu display code

I added a display board to my robot this week, a 4tronix IP display board.

This will be used as a program menu, allowing me to select the program to run by using switches on the robot itself. I looked at other displays but they either used SPI (which is taken by the motor controller) or were just a bit too big for my small robot.

This cheap little number is intended to be an IP address display board add-on for the range of 4tronix robot controller boards, but you can of course play with the code to get it to display whatever you want.

4tronix IP display board

The IP display board from 4tronix

This proved very challenging, and I’ve only really got it doing the bare minimum due to my lack of education of binary. The board uses an MCP23017 which I’m familiar with, but when it comes to segment displays I really struggle – especially as I don’t have a wiring diagram for the board.

You can see the original IP display code here. I didn’t find it very easy to break down and figure out, but coding isn’t my strong point. I gave up on any kind of scrolling letters or fancy business, and simply came up with a way of showing one number to represent the program to run.

4tronix display board

I’ve added a switch attached to my terminal block, which lets my cycle through programs and select which one to run

So how do we do that?

To get this display to work (the MCP23017) we use smbus. First things first, import it:

import smbus

Then we need to set up smbus. I use a ‘1’ here for the newer version of Pi, if you’re using a revision 1 Pi, use a ‘0’ instead:

bus = smbus.SMBus(1)

Next I set up some variables to make life easier later on. These are the segment numbers we want to display. I borrowed these from a forum post I stumbled across:

N0 = 0x3F
N1 = 0x06
N2 = 0x5B
N3 = 0x4F
N4 = 0x66
N5 = 0x6D
N6 = 0x7D
N7 = 0x07
N8 = 0x7F
N9 = 0x6F
dash = 0x40
underscore = 0x08

Next you have to set up the MCP23017 used on the display board. Again, just copying the 4tronix code here:

addr = 0x20 # I2C address of MCP23017
bus.write_byte_data(addr, 0x00, 0x00) # Set all of bank 0 to outputs 
bus.write_byte_data(addr, 0x01, 0x00) # Set all of bank 1 to outputs 

After all of that confusing stuff, to display a number on the first (left) segment, we just use this:

bus.write_byte_data(addr, 0x13, 7)
bus.write_byte_data(addr, 0x12, N1)

Now I have no idea how I ended up using a ‘7’ at the end of the first line above, it happened by accident and I didn’t touch it again after it let me put a digit in the first segment. Ah the pythonic perils of the Average Man!

One day I’ll master binary and segment displays, but at the moment that feels a long way off. At least I have a menu system working though, which looks a bit like this:

That’s pretty much it for the code this week, apart from some servo code a bit further down the page.

Starting my script at boot

I had to get my script starting on boot rather than logging in via SSH, as I don’t want to have to log in to my robot on the day. I need AverageBot to be easy, simple and robust.

There are different ways of achieving this such as using rc.local, but the first method I learnt was using the ‘cron’ scheduler. You know how it is, you always stick with what you know.

One problem I find with cron is it sometimes doesn’t work when the script you want to run is in a directory, or relies on other files in a directory. I found a great Instructables post that explained how to overcome this with a launcher script, and even produce a log file for any cron errors.

Cron scheduler

Using Cron means I won’t have to manually start my script every time

That’s the auto start sorted for my script, I just need to test that PyGame and all the different functions still work when using this method. More on that next week.

Line sensors

I still haven’t coded these…I know I know!

However, the latest EduKit 3 (a new £17 robotics kit) has a worksheet for line sensors so I may use this as a starter for 10. Watch this space.

Pi Noon wire holder

I finally got round to making a wire holder for the Pi Noon challenge. Competitors haven’t been told anything about this challenge other than that your robot must be able to hold a thin wire at one end of the robot.

I looked at a few options including clamps, screws and cycle brake cable tighteners, but eventually settled for a nice simple solution that holds the wire between two pieces of acrylic, tightened up by screws either side:

Pi Noon mount

My mount for the mystery Pi Noon challenge – can you see the cowboy hat engraving?

This is simply a mix of some L-brackets from eBay, and a couple of laser cut pieces of acrylic that I got made at MakersCafe along with other parts being made.

Chassis Revision

I got most of my robot parts re-made following a few improvements that I needed to make. These were simple but useful things such as removal of unwanted holes, expanded wire holes, a cut out to let the SR-04 sensor sit a bit better and a few other things:

MakersCafe laser cutting

My new chassis parts being made at MakersCafe

AverageBot wiring

Subtle changes such as wider holes for wiring make everything a little easier

Three Point Turn

I’ve decided I’m going to ‘wing it’ on this challenge, mostly because I’m running out of time, but also because I’d like to see how far a guy can get with a very basic approach.

I’m simply going to measure out the track on my floor at home, and try to code the timing just right to make it go forward/left/reverse/right at the right times. I might add a bit of code to use the SR-04 sensor, but only if I feel I have the time.

It definitely won’t win, but it could be a chuckle if I beat someone using sensors, encoders and other magic!

The “BIG PUSHA”!

Some of you will recall an attachment I made a while back called ‘Average-Claw’. It was a minimum attempt to compete in the skittles challenge where you need to push a ball towards some skittles and knock them over.

I decided it wasn’t enough to just shunt the ball towards the pins, so I started looking at servos as a way of adding some speed to the ball push.

First I had to get a servo talking to the Pi. The wiring is very simple, just three wires that route to a GPIO, GND and 5V – no resistors or anything else. I’m using a separate 4x AA power supply to avoid any drain on my Pi battery.

Raspberry Pi servo testing

Some scruffy but functional servo testing

After it was wired up I initially tried the example scripts that came with my motor controller, which use something called Servoblaster. These scripts didn’t work for me straight away, and despite offers of help from Gareth at 4tronix, I just got fed up and started looking at other options.

After a short YouTube’ing session I came across a good video that had a nice easy servo example. Whilst I didn’t understand everything he talked about (Duty cycles?), I gave the code a go and it worked first time. A quick play with the parameters and I had it doing what I needed.

Here’s the code I’m currently using to drive 2 servos opposite eachother. They’re a bit twitchy but do the job:

p = GPIO.PWM(23,50)
q = GPIO.PWM(22,50)
p.start(7.5)
q.start(7.5)

p.ChangeDutyCycle(2.5) #180
q.ChangeDutyCycle(12.5) #0

try:
    while True:
        time.sleep(0.02)
        if GPIO.input(switch1):
            print "Firing!"
            time.sleep(1)
            p.ChangeDutyCycle(12.5) #180
            q.ChangeDutyCycle(2.5) #0
        if GPIO.input(switch2):
            print "Resetting"
            time.sleep(1)
            p.ChangeDutyCycle(2.5) #180
            q.ChangeDutyCycle(12.5) #0

With the servos working it was time to look at how to fix these to my robot with some kind of pushing paddle. I decided that making another attachment would be a good shout, however this would be an almighty add-on considering the height of the ball, battery pack and all the wires. Challenge accepted!

Long story short, here’s what I have so far. It’s work in progress, and still needs wiring up:

Big Pusha battery box

Work in progress – this battery box will be mounted and wired to the dedicated terminal block

Big Pusha servos

Here you can see the servos at each side, which will eventually be attached together with a ‘paddle’

All that’s left to do is add some kind of paddle to connect to the servos. I did originally cut one from acrylic, but stupid Average Man here got the dimensions round the wrong way. I still don’t really know how effective this will be at pushing a ball, but 10 points for effort right?

More on this next week.

Proximity attachment

With ‘Average-Claw’ now retired, I wanted to make a dedicated proximity alert challenge attachment to match my other attachments. I simply added this to the laser job I was having made. It’s a bit excessive and unnecessary, but then again, so is making a Raspberry Pi robot!

Prox claw attachment

“Prox Claw” replaces “Average-Claw”

Terminal block switch cover

Another change/upgrade was my terminal block cover. I originally made my own cover for the terminal block to replace the cheap clear one that came with it, however I needed to add a momentary switch for my display menu and saw the terminal block as a good place for it to live.

Terminal block switch

I’ve added a switch section to my terminal block cover, to control the display board menu

All I’ve done here is extended a section of the cover, added a switch hole (and the little hole to keep the switch straight) and popped it on top. I had to keep my original cover in place to make it high enough to give the switch enough clearance.

The switch is a SPDT momentary variation. I soldered a GPIO to each end of the switch, and then wired a 3.3V line to the middle shared connection.

Soldering SPDT switch

A quick solder job and the switch was ready to go

SPDT stands for ‘Single Pole Double Throw’, which just means each end of the switch has a single terminal (single pole), and the switch can go in two different directions (double throw). When I click it in one direction, it connects that GPIO to the shared 3.3V line (a GPIO input).

Using pull-down resistors instead of physical ones (thanks to RasPi.TV for the excellent article on this), I just wire the other ends of these to my Pi (no resistors needed) and flicking the switch each way triggers a different GPIO pin.

Perfect…apart from the fact that this particular switch appears to have a poor connection on one side!

Next week

With less than 10 days to go before code entries need to be submitted for judging, I suppose I best continue to work at combining and refining my code. I’m not sure my line follower code will be ready in time, but hey ho.

Sorting out the servo paddle will be the next task, getting something cut and ordering some square wood dowel to attach it to the servo horns.

Then there’s the three point turn – I’ll need to test my rough and ready approach to that one very soon.

Hmm…maybe I’m not as prepared as I thought I was?!

Until next time…

Be the first to comment on "AverageBot Devblog 6 – Code, Paddles & Switches"

Leave a comment

Your email address will not be published.


*


This website uses cookies. Please visit our privacy policy page for more information. Privacy policy

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.

Close