/***************************************************
* TODO:
* Add turn led on off and wire up led(serves as relay)
* add light detector and rewrite logic to read from meter
* Figure out why water temp sensor gives 0.00 reading every other sample
* Implement controll of light
*
*
* ****************************************************/
/***************************************************
Adafruit MQTT Library for Huzzah ESP8266 with 1 wire temp sensor (waterproof) and DHT11 sensoreExample
// Depends on the following Arduino libraries:
// - Adafruit Unified Sensor Library: https://github.com/adafruit/Adafruit_Sensor
// - DHT Sensor Library: https://github.com/adafruit/DHT-sensor-library
Must use ESP8266 Arduino from:
https://github.com/esp8266/Arduino
Works great with Adafruit's Huzzah ESP board & Feather
----> https://www.adafruit.com/product/2471
----> https://www.adafruit.com/products/2821
How To Set Up Hardware
https://learn.adafruit.com/home-automation-in-the-cloud-with-the-esp8266-and-adafruit-io/programming-the-modules
https://learn.adafruit.com/remote-control-with-the-huzzah-plus-adafruit-io
How To Set Up Software
https://github.com/openhomeautomation/adafruit-io-esp8266/blob/master/esp8266_sensor_module/esp8266_sensor_module.ino
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Tony DiCola for Adafruit Industries.
MIT license, all text above must be included in any redistribution
* ****************************************************/
/************ESP8266 Debug****************************
* http://arduino-esp8266.readthedocs.io/en/latest/faq/a02-my-esp-crashes.html
* How to debug errors thrown by ESP8266 https://github.com/me-no-dev/EspExceptionDecoder
*
* ****************************************************/
/* ****** OneWire DS18B20 Temperature Example**********
http://www.pjrc.com/teensy/td_libs_OneWire.html
The DallasTemperature library can do all this work for you!
http://milesburton.com/Dallas_Temperature_Control_Library
https://create.arduino.cc/projecthub/TheGadgetBoy/ds18b20-digital-temperature-sensor-and-arduino-9cc806
* ****************************************************/
/* *****************DHT11****************************
*
* http://www.hobbyist.co.nz/?q=documentations/wiring-up-dht11-temp-humidity-sensor-to-your-arduino
*
*
* ****************************************************/
#include "ESP8266WiFi.h"
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
#include <DHT.h>
#include <DHT_U.h>
#include <OneWire.h>
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#include <DHT.h>
// Contains Keys and access tokens. Path: Arduino/libraries/configuration/Configuration.h
#include <Configuration.h>
/************************* WiFi Access Point *********************************/
#define WLAN_SSID CONFIG_WLAN_SSID
#define WLAN_PASS CONFIG_WLAN_PASS
/************************* Adafruit.io Setup *********************************/
#define AIO_SERVER CONFIG_AIO_SERVER
#define AIO_SERVERPORT CONFIG_AIO_SERVERPORT // use 8883 for SSL
#define AIO_USERNAME CONFIG_AIO_USERNAME
#define AIO_KEY CONFIG_AIO_KEY
/************ Global State (you don't need to change this!) ******************/
// Create an ESP8266 WiFiClient class to connect to the MQTT server.
WiFiClient client;
// or... use WiFiFlientSecure for SSL
//WiFiClientSecure client;
const char MQTT_SERVER[] = AIO_SERVER;
const char MQTT_USERNAME[] = AIO_USERNAME;
const char MQTT_PASSWORD[] = AIO_KEY;
// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, MQTT_SERVER, AIO_SERVERPORT, MQTT_USERNAME, MQTT_PASSWORD);
/******************** DHT TEMP & HUMIDITY SENSOR ****************************/
#define DHTPIN 2 // Pin which is connected to the DHT sensor.
#define DHTTYPE DHT11 // DHT 11
DHT_Unified dht(DHTPIN, DHTTYPE);
/********* DS18B20 (digital temperature sensor) ****************************/
OneWire ds(13); // on pin 10 (a 4.7K resistor is necessary)
/********* TFT 1.8 inch ST7735 from Adafruit ****************************/
// These pins work for the 1.8" TFT shield on Huzzah
#define TFT_CS 14
#define TFT_RST 15
#define TFT_DC 12
#define TFT_SCLK 4 // Note, overwites the default Huzzah i2c pins. set these to be whatever pins you like!
#define TFT_MOSI 5 // Note, overwites the default Huzzah i2c pins. set these to be whatever pins you like!
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);
/****************************** Feeds ***************************************/
// Setup a feed called 'photocell' for publishing.
// Notice MQTT paths for AIO follow the form: <username>/feeds/<feedname>
//const char PHOTOCELL_FEED[] = AIO_USERNAME "/feeds/photocell";
//Adafruit_MQTT_Publish photocell = Adafruit_MQTT_Publish(&mqtt, PHOTOCELL_FEED);
const char TEMPERATURE_FEED[] = AIO_USERNAME "/feeds/temperature";
Adafruit_MQTT_Publish temperature = Adafruit_MQTT_Publish(&mqtt, TEMPERATURE_FEED);
const char WATER_TEMPERATURE_FEED[] = AIO_USERNAME "/feeds/water_temperature";
Adafruit_MQTT_Publish water_temperature = Adafruit_MQTT_Publish(&mqtt, WATER_TEMPERATURE_FEED);
const char HUMIDITY_FEED[] = AIO_USERNAME "/feeds/humidity";
Adafruit_MQTT_Publish humidity = Adafruit_MQTT_Publish(&mqtt, HUMIDITY_FEED);
// Setup a feed called 'onoff' for subscribing to changes.
const char ONOFF_FEED[] = AIO_USERNAME "/feeds/onoff";
Adafruit_MQTT_Subscribe onoffbutton = Adafruit_MQTT_Subscribe(&mqtt, ONOFF_FEED);
/*************************** Sketch Code ************************************/
// Bug workaround for Arduino 1.6.6, it seems to need a function declaration
// for some reason (only affects ESP8266, likely an arduino-builder bug).
void MQTT_connect();
void setup() {
Serial.begin(115200);
delay(10);
initilizeTFTDisplay();
connectToWifi();
// Setup MQTT subscription for onoff feed.
mqtt.subscribe(&onoffbutton);
dht.begin();
getDHTSensorDetails();
}
void loop() {
// Ensure the connection to the MQTT server is alive (this will make the first
// connection and automatically reconnect when disconnected). See the MQTT_connect
// function definition further below.
MQTT_connect();
// this is our 'wait for incoming subscription packets' busy subloop
Adafruit_MQTT_Subscribe *subscription;
// Implement to controll light
// while ((subscription = mqtt.readSubscription(1000))) {
// if (subscription == &onoffbutton) {
// Serial.print(F("Got: "));
// Serial.println((char *)onoffbutton.lastread);
// }
// }
float water_temp = readTemperatureFrom1WireWaterproofSensor();
float air_temperature = readAirTemperatureFromDHT11(air_temperature);
float air_humidity = readAirHumidityFromDHT11(air_humidity);
Serial.print("--air_temperature_data is ");
Serial.println(air_temperature);
if (! temperature.publish(air_temperature)){
Serial.println(F("Failed to publish air_temperature\n"));
}
else{
Serial.println(F("Temperature published!\n"));
}
Serial.print("--water_temperature is ");
Serial.println(water_temp);
if(water_temp > 0){
if (! water_temperature.publish(water_temp)){
Serial.println(F("Failed to publish water_temperature\n"));
}
else{
Serial.println(F("Water Temperature published!\n"));
}
}
Serial.print("--humidity_data is ");
Serial.println(air_humidity);
if (! humidity.publish(air_humidity))
Serial.println(F("Failed to publish humidity\n"));
else
Serial.println(F("Humidity published!\n"));
// reset screen for next set of readings
tft.fillScreen(ST7735_BLACK);
displayWaterTemperature(water_temp);
displayAirTemperature(air_temperature);
displayHumidityTemperature(air_humidity);
// Serial.print(F("\nSending photocell val "));
// Serial.print("...");
// if (! photocell.publish(photocell)) {
// Serial.println(F("Failed\n"));
// } else {
// Serial.println(F("OK!\n"));
// }
// ping the server to keep the mqtt connection alive
// NOT required if you are publishing once every KEEPALIVE seconds
// keepAliveMQTT();
delay(5000);
}
float readTemperatureFrom1WireWaterproofSensor(){
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius, fahrenheit;
if ( !ds.search(addr)) {
Serial.println("No more addresses.");
Serial.println();
ds.reset_search();
delay(250);
return 0.00;
}
Serial.print("ROM =");
for( i = 0; i < 8; i++) {
Serial.write(' ');
Serial.print(addr[i], HEX);
}
if (OneWire::crc8(addr, 7) != addr[7]) {
Serial.println("CRC is not valid!");
return 0.00;
}
Serial.println();
// the first ROM byte indicates which chip
switch (addr[0]) {
case 0x10:
Serial.println(" Chip = DS18S20"); // or old DS1820
type_s = 1;
break;
case 0x28:
Serial.println(" Chip = DS18B20");
type_s = 0;
break;
case 0x22:
Serial.println(" Chip = DS1822");
type_s = 0;
break;
default:
Serial.println("Device is not a DS18x20 family device.");
return 0.00;
}
ds.reset();
ds.select(addr);
ds.write(0x44, 1); // start conversion, with parasite power on at the end
delay(750); // maybe 750ms is enough, maybe not
// we might do a ds.depower() here, but the reset will take care of it.
present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
Serial.print(" Data = ");
Serial.print(present, HEX);
Serial.print(" ");
for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
Serial.print(data[i], HEX);
Serial.print(" ");
}
Serial.print(" CRC=");
Serial.print(OneWire::crc8(data, 8), HEX);
Serial.println();
// Convert the data to actual temperature
// because the result is a 16 bit signed integer, it should
// be stored to an "int16_t" type, which is always 16 bits
// even when compiled on a 32 bit processor.
int16_t raw = (data[1] << 8) | data[0];
if (type_s) {
raw = raw << 3; // 9 bit resolution default
if (data[7] == 0x10) {
// "count remain" gives full 12 bit resolution
raw = (raw & 0xFFF0) + 12 - data[6];
}
} else {
byte cfg = (data[4] & 0x60);
// at lower res, the low bits are undefined, so let's zero them
if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms
else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
//// default is 12 bit resolution, 750 ms conversion time
}
celsius = (float)raw / 16.0;
fahrenheit = celsius * 1.8 + 32.0;
Serial.print("Water Temperature = ");
Serial.print(celsius);
Serial.print(" Celsius, ");
Serial.print(fahrenheit);
Serial.println(" Fahrenheit");
return celsius;
}
void getDHTSensorDetails(){
Serial.println("DHTxx Unified Sensor Example");
// Print temperature sensor details.
sensor_t sensor;
dht.temperature().getSensor(&sensor);
Serial.println("------------------------------------");
Serial.println("Temperature");
Serial.print ("Sensor: "); Serial.println(sensor.name);
Serial.print ("Driver Ver: "); Serial.println(sensor.version);
Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" *C");
Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" *C");
Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" *C");
Serial.println("------------------------------------");
// Print humidity sensor details.
dht.humidity().getSensor(&sensor);
Serial.println("------------------------------------");
Serial.println("Humidity");
Serial.print ("Sensor: "); Serial.println(sensor.name);
Serial.print ("Driver Ver: "); Serial.println(sensor.version);
Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println("%");
Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println("%");
Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println("%");
Serial.println("------------------------------------");
// Set delay between sensor readings based on sensor details.
// delayMS = sensor.min_delay / 1000;
}
float readAirTemperatureFromDHT11(float air_temperature){
// Get temperature event and print its value.
sensors_event_t event;
dht.temperature().getEvent(&event);
if (isnan(event.temperature)) {
Serial.println("Error reading temperature!");
}
else {
Serial.print("DHT11, Air Temperature: ");
Serial.print(event.temperature);
Serial.println(" *C");
}
return event.temperature;
}
float readAirHumidityFromDHT11(float air_humidity){
// Get temperature event and print its value.
sensors_event_t event;
// Get humidity event and print its value.
dht.humidity().getEvent(&event);
if (isnan(event.relative_humidity)) {
Serial.println("Error reading humidity!");
}
else {
Serial.print("DHT11, Humidity: ");
Serial.print(event.relative_humidity);
Serial.println("%");
}
return event.relative_humidity;
}
void displayWaterTemperature(float water_temp){
tft.setCursor(0, 0);
String color = "white";
if(water_temp > 0){
if (water_temp <= 23.3 && water_temp >= 22.2){
color = "yellow";
}else if (water_temp <= 22.2){
color = "blue";
}else if (water_temp >= 23.3 && water_temp <= 25.5){
color = "green";
}else if (water_temp >= 25.5 && water_temp <= 26.1){
color = "yellow";
} else {
color = "red";
}
displayText("H2O Temp", " C", color , water_temp);
} else {
//do nothing - getting a zero value every other reading from water temp sensor
}
}
void displayAirTemperature(float air_temp){
tft.setCursor(0, 50);
String color = "white";
if(air_temp > 0){
if (air_temp <= 20 && air_temp >= 18.3){
color = "yellow";
}else if (air_temp <= 20){
color = "blue";
}else if (air_temp >= 20 && air_temp <= 22.2){
color = "green";
}else if (air_temp >= 22.2 && air_temp <= 23.3){
color = "yellow";
} else {
color = "red";
}
displayText("Air Temp", " C", color , air_temp);
} else {
//do nothing - getting a zero value every other reading from water temp sensor
}
}
void displayHumidityTemperature(float air_humidity){
tft.setCursor(0, 100);
String color = "white";
if(air_humidity > 0){
if (air_humidity <= 40 && air_humidity >= 35){
color = "yellow";
}else if (air_humidity <= 40){
color = "blue";
}else if (air_humidity >= 40 && air_humidity <= 55){
color = "green";
}else if (air_humidity >= 55 && air_humidity <= 70){
color = "yellow";
} else {
color = "red";
}
displayText("Humidity", " %", color , air_humidity);
} else {
//do nothing - getting a zero value every other reading from water temp sensor
}
}
void displayText(String parameter, String unitOfMeasure, String color, float value){
// LIST OF AVAILABLE PREDEFINED COLORS IN LIBRARY
//#define ST7735_BLACK 0x0000
//#define ST7735_BLUE 0x001F
//#define ST7735_RED 0xF800
//#define ST7735_GREEN 0x07E0
//#define ST7735_CYAN 0x07FF
//#define ST7735_MAGENTA 0xF81F
//#define ST7735_YELLOW 0xFFE0
//#define ST7735_WHITE 0xFFFF
if (color == "red"){
tft.setTextColor(ST7735_RED);
}else if (color == "green"){
tft.setTextColor(ST7735_GREEN);
}else if (color == "yellow"){
tft.setTextColor(ST7735_YELLOW);
}else if (color == "blue"){
tft.setTextColor(ST7735_BLUE);
}else {
tft.setTextColor(ST7735_WHITE);
}
tft.setTextSize(2);
tft.println(parameter + unitOfMeasure);
tft.setTextSize(3);
tft.println(value);
}
void initilizeTFTDisplay(){
// Use this initializer if you're using a 1.8" TFT
tft.initR(INITR_BLACKTAB); // initialize a ST7735S chip, black tab
Serial.println("TFT Initialized");
tft.fillScreen(ST7735_BLACK);
}
void connectToWifi(){
// Connect to WiFi access point.
Serial.println(); Serial.println();
Serial.print("Connecting to ");
Serial.println(WLAN_SSID);
WiFi.begin(WLAN_SSID, WLAN_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void keepAliveMQTT(){
// if(! mqtt.ping(3)) {
// reconnect to adafruit io
// if(! mqtt.connected())
// MQTT_connect();
// }
// if(! mqtt.ping()) {
// mqtt.disconnect();
// }
}
// 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... ");
uint8_t retries = 3;
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
retries--;
if (retries == 0) {
// basically die and wait for WDT to reset me
while (1);
}
}
Serial.println("MQTT Connected!");
}
Comments
Please log in or sign up to comment.