Freigeben über


Breathalyzer on a new board

As you may know, when a new board is announced, I try to find a good project for it.  I have to tell you that this goal is keeping me pretty busy.  This one I had to finish at the request of the Channel 9 team for PDC – that is a breathalyzer on the new Secret Labs Netduino Mini (https://www.netduino.com/netduinomini).   (Note: At this posting, the Netduino Mini is not yet available in distribution but will be in a few days – it can be preordered at:https://forums.netduino.com/index.php?/topic/551-pre-order-your-netduino-mini/.)

                                             

The mini is a 24 pin standard DIP configuration.  This means that there are not shields that you can plug into it but a number of places that you can plug it into.  For example, any breadboard (as we will see) and any device that currently takes a Parallax Basic Stamp.  I like this package for that flexibility and I like is because it is just so tiny (34 mm x 17 mm).  Don’t let this bare bones package deceive you though.  You have SPI, I2C, 4 ADCs, 4 PWMs, serial UART, and 16 GPIOs.  Compare that with anything else this size and then add Visual Studio and C# productivity!!

This is not a design for a breathalyzer that is going to let you know if you are just under the legal limits in your state and safe to drive – calibration is really hard for these devices.  You need to be able to control the exact alcohol exposure to know how to calibrate and then it varies with temperature and humidity.  But for the purposes of a fun project and to give to my daughter whose friends are just starting to drive, it is sufficient.  The breathalyzer end result looks like the picture below and works as shown in the video

IMG_0258

>. 

 

Connecting up

With this form factor (ie no USB connector), how do you connect to Visual Studio and how do you power the device?  First, you need to connect to the serial port instead of the USB Port.  To do this on the breadboard, you need to hack a serial cable.  You can see the serial pin numbering below.  image

What you need are:

Serial pin #2 to connect to Mini pin #1 - TX (Debug/Com2)

Serial pin #3 to connect of Mini pin #2 - RX RX (Debug/Com2)

Serial pin #5 to connect to Mini pin #4 - GND

You can see these in the picture below.  Then I have a regulated 5V power source running on 2 AA batteries (Bodhilabs VPack 5.0V).  I put a simple toggle switch to turn the power on and off.  This is connected to the side rails of the breadboard and jumpered into Mini pin #21 (regulated 5V input) and Mini pin #23 (GND).  Finally, I put in an LED to let me know when the power is on (so that I don't waste batteries).   That is all you need to set up the Mini to be run and ready to be programmed.  In fact, it is a good time to ping the device using MFDeploy to make sure that it responds  with ‘TinyCLR’ to double check your connections.  Now you can treat the serial port in VS just like you did the USB port in other devices.  Remember to set the NETMF tab accordingly. 

 IMG_0251

The Sensor

The sensor is an MQ-3 that I  bought at Pololu.com because I liked their carrier board.  It takes the six pins of the sensor and reduces that to three that fit into a right angle header.  This sensor costs less than $5.00.  I used a 100K variable resistor for calibration.  The sensor outputs 0-5V which is too much for the Mini to handle so I added a voltage divider to step it down by a third to 3.3V.  The analog input port theoretically returns a value between 0 and 1024 but the actual baseline measurement is dependant on a number of variables (calibration setting, temperature, and humidity).  So, I let the device stabilize before starting the measures (see The Code below). 

IMG_0260                    IMG_0263

Lighting up

As you can see, there is one clear LED and three each green, yellow, and red LEDs that I can light up to reflect the reading we get from the MQ-3.  I put three values of resistors in each color group (870, 390, and 100 Ohms) so the the first LED of each color is dimmer than the last.  These are not the optimal values to use.  I calculated them with the 5V power source in my head but these are driven off of GPIOs from the Mini which are 3.3V so that whole thing is a little dimmer than it might be.  After I built this project, I ran across something that you might want to use instead.  This is the Elabguy LED-Rainbow.  In this LED array, the LEDs are not driven by the processor but by the 5V power supply and there is a simple transistor switch that the processor interfaces with.  The resistors are internal to the array as well – much easier for the next project. 

IMG_0252

The Code

It is telling that I spend so much more time talking about the hardware than the software. I found for my setup that adjusting the baseline (using the variable resistor) so that it is around 200 gives me a full range of values.  I blink the clear LED for 15 seconds to let the sensor heat up and stabilize.  Then I take a current baseline measurement and calculate the steps for each LED.  The rest is really simple.

using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoMini;

namespace BreathalyzerMini
{
    public class Program
    {
        public static void Main()
        {
            Cpu.Pin[]  pinMap = new Cpu.Pin[10]  

                            {
                                (Cpu.Pin)Pins.GPIO_PIN_13,
                                (Cpu.Pin)Pins.GPIO_PIN_14,
                                (Cpu.Pin)Pins.GPIO_PIN_15,
                                (Cpu.Pin)Pins.GPIO_PIN_7,
                                (Cpu.Pin)Pins.GPIO_PIN_8,
                                (Cpu.Pin)Pins.GPIO_PIN_9,
                                (Cpu.Pin)Pins.GPIO_PIN_10,
                                (Cpu.Pin)Pins.GPIO_PIN_11,
                                (Cpu.Pin)Pins.GPIO_PIN_12,
                                (Cpu.Pin)Pins.GPIO_PIN_17
                            };

            OutputPort[] leds = new OutputPort[10];
            AnalogInput br = new AnalogInput((Cpu.Pin)GPIO_PIN_5);        

            int baseline = 0;
            int step;
            int value;

            // build
            for (int idx = 0; idx < leds.Length; ++idx)
            {
                leds[idx] = new OutputPort((Cpu.Pin)pinMap[idx], false);
            }

            // let the unit adjust
            for (int i = 0; i < 30; i++)
            {
                leds[0].Write(true);
                Thread.Sleep(500);
                leds[0].Write(false);
                Thread.Sleep(500);
                value = br.Read();
                Debug.Print(value.ToString());
            }
            // set baseline and steps
            baseline = br.Read() + 20 ;
            step = (1024 - baseline) / 8;
            while (true)
            {

                value = br.Read();
                Debug.Print(value.ToString());

                if (value > 0)
                    leds[0].Write(true);
                else
                    leds[0].Write(false);

                if (value > baseline)
                    leds[1].Write(true);
                else
                    leds[1].Write(false);

                if (value > (baseline + step))
                    leds[2].Write(true);
                else
                    leds[2].Write(false);

                if (value > (baseline + (2*step)))
                    leds[3].Write(true);
                else
                    leds[3].Write(false);

                if (value > (baseline + (3*step)))
                    leds[4].Write(true);
                else
                    leds[4].Write(false);

                if (value > (baseline + (4*step)))
                    leds[5].Write(true);
                else
                    leds[5].Write(false);

                if (value > (baseline + (5*step)))
                    leds[6].Write(true);
                else
                    leds[6].Write(false);

                if (value > (baseline + (6*step)))
                    leds[7].Write(true);
                else
                    leds[7].Write(false);

                if (value > (baseline + (7*step)))
                    leds[8].Write(true);
                else
                    leds[8].Write(false);

                if (value > (baseline + (8*step)))
                    leds[9].Write(true);
                else
                    leds[9].Write(false);

                Thread.Sleep(1000);
            }

        }

    }
}

 

Conclusion

This project is not going to get you a breathalyzer that will stand up in court but it will give you a way to verify that someone has been drinking and whether a lot or a little.  This was done as a demo for PDC.  There was also a Tweeting Breathalyzer demo done on the Netduino Plus which you can see at: 

https://player.microsoftpdc.com/Session/276fa8c4-c2e2-41b2-b552-80490c2a196c 

Technorati Tags: NETMF,.NET Micro Framework,Netduino,NEtduino Mini,Breathalyzer,Education,Instruction,Electronics

This form factor may not be for everyone – it does not come with all the current Arduino shield options that the original Netduino can draw on.  Maybe it just takes me back to my old bread boarding and wire wrapping days but I like this little guy.  Maybe it’s just that I like to see people’s reaction when I hold up this tiny thing and say - ‘This has .NET running on it!’.