/*
* Project L14_04_PlantWater
* Description: Automatically water your plant when the soil is too dry and publish/subscribe
* Author: Janel Sanchez
* Date: 12-Nov-2020
*/
#include <Adafruit_MQTT.h>
#include "Adafruit_MQTT/Adafruit_MQTT.h"
#include "Adafruit_MQTT/Adafruit_MQTT_SPARK.h"
#include "Adafruit_MQTT/Adafruit_MQTT.h"
#include "credentials.h"
#include "Adafruit_SSD1306.h"
#include "Adafruit_BME280.h"
#include "Air_Quality_Sensor.h"
#define OLED_RESET D4
Adafruit_SSD1306 display(OLED_RESET);
#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif
Adafruit_BME280 bme;
bool status;
AirQualitySensor airsensor(A0);
/************ Global State (you don't need to change this!) *** ***************/
TCPClient TheClient;
// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_SPARK mqtt(&TheClient,AIO_SERVER,AIO_SERVERPORT,AIO_USERNAME,AIO_KEY);
/****************************** Feeds ***************************************/
// Setup Feeds to publish or subscribe
// Notice MQTT paths for AIO follow the form: <username>/feeds/<feedname>
Adafruit_MQTT_Subscribe waterButton = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/buttonToWater");
Adafruit_MQTT_Publish soilMoisture = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/moistureLevels");
Adafruit_MQTT_Publish bmeTemperature = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/temperatureLevels");
Adafruit_MQTT_Publish bmeHumidity = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/humidityLevels");
Adafruit_MQTT_Publish bmePressure = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/pressureLevels");
Adafruit_MQTT_Publish air = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/airQualityLevels");
Adafruit_MQTT_Publish dust = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/dustLevels");
/************Declare Variables*************/
const int moistureSensor = A4;
const int moisturePump = A5;
const int dustSensor = A1;
int airQuality;
int waterButtonValue;
unsigned long last;
unsigned long lastTime;
unsigned long lastDisplayTime;
int moistureValue;
unsigned long duration;
unsigned long starttime;
unsigned long sampletime_ms = 30000;
unsigned long lowpulseoccupancy = 0;
float ratio = 0;
float concentration = 0;
float tempC;
float tempF = 0;
float pressPA;
float humidRH;
const char degreeSymbol = 247;
void setup() {
Serial.begin(9600);
delay(100); //wait for Serial Monitor to startup
pinMode(moistureSensor, INPUT);
pinMode(moisturePump, OUTPUT);
pinMode(dustSensor, INPUT);
starttime = millis();//get the current time;
if (airsensor.init()) {
Serial.println("Air Sensor READY!");
}
else {
Serial.println("Air Sensor ERROR!");
}
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 128x64)
status = bme.begin();
if(!status) {
Serial.println("Initialization Failed");
}
// Setup MQTT subscription for onoff feed.
//mqtt.subscribe(&TempF);
mqtt.subscribe(&waterButton);
sync_my_time();
}
void loop() {
MQTT_connect();
pingMQTT();
tempC = bme.readTemperature();
pressPA = ((bme.readPressure()/100.0)*0.03);
humidRH = bme.readHumidity();
tempF = (tempC*1.8)+32;
// this is our 'wait for incoming subscription packets' busy subloop
// try to spend your time here
Adafruit_MQTT_Subscribe *subscription;
while ((subscription = mqtt.readSubscription(10000))) {
if (subscription == &waterButton) {
waterButtonValue = atoi((char *)waterButton.lastread);
}
if (waterButtonValue == HIGH) {
digitalWrite (moisturePump, HIGH);
Serial.printf("Dashboard Water Button Pressed ON \n");
}
else {
digitalWrite(moisturePump, LOW);
Serial.printf("Dashboard Water Button Pressed OFF \n");
}
}
moistureValue = analogRead(moistureSensor);
readAirSensor();
readDustSensor();
if((millis()-lastTime > 30000)) {
if(mqtt.Update()) {
soilMoisture.publish(moistureValue);
Serial.printf("Publishing Moisture Value %i \n",moistureValue);
bmeTemperature.publish(tempF);
Serial.printf("Publishing Temperatue %0.1f%cF \n",tempF);
bmeHumidity.publish(humidRH);
Serial.printf("Publishing Humidity %0.2f \n",humidRH);
bmePressure.publish(pressPA);
Serial.printf("Publishing Pressure %0.2f \n",pressPA);
air.publish(airQuality);
Serial.printf("Publishing Air Quality %i \n",airQuality);
dust.publish(concentration);
Serial.printf("Publishing Dust %0.2f \n",concentration);
}
if(moistureValue >= 2500) {
activatePump();
}
lastTime = millis();
}
displayPrint ();
}
// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect() {
int8_t ret;
// Stop if already connected.
if (mqtt.connected()) {
return;
}
Serial.print("Connecting to MQTT... ");
while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
Serial.println(mqtt.connectErrorString(ret));
Serial.println("Retrying MQTT connection in 5 seconds...");
mqtt.disconnect();
delay(5000); // wait 5 seconds
}
Serial.println("MQTT Connected!");
}
void sync_my_time () {
Time.zone(-7);
Particle.syncTime();
waitUntil(Particle.syncTimeDone);
}
void displayPrint () {
String DateTime, DateOnly, TimeOnly, YearOnly;
char currentDate[11], currentTime[9], currentYear[5];
DateTime = Time.timeStr();
DateOnly = DateTime.substring(0,10);
DateOnly.toCharArray(currentDate,11);
YearOnly = DateTime.substring(20,24);
YearOnly.toCharArray(currentYear,5);
TimeOnly = DateTime.substring(11,19);
TimeOnly.toCharArray(currentTime,9);
if ((millis()-lastDisplayTime)>10000) {
display.clearDisplay();
display.display();
display.setTextSize(1);
display.setCursor(0,0);
display.setTextColor(BLACK, WHITE);
Serial.printf("Display Date: %s %s \n", currentDate,currentYear);
display.printf("Date: %s %s", currentDate,currentYear);
Serial.printf("Display Time: %s \n", currentTime);
display.printf("Time: %s\n", currentTime);
display.setTextColor(WHITE);
Serial.printf("Display Moisture: %i \n", moistureValue);
display.printf("Moisture: %i \n", moistureValue);
display.setTextColor(WHITE);
Serial.printf("Display Temperature: %0.1f°F \n", tempF);
display.printf("Temperature: %0.1f%cF \n", tempF,degreeSymbol);
display.setTextColor(WHITE);
Serial.printf("Display Humidity: %0.2f \n", humidRH);
display.printf("Humidity: %0.2f \n", humidRH);
display.setTextColor(WHITE);
Serial.printf("Display Pressure: %0.2finHg \n", pressPA);
display.printf("Pressure: %0.2finHg \n", pressPA);
display.setTextColor(WHITE);
Serial.printf("Display Air Quality: %i \n", airQuality);
display.printf("Air Quality: %i \n", airQuality);
display.setTextColor(WHITE);
Serial.printf("Display Dust Value: %0.2f \n", concentration);
display.printf("Dust Value: %0.2f \n", concentration);
display.display();
lastDisplayTime = millis();
}
}
void activatePump() {
digitalWrite(moisturePump, HIGH);
Serial.printf("Pump is ON \n");
delay(500);
digitalWrite(moisturePump, LOW);
Serial.printf("Pump is OFF \n");
}
void readDustSensor() {
duration = pulseIn(dustSensor, LOW);
lowpulseoccupancy = lowpulseoccupancy+duration;
if ((millis()-starttime) > sampletime_ms) {
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);
Serial.print(",");
Serial.print(ratio);
Serial.print(",");
Serial.println(concentration);
lowpulseoccupancy = 0;
starttime = millis();
}
}
void readAirSensor() {
int slope = airsensor.slope();
airQuality = airsensor.getValue();
}
void pingMQTT() {
if ((millis()-last)>120000) {
Serial.printf("Pinging MQTT \n");
if(! mqtt.ping()) {
Serial.printf("Disconnecting \n");
mqtt.disconnect();
}
last = millis();
}
}
Comments