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'
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"
, 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 =>
# 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)]
#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
// }
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++;
}
}