Alcoholmeter with MQ3 sensor

Dependencies:   TextLCD mbed

main.cpp

Committer:
lnadal
Date:
2011-04-09
Revision:
2:5bb97fd609cb
Parent:
1:5a58f03abfe9

File content as of revision 2:5bb97fd609cb:

/* Alcoholmeter

Range: 0-3000 ppm.

*********************************************************************************

This project was done in 2010-11 school year in Molins de Rei (Barcelona, Spain)
in Lluis de Requesens Secondari School. 

Teacher: Lluis Nadal.
Students: Agnes Garriga, Manel Tuells.

*********************************************************************************

Sensor: MQ-3 alcohol sensor.(http://www.sparkfun.com/;
http://www.bricogeek.com/shop/).

MQ-3 sensor wiring:
H1(5V), H2(ground), A(5V), B (R load = 500 Ohm - 1%),
R load (mBed pin 20 - ground).

Analog out (for datalogger or multimeter): mBed pin 18 (1V = 1000 ppm).



MQ-3 sensor response is not linear. Calibration was done by passing air
(with a fishtank air pump)
through a dilute solution of ethanol in water.
The resulting air saturated of ethanol vapor and water vapor, was continuously
introduced in an open container containing the sensor. Th voltage across a
load resistor was measured.

A 500 Ohm-1% load resistor was selected in order to achieve a measuring range
of 3000 ppm.

After a bit difficult calculations, the sensor response was aproximated in a
five degree polynomial:

X = V(in)
ppm =  2.71494E+02*X - 3.10999E+02*X^2 + 6.85051E+02*X^3 - 3.47587E+02*X^4 + 7.47499E+01*X^5


For more accurate readins is recommended a minimum heating time of 5 minutes
(the manufacturer recommends 24) but 1 minute give satisfactory results.
After heating, the sensor is autozeroed by averaging 5 measures.

In heating and in autozero operations the sensor must be left away of alcohol vapors! 

 
THIS FREE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. ENJOY IT.

*/
//*******************************************************************************


#include "mbed.h"
#include "TextLCD.h"
#include <sstream>
using namespace std;




float concentration (float x){

const float A[] = { 2.71494E+02, -3.10999E+02, 6.85051E+02, -3.47587E+02, 7.47499E+01}; 
float result;
float B[4];
B[0] = x*x;
B[1] = B[0]*x;
B[2] = B[1]*x;
B[3] = B[2]*x;

result = A[0]*x+A[1]*B[0]+A[2]*B[1]+A[3]*B[2]+A[4]*B[3];
return result;
}




char messages[5][16] = {"Heating sensor", "64 seconds", "Autozero", "Ready!", "ppm"};


int L;
float x;
float x0[5];
float x_initial;

TextLCD lcd(p24, p26, p27, p28, p29, p30); // Wiring microcontroller - LCD:
// rs(4), e(6), d4(11), d5(12), d6(13), d7(14) (R/W(5) a 0)

DigitalIn pushbutton = p8; // Pushbutton (normally open). Stops initial heating time when it is pressed.
AnalogOut output(p18); // Analog output to a multimeter or datalogger (1V = 1000 ppm).



void text_screen( char message[],  int colum, int row) {

lcd.locate( colum, row);
lcd.printf(message);

}



int main() {

output = 0.0;
lcd.cls();

text_screen(messages[0], 0, 0);
text_screen(messages[1], 0, 1);
wait(2);



for (int j = 0; j<4; j++){

lcd.cls();  // Heating sensor 4x16 = 64 seconds
text_screen(messages[0], 0, 0);


for (int i = 0; i<16; i++){  
if (pushbutton == 1){   // Pressing pushbutton stops initial heating and enters in measuring mode.
 break;
  }
 lcd.locate(i, 1);
 lcd.putc(62);
wait(1);
}
}

lcd.cls();
text_screen(messages[2], 0, 0);
wait(2);


AnalogIn value(p20); // Reads sensor voltage as a float int the interval (0-1) corresponding to (0 - 3.3V).



for (int i=0; i<5; i++){

x0[i] = value;
wait(2);

}
x_initial = (x0[0]+x0[1]+x0[2]+x0[3]+x0[4])/5.0; // Autozero. Average of 5 initial measures.

lcd.cls();
text_screen(messages[3], 0, 0);
wait(2);

while(1) {
x = value;
x = (x-x_initial)*3.3; // Calculate real voltage. 

if(x<0) x = 0;

x = concentration(x);

output = x/3000;  // If analog readings do not match digital readings you can adjust this value (1000 ppm = 1V).

wait(0.1);

// Float to string conversion.
stringstream ss (stringstream::in | stringstream::out);
ss <<x;
string reading = ss.str();
L = reading.length();


lcd.cls();
for (int i=0; i<L; i+=1){
lcd.locate(i,0);
lcd.putc(reading[i]); 



text_screen(messages[4], 10, 0);
}
wait(2);
}
}