Alcoholmeter with MQ3 sensor

Dependencies:   TextLCD mbed

Committer:
lnadal
Date:
Sat Apr 09 14:04:34 2011 +0000
Revision:
0:05d4673b2832
Child:
1:5a58f03abfe9

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
lnadal 0:05d4673b2832 1 /* Alcoholmeter
lnadal 0:05d4673b2832 2
lnadal 0:05d4673b2832 3 Range: 0-3000 ppm.
lnadal 0:05d4673b2832 4
lnadal 0:05d4673b2832 5 *************************************************************************************************************************
lnadal 0:05d4673b2832 6
lnadal 0:05d4673b2832 7 This project was done in 2010-11 school year in Molins de Rei (Barcelona, Spain) in Lluis de Requesens Secondari School.
lnadal 0:05d4673b2832 8
lnadal 0:05d4673b2832 9 Tacher: Lluis Nadal.
lnadal 0:05d4673b2832 10 Students: Agnes Garriga, Manel Tuells.
lnadal 0:05d4673b2832 11
lnadal 0:05d4673b2832 12 **************************************************************************************************************************
lnadal 0:05d4673b2832 13
lnadal 0:05d4673b2832 14 Sensor: MQ-3 alcohol sensor.(http://www.sparkfun.com/; http://www.bricogeek.com/shop/).
lnadal 0:05d4673b2832 15
lnadal 0:05d4673b2832 16 MQ-3 sensor wiring:
lnadal 0:05d4673b2832 17 H1(5V), H2(ground), A(5V), B (R load = 500 Ohm - 1%), R load (mBed pin 20 - ground).
lnadal 0:05d4673b2832 18
lnadal 0:05d4673b2832 19 Analog out (for datalogger or multimeter): mBed pin 18 (1V = 1000 ppm).
lnadal 0:05d4673b2832 20
lnadal 0:05d4673b2832 21
lnadal 0:05d4673b2832 22
lnadal 0:05d4673b2832 23 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.
lnadal 0:05d4673b2832 24 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.
lnadal 0:05d4673b2832 25
lnadal 0:05d4673b2832 26 A 500 Ohm-1% load resistor was selected in order to achieve a measuring range of 3000 ppm.
lnadal 0:05d4673b2832 27
lnadal 0:05d4673b2832 28 After a bit difficult calculations, the sensor response was aproximated in a five degree polynomial:
lnadal 0:05d4673b2832 29
lnadal 0:05d4673b2832 30 X = V(in)
lnadal 0:05d4673b2832 31 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
lnadal 0:05d4673b2832 32
lnadal 0:05d4673b2832 33
lnadal 0:05d4673b2832 34 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.
lnadal 0:05d4673b2832 35 After heating, the sensor is autozeroed by averaging 5 measures.
lnadal 0:05d4673b2832 36
lnadal 0:05d4673b2832 37 In heating and in autozero operations the sensor must be left away of alcohol vapors!
lnadal 0:05d4673b2832 38
lnadal 0:05d4673b2832 39
lnadal 0:05d4673b2832 40 THIS FREE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. ENJOY IT.
lnadal 0:05d4673b2832 41
lnadal 0:05d4673b2832 42 */
lnadal 0:05d4673b2832 43 //**********************************************************************************************
lnadal 0:05d4673b2832 44
lnadal 0:05d4673b2832 45
lnadal 0:05d4673b2832 46 #include "mbed.h"
lnadal 0:05d4673b2832 47 #include "TextLCD.h"
lnadal 0:05d4673b2832 48 #include <sstream>
lnadal 0:05d4673b2832 49 using namespace std;
lnadal 0:05d4673b2832 50
lnadal 0:05d4673b2832 51
lnadal 0:05d4673b2832 52
lnadal 0:05d4673b2832 53
lnadal 0:05d4673b2832 54 float concentration (float x){
lnadal 0:05d4673b2832 55
lnadal 0:05d4673b2832 56 const float A[] = { 2.71494E+02, -3.10999E+02, 6.85051E+02, -3.47587E+02, 7.47499E+01};
lnadal 0:05d4673b2832 57 float result;
lnadal 0:05d4673b2832 58 float B[4];
lnadal 0:05d4673b2832 59 B[0] = x*x;
lnadal 0:05d4673b2832 60 B[1] = B[0]*x;
lnadal 0:05d4673b2832 61 B[2] = B[1]*x;
lnadal 0:05d4673b2832 62 B[3] = B[2]*x;
lnadal 0:05d4673b2832 63
lnadal 0:05d4673b2832 64 result = A[0]*x+A[1]*B[0]+A[2]*B[1]+A[3]*B[2]+A[4]*B[3];
lnadal 0:05d4673b2832 65 return result;
lnadal 0:05d4673b2832 66 }
lnadal 0:05d4673b2832 67
lnadal 0:05d4673b2832 68
lnadal 0:05d4673b2832 69
lnadal 0:05d4673b2832 70
lnadal 0:05d4673b2832 71 char messages[5][16] = {"Heating sensor", "64 seconds", "Autozero", "Ready!", "ppm"};
lnadal 0:05d4673b2832 72
lnadal 0:05d4673b2832 73
lnadal 0:05d4673b2832 74 int L;
lnadal 0:05d4673b2832 75 float x;
lnadal 0:05d4673b2832 76 float x0[5];
lnadal 0:05d4673b2832 77 float x_initial;
lnadal 0:05d4673b2832 78
lnadal 0:05d4673b2832 79 TextLCD lcd(p24, p26, p27, p28, p29, p30); // Wiring microcontroller - LCD:
lnadal 0:05d4673b2832 80 // rs(4), e(6), d4(11), d5(12), d6(13), d7(14) (R/W(5) a 0)
lnadal 0:05d4673b2832 81
lnadal 0:05d4673b2832 82 DigitalIn pushbutton = p8; // Pushbutton (normally open). Stops initial heating time when it is pressed. .
lnadal 0:05d4673b2832 83 AnalogOut output(p18); // Analog output to a multimeter or datalogger (1V = 1000 ppm).
lnadal 0:05d4673b2832 84
lnadal 0:05d4673b2832 85
lnadal 0:05d4673b2832 86
lnadal 0:05d4673b2832 87 void text_screen( char message[], int colum, int row) {
lnadal 0:05d4673b2832 88
lnadal 0:05d4673b2832 89 lcd.locate( colum, row);
lnadal 0:05d4673b2832 90 lcd.printf(message);
lnadal 0:05d4673b2832 91
lnadal 0:05d4673b2832 92 }
lnadal 0:05d4673b2832 93
lnadal 0:05d4673b2832 94
lnadal 0:05d4673b2832 95
lnadal 0:05d4673b2832 96 int main() {
lnadal 0:05d4673b2832 97
lnadal 0:05d4673b2832 98 output = 0.0;
lnadal 0:05d4673b2832 99 lcd.cls();
lnadal 0:05d4673b2832 100
lnadal 0:05d4673b2832 101 text_screen(messages[0], 0, 0);
lnadal 0:05d4673b2832 102 text_screen(messages[1], 0, 1);
lnadal 0:05d4673b2832 103 wait(2);
lnadal 0:05d4673b2832 104
lnadal 0:05d4673b2832 105
lnadal 0:05d4673b2832 106
lnadal 0:05d4673b2832 107 for (int j = 0; j<4; j++){
lnadal 0:05d4673b2832 108
lnadal 0:05d4673b2832 109 lcd.cls(); // Heating sensor 4x16 = 64 seconds
lnadal 0:05d4673b2832 110 text_screen(messages[0], 0, 0);
lnadal 0:05d4673b2832 111
lnadal 0:05d4673b2832 112
lnadal 0:05d4673b2832 113 for (int i = 0; i<16; i++){
lnadal 0:05d4673b2832 114 if (pushbutton == 1){ // Pressing pushbutton stops initial heating and enters in measuring mode.
lnadal 0:05d4673b2832 115 break;
lnadal 0:05d4673b2832 116 }
lnadal 0:05d4673b2832 117 lcd.locate(i, 1);
lnadal 0:05d4673b2832 118 lcd.putc(62);
lnadal 0:05d4673b2832 119 wait(1);
lnadal 0:05d4673b2832 120 }
lnadal 0:05d4673b2832 121 }
lnadal 0:05d4673b2832 122
lnadal 0:05d4673b2832 123 lcd.cls();
lnadal 0:05d4673b2832 124 text_screen(messages[2], 0, 0);
lnadal 0:05d4673b2832 125 wait(2);
lnadal 0:05d4673b2832 126
lnadal 0:05d4673b2832 127
lnadal 0:05d4673b2832 128 AnalogIn value(p20); // Reads sensor voltage as a float int the interval (0-1) corresponding to (0 - 3.3V).
lnadal 0:05d4673b2832 129
lnadal 0:05d4673b2832 130
lnadal 0:05d4673b2832 131
lnadal 0:05d4673b2832 132 for (int i=0; i<5; i++){
lnadal 0:05d4673b2832 133
lnadal 0:05d4673b2832 134 x0[i] = value;
lnadal 0:05d4673b2832 135 wait(2);
lnadal 0:05d4673b2832 136
lnadal 0:05d4673b2832 137 }
lnadal 0:05d4673b2832 138 x_initial = (x0[0]+x0[1]+x0[2]+x0[3]+x0[4])/5.0; // Autozero. Average of 5 initial measures.
lnadal 0:05d4673b2832 139
lnadal 0:05d4673b2832 140 lcd.cls();
lnadal 0:05d4673b2832 141 text_screen(messages[3], 0, 0);
lnadal 0:05d4673b2832 142 wait(2);
lnadal 0:05d4673b2832 143
lnadal 0:05d4673b2832 144 while(1) {
lnadal 0:05d4673b2832 145 x = value;
lnadal 0:05d4673b2832 146 x = (x-x_initial)*3.3; // Calculate real voltage.
lnadal 0:05d4673b2832 147
lnadal 0:05d4673b2832 148 if(x<0) x = 0;
lnadal 0:05d4673b2832 149
lnadal 0:05d4673b2832 150 x = concentration(x);
lnadal 0:05d4673b2832 151
lnadal 0:05d4673b2832 152 output = x/3000; // If analog readings do not match digital readings you can adjust this value (1000 ppm = 1V).
lnadal 0:05d4673b2832 153
lnadal 0:05d4673b2832 154 wait(0.1);
lnadal 0:05d4673b2832 155
lnadal 0:05d4673b2832 156 // Float to string conversion.
lnadal 0:05d4673b2832 157 stringstream ss (stringstream::in | stringstream::out);
lnadal 0:05d4673b2832 158 ss <<x;
lnadal 0:05d4673b2832 159 string reading = ss.str();
lnadal 0:05d4673b2832 160 L = reading.length();
lnadal 0:05d4673b2832 161
lnadal 0:05d4673b2832 162
lnadal 0:05d4673b2832 163 lcd.cls();
lnadal 0:05d4673b2832 164 for (int i=0; i<L; i+=1){
lnadal 0:05d4673b2832 165 lcd.locate(i,0);
lnadal 0:05d4673b2832 166 lcd.putc(reading[i]);
lnadal 0:05d4673b2832 167
lnadal 0:05d4673b2832 168
lnadal 0:05d4673b2832 169
lnadal 0:05d4673b2832 170 text_screen(messages[4], 10, 0);
lnadal 0:05d4673b2832 171 }
lnadal 0:05d4673b2832 172 wait(2);
lnadal 0:05d4673b2832 173 }
lnadal 0:05d4673b2832 174 }