Lluis Nadal
/
Alcoholmeter
Alcoholmeter with MQ3 sensor
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); } }