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.

Wednesday, 8 April 2015

Arduino breathalizer (with IR remote!)

Ages ago I picked up one of these MQ3 alcohol sensors. They're part of a whole series of similar sensors which can detect the levels of various gases. Most of them are a few pounds so if you have an application where you might be worried about specific chemicals then you can pick an appropriate one. The exception to this is the Carbon Dioxide sensor which is hard to get and expensive, which is unfortunate as it would actually be interesting so see how levels change in rooms as they fill up with people. As I just wanted to play around with it, I picked the alcohol vapour sensor - I figured alcohol  was something I had easy access to that I could use safely.

Though you can get them separately, its easiest to buy the sensor already mounted on a board, like this one.  These generally have four pins. Two are for gnd/power, and the other two are outputs. Of those one is digital, in that it either turns on or off when the gas level reaches a certain threshold, setable by a small pot on the back. If you just want an alarm, you can hook this straight to a piezo buzzer, and you're good to go.

We're more interested in the other output - the analog output which produces a voltage dependant on the gas level. This will connect straight in to an Arduino, and as I just got a multifunction shield, I though I'd use that.

We'll keep all of the display code from the last two posts, and just write the new code:

make alcohol analog input A5

make min number

when start
.set buzzer to high #or it will make noise!
.forever
..set message to [alcohol*100]
..wait 0.1 secs


Easy! we just read the value (which will have a value between 0 and 1) and scale by 100.

But what does that value mean?

Others have conducted this experiment and failed to accurately calibrate these sensors. This is in part due to them forgetting to write down the results during the more intensive parts of the test regime, but there's general consensus that its hard to get any specific numbers.

In my tests the reading generally started around 20 when I turned it on, but as the sensor warmed up (its got a heating element in it), the value dropped to around 3. Putting it near the top of a bottle of vodka instantly spiked the value to around 20 again, but it dropped back again quickly when moved. Drinking a tiny amount (in the name of SCIENCE!) so there would be alcohol on my breath, produced similar results (15-20), but the level on my breath dropped back down again fairly quicky, as the vapour dissipated from my breath.

A more extended test involving half a bottle of red wine (no one said this was going to be easy) produced a reading of around 15 some time after I'd stopped drinking. As there was alcohol in my bloodstream, the level on my breath was fairly constant.

Putting these together I came up with a fairly simple ad-hoc approach which should detect the basics - record the minimum reading the sensor has ever returned as a baseline. If you blow double that you've been drinking but are probably quite sober. If you blow 4 or 5 times the minimum you're probably having a good time. If you blow 8 times the minimum, then you're wasted!

make min number

when start
.set buzzer to high #or it will make noise!
.set min to 1
.forever
..set message to [alcohol*100]
..if alcohol < min
...set min to alcohol
..set buzzer to not alcohol > 4*min
..wait 0.1 secs

That's pretty easy to code. Each time around we just check against the minimum, and update the minimum if the new version is lower. We check if the reading is higher than 4 times the minimum and sound the buzzer if it is. You can adjust the threshold for this depending on if you want to scare your kids, or set a frat house drinking challenge, but 4 seemed a fair value to me to call someone drunk and set of the alarm.

It's important to remember that this calibration is pretty arbitrary, and even if it was correct it only applies to the sensor I bought, not the one you have - under no circumstances you should you think you're safe to drive (or do pretty much anything) because some circuit you found online says so!

So given this is just for fun, lets have some fun with it!



make min number
make fakeResults boolean


when start
.set fakeResults to no
.set buzzer to high #or it will make noise!
.set min to 1
.forever
..if alcohol < min
...set min to alcohol
..
..if fakeResults
...set message to [alcohol*5*100]
...set buzzer to off
..else
...set message to [alcohol*100]
...set buzzer to not alcohol > 4*min
..wait 0.1 secs

Here I've added a fakeResults flag. When fakeResults is true it sets the reading to 5 times what it should be, and sounds the alarm (remember the buzzer is logic low). In regular mode it works as before.

So how do we control the mode? Well we could just use a button, but it might be a giveaway that you're cheating. The multifunction shield has a socket for an IR receiver. If you get a tsop4838 (about $1 on eBay) then it will plug straight in to the left three empty sockets. To use it all we need to do is make a receiveIR device on pin 2. Then tell it to "read". It sets a variable keyPressed to a different number for each key (just write a program to print out keyPressed to find the appropriate values for any remote).



make irSensor receiveIR device 2
make keyPressed number

when start
.forever
..tell irSensor to "read"
..if keyPressed=18615
...set fakeResults to not fakeResults
..wait 0.1 secs

Then we check if a key is pressed and use it to toggle fakeMode.


No comments:

Post a Comment