add MQ9 sensor
authorJulien Moutinho <julm+air@autogeree.net>
Fri, 27 Nov 2015 04:44:13 +0000 (05:44 +0100)
committerJulien Moutinho <julm+air@autogeree.net>
Sun, 29 Nov 2015 08:29:08 +0000 (09:29 +0100)
GNUmakefile
collect.pl
send.ino

index c326e8a9f89f66f9b5dda1a9c70a21c4c79658c0..64bc10cb3c4fb53cce7c73808a2a5fd40d167085 100644 (file)
@@ -22,13 +22,15 @@ all: $(views)
 
 SENSOR_LABEL_temperature=Température (°C)
 SENSOR_LABEL_humidity=Humidité (%)
-SENSOR_LABEL_particles=Particules
-SENSOR_LABEL_quality=Qualité de l’air
+SENSOR_LABEL_dust=Particules
+SENSOR_LABEL_air=Qualité de l’air
+SENSOR_LABEL_co_ch4_lpg=CO/CH4/LPG
 sensors := \
  temperature \
  humidity \
- quality \
- particles
+ air \
+ dust \
+ co_ch4_lpg
 
 #
 ## Round Robin Database (RRD)
index be527072a10deb0395b50411aebaaf92a11a7959..649e6d9df379d6271574fe8a0fd2c3876f6d398f 100755 (executable)
@@ -17,11 +17,11 @@ use RRDTool::OO;
 my $step = 30; # NOTE: sampling interval in seconds
 
 sub rrd_init () {
-       Log::Log4perl->easy_init(
-               { level    => $INFO
-               , category => 'rrdtool'
-               , layout   => '%m%n'
-               });
+       #Log::Log4perl->easy_init(
+       #       { level    => $INFO
+       #       , category => 'rrdtool'
+       #       , layout   => '%m%n'
+       #       });
        my $now
         = DateTime->now
         ( time_zone => 'local'
@@ -38,6 +38,13 @@ sub rrd_init () {
                my $month_seconds = $month_end->epoch() - $month_begin->epoch();
                $rrd->create
                 ( step => $step
+                , data_source =>
+                        { name      => "temperature"
+                        , type      => "GAUGE"
+                        , min       => -15
+                        , max       => 49
+                        , heartbeat => 2 * $step # seconds
+                        }
                 , data_source =>
                         { name      => "humidity"
                         , type      => "GAUGE"
@@ -46,24 +53,24 @@ sub rrd_init () {
                         , heartbeat => 2 * $step # seconds
                         }
                 , data_source =>
-                        { name      => "temperature"
+                        { name      => "air"
                         , type      => "GAUGE"
-                        , min       => -15
-                        , max       => 50
+                        , min       => 0
+                        , max       => 1000
                         , heartbeat => 2 * $step # seconds
                         }
                 , data_source =>
-                        { name      => "quality"
+                        { name      => "dust"
                         , type      => "GAUGE"
                         , min       => 0
-                        , max       => 1000
+                        , max       => 100000
                         , heartbeat => 2 * $step # seconds
                         }
                 , data_source =>
-                        { name      => "particles"
+                        { name      => "co_ch4_lpg"
                         , type      => "GAUGE"
                         , min       => 0
-                        , max       => 100000
+                        , max       => 31
                         , heartbeat => 2 * $step # seconds
                         }
                 , archive =>
@@ -121,15 +128,16 @@ sub main () {
                                # NOTE: process only ended lines
                                $buffer = pop @lines;
                                foreach (@lines) {
-                                       my ($counter, $uptime, $humidity, $temperature, $quality, $particles)
-                                        = $_ =~ m/^([0-9]+);([0-9]+);([0-9]+.[0-9]+);([0-9]+.[0-9]+);([0-9]+);([0-9]+.[0-9]+)$/;
-                                       if (defined $particles) {
+                                       my ($counter, $uptime, $temperature, $humidity, $quality, $dust, $coch4lpg)
+                                        = $_ =~ m/^([0-9]+);([0-9]+);([0-9]+.[0-9]+);([0-9]+.[0-9]+);([0-9]+);([0-9]+.[0-9]+);([0-9]+.[0-9]+)$/;
+                                       if (defined $dust) {
                                                #print STDOUT ($time, ";", $_, "\n");
                                                $collect[0] = $humidity if $humidity ne '';
                                                $collect[1] = $temperature if $temperature ne '';
                                                $collect[2] = $quality if $quality ne '';
-                                               $collect[3] = $particles if $particles ne '';
-                                               if ($time >= $last_time + $step && @collect == 4) {
+                                               $collect[3] = $dust if $dust ne '';
+                                               $collect[4] = $coch4lpg if $coch4lpg ne '';
+                                               if ($time >= $last_time + $step && @collect == 5) {
                                                        $rrd->update
                                                         ( time   => $time
                                                         , values => [join (':', @collect)]
index 2a968e892f98408d3edd200d7ecf5d46f8ab856b..3c93560b29517221f093bd38c963c5806294cb1d 100644 (file)
--- a/send.ino
+++ b/send.ino
@@ -6,29 +6,37 @@
 #include "AirQuality.h"
 #include "Arduino.h"
 #include "DHT.h"
-#define DHTPIN 2
- // What pin the DHT is connected to.
 
-// Uncomment whatever type you're using!
+unsigned long now;
+unsigned long counter;
+
+#define DHTPIN 2
 //#define DHTTYPE DHT11 // DHT 11
 #define DHTTYPE DHT22 // DHT 22 (AM2302)
 DHT dht(DHTPIN, DHTTYPE);
 
-AirQuality airqualitysensor;
-int current_quality = -1;
-#define BUZZER 10
+AirQuality air;
+uint8_t    air_pin = A0;
+int        air_quality = -1;
 
-int dust_pin = 4;
-unsigned long duration;
-unsigned long starttime;
-unsigned long sampletime_ms = 30000;
-unsigned long lowpulseoccupancy = 0;
-unsigned long counter;
-float ratio = 0;
-float concentration = 0;
+int           dust_pin = 4;
+unsigned long dust_duration;
+unsigned long dust_last_time;
+unsigned long dust_delay = 30000;
+unsigned long dust_lowpulseoccupancy = 0;
+float         dust_concentration = 0;
+float         dust_ratio = 0;
+
+/* MQ9: CO CH4 LPG */
+unsigned long fire_last_time;
+unsigned long fire_delay = 1000;
+float         fire_R0 = 0.40;
+uint8_t       fire_pin = A2;
+
+#define BUZZER 10
 
 void setup() {
-       Serial.begin(9600); 
+       Serial.begin(9600);
        //while (!Serial) {
        //  ; // wait for serial port to connect. Needed for native USB port only
        // }
@@ -39,128 +47,151 @@ void setup() {
        SeeedGrayOled.setNormalDisplay();        // Set display to normal mode (i.e non-inverse mode)
        SeeedGrayOled.setVerticalMode();
        //SeeedGrayOled.setPageMode();           // Set addressing mode to Page Mode
-       SeeedGrayOled.setTextXY(0,0);            // Set the cursor to Xth Page, Yth Column  
+       SeeedGrayOled.setTextXY(0,0);            // Set the cursor to Xth Page, Yth Column
        SeeedGrayOled.putString("Initializing"); // Print the String
        
        pinMode(BUZZER, OUTPUT);
        digitalWrite(BUZZER, LOW);
-       airqualitysensor.init(14);
+       air.init(14);
        dht.begin();
        
        pinMode(dust_pin,INPUT);
-       starttime = millis(); // Get the current time
-       Serial.println("counter;uptime;humidity;temperature;quality;particules");
+       now = millis();
+       dust_last_time = now;
+       fire_last_time  = now;
+       Serial.println("counter;uptime;temperature;humidity;quality;dust;co-ch4-lpg");
  }
 
 void loop() {
-       // Reading temperature or humidity takes about 250 milliseconds!
-       // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
        float h = dht.readHumidity();
        float t = dht.readTemperature();
        counter = counter + 1;
-       SeeedGrayOled.setTextXY(8,0);
-       // Check if returns are valid,
-       // if they are NaN (not a number)
-       // then something went wrong!
+       now = millis();
        Serial.print(counter);
        Serial.write(';');
-       Serial.print(millis());
-       if (isnan(t) || isnan(h)) {
-               SeeedGrayOled.putString("DHT ERROR");
-               Serial.write(';');
-               Serial.write(';');
-        }
-       else {
-               SeeedGrayOled.putString("Humidity:");
-               SeeedGrayOled.setTextXY(9,0);
-               SeeedGrayOled.putString("   ");
-               SeeedGrayOled.putFloat(h);
-               SeeedGrayOled.putString("%");
-               SeeedGrayOled.setTextXY(10,0);
-               SeeedGrayOled.putString("Temp.:");
-               SeeedGrayOled.setTextXY(11,0);
-               SeeedGrayOled.putString("   ");
-               SeeedGrayOled.putFloat(t);
-               SeeedGrayOled.putString("*C");
-               Serial.write(';');
-               Serial.print(h);
-               Serial.write(';');
-               Serial.print(t);
-        }
-       Serial.write(';');
-       Serial.print(airqualitysensor.first_vol,DEC);
+       Serial.print(now);
        
-       // Checking Air Quality
-       current_quality=airqualitysensor.slope();
-       if (current_quality >= 0) {
-               if (current_quality <= 1)
-                       // Air quality is bad.
-                       // Let's revert display to make some light!
-                       SeeedGrayOled.setInverseDisplay();
-               else
-                       SeeedGrayOled.setNormalDisplay();
-               
-               SeeedGrayOled.setTextXY(0,0);
-               SeeedGrayOled.putString("Air Quality:"); // Print the String
-               SeeedGrayOled.setTextXY(1,3);
-               SeeedGrayOled.putNumber(airqualitysensor.first_vol); // Print the String
-               SeeedGrayOled.putString("   "); // Clear any old character
-               
-               SeeedGrayOled.setTextXY(2,0);
-               if (current_quality==0)
-               SeeedGrayOled.putString("   0/4 (x_x)");
-               else if (current_quality==1)
-               SeeedGrayOled.putString("   1/4 (>_<)");
-               else if (current_quality==2)
-               SeeedGrayOled.putString("   2/4 (=_=)");
-               else if (current_quality==3)
-               SeeedGrayOled.putString("   3/4 (*_*)");
-               else
-               SeeedGrayOled.putString("   4/4 (^_^)");
-               
-               if (current_quality<1)
-                       digitalWrite(BUZZER, HIGH);
-               else
-                       digitalWrite(BUZZER, LOW);
-        }
+       /* DHT */
+               // Reading temperature or humidity takes about 250 milliseconds!
+               // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
+               if (isnan(t) || isnan(h)) {
+                // Check if returns are valid,
+                // if they are NaN (not a number)
+                // then something went wrong!
+                       SeeedGrayOled.setTextXY(0,0);
+                       SeeedGrayOled.putString("T: ERROR    ");
+                       SeeedGrayOled.setTextXY(1,0);
+                       SeeedGrayOled.putString("H: ERROR    ");
+                       Serial.write(';');
+                       Serial.write(';');
+                }
+               else {
+                       SeeedGrayOled.setTextXY(0,0);
+                       SeeedGrayOled.putString("T:          ");
+                       SeeedGrayOled.setTextXY(0,3);
+                       SeeedGrayOled.putFloat(t);
+                       SeeedGrayOled.putString("*C");
+                       Serial.write(';');
+                       Serial.print(t);
+                       
+                       SeeedGrayOled.setTextXY(1,0);
+                       SeeedGrayOled.putString("H:          ");
+                       SeeedGrayOled.setTextXY(1,3);
+                       SeeedGrayOled.putFloat(h);
+                       SeeedGrayOled.putString("%");
+                       Serial.write(';');
+                       Serial.print(h);
+                }
        
-       // Checking Dust Sensor
-       duration = pulseIn(dust_pin, LOW);
-       lowpulseoccupancy = lowpulseoccupancy+duration;
+       /* Air Quality */
+               Serial.write(';');
+               Serial.print(air.first_vol,DEC);
+               // Checking Air Quality
+               air_quality=air.slope();
+               if (air_quality >= 0) {
+                       if (air_quality <= 1)
+                               // Air quality is bad.
+                               // Let's revert display to make some light!
+                               SeeedGrayOled.setInverseDisplay();
+                       else
+                               SeeedGrayOled.setNormalDisplay();
+                       
+                       SeeedGrayOled.setTextXY(2,0);
+                       SeeedGrayOled.putString("Air:        ");
+                       SeeedGrayOled.setTextXY(2,5);
+                       SeeedGrayOled.putNumber(air.first_vol);
+                       
+                       SeeedGrayOled.setTextXY(3,3);
+                       if (air_quality==0)
+                       SeeedGrayOled.putString("0/4 (x_x)");
+                       else if (air_quality==1)
+                       SeeedGrayOled.putString("1/4 (>_<)");
+                       else if (air_quality==2)
+                       SeeedGrayOled.putString("2/4 (=_=)");
+                       else if (air_quality==3)
+                       SeeedGrayOled.putString("3/4 (*_*)");
+                       else
+                       SeeedGrayOled.putString("4/4 (^_^)");
+                       
+                       if (air_quality<1)
+                               digitalWrite(BUZZER, HIGH);
+                       else
+                               digitalWrite(BUZZER, LOW);
+                }
        
-       Serial.write(';');
-       if ((millis()-starttime) > sampletime_ms) {
-        //if the sample time == 30s
-               ratio = lowpulseoccupancy / (sampletime_ms*10.0); // Integer percentage 0=>100
-               concentration = 1.1*pow(ratio,3)-3.8*pow(ratio,2)+520*ratio+0.62; // Using spec sheet curve
-               /*
-               Serial.print(lowpulseoccupancy);
+       /* Dust */
+               dust_duration = pulseIn(dust_pin, LOW);
+               dust_lowpulseoccupancy = dust_lowpulseoccupancy + dust_duration;
                Serial.write(';');
-               Serial.print(ratio);
-               */
-               Serial.print(concentration);
-               SeeedGrayOled.setTextXY(4,0);
-               SeeedGrayOled.putString("Particles:");
-               SeeedGrayOled.setTextXY(5,3);
-               SeeedGrayOled.putString("    ");
-               SeeedGrayOled.setTextXY(5,3);
-               SeeedGrayOled.putNumber(concentration);
-               lowpulseoccupancy = 0;
-               starttime = millis();
-        }
+               if ((now - dust_last_time) >= dust_delay) {
+                       dust_last_time = now;
+                       dust_ratio = dust_lowpulseoccupancy / (dust_delay * 10.0); // Integer percentage 0=>100
+                       dust_concentration = 1.1*pow(dust_ratio,3)
+                        - 3.8*pow(dust_ratio,2)
+                        + 520*dust_ratio
+                        + 0.62; // Using spec sheet curve
+                       /*
+                       Serial.print(dust_lowpulseoccupancy);
+                       Serial.write(';');
+                       Serial.print(dust_ratio);
+                       */
+                       Serial.print(dust_concentration);
+                       SeeedGrayOled.setTextXY(4,0);
+                       SeeedGrayOled.putString("Part.:      ");
+                       SeeedGrayOled.setTextXY(4,7);
+                       SeeedGrayOled.putNumber(dust_concentration);
+                       dust_lowpulseoccupancy = 0;
+                }
+       
+       /* MQ9: CO CH4 LPG */
+               Serial.write(';');
+               if ((now - fire_last_time) >= fire_delay) {
+                       fire_last_time = now;
+                       float fire_read = analogRead(fire_pin);
+                       float fire_volt = (float)fire_read / 1024 * 5.0;
+                       float fire_RS  = (5.0 - fire_volt) / fire_volt; // omit *RL
+                       /* Replace the name "R0" with the value of R0 in the demo of First Test */
+                       float fire_ratio = fire_RS / fire_R0;  // fire_ratio = RS/R0
+                       SeeedGrayOled.setTextXY(5,0);
+                       SeeedGrayOled.putString("Feu:        ");
+                       SeeedGrayOled.setTextXY(5,5);
+                       SeeedGrayOled.putFloat(fire_ratio);
+                       Serial.print(fire_ratio);
+                }
+       
        Serial.println();
  }
 
 ISR(TIMER2_OVF_vect) {
-       if(airqualitysensor.counter==122) {
-        // set 2 seconds as a detected duty
-               airqualitysensor.last_vol=airqualitysensor.first_vol;
-               airqualitysensor.first_vol=analogRead(A0);
-               airqualitysensor.counter=0;
-               airqualitysensor.timer_index=1;
+       if(air.counter==122) {
+        // NOTE: set 2 seconds as a detected duty
+               air.last_vol    = air.first_vol;
+               air.first_vol   = analogRead(air_pin);
+               air.counter     = 0;
+               air.timer_index = 1;
                //PORTB=PORTB^0x20;
         }
        else {
-               airqualitysensor.counter++;
+               air.counter++;
         }
  }