// Licence: WTFPLv2
// Copyright 2015-2016: Julien Moutinho
#include
#include "SeeedGrayOLED.h"
#include "AirQuality.h"
#include "Arduino.h"
#include "DHT.h"
#include "DS1307.h"
unsigned long now;
/* Serial input */
#define SERIAL_INPUT_SIZE 25 // "utc=YYYY-MM-DD-HH-mm-ss-d"
void loop_serial_read () {
char input[SERIAL_INPUT_SIZE + 1];
while (Serial.available()) {
byte input_size = Serial.readBytesUntil('\n', input, SERIAL_INPUT_SIZE);
input[input_size] = 0;
char *r = input;
char *data;
r = strchr((data = r), '=');
if (!r) continue; *r++ = 0;
if (!strcmp(data, "utc")) {
DS1307 clock;
// USAGE: TZ=UTC date +"utc=%Y:%m:%d:%H:%M:%S:%u" >/dev/ttyUSB0
r = strchr((data = r), ':');
if (!r) continue; *r++ = 0;
uint16_t year = atoi(data);
r = strchr((data = r), ':');
if (!r) continue; *r++ = 0;
uint8_t month = atoi(data);
r = strchr((data = r), ':');
if (!r) continue; *r++ = 0;
uint8_t dayOfMonth = atoi(data);
clock.fillByYMD(year, month, dayOfMonth);
r = strchr((data = r), ':');
if (!r) continue; *r++ = 0;
uint8_t hour = atoi(data);
r = strchr((data = r), ':');
if (!r) continue; *r++ = 0;
uint8_t minute = atoi(data);
r = strchr((data = r), ':');
if (!r) continue; *r++ = 0;
uint8_t second = atoi(data);
clock.fillByHMS(hour, minute, second);
data = r;
uint8_t dayOfWeek = atoi(data);
clock.fillDayOfWeek(dayOfWeek);
clock.setTime();
}
}
}
/* Oled */
void setup_oled () {
SeeedGrayOled.init();
SeeedGrayOled.clearDisplay();
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.putString("Init..."); // Print the String
}
/* Buzzer */
#define BUZZER 10
void setup_buzzer () {
pinMode(BUZZER, OUTPUT);
digitalWrite(BUZZER, LOW);
}
/* RTC */
DS1307 clock;
void setup_rtc () {
clock.begin();
}
void loop_rtc () {
clock.getTime();
Serial.write(";time=");
Serial.print(clock.year+2000, DEC);
Serial.print("-");
if (clock.month < 10)
Serial.print("0");
Serial.print(clock.month, DEC);
Serial.print("-");
if (clock.dayOfMonth < 10)
Serial.print("0");
Serial.print(clock.dayOfMonth, DEC);
Serial.print("T");
if (clock.hour < 10)
Serial.print("0");
Serial.print(clock.hour, DEC);
Serial.print(":");
if (clock.minute < 10)
Serial.print("0");
Serial.print(clock.minute, DEC);
Serial.print(":");
if (clock.second < 10)
Serial.print("0");
Serial.print(clock.second, DEC);
Serial.print("Z");
/* Oled */
SeeedGrayOled.setTextXY(0,0);
switch (clock.dayOfWeek) {
case MON:
SeeedGrayOled.putString("lun");
break;
case TUE:
SeeedGrayOled.putString("mar");
break;
case WED:
SeeedGrayOled.putString("mer");
break;
case THU:
SeeedGrayOled.putString("jeu");
break;
case FRI:
SeeedGrayOled.putString("ven");
break;
case SAT:
SeeedGrayOled.putString("sam");
break;
case SUN:
SeeedGrayOled.putString("dim");
break;
}
SeeedGrayOled.putString(" ");
if (clock.dayOfMonth < 10)
SeeedGrayOled.putString("0");
SeeedGrayOled.putNumber(clock.dayOfMonth);
SeeedGrayOled.putString(" ");
switch (clock.month) {
case 1:
SeeedGrayOled.putString("jan.");
break;
case 2:
SeeedGrayOled.putString("fév.");
break;
case 3:
SeeedGrayOled.putString("mars");
break;
case 4:
SeeedGrayOled.putString("avr.");
break;
case 5:
SeeedGrayOled.putString("mai ");
break;
case 6:
SeeedGrayOled.putString("juin");
break;
case 7:
SeeedGrayOled.putString("jui.");
break;
}
SeeedGrayOled.setTextXY(1,0);
if (clock.hour < 10)
SeeedGrayOled.putString("0");
SeeedGrayOled.putNumber(clock.hour);
SeeedGrayOled.putString(":");
if (clock.minute < 10)
SeeedGrayOled.putString("0");
SeeedGrayOled.putNumber(clock.minute);
SeeedGrayOled.putString(" UTC");
/*
SeeedGrayOled.putString(":");
if (clock.second < 10)
SeeedGrayOled.putString("0");
SeeedGrayOled.putNumber(clock.second);
*/
}
/* DHT */
#define DHTPIN 2
//#define DHTTYPE DHT11 // DHT 11
#define DHTTYPE DHT22 // DHT 22 (AM2302)
DHT dht(DHTPIN, DHTTYPE);
void setup_dht () {
dht.begin();
}
void loop_dht () {
// Reading temperature or humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
float t = dht.readTemperature();
Serial.write(";temp=");
if (isnan(t)) {
SeeedGrayOled.setTextXY(2,0);
SeeedGrayOled.putString("T: ERROR ");
}
else {
Serial.print(t);
SeeedGrayOled.setTextXY(2,0);
SeeedGrayOled.putString("T: ");
SeeedGrayOled.setTextXY(2,3);
SeeedGrayOled.putFloat(t);
SeeedGrayOled.putString("*C");
}
float h = dht.readHumidity();
Serial.write(";humi=");
if (isnan(h)) {
SeeedGrayOled.setTextXY(3,0);
SeeedGrayOled.putString("H: ERROR ");
}
else {
Serial.print(h);
SeeedGrayOled.setTextXY(3,0);
SeeedGrayOled.putString("H: ");
SeeedGrayOled.setTextXY(3,3);
SeeedGrayOled.putFloat(h);
SeeedGrayOled.putString("%");
}
}
/* Air */
AirQuality air;
uint8_t air_pin = A0;
int air_quality = -1;
void setup_air () {
air.init(14);
}
void loop_air () {
air_quality=air.slope();
Serial.write(";air=");
if (air_quality >= 0) {
Serial.print(air.first_vol,DEC);
if (air_quality <= 1)
// Air quality is bad.
// Let's revert display to make some light!
SeeedGrayOled.setInverseDisplay();
else
SeeedGrayOled.setNormalDisplay();
SeeedGrayOled.setTextXY(4,0);
SeeedGrayOled.putString("Air: ");
SeeedGrayOled.setTextXY(4,5);
SeeedGrayOled.putNumber(air.first_vol);
SeeedGrayOled.setTextXY(5,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);
}
}
ISR(TIMER2_OVF_vect) {
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 {
air.counter++;
}
}
/* Dust */
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;
void setup_dust () {
pinMode(dust_pin,INPUT);
dust_last_time = now;
}
void loop_dust () {
dust_duration = pulseIn(dust_pin, LOW);
dust_lowpulseoccupancy = dust_lowpulseoccupancy + dust_duration;
Serial.write(";dust=");
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(6,0);
SeeedGrayOled.putString("Dust: ");
SeeedGrayOled.setTextXY(6,7);
SeeedGrayOled.putNumber(dust_concentration);
dust_lowpulseoccupancy = 0;
}
}
/* Fire (MQ9: CO CH4 LPG) */
unsigned long mq9_last_time;
unsigned long mq9_delay = 1000;
float mq9_R0 = 0.40;
uint8_t mq9_pin = A2;
void setup_fire () {
mq9_last_time = now;
}
void loop_fire () {
Serial.write(";fire=");
if ((now - mq9_last_time) >= mq9_delay) {
mq9_last_time = now;
int mq9_read = analogRead(mq9_pin);
float mq9_volt = (float)mq9_read / 1024 * 5.0;
float mq9_RS = (5.0 - mq9_volt) / mq9_volt; // omit *RL
/* Replace the name "R0" with the value of R0 in the demo of First Test */
//float mq9_ratio = mq9_RS / mq9_R0; // mq9_ratio = RS/R0
float mq9_R0_ = mq9_RS / 9.9; // The ratio of RS/R0 is 9.9 in LPG gas from Graph (Found using WebPlotDigitizer)
Serial.print(mq9_R0_);
SeeedGrayOled.setTextXY(7,0);
SeeedGrayOled.putString("Feu: ");
SeeedGrayOled.setTextXY(7,5);
//SeeedGrayOled.putFloat(mq9_ratio);
//Serial.print(mq9_ratio);
SeeedGrayOled.putFloat(mq9_R0_);
}
}
/* Entry points */
void setup() {
now = millis();
Serial.begin(9600);
//while (!Serial) {
// ; // wait for serial port to connect. Needed for native USB port only
// }
Wire.begin(); // Initialize I2C
setup_oled();
setup_rtc();
setup_dht();
setup_air();
setup_dust();
setup_fire();
Serial.println("loop;up;time;temp;humi;air;dust;fire");
}
unsigned long counter;
void loop() {
counter = counter + 1;
now = millis();
loop_serial_read();
Serial.write("loop="); Serial.print(counter);
Serial.write(";up="); Serial.print(now);
loop_rtc();
loop_dht();
loop_air();
loop_dust();
loop_fire();
Serial.println();
}