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.

Tuesday, 19 August 2014

Arduino Music

When working on the Gamebuno drivers I was really impressed by their audio driver, which can play up to four part harmonies by directly driving one of the Arduino's output pins from interrupts. While not exactly orchestral, the results are pretty authentic 8-bit classic video game goodness. It works on a standard Uno - just connect a piezzo, or an audio amplifier to pin 3.

However while their backend is excellent, their API is pretty confusing, and undocumented. It involves entering midi notes into an Excel spreadsheet, and then copying and pasting the results of the calculation into C data structures... In porting the code to work with Sniff, I simplified their backend, removing some of the less essential features, and build an API that should make it easy for anyone to play simple tunes. If anyone remembers programming music in Ample on a BBC micro, then the notation should be a little familiar...

Lets start of with the basic declarations:

make player avrSound device
make tune string
make channel number
make noteLength number
make soundPlaying boolean

We start by making a player device - for the moment that's avrSound, but in future we might have midiSound, or piSound device. We have variables: tune, channel, and noteLength which control the playing of notes, and soundPlaying which we'll use to check if the audio is still playing.

when start
.forever
..tell player to "update"
..wait 0.05 secs

when start
.set noteLength to 8
.set tune to " cEGCgec"
.set channel to 1
.tell player to "playTune"

Sounds play automatically in the background, but we need to regularly call update to change the notes, or sound thats playing. Every 20th of a second is recommended, so the easiest way to do that is just to make a script which just runs forever calling "update".

Then to play a sound we set the default note length which is measured in update ticks, so in this case its 8x0.05 secs which is 0.4 of a second. 8 is a good choice, as if we need to play something with smaller notes it subdivides nicely (12 would also be good, as it would allow for triplets). You can find tune the tempo by changing the tick speed. We also have to specify the channel - in this case I'm using channel 1, but you can use 1,2 or 3 (if you need 4, then you can make a minor edit to the device source code, but it will use more resources).

We specify the notes by their name, and each lasts the specified note duration. Here we start on a C, and play a major arpeggio up to the top C. We then go back down again - using lower case to indicate these are falling notes, while we used upper case notes to choose a rising pitch. If you want sharps or flats, then place a + or - before the note. If you want to change pitch by more than an octave then use > or <.

Then just call playTune, and the tune will play in the background. If you want to know that the sound has finished, then you can:

..wait until not soundPlaying

Here's a more complex example:

..set tune to " .cEF|G///|.cEF|G///|.cEF|G/e/|c/E/|d///|.EEd|c///|E/G/|Gf//|..eF|G/e/|c/E/|c///|/"

A "/" means to increase the note length by one noteLength, so you can set noteLength to the shortest note, and specific the rest using /. A dot is a rest, and a vertical bar is a bar line: you don't need to include bar lines, as they don't actually have any effect on the sound but they're very handy to help you keep track of where you are in the piece! You can also include spaces to keep things lined up, but again they have no meaning.

make fancy boolean

when start
.set fancy to no
.repeat 2
..set noteLength to 8
..set tune to " .cEF|G///|.cEF|G///|.cEF|G/e/|c/E/|d///|.EEd|c///|E/G/|Gf//|..eF|G/e/|c/E/|c///|/"
..set channel to 1
..tell player to "playTune"
..
..change channel by 1
..set tune to "<....|C.g.|C.g.|C.g.|C.g.|C.g.|C.g.|g.D.|ggAB|C/g/|C/g/|f/C/|ffAB|C/g/|g/B/|C/..|."
..tell player to "playTune"
..
..change channel by 1
..if fancy
...set noteLength to 4
...set tune to ">........|..CbC.Cb|C.......|..CbC.Cb|C.......|..CbC.Cb|C.C/b/a/|g/////"
...tell player to "playTune"
..
..wait until not soundPlaying
..set fancy to yes


Here's an example that uses three channels, and includes a repeat. The first time round we place the tune and the bass line. At the end of the loop we wait for the first verse to finish, then go back around again play three parts.

Remember tunes are just strings, so you could write code to choose notes and add them to a tune, or even write out several shorter phrases, and join them together before playing them...

The avrSound device is included in the Beta 8 release.

Tuesday, 12 August 2014

Gamebuino

Earlier this year Aurelien Rodot launched and IndieGoGo campaign so he could build 100 hand-held mini-console's inspired by the original gameboy, but powered by an Arduino. By the time the campaign finished, he was committed to build 1000! He spent over a month assembling and shipping them!!!

The result is one of the best Arduino's since the Uno. While the fixed (limited) hardware spec might seem at odds with the DIY principles, having a single device to program for makes sharing projects massively easier. and makes it a great device if you want to write games in Sniff.  We took the Gamebuino and our Bounce Out game to Scratch@MIT2014, and the reaction was literally "where can I get one of these?". Unfortunatly right now you can't - the original campaign is over and Aureleien is too burnt out to build any more just yet, but he has hinted that more might be made available in the future. Of course you could build your own (I'm working on a project to build something based on the design), as it uses completely standard components - it just won't look as nice.

The Gamebuino has 8 buttons (connected directly to digital inputs), a light dependant resistor (to control the backlight), a speaker, an SD card, a small lipo battery/charger and a Nokia 5110 screen (with controllable backlight). All of those are easily supported in Sniff, so it only took a few hours to get everything running sweetly. As of Release 8 you can compile Sniff for Gamebuino using the gb-sniff command.

Here's a walk through of the code for our first Gamebuino game "Bounce Out", which is basically Breakout with gravity!


To handle all the buttons you can use the Gamebuino device.

make gamebuino device
make buttonA boolean
make buttonB boolean
make buttonC boolean
make buttonUp boolean
make buttonDown boolean
make buttonLeft boolean
make buttonRight boolean
make batteryLevel number
make lightLevel number

when start
.forever
..tell gamebuino to "checkButtons"
..wait 0.05 secs

make quitTimer number

#backlight and reset
when start
.forever
..wait until buttonC
..set lightLevel to 1-lightLevel
..tell gamebuino to "setBackLight"
..set quitTimer to timer
..repeat until not buttonC
...if timer-quitTimer > 1
....tell gamebuino to "quit"

Here we've set up a loop which is going to keep checking the buttons regularly so we can just use the values elsewhere. ButtonC is the yellow button that's normally used to quit a game. We wait until the button is pressed, and toggle the backlight on or off. We then wait until the button is released - if we wait more than a second, then we bail out of the game, back to the loader (which is one of the smartest boot loaders in Arduino-land: it can load hex files from the SD card!). Because Sniff supports doing multiple things at the same time we can just leave this running, so we can turn the backlight on or off, and exit the game regardless of the rest of the code.

make spi device
make display nokia device
make displayX number
make displayY number
make displayColor number
make displayFlush boolean
make message string

when start
.set displayFlush to no
.forever
..set displayColor to 0
..tell display to "clear"
..
..set displayColor to 777
..set displayX to 16
..set displayY to 30
..set message to "Bounce Out!"
..tell display to "show"
..set displayX to 5
..set displayY to 10
..set message to "Hi Score:"
..tell display to "show"
..set displayX to 50
..set message to [ hiScore ]
..tell display to "show"
..tell display to "flush"
..
..wait until not buttonA
..wait until buttonA
..
..broadcast play and wait
..
..if score > hiScore
...set hiScore to score
..
..set displayY to 20
..repeat 10
...set displayX to 14
...tell display to "move"
...set displayX to 66
...tell display to "hfill"
...change displayY by 1
..set displayX to 16
..set displayY to 21
..set displayColor to 0
..set message to "Game Over"
..tell display to "show"
..tell display to "flush"
..
..wait until not buttonA
..wait until buttonA

That looks like a lot of code, but its all really simple. We make a Nokia display device, and then draw a welcome screen. We wait until buttonA is pressed, and then launch the main game loop by broadcasting play. When that's done we check if its a new high score, and display the "game over" message.

If you've used the Nokia (or other) Sniff graphics screens before you'll notice we've added something new: When you're writing games, its useful to have what's known as "double buffering" - we draw on a hidden screen, updating all the separate bits, then tell the display to display everything all at once. This reduces flickering and makes it possible to generate smooth animation. We've therefore updated the Nokia display to support this kind of hidden drawing. By default all drawing is immediately sent to the screen, but the line ".set displayFlush to no" turns this off, so no drawing appears until we tell the display to flush. By default all drawing is flushed immediately so you don't need to worry about it, but to get fast updates for games like this you should display auto-flushing, and send everything at the end of the frame. This is currently only supported on the Nokia device, but it works really well, so it should start appearing in other displays where it makes sense.

The ability of Sniff (and Scratch) to do multiple things at the same time is incredibly useful. We can move the bat by just adding:
#move the bat
when start
.forever
..set batXVel to batXVel*0.5
..if buttonRight and batXPos < 78
...change batXPos by 2
...change batXVel by 0.5
..if buttonLeft and batXPos > 5
...change batXPos by -2
...change batXVel by -0.5
..wait 0.05 secs

We use the same trick to separate the drawing into a separate "refresh" script, so our main game code lives in the play script, but never has to worry about drawing! At the beginning of the play script we broadcast refresh, to start the main drawing code. The refresh runs until the variable refreshStop is set to YES. It then sets it to NO.

when refresh
.repeat until refreshStop
..#DO LOTS OF DRAWING HERE
..#ITS BORING SO IVE NOT INCLUDED IT
.set refreshStop to no

The actually drawing is just lots of moves and draws, so I've missed it out. You can see at the end of the play method it sets refreshStop to be YES, then waits for it to become NO, so that it tells refresh to stop, and waits until it actually has stopped.

when play
.set score to 0
.set level to 1
.set batXPos to pick random 10 to 73
.set ballXPos to pick random 10 to 73
.set ballYPos to 40
.set ballXVel to 0
.set ballYVel to 0
.set boostAvailable to no
.delete all of blockData
.broadcast refresh
.repeat until ballYPos < 0
..repeat level
...add pick random 3 to 6 to blockData #Size
...add pick random 5 to 78 to blockData #X
...add pick random 10 to 30 to blockData #Y
..repeat until length of blockData = 0 or ballYPos < 0
...#bounce off BAT
...if ballYPos+ballYVel < 2
....if ballYVel>-1.5
.....set boostAvailable to yes
....if abs of (ballXPos-batXPos)<6
.....if buttonA and boostAvailable
......set ballYVel to 2.5
......set boostAvailable to no
.....else
......set ballYVel to -ballYVel*0.9
.....set ballXVel to ballXVel*0.8+batXVel
.....change score by 0.01*((abs of batXVel) + (abs of ballXVel))+0.001 
...
...#BOUNCE OFF SIDE WALLS
...if ballXPos+ballXVel<0 or ballXPos+ballXVel>82
....set ballXVel to -ballXVel*0.8
...
...#BLOCLKS
...set pCounter to 1
...repeat until pCounter >length of blockData
....set size to item pCounter of blockData
....if abs of ((ballXPos+ballXVel) - item pCounter+1 of blockData)<size
.....if abs of ((ballYPos+ballYVel) - item pCounter+2 of blockData)<size
......#WE HAVE A HIT
......if not abs of (ballXPos - item pCounter+1 of blockData)<size
.......set ballXVel to -ballXVel*0.8
......if not abs of (ballYPos - item pCounter+2 of blockData)<size
.......set ballYVel to -ballYVel*0.8
......delete item pCounter of blockData
......delete item pCounter of blockData
......delete item pCounter of blockData
......change score by 0.1
....change pCounter by 3
...
...change ballXPos by ballXVel
...change ballYPos by ballYVel
...change ballYVel by -0.1
...wait 0.05 secs
..
..if length of blockData = 0
...change level by 1
...change score by 1
.
.set refreshStop to yes
.wait until not refreshStop

There's probably too much here to go through in detail, but basically we set up the game in its initial state, and load up the blocks list with the size, and position of each block. Originally we had three lists, but that used too much memory, so we use one list to store all of the block info.

The core loop repeats until we either destroy all the blocks, or loose the ball. The main loop has to check if the ball is about to hit anything, and if it does it reverses the balls velocity. At the end of the loop it changes the balls position by its velocity. It also changes the balls Y velocity by -0.1: this is what gives us gravity.

And that's it. Bounce Out is 290 lines of code which is pretty large. What's amazing is that it runs really smoothly on the AVR, and the display refresh is really smooth. Sniff's parallelism turns out to be really great for coding up simple games as we can just handle each aspect of the game by itself, and let the interactions take care of themselves. I was able to get the game up and running in a couple of hours, and then a couple more hours of tweaking to get just right. Writing it was actually a big learning experience - it felt a bit like being a test pilot (without the fear of imminent death aspect). We've built our aircraft, and think you know what it can do, but you have to fly it for the first time, to learn how it really handles. You wouldn't write a game in this style of code in any other language, so writing Bounce Out really was a lesson in programming Sniff.


Here's the full Source Code, or you can download a compiled hex file. These are slightly different from the version that is in the current Sniff release, as a few things were tidied up, but here are functional differences. I've deliberately not talked about the sound library (which is used by BounceOut to make simple beeps), as its a whole post by itself.

Monday, 11 August 2014

Studuino

At Scratch@MIT2014 Arduino was a big thing - lots of people controlling Arduino's from Scratch (though of course only Sniff lets you actually program the Arduino!). The most visible of those groups was a large contingent from ArTeC - a Japanese company that make and sell robot contraction kits. They use a strange block mechanism that clicks together, like some strange and alien lego. They have motors and sensors to plug into those blocks. They're pretty cool, and they had some great demo robots made from the things.

To control these robots the have their own custom Arduino clone, which they call the Studuino. They were selling these at the conference for $3 - in other words they were giving them away (regular price is $30), but didn't want the first guy who turned up at their stand to take all of them. As it turns out the first guy at the stand was me, and I grabbed two!


It turns out that these are as strange as they look. The good things about them are that they're about the size of an Uno, and have standard(ish) Arduino socket layout. I say standard-ish, as the ICSP port is moved. This isn't a biggy, but it means some shields that use SPI won't work. For controlling robots, all of the i/o pins (A & D) are broken out on gnd/Vcc/Signal three pin servo headers. We like this a lot, as it makes plugging in things really easy. However the "feature" of the board is that it has two motor drivers built in, and four buttons. ArTeC's robot components will plug straight in, and they make a  really nice box that attaches the board to their block system.

So what are the downsides: The main on is that it uses an ATmega168pa which has only 16K ROM, and 1K RAM - half the specification of an UNO. It runs at 8MHz (half the speed of an UNO), though that's probably a good thing if you're running of battery, as it will save power. The whole thing operates at 3.3V which in theory is better (and again saves power), but in practise the whole 5v/3.3v arduino thing is a bit of a mess. Operating at 3.3V means you need to be a bit more careful. What all this comes down to is its going to suffer from the "not an UNO" effect: They UNO board is so prolific, any differences make it harder to work with, as everyone supports the UNO, and writes tutorials assuming that's what you're using. This isn't ArTeC's fault - Arduino's own Due is the biggest victim of the effect, but its a hassle in a board that's obviously aimed at beginners. There's a 3.3V/5V jumper on the Studuino, but it doesn't switch the whole  board over - its exact operation is unclear.

Another niggle with the board is that it uses a pl2303 USB chip, so you'll need to install drivers. The UNO and other boards which use the 16u2 to provide USB, work out of the box on Mac, but you need to install a driver to use the Studuino. There are links and instructions on the ArTeC site, or you can get the driver direct from the manufacturer.

As with most non-standard boards you need to make a few tweaks to the standard Arduino installation. Again ArTeC include instructions for installation. However you don't need those if you just want to use the Studuino with Sniff (or for that matter with Scratch - they provide a mod'ed version of Scratch too).

Plugging in and running Sniff setup detects the board fine (at least on Mac - let me know how you get on, on other platforms). If it doesn't check that there's a file: /dev/ttyXXX which shows that the driver is working correctly.

Running Sniff requires a few tweaks to the standard uno-sniff, and in the next release there'll be a stud-sniff. However to let you get started there's a zip file you can download which contains all of the extra's you need to add to the current Sniff release. Add stud-sniff to the Sniff/bin folder.

You should now be able to compile and install standard Sniff programs using stud-sniff. Try running blink from the Sniff/examples/Arduino folder:

stud-sniff blink.sniff

and the green light on the board should start blinking.


The Studuino's buttons are a nice touch - when I first got an Arduino, I was frustrated that there were button press examples, but no button on the board. Combined with the standard onboard LED, having a few buttons is a great help for beginners. The buttons are connected to A0-A3, but provided you don't press the buttons you should still be able to use those pins as you normally would.

make studuino studuinoButtons device
make buttonA boolean
make buttonB boolean
make buttonC boolean
make buttonD boolean

make led digital output 13

when start
.forever
..tell studuino to "checkButtons"
..if buttonA
...set led to off
..if buttonB
...set led to on

To use the buttons from Sniff, use the studuinoButtons device (it takes care of pull-ups, which Sniff normally doesn't), and tell the studuino to checkButtons. You can then use the state of bottonA-D to do whatever you like.

The Motor driver uses pins D2,3,4,5,7 & 8. In theory you should be able to use these for other tasks if you don't need the motors, but its probably best to avoid them if possible. It's perfectly possible to drive these directly from Sniff, but to simplify things (and make the code comparable with the standard Motor Shield), theres another device:

make buttons studuinoButtons device
make buttonA boolean
make buttonB boolean
make buttonC boolean
make buttonD boolean

make motors studuinoMotors device
make motor1 number
make motor2 number

when start
.forever
..tell buttons to "checkButtons"
..if buttonA
...set led to off
..if buttonB
...set led to on
..
..set motor1 to 0
..if buttonC
...set motor1 to 1
..if buttonD
...set motor1 to -1
..tell studuinoMotors to "update"
..
..wait 0.1 secs

Originally I set this up as a single device for both buttons and motors, but separating them is more flexible, and makes them more compatable with other Sniff programs.

Overall the Studuino is a nice board, with a couple of handy features, though it suffers from simply not being an Uno. The smaller CPU probably isn't a problem it you're just making simple robots, and if you're working with ArTeC's other products, then its great.

You can download all the bits you need to get started here. We'll add these to the next release. Let us know how you get on...

Saturday, 9 August 2014

Scratch@mit2014

We just spent the week at MIT in Boston for the 2014 Scratch conference. We've got lots to follow upon. We took more Sniff business cards than I ever thought we'd need, but we gave out every single one during an amazing poster session.

We demo'd the hot wheels speed trap, the sniff weather station, the heart monitor, and of course a bunch of neoPixels. Just follow the links to find out how to reproduce those projects yourself 

I also brought the gamebuino running Bounce Out. We'll post full details of that soon but it was a big hit with at least one kid who kept coming back to the stand for another go. 
Physical computing was a big emergent theme with lots of robots and lots of Arduino (and we brought home some studuino boards to use with Sniff). We even saw the odd raspberry pi. They fitted into a bigger theme of making, writing and coding. We teach kids to write, not so they can find jobs as writers, but because it allows them to move beyond being consumers of knowledge and become sharers and communicates of their own ideas. There's lots of talk in the new uk computing agenda about employability and not so much about how coding and making are fulfilling activities. 
It was great to meet the Scratch team, and they all seemed genuinely interested and supportive of Sniff. It was quite clear that the most important part of the scratch project is the community. Scratchers get as much out of sharing and collaborating on their work as they do creating it.

Sniff is still at the beginnings of its life, but one of the focuses for immediate future has to be to build the same sort of colaborative environment that scratch has. While we're putting better colaborative tools on place, if you talked to us at Mit and what we were saying made sense then download the code, leave a comment below,  drop us an email and follow us on twitter. 

Ian@sniff.org.uk (ian@dctsystems.co.uk)
Tom@sniff.org.uk
@sniffCode on twitter

Monday, 4 August 2014

Release 8

This week Sniff is off to the Scratch@MIT conference!!! We'll definitely by posting more about that later in the week, but as a result of this we've pushed up the release of Sniff V8 which is now available for download.

As usual this means support for a whole load of new devices, which we'll blog about over the next few weeks. Most importantly these include:

  • Gamebuino 
  • Punchthough Bean (not quite finished)
  • SIM900 Mobile Phone Shield

The Gamebuino is a really cool Arduino variant (compile with gb-sniff), in the form of a hand-held mini-console. Having fixed hardware, makes it simple to work with, and to prove it there's a really cool demo game in the examples folder: Bounce Out... like breakout with gravity! A full blog entry on this to follow.

Even if you don't have a Gamebuino you still win from this, as it uses the Nokia LCD screen. We already supported this screen, but the prospect of writing an arcade game for the Gamebuino prompted us to upgrade its performance, so now its super fast! The Gamebuino also comes with a really cool sound library, which we've modified and incorporated into Sniff, as an avrSound device. It lets you play 3 (or maybe 4) part harmonies without any hardware, other than a speaker. Again thats an entire tutorial in itself!

The Punchthrough Bean is another Arduino comparable (compile with bean-sniff), but this time it operates via Bluetooth, so you can program it over the air. You'll need to use the bean-loader to upload your hex file. The "bean" device which gives you access to the bean's onboard accelerometer, tricolour led and BLE serial needs more work, but it should get you started. Currently the Serial port only works as an output (SAY works, but ASK doesn't).

However there's also something we've not done for a while: we changed the syntax! Devices were previously identified by their device types, so if you made a dht device it was called dht. That still works, so you can carry on as before, but we've added the option to name devices so you can

make thermometer dht11 device
make display lcd device

This means you can swap out a ds18 for a dht11, or an lcdi2c for a regular lcd just by changing the declaration, rather than the whole code. However we've also taken the opportunity to rename some of the devices. Previously we tried to keep device names "meaningful" so for example the ds1307 device was called clock. Now you can name your own devices we can give the devices more specific names, and then you give them your own friendly names: "make clock ds1307 device". If you want a different kind of clock device (like the nativeClock device), then you can select it for yourself.

Finally we've improved string handling, so that it uses WAY less memory. When we initially implemented it we were just happy it worked, but now we've revisited it to re-use string workspace memory more efficiently (for example the Adventure game uses 1/5th of the memory it did).

Hopefully we've not broken anything - I'd have preferred to do a bit more testing, but we wanted to get all these goodies out to you before we head off to Boston!

Download