Table of Contents

BAC Badge Project - Summary

What? This badge was designed for use at DEFCON 18. The badge measures your Blood Alcohol Content (BAC). The board consists of an Atmel ATMEGA328, MQ-3 Alcohol sensor, 7-segment display (4), and a 9V battery.

Who? Arko, Charliex, CHS, Mmca, BeaMeR

Where? NSL. Where else?

Why? Why not?

We were also mentioned in Wired: Wired - Defcon 18

Instructions

NOTE THIS: THIS IS A TOY. THERE IS ABSOLUTELY NO GUARANTEE THIS BADGE IS ACCURATE. PLEASE DO NOT USE THIS TO DETERMINE YOUR ABILITY TO DRIVE, OPERATE HEAVY MACHINERY, OR ANYTHING OF THAT SORT. PLEASE USE RESPONSIBLY.

1) You will notice the badge has a little toggle switch, toggle to turn the badge on and off. Turn the badge on, wait 2 seconds, you should see your display pad leds doing a little spin. This is stand by mode

2) Now hold the little temporary switch at the bottom, and your display should read 0.000 for a few seconds, then begin to climb.

3) Once it has stabilized 15-30 seconds (for example 0.124 most of the time), have either a sober person blow on it or wave it in the air for a calibrated air flow. The number should jump down to anything between 0.006-0.000.

4) Your calibrated and ready to go. Note, when you toggle the entire badge off, the calibration value goes away. If you let go of the temporary switch at the bottom, and let it go into stand by mode, it will hold on to the calibration value.

5) Hold the badge 6` away from your face and blow at the orange little sensor. You will get a rough reading of your BAC.

Troubleshooting

1) Have you tried turning it on and off again? … Seriously, try it and start at step one.

2) Stuck at for example 0.127? Try lightly touching the sensor, it's normal if it's hot. Then blow on it.

3) I dunno. I'll add more solutions as I figure them out. Your a hacker, you should be able to fix it. :)

Schematic & Board Layout

Parts

Arduino ATMEGA328 - Arduino Bootloader Preloaded

Alcohol Gas Sensor MQ-3

4-Digit 7-Segment Display

SPDT Mini Power Switch

5V Voltage Regulator

Battery Connector

16Mhz Oscillator

The other components are available on digikey (diode, resistors, capacitors, etc)

This is the board design for the NSL Badge. Scroll down for the Eagle files.

This is the schematic design for the NSL Badge.

Eagle Files:

NSL Badge Board: nsl badge - board

NSL Badge Schematic nsl badge - schematic

Code

Download the NSL Badge Code: nsl_badge_code.pde

<nowiki>

/*
/*
<code>
                               ======== Breathalizer Badge ==========
=====  Product of the [[NSL]] Hackerspace  =====
==  Board Schematic, Design & Code by: Arko  ==
                         ========== Board Layout & Design: CharlieX ========
====  Special Thanks to : CHS, M, and BeaMer  ====
                               ======================================
    ` ##§M##§§###########$##                                                                   ` 
    ` #§##§B##§V###§##§C######                                                                 ` 
    `   §§###§###   §#######B$                                                                 ` 
    `   9@C###§@§    #########                                                                 ` 
    `   ##§##§?##    §*###§##§         C######?V           ###C###M##         ####C9@  @###$B  ` 
    `   *@C###%MQ    §#V%%W§Q       *@##V*§$#MM6$@       @@###$B*@C###%   $W§$#B§$#V@ V###C@V# ` 
    `   ##?§$#*@V###?$W@V###       ?§$#9@V   ###?§$#   @@V###?§  $#Q@V##  #?$W§$#W§$#6@V###C@V ` 
    `   ###?§$#8@V###?@V##§##B    @W##§§B    *#%§Q@?  ##§$B%B*    #M§Q§#V   %V#§#VMC#@?##§$B%@ ` 
    `   ?##§%@V###?BC?M#$889C88  **$@@V##§#@######### ####C§$*M§QCC@@#V*?   M%V*Q9?C%  B§Q%CM  ` 
    `   @C9V@Q8C$     *@6#M9B§%6 %@Q*§B6#C?CQ?*9WQ%9  9QVC#89B§#*6CQ%#*B§   V?9$9QMV§          ` 
    `   M@Q@V6V88     8V9§@W96M$ §??V8M@C%            %**MQ@§*              $§VC%$@*           ` 
    `   C§8?M98QC     #M$9W%$6B9  VV$$§WCMQ           $%#W8§#QB             ?W8C?$W9@          ` 
    `  96C9@V?%$*6   89BVWV@W8@    VM$M#CC8V$@M$6M*%   V#$MC6W#§%%%*8#CM@   M*B@%9$W?          ` 
    `  $9$99M$?*8B$VM8CC§CW6W@*      %W%CC?@#§?B8@W%9    ?*%$9B%8Q*§BQ$Q9  6@V9#?V98C$M$M      ` 
    ` M@%??C88M$86M$QV§WC?B?V          Q%§B8§#%?MQ         B6§BM?B9@#$%    WQMW?BBBB?#§§6      ` 
  
* /

// #include <beer.h> // #include <booze.h>

  1. include <math.h>

int segmentA = 1; int digit0 = 8;

int state = 1;

// Sensor variables int value = 0; int recordvalue = 0;

int alcoholSensorInput; int alcoholPreviousInput = 0; int SensorSkip = 100; // 400

// Display variables int digitPosition = 2; int digitMatrixbac_badge = {3, 2, 1, 0}; int powerOfTenbac_badge = {1,10,100,1000};

// Timer variables unsigned long currentMillis; unsigned long previousMillis = 0;

// Revolver variables int revolverDigitPosition = 1; int revolverstep = 0;

// Name variables int nameDigitPosition = 2; int namestep = 0;

int zero10 = {0,0,0,0,0,0,0,0,0,0}; int calZero = 940; int zeroCount = 0; int zeroSum = 0; int zeroSkip = 2; int zeroSkipCount = 0;

int randomCount = 0;

int transitionVar = 0; int stateVar = 1;

// Display segment number reference // byte:GFEDCBA

byte numbers10

{

  B1000000, // 0
  B1111001, // 1
  B0100100, // 2
  B0110000, // 3
  B0011001, // 4
  B0010010, // 5
  B0000010, // 6
  B1111000, // 7
  B0000000, // 8
  B0010000  // 9

};

byte revolvers56

{

  B1011110,  // 1
  B1111111,  // 1
  B1111111,  // 1
  B1111111,  // 1
  B1111110,  // 2
  B1111111,  // 2
  B1111111,  // 2
  B1111111,  // 2
  B1111111,  // 3
  B1111110,  // 3
  B1111111,  // 3
  B1111111,  // 3
  B1111111,  // 4
  B1111111,  // 4
  B1111110,  // 4
  B1111111,  // 4
  B1111111,  // 5
  B1111111,  // 5
  B1111111,  // 5
  B1111110,  // 5
  B1111111,  // 6
  B1111111,  // 6
  B1111111,  // 6
  B1111100,  // 6
  B1111111,  // 7
  B1111111,  // 7
  B1111111,  // 7
  B1111001,  // 7
  B1111111,  // 8
  B1111111,  // 8
  B1111111,  // 8
  B1110011,  // 8
  B1111111,  // 9
  B1111111,  // 9
  B1111111,  // 9
  B1110111,  // 9
  B1111111,  // 10
  B1111111,  // 10
  B1110111,  // 10
  B1111111,  // 10
  B1111111,  // 11
  B1110111,  // 11
  B1111111,  // 11
  B1111111,  // 11
  B1110111,  // 12
  B1111111,  // 12
  B1111111,  // 12
  B1111111,  // 12
  B1100111,  // 13
  B1111111,  // 13
  B1111111,  // 13
  B1111111,  // 13
  B1001111,  // 14
  B1111111,  // 14
  B1111111,  // 14
  B1111111,  // 14

};

byte skape4

{

  B0001100,  // P
  B0001000,  // A
  B0001001,  // k
  B0010010,  // S

};

byte arko4

{

  B1000000,  // o
  B0001001,  // k
  B1001110,  // r
  B0001000,  // A

};

byte dong4

{

  B0011100,  
  B0111110,
  B0111110,
  B0000000,

};

byte chs4

{

  B0010010,  // S
  B0001001,  // H
  B1000110,  // C
  B1111111,  // null

};

byte charlieX4

{

  B1001110,  // r
  B0001000,  // A  
  B0001001,  // H
  B1000110,  // C

};

byte ascii26

{

  B0001000,  // A  
  B0000011,  // b
  B1000110,  // C
  B0100001,  // d
  B0000110,  // E
  B0001110,  // F
  B0010000,  // g
  B0001001,  // H
  B1111001,  // i
  B1110001,  // J
  B0001001,  // K
  B1000111,  // L
  B1111111,  // M
  B0101011,  // N
  B1000000,  // O
  B0001100,  // P
  B1011000,  // q
  B0110111,  // r
  B0010010,  // S
  B0000111,  // t
  B1000001,  // U
  B1000001,  // V
  B0000000,  // W  <--- LOL, are you nuts? on a 7 segment
  B0000000,  // X  <--- Ok, now that's just crazy
  B0010001,  // Y 
  B0100100,  // Z

};

byte goon4

{

  B1001000,  // n
  B1000000,  // O
  B1000000,  // O
  B0000010,  // g

};

byte donganimation12

{

  B0011100,  //1
  B0111110,
  B0111110,  
  B0000000,
  B1111111,  //2
  B0011100,
  B0111110,  
  B0000000,
  B1111111,  //3
  B1111111,
  B0011100,  
  B0000000,

};

void setup() {

  delay(100);      // Delay incase there is an upload interrupt 
  pinMode(0, OUTPUT);  // Decimal Point
  for (byte segment = 0; segment < 8; segment++)
  {
    pinMode(segmentA+segment,OUTPUT);   // Set the 7 segments as outputs
  }
  for (byte digit = 0; digit < 4; digit++)
  {
    pinMode(digit0+digit,OUTPUT);       // Set the 4 digits as outputs
  }  

}

void Display() {

  if(state == 0)  // Display Alcohol
  {
      digitalWrite(digit0 + digitMatrix[[digitPosition]], LOW); 
      digitalWrite(0, LOW);
      digitPosition++;
      if (digitPosition > 3) digitPosition = 0;
      int digitValue = value % powerOfTen[[digitPosition+1]] / powerOfTen[[digitPosition]];
      int number =  numbers[[digitValue]];
      if ((number > 0) || (value < 1024) || (value < powerOfTen[[digitPosition+1]]))
      {
        for (byte seg = 0; seg < 7; seg++)
        {
          digitalWrite(segmentA+seg, bitRead(number, seg));
        }
        if(digitMatrix[[digitPosition]] != 0)
        {
            digitalWrite(0, HIGH);  // Place the decimal point at the first digit ie: 0.000
        }
        digitalWrite(digit0 + digitMatrix[[digitPosition]], HIGH);
      }
  }
  else if(state == 1)        // Waiting loop
  {
      digitalWrite(digit0 + digitMatrix[[nameDigitPosition]], LOW); 
      nameDigitPosition++;
      if (nameDigitPosition > 3) nameDigitPosition = 0;
      int name =  dong[[nameDigitPosition]];
      for (byte seg = 0; seg < 7; seg++)
      {
        digitalWrite(segmentA+seg, bitRead(name, seg));
      }
      digitalWrite(0, HIGH);  // Place the decimal point at the first digit ie: 0.000
      digitalWrite(digit0 + digitMatrix[[nameDigitPosition]], HIGH);
  }
  else
  {
      digitalWrite(digit0 + digitMatrix[[3-revolverstep%4]], LOW); 
      if(revolverstep < 55) 
      {
        revolverstep++;
      }
      else
      {
         revolverstep = 0;
      }
      byte revolver =  revolvers[[revolverstep]];
      for (byte seg = 0; seg < 7; seg++)
      {
        digitalWrite(segmentA+seg, bitRead(revolver, seg));
      }
      digitalWrite(0, HIGH);
      digitalWrite(digit0 + digitMatrix[[3-revolverstep%4]], HIGH);
      delay(5);
  }
  delayMicroseconds(500);

}

void loop() {

  currentMillis = millis();
  if (currentMillis - previousMillis > SensorSkip)
  {
    previousMillis = currentMillis;
    alcoholSensorInput = analogRead(0);
    if(alcoholSensorInput < 1024 && alcoholSensorInput > 3)
    {
        if(0 < alcoholSensorInput - calZero)
        {
          value = pow((alcoholSensorInput - calZero),1.2); 
          //value = calZero;
        }
        alcoholPreviousInput = alcoholSensorInput;
        if(zeroSkipCount > zeroSkip)
        {
          zeroSkipCount = 0;
          zero[[zeroCount]] = alcoholSensorInput;
          if(zeroCount >= 10)
          {
              zeroCount = 0;
          }
          else
          {
              zeroCount++; 
          }
          for(int i=0; i<11; i++)
          {
            zeroSum = zeroSum+zero[[i]];
          }
          zeroSum = zeroSum/10;
          if(zeroSum-zero[[0]] < 11 && zeroSum-zero[[0]] >= 0)
          {
               if(zeroSum < 970)
               {
               calZero = zeroSum;  
               }
               else
               {
                  calZero = 970; 
               }
          }        
          zeroSum = 0;
        }
        zeroSkipCount++;
        state = 0;
        transitionVar = 0;
    }
    else
    {
        if(transitionVar == 0)
        {
          if(stateVar < 2)
          {
            stateVar++;
          }
          else
          {
            stateVar = 1; 
          }
          state = stateVar;
          transitionVar = 1;
        }
    }   
  }
  Display();

}

</nowiki></code>

Pictures

thumb|left thumb|left thumb|left thumb|left

ICSP

wiring