Alcoholmeter with MQ3 sensor

Dependencies:   TextLCD mbed

Files at this revision

API Documentation at this revision

Comitter:
lnadal
Date:
Sat Apr 09 14:04:34 2011 +0000
Child:
1:5a58f03abfe9
Commit message:

Changed in this revision

TextLCD.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TextLCD.lib	Sat Apr 09 14:04:34 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/simon/code/TextLCD/#44f34c09bd37
--- /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);
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sat Apr 09 14:04:34 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/3944f1e2fa4f