Lluis Nadal
/
Alcoholmeter
Alcoholmeter with MQ3 sensor
Diff: main.cpp
- Revision:
- 0:05d4673b2832
- Child:
- 1:5a58f03abfe9
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sat Apr 09 14:04:34 2011 +0000 @@ -0,0 +1,174 @@ +/* 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. + +Tacher: 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 (24 hours is recommended for the manufacturer) 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); +} +}