// 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(SH1107G); SeeedGrayOled.init(SSD1327); 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.putNumber(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.putNumber(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.putNumber(mq9_ratio); //Serial.print(mq9_ratio); SeeedGrayOled.putNumber(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(); }