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.

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.


No comments:

Post a comment