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
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>
- 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
{
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
{
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
ICSP
- Pin 1 label is pin1 of the AVR , not the ICSP!!!
- Use 500kHz for the programming speed, or you might get errors.