/*
* Project L14_04_PlantWater
* Description: Plant Watering System
* Author: Wesley Eccles
* Date: 4_20_21
*/
#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 "neopixel.h"
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include "Air_Quality_Sensor.h"
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"
//TIME
String DateTime , TimeOnly ;
char currentDateTime[25] , currentTime[9];
//CAMERA
const int CameraPIN= A5;
int PhotosTaken=0;
//Air Quality
AirQualitySensor sensor(A0);
//DUST SENSOR
int DUSTPIN = 8;
unsigned long Dustduration;
unsigned long Duststarttime;
unsigned long Dustsampletime_ms = 30000;//sampe 30s ;
unsigned long lowpulseoccupancy = 0;
float ratio = 0;
float concentration = 0;
//SYSTEM
SYSTEM_MODE(SEMI_AUTOMATIC);
//BME
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME280 bme; // I2C
//ADAFRUIT.IO
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
Adafruit_MQTT_Subscribe BUTTON = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/button");
Adafruit_MQTT_Publish TEMP = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/TempF");
Adafruit_MQTT_Publish HUMIDITY = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/Humidity");
Adafruit_MQTT_Publish PRESSURE = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/Pressure");
Adafruit_MQTT_Publish MOISTURE = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/Moisture");
Adafruit_MQTT_Publish AIRQUALITY = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/AirQuality");
Adafruit_MQTT_Publish DUST = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/Dust");
Adafruit_MQTT_Publish PHOTOS = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/Photos");
int last, lastTime;
bool buttonState;
long unsigned int publishFreq= 60000; //sampe 60s ;
//RELAY
const int RELAYPIN = D3;
//MOISTURE
const int MOISTPIN = A1;
int moistureVal;
//OLED
#define OLED_RESET D4
Adafruit_SSD1306 display(OLED_RESET);
int OLEDlastTime, i;
void setup() {
//Camera
pinMode(CameraPIN, OUTPUT);
digitalWrite(CameraPIN,HIGH);
//Serial Print
Serial.begin(9600);
delay(100);
//OLED
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(10,25);
display.clearDisplay();
display.printf("Starting\n Up");
display.display();
//TIME
Time.zone(-6); // MST = -7, MDT = -6
Particle.syncTime(); // Sync time with Particle Cloud
//RELAY
pinMode(RELAYPIN,OUTPUT);
//MOISTURE
pinMode(MOISTPIN,INPUT);
//BME
bme.begin();
//ADAFRUIT.IO
Serial.printf("Connecting to Internet \n");
WiFi.connect();
while(WiFi.connecting()) {
Serial.printf(".");
delay(100);
}
Serial.printf("\n Connected!!!!!! \n");
mqtt.subscribe(&BUTTON);
//AIRQUALITY
Serial.println("Waiting sensor to init...");
//delay(20000);
if (sensor.init()) {
Serial.println("Sensor ready.");
}
else {
Serial.println("Sensor ERROR!");
}
//DUST
pinMode(DUSTPIN,INPUT);
Duststarttime = millis();
//Display
i=-1;
OLEDlastTime= -3000;
}
void loop() {
KeepConnection();
CheckButtonPress();
if((millis()-OLEDlastTime > 4000)) { // Change Display Every 3 minutes
i++;
if (i==4){
i=0;
}
Serial.println(i);
switch (i) {
case 0:
display.clearDisplay();
TimeWriteToOLED();
OLEDTemp();
break;
case 1:
display.clearDisplay();
TimeWriteToOLED();
OLEDPresMoist();
break;
case 2:
display.clearDisplay();
TimeWriteToOLED();
OLEDAir();
break;
case 3:
display.clearDisplay();
TimeWriteToOLED();
OLEDPhotos();
break;
}
OLEDlastTime = millis(); //Reset the time
}
if((millis()-lastTime > publishFreq)) { // PUBLISH EVERY 30 min
WaterPlant(3000);
PublishEnviro();
TakePhoto();
DustData();
lastTime = millis(); //Reset the time
}
}
float tempF(){
float _tempF;
float _tempC;
_tempC = bme.readTemperature();
_tempF = (_tempC*1.8)+32;
if (_tempF<50){
return 69.69;
}
return _tempF;
}
float Pressure(){
float _pressure;
_pressure= bme.readPressure() / 100.0F;
return _pressure;
}
float Humidity(){
float _humidity;
_humidity= bme.readHumidity();
return _humidity;
}
int MoisturePercent(){
int _moisturePercent, mapped;
_moisturePercent= analogRead(MOISTPIN);
mapped = map(_moisturePercent, 2000,3500, 100,0);
return mapped;
}
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 KeepConnection(){
// Validate connected to MQTT Broker
MQTT_connect();
// Ping MQTT Broker every 2 minutes to keep connection alive
if ((millis()-last)>120000) {
Serial.printf("Pinging MQTT \n");
if(! mqtt.ping()) {
Serial.printf("Disconnecting \n");
mqtt.disconnect();
}
last = millis();
}
}
void WaterPlant(int _thresholdVal){
if (analogRead(MOISTPIN)>_thresholdVal){
digitalWrite(RELAYPIN,HIGH);
delay(500);
digitalWrite(RELAYPIN,LOW);
}
}
int AirQualityRead(){
int quality = sensor.slope();
Serial.print("Sensor value: ");
Serial.println(sensor.getValue());
if (quality == AirQualitySensor::FORCE_SIGNAL) {
Serial.println("High pollution! Force signal active.");
return 3;
}
else if (quality == AirQualitySensor::HIGH_POLLUTION) {
Serial.println("High pollution!");
return 2;
}
else if (quality == AirQualitySensor::LOW_POLLUTION) {
Serial.println("Low pollution!");
return 1;
}
else if (quality == AirQualitySensor::FRESH_AIR) {
Serial.println("Fresh air.");
return 0;
}
}
int DustData() {
while ((millis()-Duststarttime) < Dustsampletime_ms) { //if the sample time == 30
Dustduration = pulseIn(DUSTPIN, LOW);
lowpulseoccupancy = lowpulseoccupancy+Dustduration;
}
ratio = lowpulseoccupancy/(Dustsampletime_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);
if(mqtt.Update()) {
DUST.publish (concentration);
}
lowpulseoccupancy = 0;
Duststarttime = millis();
return concentration;
}
void PublishEnviro (){
if(mqtt.Update()) {
TEMP.publish (tempF());
Serial.printf("Publishing TempF %f F\n",tempF());
PRESSURE.publish (Pressure());
Serial.printf("Publishing Pressure %f hPa\n",Pressure());
HUMIDITY.publish (Humidity());
Serial.printf("Publishing Humidity %f Percent\n",Humidity());
MOISTURE.publish (MoisturePercent());
Serial.printf("Publishing Moisture Level: %i Percent %i \n",analogRead(MOISTPIN), MoisturePercent());
AIRQUALITY.publish (AirQualityRead()); // Return 3-0 -- 3 is High Polution _ 0 is Clean Air
}
}
void CheckButtonPress(){
Adafruit_MQTT_Subscribe *subscription;
while ((subscription = mqtt.readSubscription(500))) {
if (subscription == &BUTTON) {
buttonState = atoi((char *)BUTTON.lastread);
if (buttonState){
WaterPlant(0);
PublishEnviro();
TakePhoto();
DustData();
}
}
}
}
void TakePhoto(){
digitalWrite(CameraPIN,LOW);
delay(500);
digitalWrite(CameraPIN,HIGH);
PhotosTaken++;
PHOTOS.publish (PhotosTaken);
}
void OLEDText() {
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(10,0);
display.clearDisplay();
display.printf("Temp\n Hum");
display.display();
}
void TimeWriteToOLED() {
DateTime = Time.timeStr(); // Current Date and Time from Particle Time class
TimeOnly = DateTime.substring(11 ,16); // Extract the Time from the DateTime String
// Convert String to char arrays - this is needed for formatted print
DateTime.toCharArray(currentDateTime ,25);
TimeOnly.toCharArray(currentTime ,6);
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(25,0);
//display.clearDisplay();
display.printf("%s",currentTime);
//display.display();
}
void OLEDTemp() {
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0,20);
//display.clearDisplay();
display.printf("Temp F: %.0f",tempF() );
display.setCursor(0,40);
display.printf("Humid: %.0f", Humidity());
display.display();
}
void OLEDPresMoist() {
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0,20);
//display.clearDisplay();
display.printf("Moist: %i",MoisturePercent());
display.setCursor(0,40);
display.printf("Pres: %.0f", Pressure());
display.display();
}
void OLEDAir() {
int _AirQuality;
_AirQuality= AirQualityRead();
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(10,20);
if (_AirQuality==0){
display.printf("Fresh Air");
}
if (_AirQuality==1){
display.printf("Low \npollution!");
}
if ( _AirQuality==2){
display.printf("High \npollution!");
}
if (_AirQuality==3){
display.printf(" Extreme\npollution!");
}
display.display();
}
void OLEDPhotos() {
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0,20);
display.printf("Photo Shot");
display.setTextSize(2);
display.setCursor(60,40);
display.printf("%i",PhotosTaken);
display.display();
}
Comments