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.

Friday, 28 March 2014

Traffic Lights

The PiBrella is designed for doing traffic light simulators, with a nice button and three big, appropriately coloured LEDS, so lets write the code that it was designed to run:

The first step is to set up all if IO devices. In the Python library that's recommended for the board, there's a lot of functions, and code to handle the i/o, but as I've been finding out as I've written more Sniff programs, Sniff is a surprisingly self sufficient language. Things like audio, and controlling servos which need their own libraries in C/Python are actually really easy and fun to code in Sniff. The same here, we just need to define the pins, and we're good to go:

make redLight digital output 27 #21 on rev 1 Pi
make amberLight digital output 17
make greenLight digital output 4

make Ain digital input 9
make Bin digital input 7
make Cin digital input 8
make Din digital input 10

make Eout digital output 22
make Fout digital output 23
make Gout digital output 24
make Hout digital output 25

make button digital input 11

make buzzer digital output 18

We can just drive them straight from Sniff, without anything extra, so lets get on with our traffic light. There are a few slightly different sequences we could use, but lets choose the traditional Pelican Crossing sequence: Its green (until the button is pressed), then goes to Amber for a couple of seconds, then Red for slightly longer. It then goes to flashing Amber before starting round again. Leaving the timing aside we can see it moves through 4 states:
  1. Green
  2. Amber
  3. Red
  4. Flashing Amber
so lets get them working first.

The great thing about Sniff is we can handle each light separately, by creating a bunch of separate scripts all with the same trigger:

make state number

when update
.if state = 1
..set greenLight to on
.else
..set greenLight to off

when update
.if state = 3
..set redLight to on
.else
..set redLight to off


We're going to broadcast an update message, and when that happens if we're in state 1 the green light is going to turn on, otherwise its off. If we're in state 3 the red light turns on. Amber is a little more compex:

when update
.set amberLight to off
.
.if state = 2
..set amberLight to on
.
.if state = 4
..forever
...set amberLight to on
...wait 0.2 secs
...set amberLight to off
...wait 0.2 secs


We start by turning it off - that takes care of states 1 and 3. In state 2 we turn it on, while in state 4 we go into a loop blinking it on and off. You might be slightly worried that state 4 never finishes the script, but in Sniff (and Scratch) a new broadcast message restarts the script, so the next "update" will get us out of that infinite loop.

Handling the button is a little subtle: we're actually not interested in if the button is being pressed, but rather if it has been pressed, so we add another script to keep an eye on the button:

when start
.forever
..if button
...set buttonPressed to yes

If the button is pressed we record that it has been pressed. The only problem with this is that the nice red button on the Pibrella board does't have a pull down resistor. In Python we can use the internal pull downs, but there's no way to code that in Sniff - its a concept which doesn't really fit in the Sniff model cleanly, so I made a simple mod to my board to add one. Without it the button may "press itself" without warning!

In the Cellular Automata post a few days ago, I talked about Top Down Design, where you write your code as if all the scripts you need already exist, then fill them in. In this case we've done the opposite - we've built the low level code first: Bottom Up Design, because we knew that we needed to be able to make the lights cycle, but exactly how is a bit trickier. Now we've got the low level stuff going we can worry about the control of the cycle.

when start
.forever
..set state to 1
..set buttonPressed to no
..set startTime to timer
..broadcast update
..wait until buttonPressed and (timer - startTime)>10
..
..#Amber
..set state to 2
..broadcast update
..wait 2 secs
..
..#RED
..set state to 3
..broadcast update
..wait 5 secs
..
..#Flashing Amber
..set state to 4
..broadcast update
..wait 2 secs

Now the low level stuff is in place, we can write a nice clean control script. We start by setting state to 1 (green light), and record that the button hasn't been pressed. We also record the time, and broadcast an update to kick off all the light scripts.

Now we "wait" until the button has been pressed, and the time since the light went green is greater than 10 seconds. This is quite nice, as it means if the lights have just gone green we keep them green for a minimum period, but if the traffic has been moving freely for a long time, we give priority to the pedestrian. In fact this is the most tricky bit, but because we've already got the little pieces working nicely we can just put them together to make it do exactly what we want.

From then on, we simply move through each of the states one at a time, before returning to state 1, and doing the whole thing over again.

Another important concept in Software Engineering is "programming in the problem domain". This is a fancy way of saying that if we're writing a program about traffic lights, at the top level (in the main script) is should look like we're writing about traffic lights. Looking at this script it does a pretty good job. How hard would it be it add a second button? Add a "fire engine override" which shortcuts the lights back to green? What if we wanted a red/amber state instead of flashing amber?

My finished version also includes code to handle the buzzer - check the Sparkfun Inventor Kit for a discussion on how to make sounds, and then combine that with another script rather like the Amber light script.

I could certainly code all of this in C or Python, but it wouldn't look as pretty. Too many programmers think that writing clever or difficult code makes them good programmers. It doesn't. Writing simple and obvious code to solve clever or difficult problems makes you a good programmer. Hopefully you can look at this code, and think its simple and obvious. In that case, I've done my job... Next time you look at someones code and can't figure out what it does or how it works, then don't assume they're better programmers than you - if they were then you'd look at their code and think "that's really clear and obvious"

Thursday, 27 March 2014

PiBrella

I read somewhere that the Raspberry Pi  is the stone in the stone soup. It doesn't actually add anything itself, but is a catalyst which attracts attention, to which the real ingredients like Scratch are quietly added. Sniff plays along with that, because we want good things to happen, and the Pi gives us a pot of boiling water to jump into (to drag the metaphor along slightly further than is really appropriate).

However the Aruduino platform has a lot of advantages over the Pi for interacting with hardware. To effectively use the GPIO you need a breakout board of some kind, which is clunky. You then need to work around all the different pin numbers, which aren't in any kind of sensible order, or even abstracted on a consistent way. Just to make it more fun there's a handy 5V or "blow up my Pi" pin to connect to. It's certainly possible to blow up an Uno in innumerable fun and original ways, but they're a bit tougher, and when you blow up an Uno, worst case its a $10 replacement, or you can probably just replace the CPU (it's socketed!) for less than $5.

While some things can't be fixed (like unpredictable timing, and power consumption) the PiBrella board looks like it actually does a pretty good job of solving a lot of the physical problems of Pi interfacing. The PiBrella is clear aimed at kids, providing a red, amber and green LED, a buzzer and a big red button, so they can write a great traffic light simulator.

However it also has 4 buffered outputs (with external power available to drive "big" stuff), and 4 protected inputs. They're clearly labeled (A to H), and with nice sockets to poke jumper cables into. Even better there are 8 surface mount led's to indicate the state of each pin... now that is handy. I also like the fact it plugs straight into the Pi without a ribbon cable, so the whole things in one package rather then being spread out over the desk.

There's an i2c header too, conveniently layed out with all the required signals in one place (though there are no pins soldered in, and it's a non-standard spacing [expletive deleted]). I2c, 8 i/o ports and a few LEDS and buttons looks like a really sweet spot which can cover most projects. While the PiBrella is clearly designed to be a kids first steps into physical programming, it's actually a pretty grown up bit of kit.

For advanced users there are a few niggling issues: To fit all the pre-wired LED's and the i/o ports on the board they've had to use the SPI pins as generic i/o's so SPI won't work with the board plugged in, which is disappointing - looking at the pin usage suggests they might have been able to make this work if they'd allocated the pins differently. Also because all of the i/o pins are buffered that's going to mess with things like the DHT11, and DS One Wire devices which use a single pin for both input and output.

Having gone to all the trouble of laying everything out so clearly, its annoying that the i/o pins are arranged in pairs which are simply labeled + and -. In fact for the inputs, the + is Vcc, and the - is the actual input. I can see this makes sense that kids will just put a switch between + and -, but they'll pretty quickly need to know that these two things are different. Similarly for the outputs.

My final niggle is Sniff specific - Sniff doesn't support the Pi's internal pull up/down resistors, and the "big red button" needs a pull down to work correctly. Yes - you can fix it in code (If Sniff supported it), but it's a fraction of a penny component, which would have meant one less thing for the programmer to deal with. I'll probably solder a 10K pulldown on there myself... (edit - have done! details to follow).

Perhaps the best feature is that all of this costs only £10. Given that a basic breakout board and cable can cost almost that much, there's a lot to like in this package, whether you're in KS2, or an experienced programmer. Despite the niggles, its currently replaced my regular breakout board.

http://pibrella.com

Wednesday, 26 March 2014

7Seg on Indiegogo

I just saw this fun little project which adds a 7 Segment display to Raspberry Pi. It's currenty seeking funding on idiegogo:
While there are a lot of projects on crowd funding sites which are pretty lazy "we don't have a business plan, so thought we'd ask everyone to send us cash instead", this one looks like a pretty good cause - Tom the designer is an A level student trying to do something pretty cool so deserves support.

He's got a few examples of how to control the thing in Python, but like most Python codes the make the whole thing look pretty complex, when in fact using this is dead simple:

make rst digital output 22
make up digital output 4

make count number

when update
.set rst to on
.wait 5 millisecs
.set rst to off
.repeat count
..wait 5 millisecs
..set up to on
..wait 5 millisecs
..set up to off


It uses two pins 15, and 17 which we've called rst (reset) and up. All we have to do is pulse rst to set the count to zero, and then pulse up to increase the value by one, so we loop count times to set it to the value we want (leaving a little delay just to make sure things have time to happen).

Now we can add it to any program just by saying:

when start
.forever
..set count to pick random 1 to 6
..broadcast update
..wait 1 secs

If you think one of these would be fun to have you can get one for £10 (if you're quick) from http://www.indiegogo.com/projects/7seg-for-raspberry-pi.
More info and pics:http://7seg.co.uk/index.html

Good luck Tom!

Tuesday, 25 March 2014

Cellular Automata

Cellular Automata are (depending on your point of view) either dumb things that programmers code, really fun toys, or important mathematical tools for understanding the fundamental concepts of computability. So when Simon Walters (@simplecy) posted a challenge on Twitter to produce an interesting CA that only used 8cells, I was hooked.

Prehaps I should be honest and say I actually spend weeks as a kid producing these things on a BBC Micro, and printing them out in a long continuous sheet on a tractor feed Epson RX80 to make what looked like 8' long slug trails. Back then they took hours to run, which was a big win because Mandelbrot sets took days!

So what are these things: A CA is a set of cells. Each cell has a state, and it has a set of neighbouring cells. At each time time it looks at its neighbouring cells state, and its own state and decides what its new state is going to be. At its simplest a cells state is quite commonly restricted to just alive or dead. The simplest neighbourhood might be the cells to my left and right. A simple rule might be "set my state to state of the cell on my right". While this might sound pretty limited, in fact with only a slightly more complex system we can produce something that's a "Turning Complete" - it can do any calculation your computer can do. That's right - a basic cells in a grid, with a simple rule could by made into an emulator to run any video game for example... OK it's actually not very practical, but in theory its possible, and that's not only cool, but its a really important idea in computing.

Lets start build a simple Automata in Sniff. We'll start by creating a list to hold the current state:

make state list of boolean

We'll restrict ourselves to cells which are "Boolean" - they're either on or off. More complex CA can have much more complex states, but not today...

.repeat 8
..if pick random 0 to 1 = 1
...add on to state
..else
...add off to state
.broadcast showState and wait

Simon wanted 8 cells in his list, so here we generate 8 random numbers, and use them to set the 8 states in our list to either on or off.

.forever
..broadcast calcNewstate and wait
..broadcast showState and wait
..wait 0.5 secs

Now we can loop forever, calculating the new state, displaying it, then waiting half a second before moving on.

You'll note that I still haven't defined calcNewstate, or showState. This is an idea called "top down design". If I was designing a car I'd decide I need an engine, some wheels and a chassis, and figure out where they would go. Then the engine team would go off and design the engine I need. The important thing is I figure out that I need an engine, and what it needs to do, then I get someone to make one for me.  The alternative is sending a team of to make an engine, a team off to make some wheels, a team off to make the propellers, and then when they finish we assemble them, and hope they make a car. This is called "bottom up design", and its important too but its better as a way of implementing you machine, rather than designing it. In practise any real project is a bit of both.

Now that I've written the top level, lets fill in the details (bottom up!).

make count number
make result string

when showState
.set result to ""
.set count to 1
.repeat length of state
..if item count of state
...set result to join result "*"
..else
...set result to join result " "
..change count by 1
.say result

Lets start with this code to print out the current state. It's useful to write this next as it'll help us see what's happening, when we write the more difficult calcNewstate script. We could output the state to some LED's but for now we'll just print them. The code simply goes through the state list, and adds either a space or a * to the string "result" depending on if its alive or dead. Another thing to note here is that this works for any number of cells in the state list. I know its 8, because that's how many we put in, and that's how many Simon asked for, but one day Simon is going to buy some more LED's and want to have 12 or 16 cells, so lets write our code so that when that happens we're ready for it (exactly how much future proofing you should put in your code is a matter of debate even among experienced programmers - don't waste too much time building things you don't need, but expect things to change in the future...)/

Now we get to the good bits - calcNewstate. We're going to use state to calculate a new state (called new), so:

make new list of boolean

when pushBack
.repeat length of state
..delete item 1 of state
.repeat length of new
..add (item 1 of new) to  state
..delete item 1 of new

There's also a new script called pushBack, which copies the new state over the old state ready to go round again. It first deletes all of the items in state, then copies each element over by copying the first element, and then deleting it. There are other ways to do this which might be clearer - I liked it cause it don't use a counter variable! (tech note: its OK to change the repeat count inside the loop - its evaluated once on entry to the loop, in both Scratch and Sniff).

We'll break calcNewstate into smaller pieces to discuss:
when calcNewstate
.set count to 1
.repeat length of state
..
..set left to count-1
..if left = 0
...set leftState to item (length of state) of state
...set leftState to on
...set leftState to item 1 of state
...set leftState to off
..else
...set leftState to item left of state

We're going to go through  state one element at a time, so count is the current item we're looking at. To keep things simple, we're going to let a cell look at its left and right neighbours, so we have a variable left which is one less than count, and right which is one more than count. Then we can set leftState and rightState to be the state of the neighbouring cells.

The only catch is what happens at the edges. Simon was actually pretty specific in on respect - the CA wasn't allowed to wrap. Normally we join the edges of CA, so that left of cell one is cell 8, and right of cell 8 is cell 1, but in this case it was banned. However he didn't say what we should do... so we can take some liberties here if left is 0, then we're at the edge, and I've written four possible things we could do: use the state of cell 8 (disallowed), make it always 1, use the state of cell 1, or make it always 0. As these all set leftState, then only the last one actually does anything, so in this case leftState is always off.

Then we set middleState (easy), and rightState, with the same options as last time:

..set middleState to item count of state
..
..set right to count+1
..if right > length of state
...set rightState to off
...set rightState to item 1 of state
...set rightState to item (length of state) of state
...set rightState to on
..else
...set rightState to item right of state

Hey - I cheated there! left of the left edge is always off, but right of the right edge is always on... It makes some rules more interesting, and you can try it lots off different ways. Besides the rules just say it can't wrap, they don't say what it should do...

..set ruleIndex to 1
..if leftState
...change ruleIndex by 4
..if middleState
...change ruleIndex by 2
..if rightState
...change ruleIndex by 1
..
..add (item ruleIndex of rule) to new
..
..change count by 1
.
.broadcast pushBack and wait

Here's the clever but. We know leftState, middleState and rightState, so we can put any code we want here to calculate the new state, but with only three Boolean inputs there are only 8 possible combinations, so we convert them into a binary number: LMR and look them up in a list. We can make any rule just by changing the list!

Then we're done, and move onto the next cell. Finally we use the pushBack script to copy the new state over the old one which we don't need any more.

  1. 000 - > 0
  2. 001 - > 1
  3. 010 - > 1
  4. 011 - > 0
  5. 100 - > 1
  6. 101 - > 0
  7. 110 - > 0
  8. 111 - > 1
To define a state we just need to fill in this table. In this case the LMR cells are off off off then the new cell becomes off. Simlarly off off on becomes on.

when makeRule
.add off to rule
.add on to rule
.add on to rule
.add off to rule
.add on to rule
.add off to rule
.add off to rule
.add on to rule


But we can also make up other rules:
when makeRule90
.add off to rule
.add on to rule
.add off to rule
.add on to rule
.add on to rule
.add off to rule
.add on to rule
.add off to rule

If you look closely you'll release that as there are only 3 inputs, that means there are 8 rows to the table. Each row can be on or off, so there are in fact only 256 ways to fill in the table! To make things even easier we can use the on/off's in the table to make a number 01011010 in binary is 90, so we call this rule 90!

 *    **
* *  ** 
   **** 
  **  * 
 *****  
**   ***
*** **  
* * ****
    *   
   * * *
  *    *
 * *  **
*   *** 
 * ** * 
*  **   
 ***** *
**   * *
*** *  *
* *  ***

Unfortunatly one feature of CA is that they tend to get stuck in loops - you'll seed that the last row is the same as one further up, that means from then on the same pattern of rows will repeat. This is inevitable with only 8 cells  - the entrĂ©e  automata only has 256 possible states in so we're going to his a loop pretty quickly.

80 cells on the other hand:
 *    **  * *  ***** *  ***    ***   * *    * ** * * ** ***   * * *   * * * ** *
* *  *****   ***   *  *** **  ** ** *   *  *  **     ** * ** *     * *      ** *
   ***   ** ** ** * *** * ****** **  * * ** *****   ***   **  *   *   *    *** *
  ** ** *** ** **   * *   *    * ****    ** *   ** ** ** ***** * * * * *  ** * *
 *** ** * * ** *** *   * * *  *  *  **  ***  * *** ** ** *   *          ****   *
** * **     ** * *  * *     ** ** ******* ***  * * ** **  * * *        **  ** **
**   ***   ***    **   *   *** ** *     * * ***    ** ****     *      ******* * 
*** ** ** ** **  **** * * ** * **  *   *    * **  *** *  **   * *    **     *   
* * ** ** ** *****  *     **   **** * * *  *  ***** *  ***** *   *  ****   * * *
    ** ** ** *   *** *   **** **  *      ** ***   *  ***   *  * * ***  ** *    *
   *** ** **  * ** *  * **  * **** *    *** * ** * *** ** * **    * *****  *  **
  ** * ** ****  **  **  ****  *  *  *  ** *   **   * * **   ***  *  *   *** *** 
 ***   ** *  ************  *** ** ** ****  * **** *    *** ** *** ** * ** * * * 
** ** ***  ***          **** * ** ** *  ***  *  *  *  ** * ** * * **   **       
** ** * **** **        **  *   ** **  *** *** ** ** ****   **     *** ****     *
** **   *  * ***      ***** * *** ***** * * * ** ** *  ** ****   ** * *  **   **
** *** * **  * **    **   *   * * *   *       ** **  **** *  ** ***    ***** ** 
** * *   ****  ***  **** * * *     * * *     *** *****  *  **** * **  **   * ** 
**    * **  **** ****  *      *   *     *   ** * *   *** ***  *   ******* *  ** 
***  *  *****  * *  *** *    * * * *   * * ***    * ** * * *** * **     *  **** 
* *** ***   ***   *** *  *  *       * *    * **  *  **     * *   ***   * ***  * 
  * * * ** ** ** ** *  ** ** *     *   *  *  **** *****   *   * ** ** *  * ***  
 *      ** ** ** **  **** **  *   * * * ** ***  * *   ** * * *  ** **  **  * ***
* *    *** ** ** *****  * **** * *      ** * ***   * ***      **** ********  *  
   *  ** * ** ** *   ***  *  *    *    ***   * ** *  * **    **  * *      *** **
  * ****   ** **  * ** *** ** *  * *  ** ** *  **  **  ***  *****   *    ** * * 
 *  *  ** *** ****  ** * * **  **   **** **  *********** ****   ** * *  ***     
* ** **** * * *  *****     ******* **  * *****         * *  ** ***    *** **   *
  ** *  *      ***   **   **     * ****  *   **       *   **** * **  ** * *** **
 ***  ** *    ** ** **** ****   *  *  *** * ****     * * **  *   ******   * * * 
** *****  *  *** ** *  * *  ** * ** *** *   *  **   *    **** * **    ** *      
** *   *** *** * **  **   ****   ** * *  * * ***** * *  **  *   ***  ***  *    *
**  * ** * * *   ******* **  ** ***    **    *   *    ****** * ** **** *** *  **
****  **      * **     * ****** * **  ****  * * * *  **    *   ** *  * * *  *** 
*  ******    *  ***   *  *    *   *****  ***       *****  * * ***  **     *** * 
 ***    **  * *** ** * ** *  * * **   **** **     **   ***    * ******   ** *   
** **  *****  * * **   **  **    *** **  * ***   **** ** **  *  *    ** ***  * *
** *****   ***    *** ********  ** * ****  * ** **  * ** **** ** *  *** * ***  *
** *   ** ** **  ** * *      *****   *  ***  ** ****  ** *  * **  *** *   * ****
**  * *** ** ******    *    **   ** * *** ***** *  *****  **  ***** *  * *  *   
****  * * ** *    **  * *  **** ***   * * *   *  ***   ********   *  **   ** * *
*  ***    **  *  *****   ***  * * ** *     * * *** ** **      ** * ***** ***   *
 *** **  ***** ***   ** ** ***    **  *   *    * * ** ***    ***   *   * * ** **
** * *****   * * ** *** ** * **  ***** * * *  *    ** * **  ** ** * * *    ** * 
**   *   ** *    ** * * **   *****   *      ** *  ***   ****** **      *  ***   
*** * * ***  *  ***     *** **   ** * *    ***  *** ** **    * ***    * *** ** *
* *     * *** *** **   ** * *** ***    *  ** **** * ** ***  *  * **  *  * * ** *
   *   *  * * * * *** ***   * * * **  * **** *  *   ** * *** **  **** **    ** *
  * * * **        * * * ** *      ****  *  *  ** * ***   * * *****  * ***  *** *
 *      ***      *      **  *    **  *** ** ****   * ** *    *   ***  * **** * *
* *    ** **    * *    ***** *  ****** * ** *  ** *  **  *  * * ** ***  *  *   *


Things get more fun when you add bigger neighbourhoods and more states!


here's the complete code. Have fun with it...

Monday, 24 March 2014

Release 5 = Minecraft

The Beta 5 release is now available on the Downloads page, and it contains lots of fixes, and improvements. However the one you're really interested in is Minecraft support!!!

While we love our gadgets, the main concept of Sniff is that its a programming language that lets experienced Scratch users move on to a "written" language that they will be familiar with. The need for this is made clear looking at the Python and Java examples that are provided with the Raspberry Pi version of Minecraft.

Minecraft has been released as a free download for Pi, with an option for external programs to tap into it, so that kids can learn to program by writing scripts to build things inside the 3D world. It's a great idea which is let down by the fact that one look at that examples provided will send any kid running and screaming. They're not particularly complex examples but even for an experienced (non-Python) programmer the syntax,  and code overhead makes them look difficult and hard to follow.

This exactly what Sniff is designed to avoid - Kids already know Scratch, which means that the Sniff syntax is familiar, so they can jump straight into problem solving, and making things! Introducing the Sniff Minecraft Device!

make minecraft device
make message string
make mcX number
make mcY number
make mcZ number
make blockType number
make blockData number

You make minecraft device and its variables like any other Sniff device. This sets up the connection to Pi Minecraft running on the current machine (if you want to use a different machine you can edit lib/Xminecraft.c - not recommended for public editing, but its pretty easy).

Now we can start doing things:

when start
.set message to "Sniff woz here"
.tell minecraft to "show"

broadcasts the message!

.set mcX to 5
.set mxZ to 5
.tell minecraft to "getHeight"
.tell minecraft to "setPos"

Moves the player to square (5,6). However before doing so, it checks the height of the land at that square, which sets mcY to the right value (Y is up) so that the player is standing on the ground rather than flying (or burried!). You can also check the players position with "getPos"

Now lets build a tower:

when start
.set mcX to 0
.set mcY to 0
.set mcZ to 0
.
.repeat 100
..tell minecraft to "getBlock"
..if blockType = 0
...set blockType to 1
...set blockData to 0
..else
...set blockType to 0
...set blockData to 0
..
..tell minecraft to "setBlock"
..change mcY by 1
..wait 0.2 secs
.
.set message to "like my tower?"
.tell minecraft to "show"

We set x/y/z to 0 (the spawn point). We check the block at that position, which gives us the blockType (ID). In addition blockData tells is more about the block (http://minecraft.gamepedia.com/Data_values). If the block is currently air (type 0), then we set it to 1 (stone), which builds a tower. If there's already a block there (because we've run the code before) we delete it by setting it to air.

There are other aspects to the Minecraft API, but they either provide duplicate ways of doing things we can already to with these functions, or they're not completely implemented/documented in the current release of minecraft for Pi. If I've missed anything that we should add, then either add it yourself (the files are there for you to change, and we'd love to receive your improvements), or email/DM/leave a comment letting us know.

So what are you waiting for? Go program Minecraft using Scratch like syntax!

Tuesday, 18 March 2014

Fun with Fourier

After the success of generating sound directly in Sniff, I guess I had some signal processing ideas in my head (Also I taught a class on sampling theory yesterday so maybe that had something to do with it!). Recording audio is pretty easy - just hook a mic up to an analog input and you can measure it sufficiently fast to fill up an Arduino's memory in no time at all. We could easily record a snapshot of audio and draw it on screen, but to see what's really going on plotting amplitude against time is only of limited use.

To get a good look inside a piece of audio we need to plot amplitude against frequency. Almost all sounds are a mix of low sounds and high sounds played at the same time, and drawing them this way lets us see how a particular complex sound is made up from these simpler components.

At this point a whole load of complex maths gets involved, but the main thing is that we can convert our simple amplitude/time recording to a amplitude/frequency version using a Fourier Transform. There's a special version of this that we normally use when we implement it on a computer called the Fast Fourier Transform or FFT for short. That's not to say that the FFT is fast - it's still quite a lot of work for a small computer, but its the fastest way to do it.

There are a bunch of FFT libraries which you can download (including some good ones for Arduino), because you really don't want to write your own - its tricky, and to get good performance you need to add in a lot of tricks (check out FFTW for a serious implementation). There's also the issue that if we're running on Arduino we don't have a lot of memory. To make the FFT run quickly they use a lot of precomputed tables which are going to eat up memory.

Then I stumbled across the Goertzel algorithm - its slower than an FFT if you can't to compute the full transform, but has the neat property that it calculates one value at a time - if we're plotting the graph we can calculate each point independently rather than having to calculate all the points. It's also light on trig functions, so we don't need any pre-computed tables. In other words its slower, but doesn't use any significant memory other than the source data. In fact if we only want to measure a particular frequency (how much 440Hz is in this audio) then we don't even need to store the incoming signal!

As an extra bonus its much simpler that an FFT, and is non-recursive.

Step 1 is to make a signal for us to process:
make x list of number

.repeat 32
..add 1 to x
.repeat 32
..add 0 to x

This fills x with a 64 samples of a square wave. Next we can use the Goertzel code to show how much energy is in the signal a frequencies from 0 (any constant signal) 1 (1 wave is 64 samples) up to 32 (32 cycles within the 64 samples we have).

.set k to 0
.repeat 33
..broadcast Goertzel and wait
..say join join [ k ] ":" [ power ]
..change k by 1

The actually Goertzel code is remarkably simple. How it works on the other hand isn't:

when Goertzel
.set coeff to 2 * cos of (360*k/64)
.set sp to 0
.set sp2 to 0
.set n to 1
.repeat 64
..set s to (item n of x) + coeff*sp -sp2
..set sp2 to sp
..set sp to s
..change n by 1
.set power to (sp2*sp2+sp*sp-coeff*sp*sp2)/32

It basically goes through the list of samples calculating a value s which at each step by summing the value of that sample, and the value of s at the previous two steps (sp and sp2). The sum is weighted by coeff which is dependant on the frequency band we're interested in.

If we run this we get the results:
0.000:32.000
1.000:12.980
2.000:0.000
3.000:1.451
4.000:0.000
5.000:0.529
6.000:0.000
7.000:0.275
8.000:0.000
9.000:0.171
10.000:0.000
11.000:0.118
12.000:0.000
13.000:0.088
14.000:0.000
15.000:0.069
16.000:0.000
17.000:0.057
18.000:0.000
19.000:0.048
20.000:0.000
21.000:0.042
22.000:0.000
23.000:0.038
24.000:0.000
25.000:0.035
26.000:0.000
27.000:0.033
28.000:0.000
29.000:0.032
30.000:0.000
31.000:0.031
32.000:0.000

You'll see that the 0 has a value of 32 - the sum of all the samples.

The value of 1 is large because our square wave looks a lot like a sine wave of period 64. From there we see that all of the even values are 0, and the odd values decrease progressively -the frequency signature of a square wave!

Here's the complete code:
make k number
make n number
make x list of number

make s number
make sp number
make sp2 number
make coeff number
make power number

when Goertzel
.set coeff to 2 * cos of (360*k/64)
.set sp to 0
.set sp2 to 0
.set n to 1
.repeat 64
..set s to (item n of x) + coeff*sp -sp2
..set sp2 to sp
..set sp to s
..change n by 1
.set power to (sp2*sp2+sp*sp-coeff*sp*sp2)/32

make t number
when start
.repeat 32
..add 1 to x
.repeat 32
..add 0 to x
.
.set t to timer
.set k to 0
.repeat 33
..broadcast Goertzel and wait
..say join join [ k ] ":" [ power ]
..change k by 1
.say join "time:" [timer - t]

It's pretty slow - on an Uno its around 0.1 secs, excluding the printing, which is far slower than an FFT, but there's a big win in terms of simplicity, flexibility memory footprint.

But here's the fun bit... Scratch and Sniff are essentially the same language: If we can do it in Sniff we can do it in Scratch!
This is identical code - I simply dragged out the Scratch blocks, copying the Sniff code. Though in this case we're going the opposite direction to the way we expect students to (moving from Sniff to Scratch rather from Scratch to Sniff) the experience confirmed a couple of core Sniff ideas:
  • We were able to move code directly between Scratch and Sniff
  • Knowledge of one made working the other easier
  • Building code in text form required more concentration
  • Building complex code graphically was slower
It's also a great endorsement of Scratch - we solved a University level problem in a Kindergarten tool! It shows that as a language Scratch is sufficiently powerful to express complex ideas, though for experienced programmers Sniff is probably a better way to do Scratch!

Thursday, 13 March 2014

Sparkfun Inventor kit in Sniff

I recently stumbled across the Sparkfun Inventor Kit (https://www.sparkfun.com/products/12001) - This is a great kit of bits and pieces to get you started with Arduino. It includes a bunch of handy components to get you started, but more importantly it includes a really great guidebook which walks you through 15 mini-projects using the components in the kit.

It's a great way for kids to get started, but of course it used standard Arduino/C++ which is probably going to be hard work for younger kids (the kit is listed as being for ages 10+, which is probably reasonable in terms of the physical components but ambitious in terms of the coding), so I thought it would be fun to rewrite the 15 examples in Sniff.

Most of the examples are pretty simple to convert, but some are more interesting. Example 11 uses the Tone function of the Arduino library, but Sniff has no sound support. However it turns out you can write your own sound code in Sniff pretty easily:

when makeSounds
.forever
..set buzzer to on
..wait halfWavelength microsecs
..set buzzer to off
..wait halfWavelength microsecs


What's great about this is you can actually see that to play a sound we're pushing the speaker cone forwards and backwards. To play A440 for half a second you just have to write:

.set f to 440
.set halfWavelength to 500000/f
.wait 0.5 secs
.set halfWavelength to 0

Setting the half wavelength to 0 makes the sound well outside of human hearing (and the capabilities of any audio system to reproduce it!) The full example uses a string of note names, from which we pick out the letters, and look them up in a list to find their frequency.

You can download the full set of SIK examples from the link below. They're not all fully tested, as I don't have the exact components needed, so there's sure to be a few bugs - let us know so we can fix them. This code will be included with the examples in future Sniff releases.

Wednesday, 12 March 2014

The 20 cent Heart Monitor

We all love quick, and cheap science projects, so when I saw a "heart rate sensor for Arduino" on Ebay I almost grabbed one instantly... but then I looked a bit closer and realised that it looked a bit shoddy... Was I really getting value for money from my hard earned $2?

Reading the description and looking at the picture it appeared this thing was just and IR led, and photo-transistor soldered onto a PCB. The LED shines into your fingertip, the photo-resistor measures how much is reflected back (or transmitted - either should work). It turns out this is a perfectly reasonable way to measure blood flow. More blood means more (or maybe less?) reflection, means a changing voltage we can measure, and plot!

However I didn't feel like blowing a whole $2 on this - times are tight, and anyway I bought a whole bunch of IR emitter/photo-transistor packages last week to do proximity sensing! They're called TCRT5000's and for $2 you'll get a bag of ten. Wiring them up just needs a couple of resistors, and we can start measuring with them.


make pulseSensor analog input A5

when start
.forever
..say [ pulseSensor ]
..wait 0.1 secs

We need analog input so this isn't going to run on a Pi, but hooking this into an Arduino Uno I started getting measurements: about 0.9 when the sensor was clear, and about 0.03 when I put my thumb over it. The reading of 0.03 is a bit small, but importantly, it did seem to be changing in time with my pulse. I adjusted the resistor value on the photo-transistor, and got a reading of somewhere between 0.17 and 0.19 which was clearly indicating that I definitely have a pulse.

The coffee cup measurements from last week worked so well I thought that the tft screen might be worth another run out, and I could use the same two script approach:

when start
.set displayColor to 000
.tell tft to "clear"
.broadcast startMeasuring
.broadcast startDrawing

For the measuring thread I decided to include some averaging, so that the several readings are combined. With a bit of tweaking I ended up with:

make currentVal number
when startMeasuring
.forever
..set currentVal to 0.8 *currentVal +0.2 * pulseSensor
..wait 0.02secs

For drawing I wrote:
when startDrawing
.forever
..set displayY to (40*timer) mod 320
..
..set displayColor to 777
..set displayX to 0
..tell tft to "move"
..set displayX to 239
..tell tft to "hfill"
..
..set displayColor to 700
..set displayX to (currentVal)*50*200
..tell tft to "setPixel"

the tft device has an "hfill" command that makes it quick to blank out an individual line - there's no equivalent vfill (perhaps there should be?) so it was easiest to plot the graph from bottom to top, and then turn the screen around when it was finished. We pick a row based on time (40 samples per second was perfectly manageable with this hardware and looked about right), and assign that to displayY so all drawing takes place on that line.
We then use hfill to blank the line, and set a single pixel based on the current reading of the sensor. The result is a graph of my pulse! (sorry for the photo - it's hard to get a good picture of the screen when you've got to keep you thumb on the sensor!)

One minor problem was that depending on how hard I pressed and what part of my thumb I used the values could change substantially - the trace would disappear completely if I moved my thumb a little too much. We're only interested in the variation with a period of about 0.5 seconds, so the final refinement was to add an averageValue variable which is the average of the reading over several seconds. By removing the, we still get the the nice pulse, but the graph automatically centres itself on screen if you keep your finger still for a few seconds.

Here's the final code:

make pulseSensor analog input A5

make tft device
make displayX number
make displayY number
make displayColor number
make message string

when start
.set displayColor to 000
.tell tft to "clear"
.broadcast startMeasuring
.broadcast startDrawing

make currentVal number
make averageVal number

when startMeasuring
.forever
..set currentVal to 0.8 *currentVal +0.2 * pulseSensor
..set averageVal to 0.01*currentVal + 0.99*averageVal
..wait 0.02secs

when startDrawing
.forever
..set displayY to (40*timer) mod 320
..
..set displayColor to 777
..set displayX to 0
..tell tft to "move"
..set displayX to 239
..tell tft to "hfill"
..
..set displayColor to 700
..set displayX to (currentVal-averageVal)*50*200+120
..tell tft to "setPixel"

Isn't that the best $0.20 you ever spent?


Tuesday, 11 March 2014

Motion Triggered Camera

I just got a bunch of PIR motion sensors of Ebay - they're about £1 each and basically do all the hard work for you. Of course the first thing I did was hook them up to an Arduino - power, earth and signal, then wrote a Sniff program to test it:

make pir digital input 2
make led digital output 13

when start
.forever
..set led to pir


That didn't take long. After a little tweaking on the trim pots on the sensor to adjust its sensitivity, it was firing nicely whenever there was any movement around my desk.

So what next... I'll probably attach one to a battery and a buzzer and put it inside the biscuit jar - we have a seven year old biscuit burglar, but that doesn't actually need code. Then I remembered the new "system" device that lets you run shell commands on the Pi. If I had a camera hooked up...

make pir digital input 17
make system device
make command string

when start
.forever
..if pir
...set command to "raspistill -o image.jpg"
...tell system to "run"
... wait 10 secs

Of course this overwrites the image each time so:

make i2c device
make clock device
make clockValue string

make system device
make command string

make pir digital input 17
make filename string

when start
.forever
..if pir
...tell clock to "getTime"
...set filename to join clockValue ".jpg"
...set command to "raspistill -o "
...set command to join command filename
...tell system to "run"
...wait 10 secs

Now we use the clock device to get the real time in hours/min/secs (timer just gives us time since the program started - clock actually knows the time of day), and use that to make a filename.

Of course it doesn't  have to be a PIR - anything that the Pi can read could be used, and it doesn't have to be a camera command... 

Monday, 10 March 2014

Beta 4 gives full support to the Pi

Raspberry Pi support first appeared in Beta 3, but only as a generic Unix platform.  Beta4 which has just been released takes this a step further, and makes the Pi a fully capable Sniff platform, comparable to the Arduino. If you install WiringPi before compiling your Sniff program it will be detected, allowing you to write Sniff code which access the GPIO (including SPI and I2C). It's written in such a way that most of the existing "devices" which were supported on Arduino, now work on Pi too.

In addition to the existing devices, we've added a bunch of new devices especially for Pi. While you can still hang an sdcard reader on the GPIO port, and access files that way, the new nativeFile device behaves just like the old fileSystem device but accesses the regular Pi files. Simlarly framebuffer behaves like the old Arduino's tft device, but uses the Pi's built in graphics. Finally taking a leaf from the Galeleo there's the "system" device, which lets you run a regular Pi command from inside Sniff.

I'm planning on using a Syndrome from Disney Infiniti/Incredibles to trigger an RFID reader to shut down my Pi by running "poweroff"! (as soon as I've debugged the RFID reader).




Wednesday, 5 March 2014

Coffee Break

We're hard at work on the Beta 4 release, which is looking like its going to focus on the Pi: it should detect if you have wiringPi installed, and use it to access the GPIO port. SPI, and I2C should be working, so devices like the RFID reader, and the Wii NunChuck should work on Pi just as well as they do on Arduino.

However I couldn't resist a quick physics experiment. Plug in the tft shield, and add a ds18 temperature sensor on pin A5 (the only one that shield leaves free!), and we an plot a graph of my coffee cooling!

Here's the code:

make ds18 device A5
make temperature number

make tft device
make tftX number
make tftY number
make tftColor number
make message string

when start
.set tftColor to 777
.tell tft to "clear"
.set tftColor to 700
.set tftX to 20
.set tftY to 100*3+20
.tell tft to "move"
.set tftY to 0*3+20
.tell tft to "draw"
.set tftX to 220
.tell tft to "draw"
.broadcast startMeasuring
.broadcast startDrawing

when startMeasuring
.forever
..tell ds18 to "start"
..wait 1 secs
..tell ds18 to "read"
..#say [ temperature ]
..set tftY to (temperature-40)*12+10


when startDrawing
.forever
..wait 1 secs
..set tftX to 0.25*timer+20

..tell tft to "setPixel"

Drawing the axis is the hardest part...

And here's the result:

It works! And we get something that's the beginnings of an asymptotic curve. If I'd left it longer it would have looked better, but then my coffee would be cold...