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, 28 October 2014

Release 11: Sniff for Windows

One of the biggest issues in getting Sniff out to a wider audience has been that until now Sniff has been Unix only: it runs on Mac/Linux and Pi. While we recognise that most schools are running Windows. It's not that we didn't see that as a problem, but rather there were several very pragmatic reasons for developing on Unix over Windows:

  • Portability: Sniff runs essentially unchanged on all Unix platforms
  • Developer Tool: Unix is just better set up to develop an system like this. It's easier for us, but also easier for users: Apple/Pi/Linux provide all the pieces users need, whereas MS don't.
  • Developer Skills: We like Unix. It's a better platform, so we develop for that first.
However we've finally found the resources to develop a Windows build. Release 11 includes initial support for Windows. In fact R11 comes in two favours: Generic and Windows. The generic version runs on all platforms, including Windows but if all the text files are all in "Unix" format, which may cause problems (If you've worked on cross platform systems before you'll understand), so we've also made a Windows only release which will work better, but only includes the Windows components.

On all platforms you need a C compiler, but this is trickier on Windows that Unix platforms, as its not included by default (and MS charge for their Visual Studio, while Apple give away Xcode for free!). However we can use MinGW. This is a Windows version of the tools usually used to develop for Linux. You'll need to download it from www.mingw.org and install it, along with the included Msys tools. Once you've done this you're read to go!

Download the Sniff Windows version, and unzip it in the MSys home folder (something like c:\mingw\msys\1.0\home\username). This is an odd place to work but it's how MinGW likes to do things, then open an MSys Shell (as you set it up when you installed MinGW), and typing "ls" should show you the Sniff folder. "cd Sniff", then type ". ./setup" just as you would on any other platform to get everything setup!

From there on everything's the same. Use the MSys shell to compile and run the examples using the same commands you'd use in Unix (cd examples/Generic; sniff hello.sniff; ./hello). Arduino works (using uno-sniff). Most of the examples that previously were in the Unix folder are now in a folder called Hosted, as they run fine on Win32.

Once you've compiled a program with Sniff for Windows, its a regular Windows program so you can run it from the DOS CMD prompt, or even double click on it to make it go!

As this is the first release for Windows, there are likely to be a few glitches and problems, simply because the platform is different (and and of course there are different versions of Windows), so any feedback is appreciated.


Saturday, 25 October 2014

Arduino phone home

Every month or so someone gets 5 minutes of internet fame claiming they just invented their own smart phone using a raspberry pi and a few hundred pounds in parts... Trouble is that's a lot of money for something that's actually not a very good smart phone. I'm far more interested in building a dumb phone. For about £30 you can build a phone based on an Arduino. If you wanted to you could add a touch screen, but its far more fun to think about what you could do with a phone which has no screen at all, but is attached to one of your projects: Hook it into a temperature sensor, and it will phone you when your greenhouse gets to cold for your tomatoes. Or use a humidity/water depth gauge and get it to send you a text to let you know your garage is flooding...

To make a phone you basically need a GSM shield. These used to be quite expensive, but the price has fallen a lot, and you can get one for about £20 now. There are some variations, but most of them are based around the SIM900 chipset. The main difference between them is that they may use different pins: The Sniff device is set up to use pin8 to control power on, 9 reset, 2 receive and 3 transmit. These are easily changed in lib/Xphone.c if you have a slightly different model.

I also hooked up an i2c lcd display, so I could see what's going on. We can set up the drivers for the phone and the display in Sniff as:

make i2c device
make display lcdi2c device 4
make message string
make displayFlush boolean
make phone device

make phoneNumber string

I was using a 4 line LCD - hence the 4 config parameter to the lcdi2c device.

Then you start up the first thing that happens is that the system tries to automatically turn then the phone on, and connect to the network. This can take a few seconds, so we start by printing a message and then waiting for the phone to tell us its ready:

when start
.set message to "Sniff Phone"
.tell display to "show"
.
.repeat until message="ready"
..wait 0.5 secs
..tell phone to "checkStatus"
.tell display to "show"
.

Once "checkStatus" returns the "ready" message we're good do go. From here on in there are basically 4 things we might want to do: answer a phone call, make a phone call, send an SMS or receive an SMS. The GSM board also supports mobile data, but that at least in the UK that can get expensive if you're not on the right contract. By contrast for £5/month, I can send and receive unlimited texts, receive calls, and make unlimited calls to phones on the same network. If I only receive calls and texts, and may send a few texts, than I can probably make that £5 last all year.

The easiest thing to do is send and SMS:
.set phoneNumber to "+441234111222"
.set message to "Sent from my Arduino"
.tell phone to "sendSMS"
.tell display to "show"

We just set the number and the message, and the tell the phone to "sendSMS". If all goes well then the variable message should be set to "Sent", or if there's a problem it will be set to "Failed".

Calling a number is almost as easy:
.set phoneNumber to "+441234111222"
.set message to join "Calling:" phoneNumber
.tell display to "show"
.tell phone to "startCall"

You can plug a headset into the GSM shield, so you can chat to someone! One project we've discussed is for a someone we know who is disabled, and unable to dial a phone: It would be trivial to  make a custom phone which dials their emergency contact, by pressing a single large button.

During a call you can check its status by calling:
.tell phone to "checkStatus"
.tell display to "show"
.set message to join "busy:" phoneNumber
.tell display to "show"
This also works for incoming calls too.

When you're done just hang up:
.tell phone to "endCall"

Receiving calls and texts is a bit harder, as they can arrive at any time, so you need to check for them:
.forever
..broadcast checkSMS and wait
..wait 0.5 secs

To actually check the message:
when checkSMS
.tell phone to "checkSMS"
.if not message = ""
..tell display to "show"
..set message to join "from:" phoneNumber
..tell display to "show"
..tell phone to "deleteSMS"

We try to receive the message by telling the phone to "checkSMS". which will fill in the message, and phoneNumber (though note that on AVR's Sniff strings are limited to 128 characters which is shorted than the longest possible message - there's simply not enough memory on an Arduino to hold long strings). Here we print out the message, and number then delete the SMS. If you don't delete it, it will be there next time you check.

You could use the contents of the message to do pretty much anything - for example you could send a text to the arduino, and use its contents to change the colour of your neoPixel christmas tree lights (When I show this code in CPD groups with teachers I also point out it could be used to do unpleasant stuff that the chemistry teacher could help them with, but its probably not in my best interests to make that joke online...).

The final think we can do as answer a phone call. These have to be handled slightly differently to texts, as while texts can always be stored for later calls pretty much need to be handled straight away.

.repeat until not message = "ready"
..wait 0.5 secs
..tell phone to "checkStatus"
..if message="ringing"
...set message to "Incoming Call"
...tell display to "show"
...set message to join "From:"phoneNumber
...tell display to "show"
...
...tell phone to "answerCall"
...

When we call "checkStatus" it will return "ringing" if there's an incoming call. We can also get the caller ID. If we want to answer the just tell the phone to "answerCall".

We can wait for the phone to either stop ringing, or for the call to end (busy status) by waiting for the status to go back to "ready":

...repeat until message="ready"
....tell phone to "checkStatus"
....wait 0.5 secs
...
...set message to "call ended"
...tell display to "show"

And that's all the bits you need to integrate phone calls and texts into you app. All of these are demonstrated in the sPhone.sniff example included in the current Sniff release (along with the necessary device files). sPhone isn't a complete phone, but rather all the code here broken into parts you can use for yourself, and a general demo of the phone functions.

Lets put them together some simple code that waits for a call, and then sends  a text back to that number back. You could use this to remotely check the status of an experiment, but it only sends you data when you (or anyone else) asks for it:

make lastPhoneNumber string

.forever
..tell phone to "checkStatus"
..repeat until message = "ringing"
...wait 0.5 secs
...tell phone to "checkStatus"
..
..set lastPhoneNumber to phoneNumber
..
..repeat until message = "ready"
...wait 0.5 secs
...tell phone to "checkStatus"
..
..set phoneNumber to lastPhoneNumber
..set message to "hello from phone"
..tell phone to "sendSMS"

Lets assume you've set everything up as before. Now we wait for the status becomes "ringing" to indicate that there's call. This also sets the phoneNumber variable, which we copy to lastPhoneNumber (strictly we don't need to do this, but its safer and clearer). Now just wait for the call to go away, and then send out a text containing whatever data you think the user wanted.

One final obligatory comment: Don't make an auto-dialler which calls random people. Only use it with your own phones, or you could make a lot of people unhappy.

Wednesday, 22 October 2014

The Temperature Differential

Release 10 had a really significant change to the way it handles devices - changes that mean rewriting code for every device that's been supported so far. It was a LOT of really tedious and intense work, but the change was necessary, and now we're going to do an experiment that uses the new feature that all that work went towards.

In the original implementation of Sniff it was clear that there needed to be a way to hook into external library code, so that Sniff wasn't just a sandbox, but a real tool. In Scratch that takes the form of additional "extension" blocks, but that approach is fundamentally problematic (and the Scratch Team are still struggling with this), as it creates an explosion of blocks. Each new device essentially extends the language. This wasn't really an option for Sniff. Instead we added the 'tell" command so you could tell a library to "doSomething", essentially providing a mechanism for Sniff to call an external C function. Libraries of external code are good solid programming practise.

However it turned out it worked a little too well. We LOVED devices, and writing new devices for all sorts of hardware was great fun. And as we wrote more we started to want to do more with them, and so for example the DS18 thermometer library and the DHT thermometer library started to become more like objects. We added the configuration parameter so you could bind a ds18 to a particular pin. Then we added aliasing so you could swap between different libraries with similar operations.

However one thing was missing: multiple instances. What if we wanted two thermometers? Sure we could use one ds18 and one dht, but that's clunky. We needed a way to connect two ds18's on different pins. With the new release that becomes possible, and it works exactly as you'd expect. Let's connect two ds18:

make airThermometer ds18 device A2
make pondThermometer ds18 device A3

and it simply works. Of course not all devices can have multiple instances - for most devices its simply not possible to physically connect multiple pieces of hardware, but for the types of devices where it makes sense, it should just work (by which we mean we spent many hours making it work, so it would "just work" for you).

So what can we do with this... Well in the gardens of Sniff Manor is the ornamental lake, and in winter the fish seem to get along fine, even when the surface freezes. If we had two thermometers we could measure the air temperature and the water temperature a few feet down and understand whats going on.



The DS18 family of thermometers, are cheap, use a single pin, and are available in a waterproof casing/cable configuration. Wiring up a DS18 is pretty easy: connect the black wire to earth, red to 5V, and yellow to a data pin. The only tricky bit is to connect a 4K7 resistor between  signal and 5V, and you're good to go.

As this is going to be outside, running on batteries an Arduino is a better choice than a Pi, but the DS18 plugs into a Pi fine, so for other applications the code would run fine on a Pi too.

make i2c device
make display lcdi2c device
make message string
make displayFlush boolean

when start
.forever
..tell pondThermometer to "start"
..tell airThermometer to "start"
..wait 2 secs
..tell airThermometer to "read"
..set message to join "Air  " [ temperature ]
..tell display to "show"
..tell pondThermometer to "read"
..set message to join "Pond " [ temperature ]
..tell display to "show"

As this wasn't going to be connected to the computer I added an i2c lcd text display. The wiring here is even easier, as they simply plug into the breakout shield with a 4pin dupont cable. With that done the code is about as trivial as it gets.

The next step was to add data logging, so I added an SD card reader. Using the sdcard and filesystem devices I added code to write the readings to a file once per minute. At this point I could have removed the LCD display, as its using battery, and isn't strictly needed to log the data, but it was still useful to be able to see that everything was working.

Now we just put it all in a plastic bag, and of down to the lake!


Here's everything set up at around 6PM at night. You can just about see that the air temperature is around 21 degrees C, and the water is 17.


Two hours later we're just around sunset. Air temp has dropped to just under 18, but the water has stayed rock solid at the same 17 degrees.

The data on the SD card is record as text with each line containing the time, and the two temperatures, with comma's between them. This is exactly what we need to load into any spreadsheet program as a CSV file. I bit of tweaking an we get a graph:


Wow! That's real data that is, and it shows something pretty amazing. This log runs for a little under six hours starting late morning. Nothing much happens for the first hour, but then the sun gets over the trees at around lunchtime, and the air starts to warm up from around 23 degrees to over 28. We also get lots of great peaks and troughs - presumably from cloud cover. By mid afternoon we see that the has got less intense, and temperature starts to fall away.

However sometimes the most exiting thing is what doesn't happen - look at the green line. It starts at about 16.5, and be mid afternoon its risen by only 1 degree. Towards the end of the day its still going up slightly (as the sun is still hitting it, and the air is still warmer than the water), but it's levelled off.

1 degree is pretty small... or is it? 1Joule of energy is required to raise the temperature of 1g of water by 0.24K (or 0.24C - its the same thing). We've raised it by 1 degree in about 4 hours, or 1 joule/gram/hour.

To find out how much energy that is in total we need to know water we have! That's easy its 5mx2m and 1m deep. Or 10 cubic metres. 1 cubic cm of water weights 1g, and there are 1million cubic cm in 1 cubic metre. In other words we've got 10million grams of water!!!!! That sort of changes things as our 1j/g/h is now 10,000,000 joules per hour! That's about 3000 joules per second, which are better known as Watts. 3kWatts is quite a lot of power - if you tried to get that much power out of an electric socket you'd blow the fuse! You could power pretty much all of the electrical stuff in your house with that... until it gets dark.

Theoretically we could get more than that: According to more accurate measurements we should be able to get 1.4kW per square meter which would make a very impressive 14kW of energy going into the pond, but no system is 100% efficient, and the energy going into the pond is also heading the ground at the bottom of the pond (aka the planet - its pretty big!), so if we're keeping 3kW (about 20%), then that's pretty good.

I get really excited when an experiment works like this - we got a great graph, analysed some data, and got some big numbers which actually match what the theory says we should get. That's a good days work!

the next step is to hook up some better batteries, and solar cells and see if we can get this thing running 247!