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.

Monday, 9 May 2016

Microbit Sat-Nav

One of the features we added in a recent build of Sniff was support for a GPS module. These cost less than £10, and are really easy to hook up. However so far, I've only tested them at home. While that was initially exciting, it quickly became very boring, as I always got the same (pretty accurate and correct) reading for where my house is.

Note, this one has an integrated antenna on the board,
Many have an exteneral one which probably performs
better, but it going to be more fragile/tricky to hook up

Once I realised I could hook it up to a microbit, things got more interesting, as combined with the built in screen and compass we could build something that would be sufficiently portable to be viable. Unfortunatly when I hooked up the GPS to the microbit a few weeks ago it didn't work. The problem was that the Microbit is pretty slow, and couldn't keep up with the required maths and timing to process the data from the gps as fast as the gps was sending it. A helpful suggestion (and sympathic ear to my rambling DM's) from @whaleygeek sorted the bit timing, and once stuff started getting decoded I was able to optimise the handling of the data so the Microbit could keep up. The new GPS code will be in Release 28, or if you really can't wait, then drop me an email/DM (ian at dctsystems.co.uk, or @sniffCode on twitter). The code should also work on a Arduino with minor tweaks.

To hook up the GPS Module, connect 0v, and Vcc (it works find on 3v), and then connect "tx" to a data pin on the Microbit. There's also an rx pin which allows you to change settings on the GPS, but we shouldn't need to change anything, so we can ignore it.

make gps device D2
make longitude number
make latitude number

Here I tell Sniff there's gps plugged into D2. As we're only ever likely to have one gps device plugged in at the same time, I've not bothered to give it a name. You can miss out the names on devices and they just inherit the device name, so this is equivalent to :

make gps gps device D2

The gps is going to return out longitude and latitude in degrees. It can also give us the time/date, speed and heading, but we're not going to need any of those.

make deltaX number
make deltaY number
make distance number

when start
.set targetLat to 50.7429791
.set targetLong to -1.89716810
.
.forever
..tell gps to "update"
..set deltaX to targetLong-longitude
..set deltaY to targetLat-latitude
..
..set distance to sqrt of (deltaX*deltaX+deltaY*deltaY)
..if abs of distance < 0.001
...set deltaX to 0
...set deltaY to 0
..else
...set deltaX to deltaX/distance
...set deltaY to deltaY/distance
..wait 9.5 secs

This is the main script which updates the position every 9.5 seconds. I've pre-programmed in the location that I want to go to, and work out the direction I need to go in by subtracting my current position. This is incorrect. This would be right if the earth was flat, but long lat aren't cartesian coordinates, they're spherical polar. This will particularly break if you're traveling ling distances, or are traveling within the arctic circle. In either case I suggest you make more serious navigational plans! If you're in the UK and traveling normal distances then its close enough for a fun project... or you could look up the maths for doing this properly yourself - I just wanted to see if it would work at all!

We also approximate the distance, and divide the direction vectors by the distance so that they're normalised. We also check if the distance is very small, in which case we're there, and don't need to display anything.

Now lets make a compass and display:
make i2c device
make compass mag3110 device
make heading number

make display microbitDisplay device
make displayX number
make displayY number
make displayColor number

when start
.forever
..tell display to "tick"

All of this should be familiar - if not, check out our Microbit tutorials on using the compass and screen. We can now write another script that will run at the same time as the previous one, which do our drawing (this is a handy devision of tasks that is very "scratch-like").

make midX number 3
make midY number 3
make rX number
make rY number

when start
.forever
..tell compass to "read"
..change heading by -90
..set rX to (cos of heading)*deltaX-deltaY*(sin of heading)
..set rY to (sin of heading)*deltaX+deltaY*(cos of heading)
..
..set displayColor to 000
..tell display to "clear"
..
..set displayColor to 777
..set displayX to midX
..set displayY to midY
..tell display to "move"
..change displayX by midX*rX
..change displayY by midY*rY
..tell display to "draw"
..tell display to "flush"
..wait 0.1 secs

Now we tell the compass to read, and use the heading to rotate the deltaX/Y that we calculated in the previous script. We have to adjust heading by -90 so that North is at the top. This is just a quirk of the way the magnetometer is attached relative to the orientation of the screen. Then we just clear the screen and draw the rotated vector!


So how did it work out? Pretty well. The only issue is that reading from the GPS can take up to a second, as the simple device driver code just waits for the GPS to send it a message, which happens once per second. That's normally fine, but means the microbit display blinks off for half a second too. That's one of the reasons for only updating every 10 seconds.

I had a Sniff workshop (building robots) at the weekend and had someone in the car to check the microbit, so though I'd test it out on the way there (I did know where I was going, just in case). This is the first time I've used the microbit compass inside a metal box! Normally when you start using the compass you need to wave the microbit around, but that's a bad idea in a car, as you want it to learn the car's magnetic field as well as its own. That meant the car had to take few turns before the microbit settled down, but from then on it was pretty much spot on. We drove for about ten minutes, and by the end it was pretty solid. It even noticed when we drove past the destination to find parking, and started pointing backwards. It was really pretty good!

In the version I used I had another script which ran, checking the buttons so if you pressed one of them it would set the target location to be the current location - get me back to here, but you could pre-program several locations, and switch between them (great for geo-caching). When I googled for similar projects I found something called a "Jerusalem Compass", which is supposed to point to Jerusalem, but actually just points East - we've made a real one which can point wherever you want to!


No comments:

Post a Comment