Sniff is a "Scratch-like" programming language that's designed to help Scratchers move gently from Scratch to more conventional languages. They can start writing programs, without having to learn a new language because Sniff is based on Scratch. They learn a little more about variables, compiling, syntax errors (!), and they can have fun controlling real hardware while they're doing it.

Saturday, 17 May 2014

Building GCC for the Yun (in 12 not-easy steps)

The Arduino Yun is a pretty neat bit of kit and should make an ideal place to run Sniff. It has two distinct parts: what is effectivly an Arduino Leonardo, coupled with a Mips Linux host. The trouble is  the Linux side is based on OpenWRT. While this is an OK embedded Linux its designed to run on stuff like routers, where resources are tiny. The Yun processor has 64Mb of Ram, and a 400MHz MIPS processor. With the newly released "overlay" patch, it can (effectively) boot from the SD card, so it has at least 2GB of storage. While that may not sound like a lot, that's a slightly higher spec that the first MIPS machine I used, which supported about 20 users all at the same time. In that context there's no reason why we shouldn't be able to run the Sniff compiler on the Linux side, and have it program the Arduino side...

The rest of this post will be of NO INTEREST AT ALL to anyone who usually reads my blog. It may be of no interest at all to anyone in fact. It's aimed at hardcode Linux/Arduino hackers, with the hope they'll be able to reproduce,and improve on my results (its also essentially my notes, so I can reproduce the build!). This in turn makes Sniff on Yun even cooler!

If you're looking for cool educational computing stuff please just scoll past this.

The main catch to this is that there's no C compiler. Huh? a Unix machine without a C compiler? Well there is a C compiler somewhere, but not one which runs on the Yun. To generate code to run on the Linux side, you need to cross compile it on a different machine. To make matters worse it needs to be Debian Linux! Not that I've got anything against Debian, but it is quite specific...

Step 1: Install Debian in a VirtualBox VM.

I don't have a Debian machine (or a regular Linux machine for that matter - got a FreeBSD box, and a  bunch of Mac's - no the Pi does not count. This is taking several days on a Quad i7!). In any case its nice to have a clean install, just to be safe so I used VirtualBox on the Mac and installed the latest Debian.

apt-get install git subversion build-essential asciidoc \
    fastjar flex gawk libgtk2.0-dev intltool zlib1g-dev \
    genisoimage libncurses5-dev libssl-dev ruby sdcc unzip \
    bison libboost-dev libxml-parser-perl libusb-dev bin86 \
    bcc sharutils openjdk-7-jdk mercurial cvs bzr
The instructions for building on Debian can be found on github but they have a couple of glitches. the first is that it suggest installing the "npm" package. This doesn't exist in my version of Debian. I used the list above, and it worked fine...

Step 3: Clone the Repo


This works as per the instructs

Step 4: Build The YUN Linux OS


The again following the instructions on github don't quite work. They sort of work, but then it randomly crashes out. Restarting it seemed to "solve" the problem. It looks like a race condition, as the build tries to use multiple processes to build elements in parallel. I used the command:

make -j 1 V=s

which seemed to solve the problem. The build is still running after about 24 hours, which is actually a good thing!

Step 5: Check GCC cross compiler


At some point long before the build is complete it will make a working version of gcc that runs on Debian, but generates programs for the Yun!

To use it you need to add it to your PATH, and set up STAGING_DIR so that it can find includes and libs:
export PATH=$PATH:$HOME/Open-Wrt-yun/staging_dir/toolchain*/bin
export STAGING_DIR=$HOME/Open-Wrt-yun/staging_dir

Once you can compile a program:

mips-openwrt-linux-uclibc-gcc hello.c

produces a MIPS executable. You can move this over to the YUN with scp, then ssh and run it!!!!!


Step 6: add "cc"


This long and tangled process doesn't generate "cc" only "gcc". At some point we're going to need both (even though they're the same) so:

cd $HOME/Open-Wrt-yun/staging_dir/toolchain*/bin
ln -s mips-openwrt-linux-uclibc-gcc mips-openwrt-linux-uclibc-cc


Step 7: Download GCC


I went for 4.6.4... the cross compiler is 4.6.2, so I figured I'd stick with 4.6, but take a couple of bug fixes.

Download it and unpack it. Then download the "extra" bits it needs.
cd gcc-4.6.4
./contrib/download_prerequisites
cd ..
mkdir objdir
cd objdir

This also makes a directory to do the actual build in.

Step 8: Build GCC to RUN on Mips

$PWD/../gcc-4.6.4/configure --host=mips-openwrt-linux-uclibc --target=mips-openwrt-linux-uclibc --prefix=/gcc --enable-languages=c,c++

(we;re just building c and c++ as anything more will break later on) and finally 

make

This will crash after a couple of minutes: It turns out theres a REAL bug which affects gcc4.4 and later: it means we need to change mpfr/ mpfr-longlong.h.

#if defined (__mips) && W_TYPE_SIZE == 32

-#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7

+#if __GMP_GNUC_PREREQ (4,4)

+#define umul_ppmm(w1, w0, u, v) \

+  do { \

+    UDItype __ll = (UDItype)(u) * (v); \

+    w1 = __ll >> 32; \

+    w0 = __ll; \

+  } while (0)

+#endif

+#if !defined (umul_ppmm) && __GMP_GNUC_PREREQ (2,7)

 #define umul_ppmm(w1, w0, u, v) \

   __asm__ ("multu %2,%3" : "=l" (w0), "=h" (w1) : "d" (u), "d" (v))

-#else

+#endif

+#if !defined (umul_ppmm)

 #define umul_ppmm(w1, w0, u, v) \

   __asm__ ("multu %2,%3\n\tmflo %0\n\tmfhi %1" \

    : "=d" (w0), "=d" (w1) : "d" (u), "d" (v))

@@ -1034,10 +1043,20 @@


 #endif /* __mips */


At some point during the build of the standard C++ library you'll get an error about fenv.h being missing. This isn't needed so find the relevant include file, and just comment out the include.

Step 9: Install

make install

to "install" it on the Debian machine - if course this doesn't work, but it makes the files. It's set to install in /gcc, so once that's done, tar it up and scp it to the Yun.

You also need binutils. You can either build them (exactly the same way as we built gcc, using the same configure options), or install the pre-built package. I tried both... Not sure if they both work, but I ended up building it myself, and copying it over with gcc.

Step 10: Add the Libraries

You've now got a compiler, but you need includes and libs. Fortunatly we've already built them as part of the OpenWRT build (which has now failed completely trying to make a JavaScript VM - I guess you do need npm for that bit). Copy include and lib from them OpenWRT build on Debian onto the Yun, and put them in /gcc

Step 11: Fix the Libraries

No idea what's going on here, but a bunch of really important files ended up in the wrong place. Fix it with:

cd /gcc/lib/gcc/mips-openwrt-linux-uclibc/4.6.4
for i in ../*.o ../*.a
do
ln -s $i .
done


Step 12: Enjoy!

export PATH=/gcc/bin:$PATH
gcc hello.c
./a.out

You'll get a warning about hard and soft floats. Looks like there's a config error in the compiler, as the Yun doesn't have an FPU, which is going to break a lot of stuff. I need to go back around and start over to fix this, but in the mean time

gcc -msoft-float xxx.c

is a pretty good work around.


Step 1A: Alterative Approach

I deliberately built it to live in the /gcc folder, so you could tar it all up and make it easy to install:

You can download it here.

Gunzip and untag it so that its in /gcc. You'll either need to have turned on the "overlay" expanded file store (so the SD card is holding everything -recommended), or unpack it to the SD, and add a link. Add /gcc/bin to your path.

You might also want to install make with:
opkg update
opkg install make

Conclusion and Disclaimer

It's currently almost completely untested - I've compiled hello world! It works. It could do with being improved. There's a couple of bodges in there, but this is really a proof of concept, and a stop gap until someone integrates all this into the proper build. You can compile C on the Yun, and while the above process is pretty tortured, I managed to get it working in a couple of days. An experienced Linino/OpenWRT/GCC+ hacker should be able to make sense of my notes, and produce something better in a fraction of the time.

Hopefully now we can get past the "it can't be done"stage, and actually make this thing useful...

Thursday, 15 May 2014

SniffBot Part 3: Which way are we going?

In the last SniffBot post we were left with the final piece of code:


#What should go in here?
when start
.forever if not manualMode
..set leftDrive to 0
..set rightDrive to 0
..broadcast updateMotors
..wait 0.05 secs

When we flip the switch on RC transmitter, the joysticks are disabled and the car goes into non-manual mode. In this version of this that just means the car stops both sets of motors, and waits until the driver decides to take over again. Anyone who's ever built a robot will appreciate that this is more than just a place holder - being able to reliably stop a robot dead in its tracks is actually a very useful feature.

If we wanted to do some kind of line following it would go in this part of the code. However I had something else in mind... To get a robot to keep track of where it is you either need to have some absolute positioning system (like GPS), which is a bit tricky, or a relative positioning system: I know where I started, I know which way I'm pointing and I know how far I've gone so I know where I am now.

The "how far have I gone" is generally done by counting wheel rotations (10cm diameter wheel, turned 4 times... how far have I gone? Maths in action!). Having a four wheel drive robot is actually a disadvantage here, as its best to run this from a non-driven wheel, so you know if the robot is stuck and driving wheels are just slipping. I've not put the sensors on Sniffbot for this one yet so we'll leave that for another day...


Instead lets address the "which way am I going problem". To do that we use a compass! You can pick up an HMC5883L board for a couple of pounds on Ebay, and it plugs straight into a Arduino via i2c (a 3v one should work, but probably best to get one that is explicitly 5V tolerant). Fortunatly (or by careful design) the motor shield doesn't use the analog pins, so the i2c interface on the Uno's A4/A5 pins is free.

With that plugged in we can measure the magnetic field around the robot:

make i2c device
make magnetometer device
make xMagneticField number
make yMagneticField number
make zMagneticField number

when start
.forever
..tell magnetometer to "read"
..say [ xMagneticField ]
..say [ yMagneticField ]
..say [ zMagneticField ]
..say ""
..wait 3 secs

We can use the field strings in each direction to form a vector which points North-ish. Magnetic North can be remarkably different from true North, and its quite interesting to find out out more about it but as our robot probably isn't travelling 100s of miles we can don't really need to worry about it. Taking the inverse tangent  of x/y will give us the heading of our robot.

As this is such a common thing to do (I'm sure there are experiments you can do with a magnetometer, but most of the time we want a compass) we can use the compass device to provide a simpler interface to the magnetometer:

make i2c device
make compass device
make heading number

when start
.forever
..tell compass to "read"
..say [ heading ]
..wait 3 secs

To integrate this into our existing code for SniffBot I just replace the existing "auto" behaviour with:

make i2c device
make compass device
make heading number

when start
.forever if not manualMode
..tell compass to "read"
..set leftDrive to -10*(heading/180)
..set rightDrive to -leftDrive
..broadcast updateMotors and wait
..wait 0.01 secs

Now when you switch out of manual mode the car immediately orients itself to point North. If you try this you'll probably see that sometimes he rotates too far, and then corrects. This is a "control theory" issue, and is way outside the scope of anything I ever want to think about again, so depending on your motors you may need to tweak the timings and scale factors to get nice reliable orienting.

Moding this code to point the Robot in a specified is easy enough (and left as an exercise for the reader!).

You might find that depending on what code you add that this pushes the limits of what an Uno can handle: we're running lots of things at the same time, on a slow machine, and some of those things are very timing critical. Particularly accessing i/o devices like the compass can be slow, which in turn can mess with the timings of the RC receiver signals. When this happens you'll start to see juddering. So far I've been able to weak things and adjust the delays on low priority tasks to keep things running smoothly.


Wednesday, 14 May 2014

Text Adventures in Sniff

Last week I went on the Year 2 school trip and spent a fun (and tiring!) day helping 7 and 8 year olds draw maps of the beach and park. There was also an article going around online about someone who'd ported the Zork engine to Arduino. Seeing the four walls of the classroom labeled N/S/E/W got me thinking about putting that all together and thinking about text based games in Sniff.

Text based games run at a slower pace than video games, and encourage discussion and problem solving rather than just blasting. You actually have to read stuff, and I've still got old notebooks with maps for most the Level 9 games. I wasn't that great at the games but I did love drawing the maps.

I also wrote a bunch of adventure games for the BBC Micro. One called Atlantis (which made up in size what it lacked in quality), was co-authored with a less techy kid from school who was into the games, and did most of the text, while I focused on the core code, and trickier parts of the game logic. The best one I wrote was based on the book "Help! I'm a prisoner in a toothpaste factory" by John Antrobus (It's great - read it!), and featured some pretty impressive mode 7 graphics loaded from floppy disc (I wrote a mode 7 paint package to generate the images!). The last BBC Micro effort which never got past the engine stage used an AMX Mouse to click icons for each action. At Uni I moved on to Sun workstations, and one of my side projects for a number of years was a multi user adventure.

You can use text adventures with kids in a bunch of different ways - start by just letting them play (it's reading!), and pretty soon they'll start making maps of the game world. These are "topological" maps as they connect rooms together rather than (necessarily) making an coherent 3D space (they may even be directed graphs if you want to explore that idea!). From there they can make topological maps of a real place.

Once you've got a "map" its pretty easy to put that into a game engine. You can do this without writing any code, though it does require careful planning and organisation. Any adventure game will basically have a core engine which lets you walk round a map, and manipulate basic objects. The idea is that this handles 90% of the interactions, and then specific code is added to handle the actual progress through the game (if you're on the space ship with the ham sandwich, then the elephant will share his lunch with you).

Lets start with the basic stuff: back in the "old days" we had to squeeze adventure games into 16K of memory, but now we can just store all the text in files, and we can make the games as big as we like. In the Sniff Adventure Engine (SAE!), start by making a folder called "rooms". Give each room on your map a number, and then for each of them create a file named 1.txt, 2.txt, 3.txt and so on with a description of the room. These descriptions get displayed every time you enter that room.

The next step is to connect the rooms up. Also in the rooms folder are files called 1.dat, 2.dat etc. These contain the rooms that will you will go to when you move N,S,E,W,Up,Down from the room. For example the first line of 1.dat indicates what happens when you go north from room 1. There is no room zero, so a zero means you can't go in that direction.

There's also a folder for objects, which contains a file called startInfo.txt. This contains pairs of lines, giving objects names and the rooms the can be found in. For example:

lamp
2
pen
0
sword
4
elephant
999

makes lamp object number 1, and places it in room 2. The sword (object number 3) is in room 4. As previously noted there is no room 0 so that means the player is carrying the pen. In the objects folder there's also a file lamp.txt which contains a description of the lamp (and similarly for there objects).

Just by creating these files, we get to make a world that we can walk around in (It's like minecraft with words!). While I've described the steps in sequence, in practise you'd probably want to develop small areas of the game, and play test them before moving on to the next area.

Just getting this far with a project, we've done mapping, lots of organisation and file management, team working, and descriptive writing. If you're working in a group you've probably had some heated debates. You could make a virtual school, or you could tie this into a book the class is reading: What are the places in the book, how are they related, are there key events or objects (what's the MacGuffin?).

That's before we've even started coding! It's really important to tie together things like descriptive writing, and story telling with technical subjects. We all remember counting how many pieces of cake the hungry caterpillar ate! Computing (or maths) is a tool for doing things, so projects should do interesting things, rather than just learning a technique.

You can download SAE along with an example game, which has 7 rooms and 4 objects. There are two versions of the engine included: adv.sniff is the generic game engine which you can use to walk round maps, while demo.sniff contains a simple example with a couple of puzzles. As written it won't run on an Arduino, as it use native file access, and in any case all that string handling eats memory, so run it on a Pi, Mac or Linux machine.

This has turned into another multi-part post, as this si getting a bit long, but in a future post I'll explain how SAE works internally, and how you can add your own puzzles. In the meantime, please leave a comment, and let us know if you're using games like these.

Tuesday, 13 May 2014

Back to the Screen (Part 1: Text)

One of the cool things about Sniff is getting away from computer screens - we have screens everywhere, and we're bored of them. When I got my first computer we plugged it into the family TV, and I typed in the BASIC code to display my name on the screen. If you weren't "there", then its impossible to explain how big a deal that was. TV was the  only screen we had, and it was controlled by "the powers that be". To control what appeared on screen was incredibly subversive. It's not too big a leap to claim that those were the first steps in democratising video distribution, not just technically but politically.

The problem now however is the exact opposite - access to screens is ubiquitous. No kid makes it to Reception without having seen their name on a screen. That's why physical computing is important in getting people to engage with computers. The screens that made those old computers special make contemporary systems dull. To get people excited about something you need to show it to them NOT ON A SCREEN.

However sometimes you need to display some information, and you've considered every other option - LED's, buzzers, neoPixels? Say and Ask are quick and practical ways of getting info back to the programmer but they are SO DULL...

All is not lost though - even if you need to attach a screen it doesn't have to be a boring screen. The simplest screen you can attach is a text LCD. These can display text pretty nicely, are cheap and easy to use, and don't require plugging your system into a boring monitor.

The easiest way to use an LCD is to get a prebuilt shield or Arduino, and just plug it in.
These are pretty common, and provide a 16 column, 2 line display. As such they're perfect for displaying the results of experiments like the Hot Wheels Speed Trap.

make lcd device
make message string

when start
.set message to "hello"
.tell lcd to "show"

To display a message just assign it to the string message, and call "show". Messages appear on the bottom row, and scroll up.

Connecting an LCD directly like this is cheap and easy (on an Arduino), but more problematic on a Pi where GPIO pins are in short supply. It would be pretty easy to adapt the lcd device to work on Pi, but a better option is to use an LCD display with an attached i2c i/o expander.  I2c allows you to talk to lots of devices using only 2 i/o pins so these are both easier to hook up and leave more pins free for other things (though they're a little more expensive, and a bit slower).

Unfortunatly different manufacturers configure their boards slightly differently. If you find your's doesn't work, check its specification, and compare it to the first few lines of the file SNIFFDIR/lib/Xlcdi2c.c. The code is currently set up for a 20x4 display, connected with a Funduino expander board. Other boards are functionally identical, but need a few minor tweaks - I can only work with the hardware I have, so if you have a different board it would be great if you could send me the config data you used, and I'll add it in.

Once you're set up though, you can use the i2c lcd just as you would a regular display:

make i2c device
make lcdi2c device
make message string

when start
.set message to "hello"
.tell lcdi2c to "show"


LCD's are a great way to display data without putting it on a monitor, but for more bling (or impact if you prefer, but we know you mean bling) you need LEDs - the more the better.

The simplest form of LED display (other than an LED!) is a 7 segment display. You can buy them a digit at a time, but the problem is they use a lot of pins so to do anything useful you need a driver board. The simplest is the 7Seg for Pi which is totally trivial to use, and only requires 2 pins. If you need more digits then you need something like these. I've not got my hands on one yet, but they should be really easy to code for...
However 7 segments isn't enough to display text - for that we need either a 14 or 16 segment display. Sniff has a driver for these 14 segments displays, but its currently untested - I had to go and order the blue one which is out of stock. I'll blog it in detail when it arrives, but the basics should be pretty obvious by now:

make led14seg device
make message string

when start
.set message to "hello!"

.tell led14seg to "show"



For a REALLY impressive display you need an LPD8008 (or two). These are bitmap displays, but they're ideal for displaying BIG text. There's lots of info in the previous blog post (and it should work on Arduino and Pi).

While this isn't the most exciting post, that's really because its only part 1. I wanted to post about drawing graphics, but ran out of space... I'll cover graphics in parts 2 (and 3?).

Monday, 12 May 2014

SniffBot Part 2: RC Control

In a previous post I talked about how SniffBot was wired up to provide basic Arduino control over the four wheels, making it simple to write code made the car move around. However anyone who's coded robots knows that they have a habit of "doing their own thing" now and then, at which point you end up chasing them round the room, trying to grab them and find the off switch. One of the things I wanted to add was to an RC unit so I could take manual contral to bring it back home. It's also just great fun to drive the car around under RC control, and driving SniffBot around the hall was a popular activity at a recent STEMNet meeting.

Gettiing an RC system is a bit of an investment, but the good thing is that once you've got a transmitter you can buy additional receivers fairly cheaply. Planet T5 transmitters (packaged with a single receiver) cost around £65, but as I already had a couple from previous projects I just added an extra "R6m" receiver to make SniffBot RC-Ready.

RC Receivers like these encode the position of the joysticks in a format ready to plug directly into a Servo. Each channel has three pins: Ground, 5V(ish) and Signal. There's also a power-in connector, so that the receiver can distribute power to the servo's.

By happy coincidence the Motor Shield on the SniffBot has two headers for plugging in Servo's which use the same format. They're "intended" to be outputs, but they work just as well as inputs, so we can just connect the Shield and Receiver using a couple of 3way DuPont cables (these are horribly expensive from RC shops, but you can get them for pennies from China). These also provide power to the receiver. I plugged them into channels 2 and 3 which correspond to the right joystick (channel 1 is traditionally the "accelerator": left joystick front/back, though it depends how your transmitter is configured).

Servo's are controlled by a pulse that the receiver sends to them every 50th of a second or so. The position is controlled by the duration of that pulse, which should be in the range 1-2mS. We therefore need to wait for the pulse, start a timer, then wait for the pulse to end, and record the time. 

make forwardBack digital input 10
make j1startTime number
make joystick1 number

when start
.forever
..wait until forwardBack
..set j1startTime to timer
..wait until not forwardBack
..set joystick1 to timer-j1startTime
..set joystick1 to ((joystick1*1000)-1.5)*2
..if joystick1 <-1 
...set joystick1 to -1
..if joystick1 >1 
...set joystick1 to 1

Having recorded the time in seconds, we convert to milliSeconds and take away the average value (1.5). We should now have a value between +/-0.5, so we double that to get a value between -1 and +1 which we can use in future calculations. There's also a couple of checks to make sure that the value we have is in range.

If we were doing this in Python or C we'd need to be make sure we don't "miss" a pulse while we're doing some other calculation, but in Sniff we just use the above code as-is, and let it run forever. It updates the value of joystick1 whenever theres a new pulse. To decode the second joystick, just duplicate the code, but reading from a input 9.

when start
.forever 
..set leftDrive to joystick1
..set rightDrive to joystick2
..broadcast updateMotors
..wait 0.05 secs


Having got the position of the joysticks the simplest thing do to is to assign one joystick to each set of wheels, and do some driving. This is called tank steering, and works OK if you use the two forward/back sticks to control each side, but we can do better...

To make the car drive from the two channels of a single stick, with forward/back, left/right controls we need to calculate the power we should be sending to each set of wheels. In the RC world this is done with a V-Tail Mixer - a surprisingly common component, as its also used to control the ailerons of RC planes.
The maths behind v-tail mixing is at the same time totally trivial, and completely non-obvious:


when start
.forever 
..set leftDrive to (joystick1+joystick2)
..if leftDrive>1
...set leftDrive to 1
..if leftDrive<-1
...set leftDrive to -1
..
..set rightDrive to (joystick1-joystick2)
..if rightDrive>1
...set rightDrive to 1
..if rightDrive<-1
...set rightDrive to -1
..broadcast updateMotors
..wait 0.05 secs

One side gets the sum of the two joysticks and the other gets the difference (its worth going through it yourself to figure out why this works, but it does). You may find your car drives backwards and/or steering is inverted when you try this. The Planet transmitter has a set of switches under the perspex panel which let you reverse the polarity of the joysticks, or you can fix it in software.

Here's the complete code:
#a fly-by-wire RC car...

######first read the RC input
######to get the two joystick values
######and a mode switch

make forwardBack digital input 10
make j1startTime number
make joystick1 number

when start
.forever
..wait until forwardBack
..set j1startTime to timer
..wait until not forwardBack
..set joystick1 to timer-j1startTime
..set joystick1 to ((joystick1*1000)-1.5)*2
..if joystick1 <-1 
...set joystick1 to -1
..if joystick1 >1 
...set joystick1 to 1


make leftRight digital input 9
make j2startTime number
make joystick2 number

when start
.forever
..wait until leftRight
..set j2startTime to timer
..wait until not leftRight
..set joystick2 to timer-j2startTime
..set joystick2 to ((joystick2*1000)-1.5)*2
..if joystick2 <-1 
...set joystick2 to -1
..if joystick2 >1 
...set joystick2 to 1

make modeSwitch digital input 2
make modeStartTime number
make manualMode boolean
when start
.forever
..wait until modeSwitch
..set modeStartTime to timer
..wait until not modeSwitch
..set manualMode to (timer-modeStartTime)>0.0015




##### NOW CONTROL THE MOTORS #####
make leftDrive number
make rightDrive number

make motorController device
make motor1 number
make motor2 number
make motor3 number
make motor4 number

when updateMotors
.set motor1 to leftDrive
.set motor2 to leftDrive
.set motor3 to rightDrive
.set motor4 to rightDrive
.tell motorController to "update"


##### USE THEINPUTS TO CALCULATE leftDrive and rightDrive
when start
.forever if manualMode
..set leftDrive to (joystick1+joystick2)
..if leftDrive>1
...set leftDrive to 1
..if leftDrive<-1
...set leftDrive to -1
..
..set rightDrive to (joystick1-joystick2)
..if rightDrive>1
...set rightDrive to 1
..if rightDrive<-1
...set rightDrive to -1
..broadcast updateMotors
..wait 0.05 secs

#What should go in here?
when start
.forever if not manualMode
..set leftDrive to 0
..set rightDrive to 0
..broadcast updateMotors
..wait 0.05 secs

This final version also adds a kill switch. The switch on the shoulder of the Planet transmitter transmits on channel 5, so I hooked that up in pin 3 - the one unused digital pin on the Motor Shield, and added code to make that control a boolean: manualMode. Now if we're in manual mode we use the joysticks to control the motors, but otherwise we set the motors to 0. Now we can halt our runaway robot with the flick of a switch.

In a future post I'll show add some smarter code in here so the car can execute tasks by itself (you could add line following code here), and when it decides to misbehave you can flip the switch back to manual and drive it back to base for repairs! No more chasing your robot round the room!

Friday, 2 May 2014

Hosting Arduino Sniff on Pi

The Sniff compiler can be run on Mac, x86 Linux and Raspberry Pi, and (obviously) if you compile your programs on a Mac, they can run on a Mac. However the compiler can also TARGET Arduino. The two main systems used for development are compiling on Mac to run on Arduino, and compiling on Pi to run on Pi. However until now there's been one "gotcha"...

About 18months ago the Arduino developers released the Arduino 1.5 Beta software. Sniff requires this version as it includes support for Due and Yun, and quite simply its going to replace the 1.0 version, so why support the old version? All would be fine, except that its still  in beta, and the Raspberry Pi team are still bundling the old 1.0 release. There's no easy way to run the 1.5 release on Pi, which means while Sniff runs great on the Pi (and you can control the GPIO), you couldn't program an Arduino in Sniff on a Pi.

Ideally Arduino would just announce that 1.5 is not "released", Raspberry Pi would bundle it into Raspian, and we'd be ready to go, but in the mean time there's a hack... The Arduino software consists of three parts:
  • The IDE
  • The Compiler Toolchain
  • The Arduino/Wiring Source Code/Headers
The trick is that for Sniff we don't care about the IDE, we have a perfectly good set of compilers which came with the 1.0 release and run on Pi, and a bunch of Arduino code, which runs on the Arduino, so which is the same on all platforms, so doesn't need changed for the Pi.

To get this working, first install the standard Pi IDE with:
sudo apt-get install arduino

You've probably done this already. This puts everything in the folder "/usr/share/arduino".

Now we've got our toolchain, you need to download the PC or Mac version of the latest 1.5 IDE, and unpack it. Somewhere inside that you'll find a folder which looks a lot like the one you have. The bit we're interested in is in a sub-folder called "hardware".

In /usr/share/arduino/hardware you already have is another folder called "arduino" (along with a tools folder you shouldn't touch). Rename that arduino folder to arduino1.1 (in case we need it again), and then copy the corresponding hardware/arduino folder from the new 1.5 release to /usr/share/arduino/hardware/arduino1.5. Finally link the new 1.5 folder to the name arduinio:

cd /usr/share/arduino/hardware
ln -s arduino1.5 arduino

This will almost certainly break the Arduino IDE, so if you need to use the IDE again, link the arduino folder back to arduino1.1. However with the link changed to 1.5 you can compile Sniff programs against the Arduino 1.5 library using on a Pi!!!!

#SniffBot Part 1

Blame Tom for the name - he called it SniffBot, when he posted a pic of it on twitter next to his PiBot.

Now we've got that out of the way - lets build a robot!


SniffBot starts out as an insanely cheap chassis kit - bought from China via Ebay (http://r.ebay.com/QeWdGR). Seriously £16 for chasis, motors and wheels. You can barely get a good set of wheels for that price! The only negative I can say is that while it comes with shaft encoder disks it doesn't come with the IR sensors to use them - OK that would make it more expensive, but presumably the chassis is sized and cut to fit a specific sensor, but we don't know which one! It's got for separate motors, for independent 4 wheel drive which is a nice option even though I've not done anything with it specifically. There are cheaper two wheel versions, but its nice to have a good solid platform to work on, and this thing doesn't get stuck easily!

While a lot of people seem stuck on Raspberry Pi robots, its really not the way to go! Arduino is a fraction of the price, but it also does a better job. The Pi's designed to be driven from mains, so you need to rig a power supply, and it better be a big one to supply around 1A to the Pi. The Arduino has a built in regulator (so you can plug a battery straight in) and uses a fraction of the power, so we can use smaller batteries and/or get better performance. The Arduino also has more I/O so we can control more stuff, and its going to be able to handle the timing requirements we need.

Step one is to build the chassis (adults may need assistance from a small child with a lego obsession to follow the instructions, and handle the small screws!), and then we can drop an Arduino on top. I ditched the supplied AA batter box in favour of a NiCad pack I had. To drive the motors we need a Motor Shield, which you can pick up for about £3 (on Ebay again  - search for L293D motor shield).

These are based on a design originally by AdaFruit, but they've replaced them with a better (more expensive!) design. Sniff supports this old one, which can drive four motors independently. I wired the left wheels to channels 1 and 2, and the right to 3 and 4. We actually only need a two channel board, as we could easily hook two motors up to each channel, but as we have the hardware, we might as well use it - one day we might add traction control! 

There's a (in this case Yellow!) jumper on the board which controls power. I connected the batter back to the power terminals on the motor shield, and left the jumper on, so that the shield is also powering the Arduino. This also means that when you connect USB, the USB will try and power the motors, which isn't such a great idea, but is OK for these little motors. If you're using more powerful motors, which use more than the 5(ish)V that I get from my small batter pack, then you should remove the jumper, and connect a separate battery pack to the Arduino directly.  Then you can safely connect a larger (and/or higher voltage) battery pack to the shield. Having separate power systems also helps with interference - CPU's don't like motors near then, but in this case I've had no problems.

Once that's hooked up we can make this thing move!

make motorController device
make motor1 number
make motor2 number
make motor3 number

make motor4 number

when start
.set motor1 to 1
..tell motorController to "update"

To drive a motor, just make a motorController device, and four variables to control each motors speed.  Set each variable to a value between -1 and 1, and tell the controller to update. At this stage you'll probably want to go through and turn on each motor in turn, checking that they're connected as you think they are, and that 1 is forwards and -1 backwards (switching the red and black wires as appropriate).

Once that's sorted out, we can write a script to drive each of the pairs of motors at once:
make leftDrive number
make rightDrive number
when updateMotors
.set motor1 to leftDrive
.set motor2 to leftDrive
.set motor3 to rightDrive
.set motor4 to rightDrive
.tell motorController to "update"

To make the SniffBot do the "PiBot Dance":

when start
.forever
..set leftDrive to  sin of (timer * 100)
..set rightDrive to  cos of (timer * 100)
..broadcast updateMotors and wait

You've now for a working SniffBot for under £30, including Arduino, Chasis, Motors/wheels, Batteries and Motor Controller. It does everything PiBot can do, and as I'll show in the next post we can use it as a platform for even more fun...