Category Archives: Arduino

Model Railway Arduino Signals – Design

As previously explained, I’m working on the use of an Arduino and an old laptop to control the points on my very small N Gauge model railway. Well, I’m also going to control the signals too.

Working on this track plan:

Simplified Garwick Track Plan

I consulted my tame signalling engineer (some say that he once completly ruined the brakes on my MG Montego, and that he spends his spare time writing cod-1950s hard-boiled detective story versions of his work, but all we know is that he’s called The Sig), explaining to him that all the lines were bi-directional. He put on his thinking-trilby, sharpened his crayons, and came up with this idea:

timmy2

(Only the signals inside the box are to be modelled. The ones outside it are off-scene, and therefore just implied to be there and functioning.)

So, 6 signals. As I only had six remaining outputs left on the Arduino, I decided on 2-Aspect light signals.

And, lo, these were on eBay:

z0a

Six of them for £19 incl shipping, actually from http://hezhiqing.com/NSIGNAL.html (yeah, it says 5 on the website, but all the eBay listings show 6 of them).

Nominally they run off 12v but are plenty bright enough with 5v from an Arduino supplied to them. Plus, if you tie the Green line to 5v and the Black to GND, putting 5v up the Red line from the Arduino will switch the signal from green to red. This is counter-intuitive to me, as surely the signals should fail-to-Red, not fail-to-Green?

No, matter, it still make the wiring easier.

sigwires

Eagle-eyes will spot the the lights are the wrong way up.  Ah, well, it’s too late now.

Next… build up the control board for one pair of points, and one signal as a test.

 

Model Railway Arduino Point Control – Design

As stated elsewhere, I’ve mothballed the Arduino Dalek Project, and started to cannibalize bits for a new project: Arduino control of the turnout points on an N Gauge model railway layout.

For a start, heres some information about the point motors I’m using: The PECO PL-11 side mounted motors, which attach to the side of the points, like this:

PECO PL-11 (© PECO Publications)
PECO PL-11 (© PECO Publications)

These motors operate on 16v AC and require only (and indeed cannot tolerate more than) momentary current, and are currently controlled from “passing contact switches” drawing power from a Capacitor Discharge Unit.

There are currently 6 turnouts/points, arranged in pairs as below. As it would be reckless (and in real life impossible, due to interlocking) to operate either of the pair independently, I’ve decided to activate them together.

points1Thus, at all times both A and B will either both lead straight ahead, of both lead off to the left (for sets C&D and E&F it will be right not left).

As the Arduino can only throw out 5v DC, each pair of motors will need to be driven via a 5v DPDT replay. But, as we can’t leave the current on without melting the motors, each pair will actually need two relays (one for each direction of change), driven independently from different output pins. Another complication is that the relays will have to energised and then de-energised within a specific time-frame to avoid motor damage, but this is a programming issue to be dealt with later.

PL-11-CDU-Relay WiringThe above diagram shows only the 16vAC side of the wiring. The Arduino 5vDC is shown below.

Arduino-Relay Wiring

Obviously I could have chosen to just use SPDT relays, and connect the outputs together, but due to the vagaries of how the motors work and the orientation and placement of them on the layout, I thought it was safer to design and wire it this way at the outset, rather than back-fix it later when it went wrong. Plus, I had all the wiring in place, so thought I might as well use it.

Note the lack of common Ground between the two halves of the circuit. Grounding AC and DC together isn’t a good idea. Just say no.

Anyway, here is all is again on one convenient image.

Arduino-Relay-PL-11 Wiring
Click to embiggen

So now the next stage to to take that abstract squiggle and build it as a circuit.

Note – for myself, mainly: Each “pair” takes up 2 outputs, so for the three pairs of points we need 6 lines from the Arduino, out of a total of 12 (not 14, as I’d rather not use the 0 and 1 lines (RX & TX) as this could cause issues with data transfers activating the relays – something that the Dalek had problems with at first.

To be continued… with a start on Signalling!

Death to the Arduino Dalek

Here I go again, repurposing shit. In this case it is both a Doctor Who episode title and some  electronic bits.

The Arduino Dalek/Raspberry Dalek project has been on hold for some time (obviously), due to me not being arsed to sort out a niggling wiring problem that only allowed one of the motors to run in one direction.  That and the camera melting itself into slag. That didn’t help.

Anyway, today it suffered a major setback when the Arduino and relays got removed for use in another project.

But Daleks never say die, so it might come back later.

The gubbins are being reassigned to Project Railway, and will act as the point motor control system, once I’ve worked the circuit design out.

Protocol of the Ardunio Dalek

Ok, so now I’m just making Doctor Who episode titles up…

Anyway, while eagerly awaiting the release of the Raspberry Pi, which should be available within a month, I’ve been playing about with the communication method twixt Raspberry and Arduino.

As the ‘berry will be running Debian Linux, my Ubuntu server had been used as the test host, despite it being far too massive and heavy to be carried by the Dalek. I have a very long USB cable for such eventualities.

The plan has come down to initially sending single character commands to the Arduino over the serial port, and listening for a response. The responses will be a 5 character code with optional additional data.

The single character commands, their actions and return messages are:

Command Action Response
q Move forward and left MOVSF Ok
w Move forward MOVFF Ok
e Move forward and right MOVFS Ok
a Spin left MOVBF Ok
s Stop MOVSS Ok
d Spin right MOVFB Ok
z Move back and left MOVBS Ok
x Move back MOVBB Ok
c Move back and rigt MOVSB Ok
h Return last movement order MOTOR {motor status} Ok
v Return version number VERSN {version number}
l Get distance from left sensor DISTL {distance in cm}
r Get distance from right sensor DISTR {distance in cm}
  Unknown command UNKNW

So, here is the Arduino Sketch for this protocol:

// Project: Dalek control system – Receive and process commands from USB
// Version 1.0 (2012-02-09-09-06)
// Tony Blews tony@tonyblews.co.uk

int MotorDirectionR = 10;
int MotorDirectionL = 11;
int MotorPowerR = 12;
int MotorPowerL = 13;
int IRPinLeft = 2;
int IPPinRight = 3;
String motorStatus = String (“”);

void setup()
{
pinMode(MotorDirectionR, OUTPUT);
pinMode(MotorDirectionL, OUTPUT);
pinMode(MotorPowerR, OUTPUT);
pinMode(MotorPowerL, OUTPUT);
motorStatus= String(“MOVSS”);
Serial.begin(9600);
Serial.println(“START Serial control Dalek system starting…”);
}

void check_distance(int IRpin) {
float volts = analogRead(IRpin)*0.0048828125; // value from sensor * (5/1024) – if running 3.3.volts then change 5 to 3.3
float distance = 30*pow(volts, -1.10); // worked out from graph 65 = theretical distance / (1/Volts)S – luckylarry.co.uk
Serial.println(distance); // print the distance
delay(100); // arbitary wait time.
}

// modes for the motor control
// convention here is modeXX – where X is F for forward, S for stationary and B for backwards
// first X is the left motor, second X is the right one
// for direction control, the LOW if forward and HIGH is backward
// for power control, LOW is off and HIGH is on

// all stop
void modeSS()
{
digitalWrite(MotorDirectionR, LOW);
digitalWrite(MotorDirectionL, LOW);
digitalWrite(MotorPowerR,LOW);
digitalWrite(MotorPowerL,LOW);
motorStatus= String(“MOVSS Ok”);
Serial.println(motorStatus);
}

// move straight ahead
void modeFF()
{
digitalWrite(MotorDirectionR, LOW);
digitalWrite(MotorDirectionL, LOW);
digitalWrite(MotorPowerR,HIGH);
digitalWrite(MotorPowerL,HIGH);
motorStatus= String(“MOVFF Ok”);
Serial.println(motorStatus);
}

// move straight backwards
void modeBB()
{
digitalWrite(MotorDirectionR, HIGH);
digitalWrite(MotorDirectionL, HIGH);
digitalWrite(MotorPowerR,HIGH);
digitalWrite(MotorPowerL,HIGH);
motorStatus= String(“MOVBB Ok”);
Serial.println(motorStatus);
}

// spin left
void modeBF()
{
digitalWrite(MotorDirectionR, LOW);
digitalWrite(MotorDirectionL, HIGH);
digitalWrite(MotorPowerR,HIGH);
digitalWrite(MotorPowerL,HIGH);
motorStatus= String(“MOVBF Ok”);
Serial.println(motorStatus);
}

//spin right
void modeFB()
{
digitalWrite(MotorDirectionR, HIGH);
digitalWrite(MotorDirectionL, LOW);
digitalWrite(MotorPowerR,HIGH);
digitalWrite(MotorPowerL,HIGH);
motorStatus= String(“MOVFB Ok”);
Serial.println(motorStatus);
}

// move forward left
void modeSF()
{
digitalWrite(MotorDirectionR, LOW);
digitalWrite(MotorDirectionL, LOW);
digitalWrite(MotorPowerR,HIGH);
digitalWrite(MotorPowerL,LOW);
motorStatus= String(“MOVSF Ok”);
Serial.println(motorStatus);
}

// move forward right
void modeFS()
{
digitalWrite(MotorDirectionR, LOW);
digitalWrite(MotorDirectionL, LOW);
digitalWrite(MotorPowerR,LOW);
digitalWrite(MotorPowerL,HIGH);
motorStatus= String(“MOVFS Ok”);
Serial.println(motorStatus);
}

// move backward left
void modeSB()
{
digitalWrite(MotorDirectionR, HIGH);
digitalWrite(MotorDirectionL, LOW);
digitalWrite(MotorPowerR,HIGH);
digitalWrite(MotorPowerL,LOW);
motorStatus= String(“MOVSB Ok”);
Serial.println(motorStatus);
}

// move backward right
void modeBS()
{
digitalWrite(MotorDirectionR, LOW);
digitalWrite(MotorDirectionL, HIGH);
digitalWrite(MotorPowerR,LOW);
digitalWrite(MotorPowerL,HIGH);
motorStatus= String(“MOVBS Ok”);
Serial.println(motorStatus);
}

//report distance left
void lookLeft()
{
Serial.print(“DISTL “);
check_distance(2);
}

//report distance right
void lookRight()
{
Serial.print(“DISTR “);
check_distance(3);
}

// report Status back to host
void helloDalek()
{
Serial.print(“MOTOR “);
Serial.println(motorStatus);
}

//report software version
void reportVersion()
{
Serial.println(“VERSN 1.0”);
}

//main program loop
void loop()
{
if (Serial.available() >0)
{
char inByte = Serial.read();
// this version uses the QWEASDZXC “square” on the keyboard
// as my laptop doesn’t have a numeric keypad
// L and R are used to “look” left and right for distance sensing
// H is for Hello. To report the status of the device.
switch (inByte)
{
case ‘q’:
modeSF();
break;
case ‘w’:
modeFF();
break;
case ‘e’:
modeFS();
break;
case ‘a’:
modeBF();
break;
case ‘s’:
modeSS();
break;
case ‘d’:
modeFB();
break;
case ‘z’:
modeBS();
break;
case ‘x’:
modeBB();
break;
case ‘c’:
modeSB();
break;
case ‘l’:
lookLeft();
break;
case ‘r’:
lookRight();
break;
case ‘h’:
helloDalek();
break;
case ‘v’:
reportVersion();
break;

default:
Serial.println(“UKNWN”);
break;
}
}
}

Again, parts of this come from Lucky Larry‘s site.

And the C part:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <getopt.h>

void usage(void);
int serialport_init(const char* serialport, int baud);
int serialport_writebyte(int fd, uint8_t b);
int serialport_write(int fd, const char* str);
int serialport_read_until(int fd, char* buf, char until);

int main(int argc, char *argv[])
{
int fd = 0;
char serialport[256];
char buf[256];
int rc,n;

fd = serialport_init(“/dev/ttyUSB0”, B9600);
if(fd==-1) return -1;
strcpy(buf,argv[1]);
rc = serialport_write(fd, buf);
if(rc==-1) return -1;
usleep(100 * 1000 ); // sleep milliseconds
serialport_read_until(fd, buf, ‘n’);
printf(“read: %sn”,buf);
exit(EXIT_SUCCESS);
} // end main

int serialport_write(int fd, const char* str)
{
int len = strlen(str);
int n = write(fd, str, len);
if( n!=len )
return -1;
return 0;
}

int serialport_read_until(int fd, char* buf, char until)
{
char b[1];
int i=0;
do {
int n = read(fd, b, 1); // read a char at a time
if( n==-1) return -1; // couldn’t read
if( n==0 ) {
usleep( 10 * 1000 ); // wait 10 msec try again
continue;
}
buf[i] = b[0]; i++;
} while( b[0] != until );

buf[i] = 0; // null terminate the string
return 0;
}

// takes the string name of the serial port (e.g. “/dev/tty.usbserial”,”COM1″)
// and a baud rate (bps) and connects to that port at that speed and 8N1.
// opens the port in fully raw mode so you can send binary data.
// returns valid fd, or -1 on error
int serialport_init(const char* serialport, int baud)
{
struct termios toptions;
int fd;

//fprintf(stderr,”init_serialport: opening port %s @ %d bpsn”,
// serialport,baud);

fd = open(serialport, O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) {
perror(“init_serialport: Unable to open port “);
return -1;
}

if (tcgetattr(fd, &toptions) < 0) {
perror(“init_serialport: Couldn’t get term attributes”);
return -1;
}
cfsetispeed(&toptions, B9600);
cfsetospeed(&toptions, B9600);

// 8N1
toptions.c_cflag &= ~PARENB;
toptions.c_cflag &= ~CSTOPB;
toptions.c_cflag &= ~CSIZE;
toptions.c_cflag |= CS8;
// no flow control
toptions.c_cflag &= ~CRTSCTS;

toptions.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl

toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw
toptions.c_oflag &= ~OPOST; // make raw

// see: http://unixwiz.net/techtips/termios-vmin-vtime.html
toptions.c_cc[VMIN] = 0;
toptions.c_cc[VTIME] = 20;

if( tcsetattr(fd, TCSANOW, &toptions) < 0) {
perror(“init_serialport: Couldn’t set term attributes”);
return -1;
}

return fd;
}

This is a canibalisation of code from Tod Kurt‘s site.

My botch of this just takes a single character as a command line option, passes it the Arduino and prints the reply. eg:

$ ./dav s

read: MOVSS Ok

$ ./dav v

read: VERSN 1.0

$ ./dav l

read: DISTL 42.15

$ ./dav k

read: UKNWN

In other news, I’ve ordered a DIY Shield Kit from Amazon, so I can tidy up the hardware a bit, and a miniscule USB webcam which I intend to fit into the head part of the Dalek. I also plan to move all the clever bits of circuitry into to the top half, of the Dalek, and Meccano-up a set of brackets to hold the various battery sets that are needed in the bottom half.

The Arduino Dalek Master Plan – Episode 2

Looking back on my grand ideas, I’ve decided on a bit of a change of plan.

The current scheme will not have ports for video, or extraneous USB holes for keyboards and things of that ilk.

The current list of ports to stick on the Dalek is:

  • Ethernet – as i think I’ll need it in case the wifi fails
  • USB (using the already fitted port) for power while testing

The Raspberry will need USB for these:

  • Connection to the Arduino
  • Connection to the webcam (unless i can get a camera that uses the on-board connection)
  • Some form of microphone

So it still looks like I’ll need an unpowered hub.

It will also need a speaker connection for whatever sound output I decide to use.

Also, at some point i intend to get the ear lights working again.

Evolution of the Arduino Dalek

The DIY Arduino Shield Kit arrived from Amazon, and has been soldered up.

emptyshieldAnd it looks really boring, without the other parts stuck on it.

The parts in question are four 5v DPDT relays (Maplin part no N05AW – which seem to be out of stock a lot of the time, but are better that the alternative BT Type 47s, as the coil isn’t fussy about the polarity of the voltage), four 1N4004S diodes (part no QL78H), and a mess of wires. Rather than try to describe the layout, I’ve drawn a really bad diagram.

Circuit-ComponentsThis is the view from the component side. The yellow boxes show the relay placements, the four vertical block are the connections to the arduino. The Cyan areas are connections on the other side of the board, either whopping great solder blobs or lines joining the pads drawn with a pcb pen. The other technicolour lines are various wires.

Although that diagram gives the impression that I’ve used a double sided board, I haven’t. In retrospect that would have made things a lot easier.

Another collosal lack of planning (ie putting the Arduino header blocks too close to the top of the board) means that the Massively Ugly Blob Of Solder at the top sits directly over the ICSP header on the <a href="http://arduino best ed pills non prescription.cc/en/Main/arduinoBoardDuemilanove”>Arduino Duemilanove that I’m using, requiring a bit of electrical tape to stop it shorting.

Here is what it looks like now, shitty soldering included for free:

2012-02-24-16.47.06 2012-02-24-16.47.19

Maybe you’ve spotted some things that aren’t on the diagram. Such as the 2 pin header, the two 3 pin headers and and 4 pin header. Well, the 2 pin is for the motor power input, and the 4 pin one is for the motor driver outputs. They were an afterthought, as were the two 3 pin headers which are for the distance sensors input, and are currently not connected. That bit comes next.

The Arduino Dalek Master Plan

All has been quiet on the Arduino Dalek front for a while now, as I’ve stopped all work on it pending the release of the Raspberry Pi credit card sized sub-£20 computer

For those not in the know, the Raspberry Pi will be an ARM11 700Mhz based computer running Debian Linux and capable of operating from 4 AA batteries. The “Model B” will have 2 USB ports and on-board ethernet.

There will be plenty of space inside the Dalek to accommodate one of these, along with the extra battery packs required.

So, assuming that they start shipping these things soon, the Master Plan (oh just guess where the title of this post is derived from) is:

  • Strip down the existing code for the Arduino version so that it just accepts commands to drive the motors and read the sensor data (pretty much like version 0.1 did).
  • Work up a protocol for the Raspberry and Arduino to communicate with. Then implement it.
  • Fit the Dalek with all the connectors for the Raspberry (RCA, HDMI, Ethernet, USB via an unpowered hub, Audio jack and micro-USB power)
  • Recode the current “free-roaming” software to run on the Raspberry.
  • Source a suitable USB WiFi dongle and camera to install.
  • Jig up a web based “Control Panel” for the beastie.

The above list includes “USB via an unpowered hub”, as I currently envision needing more than 2 USB ports:

  • USB connection to the Arduino (direct)
  • USB WiFi dongle (via hub)
  • USB Keyboard (via hub on case exterior)
  • USB Mouse (via hub on case exterior)
  • USB Memory stick/Disk interface (via hub on case exterior)

Now why, you may be thinking, would I be needing the keyboard, mouse and storage (and video outputs)?

Well, the objectives are now two-fold. Primarily I still want to build the original free-roaming robot idea, but I also want it to double as a cool set-top box to connect to our stupidly large television which has been gathering dust since the Digital Switchover (our TV aerial is really shite and Freeview is UNWATCHABLE).

I could do that using a second Raspberry as a dedicated set-top box, but that would not be as cool.

Imagine: The Dalek is connected to the TV, playing a copy of an old Doctor Who episode featuring Daleks. The on-board camera is pointing at the TV, relaying the images to a web server. So a Dalek is watching a Dalek on a Dalek (not in that way). Open up another window and the Dalek is also watching itself. Thats the kind of thing that Christopher H. Bidmead could only dream about.

I’ll be buying a second one anyway, to it inside one of these keyboards.

But as I said, it is all on hold until the Raspberry Pi ships (and I remember how to program in C again).

Then maybe I can actually make use of the contrived acronyms DAVROS (Dalek Automatic Roving Vehicle Operating System), and SKARO (Stupid Kludged Arduino Remote Operation).

Vision of the Arduino Dalek

Ok, so that post title isn’t based on a Doctor Who episode title. Sue me.

Recently I’ve bought two <a href="http://robosavvy viagra without a doctor prescription.com/store/product_info.php/cPath/27/products_id/320″>Sharp GP2Y0A21YK Infrared Proximity Sensors from RoboSavvy. These little things can detect object in a range of 10cm to 80cm.

irsensorSo, the task now is to wire them up, and use them to detect when the Dalek get within 20 cm of an obstacle.

The circuitry is fairly easy. The Red wire goes to the 5v connection, the Black goes to GND, and the yellow wire goes to one of the Analogue inputs on the Arduno. I’m using pins A2 and A3, one for each sensor.

My soldering is, as ever, attrocious, so we’ll not have a picture of of that. Instead, here is a picture of the sensors Blu-Taked on to the front of the thing.

irmounted

And, as a bonus, a picture of the button that I’ve also fitted (and wired to Digital Pin 8).

dalekbutton

So, what we are going to do now is have the Dalek spin left if detects an obstable to the right, and spin right if it sees something to the left.

Also, if the button on the back is pressed, it will sleep for five seconds.

Portions of this code come from Lucky Larry’s website.

// Project: Dalek control system
// Version 0.3 - IR Sernsors
// Tony Blews tony@tonyblews.co.uk

int ButtonPin       = 8;
int MotorDirectionR = 10;
int MotorDirectionL = 11;
int MotorPowerR     = 12;
int MotorPowerL     = 13;
int IRPinLeft       = 2;
int IRPinRight      = 3;

void setup()
{
 pinMode(MotorDirectionR, OUTPUT);
 pinMode(MotorDirectionL, OUTPUT);
 pinMode(MotorPowerR, OUTPUT);
 pinMode(MotorPowerL, OUTPUT);
 pinMode(ButtonPin, INPUT);    // declare pushbutton as input

 Serial.begin(9600);
 Serial.println("Serial control Dalek system starting...");

}

float check_distance(int IRpin) {
 float volts = analogRead(IRpin)*0.0048828125;   // value from sensor * (5/1024) - if running 3.3.volts then change 5 to 3.3
 float distance = 30*pow(volts, -1.10);          // worked out from graph 65 = theretical distance / (1/Volts)S - luckylarry.co.uk
 return(distance);                               // http://luckylarry.co.uk/arduino-projects/arduino-using-a-sharp-ir-sensor-for-distance-calculation/     
}

// modes for the motor control
// convention here is modeXX - where X is F for forward, S for stationary and B for backwards
// first X is the left motor, second X is the right one
// for direction control, the LOW if forward and HIGH is backward
// for power control, LOW is off and HIGH is on

// all stop
void modeSS()
{
 digitalWrite(MotorDirectionR, LOW);
 digitalWrite(MotorDirectionL, LOW);
 digitalWrite(MotorPowerR,LOW);
 digitalWrite(MotorPowerL,LOW);
}

// move straight ahead
void modeFF()
{
 digitalWrite(MotorDirectionR, LOW);
 digitalWrite(MotorDirectionL, LOW);
 digitalWrite(MotorPowerR,HIGH);
 digitalWrite(MotorPowerL,HIGH);
}

// move straight backwards
void modeBB()
{
 digitalWrite(MotorDirectionR, HIGH);
 digitalWrite(MotorDirectionL, HIGH);
 digitalWrite(MotorPowerR,HIGH);
 digitalWrite(MotorPowerL,HIGH);
}

// spin left
void modeBF()
{
 digitalWrite(MotorDirectionR, LOW);
 digitalWrite(MotorDirectionL, HIGH);
 digitalWrite(MotorPowerR,HIGH);
 digitalWrite(MotorPowerL,HIGH);
}

//spin right
void modeFB()
{
 digitalWrite(MotorDirectionR, HIGH);
 digitalWrite(MotorDirectionL, LOW);
 digitalWrite(MotorPowerR,HIGH);
 digitalWrite(MotorPowerL,HIGH);
}

//main program loop
void loop()
{
 if (digitalRead(ButtonPin) == HIGH)
 {
 modeSS();
 delay(5000); // sleep for 5 seconds if button pressed.
 }
 modeFF();
 if ((check_distance(IRPinLeft) <20) && (check_distance(IRPinLeft) <20) )
 {
 //back up a bit
 modeBB();
 delay(1000);
 //rotate on spot for 2 sec (approx timing for 180 degrees)
 modeFB();
 delay(2000);
 }

 if (check_distance(IRPinLeft) <20)
 {
 // rotate on spot for 1 second (approx timing for 90 degrees)
 modeFB();
 delay(1000);
 }
 if (check_distance(IRPinRight) <20)
 {
 // rotate on spot for 1 second (approx timing for 90 degrees)
 modeBF();
 delay(1000);
 }
}

Video coming soon, I promise.

Power of the Arduino Dalek

It has been a while since I’ve messed with the Dalek project, so this is just a brief update of the minor twiddling I’ve done.

Firstly, the Dalek now has a USB Type B socket on the rear of the casing replacing one of the “Dalek Bumps”, as shown:

dalekusbAcquired from Maplin (part no N57FL), this USB Panel Mount Socket is reversible, with a Type A socket on one side, and a Type B on the other.

As a PC generally has a Type A socket, and the Arduino I’m using has a Type B socket, I opted to have the Type B on the outside.

This will allow the use of a normal A-B cable to connect between the PC and the case socket, and require a short A-B cable to connect between the case socket and the Arduino (as having a 3m cable curled round inside the thing seems a bit stupid).

Sadly, getting a short USB A-B cable isn’t easy. So I had to chop up an existing cable and butcher it.

usb-cable1

usb-cable2

Now, the Arduino can be left inside the Dalek case, which can be screwed shut again.

However, when the Arduino isn’t connected via the USB link, it loses power (tenuous link to the title of the post). Luckily, the Arduino Duemilanove that I’m using has a 2.1mm socket, and will run from a 9v battery.

So we need a PP3 9V battery clip, and a 2.1mm DC power plug.

powerparts

Solder the battery clip’s black wire to the outside connection of the plug, and solder the battery clip’s red wire to the centre connection of the plug.

For clearer instructions, and clearer pictures (I have a crap camera), see the relevant page at Arduino Playground.

powerlead

The yellow tape is not being used to hide a massive solder disaster this time, but merely to keep the wires together.

So, now I have a Dalek with a battery pack for the motors (from the original casing), a battery pack for the Arduino (ok, a PP3 taped inside), and a USB socket on the casing.

Now it can be programmed, unplugged, and be left to trundle into things.

So here is some code to make it wait for five seconds, spin right for one second, wait for two seconds, spin left for one second, and repeat for ever (or until the power is removed):

// Project: Dalek control system
// Version 0.2 - Sit and spin
// Tony Blews tony@tonyblews.co.uk

int MotorDirectionR = 10;
int MotorDirectionL = 11;
int MotorPowerR     = 12;
int MotorPowerL     = 13;
long randNumber;

void setup()
{
 pinMode(MotorDirectionR, OUTPUT);
 pinMode(MotorDirectionL, OUTPUT);
 pinMode(MotorPowerR, OUTPUT);
 pinMode(MotorPowerL, OUTPUT);
   randomSeed(analogRead(0));

}

// modes for the motor control
// convention here is modeXX - where X is F for forward, 
//S for stationary and B for backwards
// first X is the left motor, second X is the right one
// for direction control, the LOW if forward and HIGH is backward
// for power control, LOW is off and HIGH is on

// all stop
void modeSS()
{
 digitalWrite(MotorDirectionR, LOW);
 digitalWrite(MotorDirectionL, LOW);
 digitalWrite(MotorPowerR,LOW);
 digitalWrite(MotorPowerL,LOW);
}

// spin left
void modeBF()
{
 digitalWrite(MotorDirectionR, LOW);
 digitalWrite(MotorDirectionL, HIGH);
 digitalWrite(MotorPowerR,HIGH);
 digitalWrite(MotorPowerL,HIGH);
}

//spin right
void modeFB()
{
 digitalWrite(MotorDirectionR, HIGH);
 digitalWrite(MotorDirectionL, LOW);
 digitalWrite(MotorPowerR,HIGH);
 digitalWrite(MotorPowerL,HIGH);
}

//main program loop
void loop()
{
delay (5000);
modeFB ();
delay (1000);
modeSS ();
delay(2000);
modeBF();
delay(1000);
modeSS();
}

The next step will be to install some sensors.

 

USB Panel Mount Socket

Genesis of the Arduino Dalek

As previously mentioned here, I was recently given a broken toy Dalek, which I promptly took apart (in the name of Science).

Here it is before surgery commenced…

dalek-1

Having stripped the thing down, I found inside two perfectly good electric motors, and when you find two working motors inside a toy there is only one thing to do: Work out how to use a computer to control them!

So, figuring out that the easiest way of doing this was with an Arduino, I bought one.

I won’t bleat on about how good the Arduino is, or how easy it is to use. There are hundreds of sites that do that.

Instead, here is a list of things wot i dun to get a PC controlling the Dalek.

To start with, I think we’ll have a bit of circuit design. Below is a simple circuit that takes 2 inputs from the Arduino and runs a motor either forwards or backwards. One input decides the direction of the motor, the other whether it is on or off.

relay-circuit

All very nice and abstract, but to be of any use it’ll need to be built. The quickest and easiest way is on Veroboard. So here is the design for that:

relay-vero

The relays do the switching, and the diodes are there to protect the Arduino from back-emf currents when the relays toggle. Two of these circuits will be used, one for each motor. I built them on separate strips of board to make things easier for myself. This is what they look like when all connected up and dumped onto the Dalek chassis:

dalek-wired1

The small board in the top left of the picture is just a plug I bodged up to make connecting the thing easier.

The parts used are 4x 1A5VDC DPDT relays, 4x 1N4004 diodes, a 10×39 strip of Veroboard and some wires.

After all that soldering and burning my fingers, the next step is to write some code to make the thing move.

Each motor can be controlled to go backwards, forwards or stop. This gives nine possible movements, as this table shows:

dalek-matrix

And now its time to test this whole think by writing a program that takes keyboard commands (the letters in red, above) and sending signals to the circuitry to control the motors. Heres it is:

// Project: Dalek control system
// Version 0.1 - Written before my Arduino even arrived
// Tony Blews tony@tonyblews.co.uk

int MotorDirectionR = 10;
int MotorDirectionL = 11;
int MotorPowerR     = 12;
int MotorPowerL     = 13;

void setup()
{
 pinMode(MotorDirectionR, OUTPUT);
 pinMode(MotorDirectionL, OUTPUT);
 pinMode(MotorPowerR, OUTPUT);
 pinMode(MotorPowerL, OUTPUT);

 Serial.begin(9600);
 Serial.println("Serial control Dalek system starting...");

}

// modes for the motor control
// convention here is modeXX - where X is F for forward, S for stationary and B for backwards
// first X is the left motor, second X is the right one
// for direction control, the LOW if forward and HIGH is backward
// for power control, LOW is off and HIGH is on

// all stop
void modeSS()
{
 digitalWrite(MotorDirectionR, LOW);
 digitalWrite(MotorDirectionL, LOW);
 digitalWrite(MotorPowerR,LOW);
 digitalWrite(MotorPowerL,LOW);
}

// move straight ahead
void modeFF()
{
 digitalWrite(MotorDirectionR, LOW);
 digitalWrite(MotorDirectionL, LOW);
 digitalWrite(MotorPowerR,HIGH);
 digitalWrite(MotorPowerL,HIGH);
}

// move straight backwards
void modeBB()
{
 digitalWrite(MotorDirectionR, HIGH);
 digitalWrite(MotorDirectionL, HIGH);
 digitalWrite(MotorPowerR,HIGH);
 digitalWrite(MotorPowerL,HIGH);
}

// spin left
void modeBF()
{
 digitalWrite(MotorDirectionR, LOW);
 digitalWrite(MotorDirectionL, HIGH);
 digitalWrite(MotorPowerR,HIGH);
 digitalWrite(MotorPowerL,HIGH);
}

//spin right
void modeFB()
{
 digitalWrite(MotorDirectionR, HIGH);
 digitalWrite(MotorDirectionL, LOW);
 digitalWrite(MotorPowerR,HIGH);
 digitalWrite(MotorPowerL,HIGH);
}

// move forward left
void modeSF()
{
 digitalWrite(MotorDirectionR, LOW);
 digitalWrite(MotorDirectionL, LOW);
 digitalWrite(MotorPowerR,HIGH);
 digitalWrite(MotorPowerL,LOW);
}

// move forward right
void modeFS()
{
 digitalWrite(MotorDirectionR, LOW);
 digitalWrite(MotorDirectionL, LOW);
 digitalWrite(MotorPowerR,LOW);
 digitalWrite(MotorPowerL,HIGH);
}

// move backward left
void modeSB()
{
 digitalWrite(MotorDirectionR, HIGH);
 digitalWrite(MotorDirectionL, LOW);
 digitalWrite(MotorPowerR,HIGH);
 digitalWrite(MotorPowerL,LOW);
}

// move backward right
void modeBS()
{
 digitalWrite(MotorDirectionR, LOW);
 digitalWrite(MotorDirectionL, HIGH);
 digitalWrite(MotorPowerR,LOW);
 digitalWrite(MotorPowerL,HIGH);
}

//main program loop
void loop()
{
 if (Serial.available() >0)
 {
 char inByte = Serial.read();
 // this version uses the QWEASDZXC "square" on the keyboard
 // as my laptop doesn't have a numeric keypad
 switch (inByte)
 {
 case 'q':
 modeSF();
 break;
 case 'w':
 modeFF();
 break;
 case 'e':
 modeFS();
 break;
 case 'a':
 modeBF();
 break;
 case 's':
 modeSS();
 break;
 case 'd':
 modeFB();
 break;
 case 'z':
 modeBS();
 break;
 case 'x':
 modeBB();
 break;
 case 'c':
 modeSB();
 break;
 default:
 modeSS();
 break;
 }
 }
}

And with that done, I suppose all that is left to do is show a video of the bottom bit of the dalek trundling around under computer control…

… which have to wait until the next post.