Showing posts with label usb. Show all posts
Showing posts with label usb. Show all posts

Wednesday, October 5, 2016

NexDock thoughts on using with Raspberry Pi


Earlier this year I backed the NexDock Indiegogo.  The NexDock was primarily being promoted as a Windows Phone accessory as it supports Continuum, but since it has a miniHDMI some of us thought it might be a great partner for the Raspberry Pi.

It took them 2 attempts to get funded but made it in the end.
Then they had a fire at the factory which set the project back even further.






All respect to the NexDock team, instead of throwing in the towel they rallied and with their ODM partner picked up the pieces, had new NexDock manufactured and in the end I took delivery on the 9th of September and have been using the NexDock a fair bit since.




Power, we have power. Oh!, maybe not

My life with a NexDock didn't start too well when I noticed it wasn't charging.
The charger did look a bit ropey but thought since it passed QA at the factory it must have been OK.

Not the cleanest. Should still be OK, right

A bit of dirt never hurt anyone

I'm sure it's fine

Checked the power supply with a multimeter and it was dead.
I submitted a Help Desk request on the support site and NexDock replied quickly that this shouldn't have happened and they were very sorry.  Advising it would take a while to send me a replacement power supply so as an alternative if I was OK with it they would refund me $15 as that is the equivalent cost of a PSU on Amazon.  Les Pounder who has blogged his experience here (http://bigl.es/nexdock-initial-impressions/) decided the US power supply with an adapter was not for him and he bought a suitable supply with 3.2A from CPC (http://cpc.farnell.com/stontronics/t5004st/ac-dc-power-supply-5v-3-2a-universal/dp/PW03046)

I still have to get a replacement power supply so in the short term I used a microUSB adapter board with the original cable to make a solution that would allow me to use any of the many microUSB chargers I have due to my Raspberry Pi addiction.

Functional, but maybe not a long term solution

This is what I have been using with the NexDock and it's served me well.  The green light you can see is the power LED.  Orange when charging and Green when fully charged.

Teething problems out of the way. What is the NexDock like to use.

Keyboard and Trackpad

The keyboard is a decent size.  The travel on the keys is comfortable.
One irritation for me is the power button is where the [delete] key should be and the [delete] key has been placed below the [backspace] . So, when I make a mistake and blindly stab at [delete] I'm pressing [power] and no delete happens.  Luckily the power button has to be held down for the usual 5 seconds to turn off the NexDock.  What it did mean is for a while I kept thinking the keyboard unpaired from the Pi and so I went into the menu, disconnected and reconnect the NexDock. 
Once I figured out it was user error all was good.  Still, funky placement of keys is becoming an ongoing annoyance on laptops as manufacturers pick different places for keys.
Oh, and the keyboard layout is US.  I'm in the UK.  I can live with it as I am comfortable using different keyboard layouts, just something to be aware of.

You can see the keyboard layout here


The trackpad works well once you up the speed of the  'mouse' on the Raspberry Pi.  No idea why this is needed but it does work.

It's important to note the keyboard and trackpad are Bluetooth and not USB.  So, for Pi users this works well for the Pi3, but not the Pi2 or PiZero as they do not have Bluetooth.  More on this later.

Screen

The screen, even though LCD and not IPS is sharp and works well for extended use.  The resolution is the classic 1366x768.  Fairly standard for laptops, but not a mode the Pi has automatically. (http://elinux.org/RPiconfig#Video_mode_options).  Not a problem if auto selected from HDMI, but as noted below can cause some fun when working with realVNC.

First boot with Pi3 powered from NexDock

Bluetooth and power 

As mentioned above the keyboard and trackpad are Bluetooth.  They are not available over USB.
With the Pi3 the NexDock is found when scanning and once paired works well.

You can't back power the Pi3 through USB so it has to be powered from the microUSB power connection.  This means when powering the Pi3 from the NexDock the USB devices built-in (webcam, microphone, microSD slot and USB port on the right) to the NexDock are not available.  The USB port on the left that provides  power is also the hub connection port.
On the Pimoroni Bilge Tank they had a a frankin-cable that does power the Pi3 and connect USB so all devices are available.


Also, Mike Redrobe did the diagram below showing the connections. 

Connections on NexDock

Personally, I haven't needed the webcam or other devices so it hasn't been a problem for me so far.
I just use the USB ports on the Pi3 to connect my devices.

We know that the PiZero can be back powered through  USB so this looked like it could be ideal, except the keyboard and trackpad are Bluetooth.
I connected a PiZero and powered it from the NexDock. Then connected a Bluetooth dongle bought on eBay to the port on the right.


All booted, Bluetooth dongle seen, paired with NexDock. Working great, then Bluetooth device disappears. Icon in top bar grayed out.  As an eBay purchase I suspected it might be faulty so used on a couple of PCs and plugged directly into a USB port on a Pi2 with the NexDock and all worked well.

My conclusion is that even though there is a nice big battery inside the NexDock the USB port on the right is not a powered port and so doesn't have enough power to support the Bluetooth Dongle.  It works great for an external mouse and other lower power devices, but this Bluetooth dongle seems to need more power than the port can handle.

Continuing my adventure with the PiZero I used a Zero4U USB hub bought at Cambridge Raspberry Jam from Ryanteck.



This attaches directly to the PiZero taking it's power from the 5V line directly to give a powered hub.
With this and again back powering the PiZero from the NexDock the Bluetooth dongle worked great.
Now I have a PiZero computer with keyboard/trackpad, webcam, microphone, speakers, 3.5MM headphone jack, another USB port and a microSD slot.

One thing to note on Bluetooth with the Raspberry Pi is that in Raspbian Bluetooth is not set up to auto pair with devices on boot up, so for first set up you need an external mouse to pair the NexDock and the Pi.
NexDock address this on their support page and give instruction on how to set up a cronjob to enable the pairing each time your Raspberry Pi starts up.
The support page also explains how to get the internal speakers working and a couple of other things.

The longest time the NexDock was running was at the Cambridge Jam in September which runs from 10:30am to 4:30pm.   The NexDock was set up with a Pi3 powered externally so the USB from the Pi3 was connected to the NexDock to enable the webcam.  It was running Scratch Pac Man and a simple webcam viewer python program showing the person using the computer their image. Code on GitHub


Battery test

The last thing is the battery in the NexDock.  It's a 10,000mA battery, so a decent size.

Powering a Pi3 idle it lasted ~6 hours and powering a Pi3 under load it lasted 3 1/2 hours..

These were the times I expected using back of an envelope calculations.

To run these tests I ran sysbench in one terminal window and in a second window ran a small python script that recorded to start time and every 60 seconds recorded the time.
The Pi3/NexDock ran until it shut down. Then starting the Pi3 again it was just a matter of subtracting one time from the other.


Other findings

I mentioned above about connecting over realVNC.  Using the Pi3 on a NexDock as the client and then realVNC running on a PiZero as the server. realVNC by default sets the screen resolution to 640x480 and this function, but as you'd expect a bit painful to do anything constructive.
You can change the Pi resolution by modifying the config.txt file in /boot.
Problem is there is no 1366x768 resolution option, meaning full native NexDock resolution wasn't possible. I could do 1360x768(mode 39) and this worked but it did leave a few unused pixels either side of the screen. Not a massive thing, just worth noting.

I also tried to enable the experimental OpenGL drivers and this failed completely.  Black screen.  No flashing cursor, no scrolling of the messages at start up (pre Raspbian PIXEL)
To be fair to the NexDock I have the same problem with the pi-topCEED, so it might be something to do with the default non-standard (to the Pi) resolution.

So, it looks like the experimental OpenGL drivers are not compatible with the NexDock display.  Pity as this could have been fun for Minetest, the Minecraft-a-like open source game that is in the repo so can be installed with apt-get install minetest.
It's not the latest version, but it plays great on a Pi3 with OpenGL enabled and 256MB set aside for the GPU.  NOTE: Minetest makes the SOC run hot. If you are going to play Minetest on the Pi2/3 then you will need a fan. I have a heatsink on a Pi3 and that's not enough. Previous blog post about Minetest on the Pi3

Also on Minetest, if you are walking/flying around and you use the trackpad to change direction you stop moving. I don't know if this is a Bluetooth keyboard/trackpad combo thing or if this is NexDock specific.  Either way it means on the NexDock you can play Minecraft, but if you want to change direction while moving you have to release the forward/backward key and press it again

Conclusions and wish list

With everything above I do like the NexDock.  It feels nice to use. The keyboard and trackpad work well.  For it's intended use with Windows Phone I expect it is a perfect match.  With the Raspberry Pi the needs are a bit different but it does provide what I need to use it regularly.

With that said for me it would go from being great to amazing as a Raspberry Pi device if:

  • Left side had 2 USB ports. One capable of providing power and USB connection, second one USB connection at standard power rating.
  • Keyboard/trackpad with the option to connect as Bluetooth or USB
  • 2 USB ports on the right.
  • Powered internal USB hub meaning the 2 (wish list) USB ports on the right would be able to handle devices that need power like the Bluetooth dongle and external hard drives.
  • UK Power supply instead of US with adapter
  • UK keyboard layout option

I see myself using the NexDock as my primary Pi device and will over time be doing the expected nerd/geek activity of covering it in stickers which to me is a real sign of a keeper that you expect to have part of your life for a good while to come.








Saturday, September 20, 2014

Setting up RetroPie on Raspberry Pi with USB gamepad

Every since it started I've watch the development with RetroPie a Raspberry Pi image that includes a number of console/computer emulators optimised for the Raspberry Pi.

I'm not a major gamer but sometimes a bit of nostalgia is worthwhile so I decided to install RetroPie

A few things to note. RetroPie is built on Raspbian, so the foundation is solid.
You can even use raspi-config to expand the SD partitions and set overclocking and GPU memory split.

The easiest way to use RetroPie is to download the pre-made image from the website http://blog.petrockblock.com/retropie/

Use your tool of choice to burn the SD card.  I did it on Windows 7 so I used Win32DiskImager

Once install in the Pi and all cables attached I added power.
Up comes the lovel RetroPie splash screen and it boots straight into Emulation Station which is a great front end giving access to the emulators where roms are available.
Splash Screen

On first boot Emulation Station prompts you to configure your controller/gamepad to operate the menus in Emulation Station. This confused me a little as I thought it was asking to configure the gamepad for the games.

But once I got a few roms on it became clear the this setup was only for Emulation Station and for that it worked perfectly.


I quit Emulation Station and ran raspi-config to expand the partition, split the memory 256MB/256MB as I read the PSX emulator may need it and also to do some minor over clocking (it can't hurt to have a bit more speed)

Then to get RetroPie setup correctly.

From the home directory do:

cd RetroPie-Setup
sudo ./retropie_setup.sh

This brings up the RetroPie configuration menu.
I selected Option 1 to do the Binaries-based INSTALLATION.
RetroPie comes with the bare minimum to get going in the image so you have to do this to get the other emulators.
As expected this can take a bit of time. 
Main Menu for retropie_setup

Once this finished I then selected option 3. SETUP (only if you already have run one of the installations above)

This is where you get the extra options to customize RetroPie.
If you are building a cabinet or want that genuine old school feeling of using original controllers there are a number of tools in the SETUP menu to make it a lot easier.  I was not interested so the only thing I enabled here is 310 SAMBA ROM Shares.
This enables SAMBA shares so you can drag and drop files from your computer to the Raspberry Pi making it much easier to get ROMs into RetroPie

SETUP menu 
At this stage RetroPie has all the emulators installed and the menus works but there are no ROMs and the games (once ROMs are copied across) will only work with the keyboard.

I mentioned I enabled SAMBA above so I could copy ROMs across. In the end I didn't use this. I used WinSCP which allows you to login to the Pi and drag and drop files from your computer onto the Pi in a nice GUI tool 

You have to copy the ROMs to the relevant folders for the different emulators.
Really simple. Reminded me of the olf Windows 3.11 FileManager with 2 panes to drag and drop between.

Last item was to get the gamepad working with the games and not just the Emulation Station menu.
This took a bit of hunting online as I have a feeling the method may have changed in the last update of RetroPie to v2.3.

In the end the method I found that work for me with my gamepad was from a reply on the following webpage.  http://blog.petrockblock.com/forums/topic/how-to-configure-a-controller-on-retropie/ from user flipbug

sudo chown pi /opt/retropie/configs/all/retroarch.cfg

cd /opt/retropie/emulators/RetroArch/installdir/bin

sudo ./retroarch-joyconfig -j 0 >> /opt/retropie/configs/all/retroarch.cfg

The first command gives the user pi the right to change the retroarch.cfg file.
The second goes to the directory where the retroarch-joyconfig command is located
The final command rund retroarch-config and outputs its results to retroarch.cfg 

I found the tool to be a bit sensitive when dealing with the analog sticks so ended up having to do it a few times.

In case my configuration matches some elses here is the configuration I use.

input_player1_joypad_index = "0"
input_player1_b_btn = "2"
input_player1_y_btn = "0"
input_player1_select_btn = "8"
input_player1_start_btn = "9"
input_player1_up_btn = "h0up"
input_player1_down_btn = "h0down"
input_player1_left_btn = "h0left"
input_player1_right_btn = "h0right"
input_player1_a_btn = "3"
input_player1_x_btn = "1"
input_player1_l_btn = "4"
input_player1_r_btn = "6"
input_player1_l2_btn = "5"
input_player1_r2_btn = "7"
input_player1_l3_btn = "10"
input_player1_r3_btn = "11"
#input_player1_r3_axis = "+3"
input_player1_l_x_plus_axis = "+0"
input_player1_l_x_minus_axis = "-0"
input_player1_l_y_plus_axis = "+1"
input_player1_l_y_minus_axis = "-1"
input_player1_r_x_plus_axis = "+3"
input_player1_r_x_minus_axis = "-3"
input_player1_r_y_plus_axis = "+2"
input_player1_r_y_minus_axis = "-2"

It was a bit of a trial and error session getting RetroPie working but in the end I have a fantastic emulator system set up on a model B+ that looks well and performs brilliantly.  I am really impressed at how well it runs PSX games as from a raw CPU power I always though the PSX and the Raspberry Pi would be quite similar.

Now all I have to do is actually be better at the games to fully enjoy them.


Sunday, February 23, 2014

Arduino Compatible robot for £15

I was looking for a low cost way of building a vehicle controlled by an Arduino or Raspberry Pi and eBay once again came up with the solutions.

1 x Smart Robot Car Chassis Kit  - £7.60
1 x L298N - £1.86
1 x Arduino Compatible Pro Mini - £2.53

Total Cost: £11.99

The Smart Robot Chassis comes with 2 motors and wheels.  It comes with the encoding wheels for optical encoder to measure rotation, but without the electronics.
All the parts with chassis. 


The L298N is a Motor Driver Module
That's it on the right next to the battery pack


While the Pro Mini is a small Arduino compatible board that I previously blogged about programming (http://winkleink.blogspot.co.uk/2014/01/programming-arduino-pro-mini-16mhz-5v.html) and soldering the headers (http://winkleink.blogspot.co.uk/2014/01/soldering-up-pro-mini-arduino.html)

You need a USB to serial adaptor to program it. For this adaptor you have to solder a pin to the DTR and then attach that to the RST line on the Pro Mini when programming.

I built the Chassis and attached the L298N
All the parts

Bits for the front wheel mounting
Screw the spacers to the chassis


Attach the swivel wheel to the spacers.
Note nuts not in original picture

Parts for motor/wheel mount

Use small screws to attach pillars to chassis

Parts for connecting motors

Screw motor to the outside of the pillars.
Note: make sure to have motor connectors on the inside
for easy cable management

Add the encoder wheels if you want and the actual wheels

See in front of batter holder are the two holes where
the battery holder will be bolted to.
Use 2 of the slightly longer bolts for this.

All finished.  Still needed to solder the wires to the motors.


The L298N is then wired.

+ Battery to VCC and 5V on the L298Nand RAW on the Pro Mini. The L298N appears to be OK with 6V going to the 5V line. And the Pro Mini doesn't complain about the 6V from the batteries either.
As always connect all the GNDs together

Then for each motor connect Out1 and Out2 to one Motor and Out3 and Out4 to the other motor. Depending on which way around you do the connection will decide which way the motors spins, so if this is wrong you can either swap the wires or modify the code.

Then for control from the Pro Mini I connected

IN1 to 3
IN2 to 5
IN3 to 9
IN4 to 10

The eagle eyed will have noticed these are 4 of the PWM lines so in the future I can enable speed control by driving using PWM rather than digital.


Uploaded the following Sketch tot he Pro Mini and let it rip - see video at the bottom

// motor driver using PWM

int lb = 3;
int lf = 5;
int rb = 10;
int rf = 9;


void setup() {
  // put your setup code here, to run once:

  pinMode(lb, OUTPUT); 
  pinMode(lf, OUTPUT); 
  pinMode(rb, OUTPUT); 
  pinMode(rf, OUTPUT); 
  
  digitalWrite (lb, LOW);
  digitalWrite (lf, LOW);
  digitalWrite (rb, LOW);
  digitalWrite (rf, LOW);

}

void loop() {
  // put your main code here, to run repeatedly: 
  
    digitalWrite (lf, HIGH);
    digitalWrite (lb, LOW);
    digitalWrite (rf, HIGH);
    digitalWrite (rb, LOW);

    delay(1000);

    digitalWrite (lf, LOW);
    digitalWrite (lb, LOW);
    digitalWrite (rf, LOW);
    digitalWrite (rb, LOW);

    delay(1000);

    digitalWrite (lf, LOW);
    digitalWrite (lb, HIGH);
    digitalWrite (rf, HIGH);
    digitalWrite (rb, LOW);

    delay(600);

    digitalWrite (lf, HIGH);
    digitalWrite (lb, LOW);
    digitalWrite (rf, HIGH);
    digitalWrite (rb, LOW);

    delay(1000);

    digitalWrite (lf, HIGH);
    digitalWrite (lb, LOW);
    digitalWrite (rf, LOW);
    digitalWrite (rb, HIGH);

    delay(600);
}



All worked well.
Next I need to put in place a way of controlling it remotely.
The adventure continues.

Note: This chassis and L298N should also work with a Raspberry Pi. Need to be more careful with the power and a few other bits. 


Thursday, April 18, 2013

Raspberry Pi, Unipolar Stepper motors, ULN2003 Darlington Pairs, USB Gamepad, Python

For the Raspberry Jam on Sunday I want to bring something that moved and was also interested in getting stepper motors to work with the Raspberry Pi so I decided to build a vehicle using stepper motors to drive the wheels (very slowly) and control it with a USB Gamepad/Joystick

The first thing I had to do was to sort out the sequence of pulses for the Stepper Motors. I did this originally with an Arduino Uno as I wanted to remove as many opportunities for human error as possible and since this would be the first time I would user stepper motors with the Raspberry I thought it best to begin with a platform where I was use to doing I/O.

To operate a stepper motor you send signals to the 4 lines in a set sequence.
For the motors I purchased are 28BYJ48 DC 5V and their sequence is. Yours may be different.

        Line1 Line2 Line3 Line4
Step 1    0     0     1     1  
Step 2    1     0     0     1  
Step 3    1     1     0     0  
Step 4    0     1     1     0  

To get the motor to go in reverse you just run this sequence in reverse order.
Also, strangely if you are doing this using an Arduino the stepper library worked first time for me even though  the sequence is different. But when I tried a second, third or more times it failed unless I changed the sequence.  See here for the details on the sequence in the Arduino Stepper Motor library: http://www.tigoe.net/pcomp/code/circuits/motors/stepper-motors/
This post also has a lot of useful information on stepper motors generally

The first thing that I discovered was that the stepper motors and driver board that was a ULN2003 and some indicator LEDS with the right connector for the motors I bought (Amazon UK / Amazon US - these are available cheaper on eBay) had a slightly different pulse sequence than the examples I found so once I figured that out the motors turned clockwise and anti-clockwise as I expected.

All good, motors and driver board working as expected.

Next to get it wired up to the Raspberry Pi.





Here is an layout using a breadboard and a couple of UNL2003 Darlington Pair ICs. These are the same ICs as on the board so the wiring is the same. The board just makes it a lot easier.

NOTE: I used Fritzing to make the layout and it shows the motor as having 6 wires. There are 6 terminals on  unipolar stepper motor, but the model I bought had the two power lines tied together so only came out to a single wire.  Depending on the unipolar motor you have it may have 5 or 6 wires.



With all the wiring done next it was onto the code.

As I said above the goal was to get the motors controlled by a USB gamepad. The gamepad I used is a Saitek P380 (Amazon UK / Amazon US). I bought mine in PC World for about £10.00 For this I decided to use Python as learning to code properly in Python is one of my 2013 resolutions. Also, Python has a nice library in Raspbian for the GPIO pins and I knew that Pygame which works with Python 2.6x had the ability to read USB gamepads.

After figuring out all the mad stuff to do with getting the motors to work on the Arduino I was delighted that using Python and the GPIO library I got the motor to spin with no real problems.

After a bit of hunting on the Internet I got the code to read the USB gamepad and depending on how you push/pull the analog sticks the motors turned.  Effectively allowing you to drive the vehicle like a tank with independent control for both wheels.

Here is the code I used. It is very simplistic as my hope is that it will be easily understandable by others so it can form the basis of something more interesting. I would expect with a bit of effort even I could reduce the code to about a 3rd of its current size and someone who can code properly could get it even shorter. But for this exercise I wanted to literally show every step in the sequence so it is easy to read, easy to understand and east to adapt.


#!/usr/bin/env python

import os, sys, pygame 
from pygame import locals
import time
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BOARD)
GPIO.cleanup()

# set the delay between steps
stepDelay = 0.002

# set up motor 1
GPIO.setup(8, GPIO.OUT)
GPIO.setup(16, GPIO.OUT)
GPIO.setup(18, GPIO.OUT)
GPIO.setup(22, GPIO.OUT)

GPIO.output(8, GPIO.LOW)
GPIO.output(16, GPIO.LOW)
GPIO.output(18, GPIO.LOW)
GPIO.output(22, GPIO.LOW)

# set up motor 2
GPIO.setup(11, GPIO.OUT)
GPIO.setup(13, GPIO.OUT)
GPIO.setup(15, GPIO.OUT)
GPIO.setup(21, GPIO.OUT)

GPIO.output(11, GPIO.HIGH)
GPIO.output(13, GPIO.HIGH)
GPIO.output(15, GPIO.HIGH)
GPIO.output(21, GPIO.HIGH)


os.environ["SDL_VIDEODRIVER"] = "dummy"
pygame.init()

pygame.joystick.init() # main joystick device system

deadZone = 0.6 # make a wide deadzone
m1 = 0 # motor 1 (1 = forward / 2 = backwards)
m2 = 0 # motor 2 (1 = forward / 2 = backwards)
try:
   j = pygame.joystick.Joystick(0) # create a joystick instance
   j.init() # init instance
   print 'Enabled joystick: ' + j.get_name()
except pygame.error:
   print 'no joystick found.'


while 1:
   for e in pygame.event.get(): # iterate over event stack
      if e.type == pygame.locals.JOYAXISMOTION: # Read Analog Joystick Axis
         x1 , y1 = j.get_axis(0), j.get_axis(1) # Left Stick
         y2 , x2 = j.get_axis(2), j.get_axis(3) # Right Stick

         print x1
         print y1
         print x2
         print y2

         if x1 < -1 * deadZone:
             print 'Left Joystick 1'

         if x1 > deadZone:
             print 'Right Joystick 1'

         if y1 <= deadZone and y1 >= -1 * deadZone:
    m1 = 0 # Dont go forward or backwards

         if y1 < -1 * deadZone:
             print 'Up Joystick 1'
             m1 = 1 # go forward
             print m1
             
         if y1 > deadZone:
             print 'Down Joystick 1'
             m1 = 2 # go forward
             print m1

         if y2 <= deadZone and y2 >= -1 * deadZone:
    m2 = 0 # Dont go forward or backwards
              
         if y2 < -1 * deadZone:
             print 'Up Joystick 2'
             m2 = 1

         if y2 > deadZone:
             print 'Down Joystick 2'
             m2 = 2

         if x2 < -1 * deadZone:
            print 'Left Joystick 2'

         if x2 > deadZone:
            print 'Right Joystick 2'

         
   if m1 == 1: # motor 1 go forward
# step 1 motor 1
      GPIO.output(8,GPIO.LOW)
      GPIO.output(16,GPIO.LOW)
      GPIO.output(18,GPIO.HIGH)
      GPIO.output(22,GPIO.HIGH)

   if m2 == 1: # motor 2 go forward
# step 1 motor 2
      GPIO.output(11,GPIO.LOW)
      GPIO.output(13,GPIO.LOW)
      GPIO.output(15,GPIO.HIGH)
      GPIO.output(21,GPIO.HIGH)

   time.sleep(stepDelay)



   if m1 == 1: # motor 1 go forward
# step 2 motor 1
      GPIO.output(8,GPIO.HIGH)
      GPIO.output(16,GPIO.LOW)
      GPIO.output(18,GPIO.LOW)
      GPIO.output(22,GPIO.HIGH)

   if m2 == 1: # motor 2 go forward
# step 2 motor 2
      GPIO.output(11,GPIO.HIGH)
      GPIO.output(13,GPIO.LOW)
      GPIO.output(15,GPIO.LOW)
      GPIO.output(21,GPIO.HIGH)

   time.sleep(stepDelay)

   if m1 == 1: # motor 1 go forward
# step 3 motor 1
      GPIO.output(8,GPIO.HIGH)
      GPIO.output(16,GPIO.HIGH)
      GPIO.output(18,GPIO.LOW)
      GPIO.output(22,GPIO.LOW)

   if m2 == 1: # motor 2 go forward
# step 3 motor 2
      GPIO.output(11,GPIO.HIGH)
      GPIO.output(13,GPIO.HIGH)
      GPIO.output(15,GPIO.LOW)
      GPIO.output(21,GPIO.LOW)

   time.sleep(stepDelay)

   if m1 == 1: # motor 1 go forward
# step 4 motor 1
      GPIO.output(8,GPIO.LOW)
      GPIO.output(16,GPIO.HIGH)
      GPIO.output(18,GPIO.HIGH)
      GPIO.output(22,GPIO.LOW)

   if m2 == 1: # motor 2 go forward
# step 4 motor 2
      GPIO.output(11,GPIO.LOW)
      GPIO.output(13,GPIO.HIGH)
      GPIO.output(15,GPIO.HIGH)
      GPIO.output(21,GPIO.LOW)

   time.sleep(stepDelay)

   if m1 == 2: # motor 1 go reverse
# step 4 motor 1
      GPIO.output(8,GPIO.LOW)
      GPIO.output(16,GPIO.HIGH)
      GPIO.output(18,GPIO.HIGH)
      GPIO.output(22,GPIO.LOW)

   if m2 == 2: # motor 2 go reverse
# step 4 motor 2
      GPIO.output(11,GPIO.LOW)
      GPIO.output(13,GPIO.HIGH)
      GPIO.output(15,GPIO.HIGH)
      GPIO.output(21,GPIO.LOW)

   time.sleep(stepDelay)

   if m1 == 2: # motor 1 go reverse
# step 3 motor 1
      GPIO.output(8,GPIO.HIGH)
      GPIO.output(16,GPIO.HIGH)
      GPIO.output(18,GPIO.LOW)
      GPIO.output(22,GPIO.LOW)

   if m2 == 2: # motor 2 go reverse
# step 3 motor 2
      GPIO.output(11,GPIO.HIGH)
      GPIO.output(13,GPIO.HIGH)
      GPIO.output(15,GPIO.LOW)
      GPIO.output(21,GPIO.LOW)

   time.sleep(stepDelay)

   if m1 == 2: # motor 1 go reverse
# step 2 motor 1
      GPIO.output(8,GPIO.HIGH)
      GPIO.output(16,GPIO.LOW)
      GPIO.output(18,GPIO.LOW)
      GPIO.output(22,GPIO.HIGH)

   if m2 == 2: # motor 2 go reverse
# step 2 motor 2
      GPIO.output(11,GPIO.HIGH)
      GPIO.output(13,GPIO.LOW)
      GPIO.output(15,GPIO.LOW)
      GPIO.output(21,GPIO.HIGH)

   time.sleep(stepDelay)

   if m1 == 2: # motor 1 go reverse
# step 1 motor 1
      GPIO.output(8,GPIO.LOW)
      GPIO.output(16,GPIO.LOW)
      GPIO.output(18,GPIO.HIGH)
      GPIO.output(22,GPIO.HIGH)

   if m2 == 2: # motor 2 go reverse
# step 1 motor 2
      GPIO.output(11,GPIO.LOW)
      GPIO.output(13,GPIO.LOW)
      GPIO.output(15,GPIO.HIGH)
      GPIO.output(21,GPIO.HIGH)

   time.sleep(stepDelay)


Once I put together the physical vehicle using cardboard, Nutella jar lids and some glue I tried it out.
It worked. The main thing that would need to be improved is the wheels.
As the Nutella jar lids are light plastic they wobbled a lot causing them to grind on the cardboard chassis. I used some toothpicks to stop the wheels turning in too much and this for the most part stopped the problem.
Here is a short video of it working.


As you can see I definitely won't be racing this bad boy, but it was great to work with stepper motors, python and pygame as well as upgrade some of my cardboard cutting and shaping skills.