Please read Liability Disclaimer and License Agreement CAREFULLY
Revolutionize your plant care with this Arduino code for ESP8266 used on a plant sensor.
This code is measuring vital plant health indicators like soil moisture, temperature, UV and light and humidity in air.
With user-friendly instructions and customizable settings, the code is the perfect tool for hobbyists and professionals alike.
Read further to learn more and take your plant care to the next level.
This is the code that runs on the ESP8266 connected to
#include <ESP8266WiFi.h>
#include "PubSubClient.h" // Connect and publish to the MQTT broker
enum data_type {
int_data,
float_data
};
//Sensors on board
//#define has_BMP280 //Bosch Absolute barometric pressure and temperature - comment if not used
//#define has_SI7006 //Silicon Labs Humidity and temperature sensor - comment if not used
//#define has_TCS3471_a //AMS Color sensor - comment if not used
//#define has_TCS3471_b //AMS Color sensor - comment if not used
//#define has_VEML6070 //Vishay UV sensor - comment if not used
//Sensor location
#define sen_location "outdoor"
#define sen_ID "S1"
#define clientID (sen_ID sen_location) // MQTT client ID
#define dataLen 0
//MQTT topics - comment the defines not used on specific board configuration
//Battery level
#define BL_topic sen_location "/" sen_ID "/bl"
#ifdef BL_topic
const uint8_t BL_len = 4;
#else
const uint8_t BL_len = 0;
#endif
#ifdef has_BMP280
#define AP_topic sen_location "/" sen_ID "/ap"
const uint8_t BMP280_len = 4;
#else
const uint8_t BMP280_len = 0;
#endif
#ifdef has_SI7006
#define AH_topic sen_location "/" sen_ID "/ah"
const uint8_t SI7006_len = 4;
#else
const uint8_t SI7006_len = 0;
#endif
#ifdef has_SI7006 || has_BMP280
//If we use only BMP280 or SI7006 publish only one temperature
//If we use both the we publish the average
#define AT_topic sen_location "/" sen_ID "/at"
const uint8_t AT_len = 4;
#else
const uint8_t AT_len = 0;
#endif
#ifdef has_TCS3471_a
#define R_topic0 sen_location "/" sen_ID "/r0"
#define G_topic0 sen_location "/" sen_ID "/g0"
#define B_topic0 sen_location "/" sen_ID "/b0"
#define C_topic0 sen_location "/" sen_ID "/c0"
const uint8_t TCS3471_a_len = 8;
#else
const uint8_t TCS3471_a_len = 0;
#endif
#ifdef has_TCS3471_b
#define R_topic1 sen_location "/" sen_ID "/r1"
#define G_topic1 sen_location "/" sen_ID "/g1"
#define B_topic1 sen_location "/" sen_ID "/b1"
#define C_topic1 sen_location "/" sen_ID "/c1"
const uint8_t TCS3471_b_len = 8;
#else
const uint8_t TCS3471_b_len = 0;
#endif
#ifdef has_VEML6070
#define UV_topic sen_location "/" sen_ID "/uv"
const uint8_t VEML6070_len = 8;
#else
const uint8_t VEML6070_len = 0;
#endif
//Up to 6 soil humidity sensors
#define SH0_topic sen_location "/" sen_ID "/sh0"
//#define SH1_topic sen_location "/" sen_ID "/sh1"
//#define SH2_topic sen_location "/" sen_ID "/sh2"
//#define SH3_topic sen_location "/" sen_ID "/sh3"
//#define SH4_topic sen_location "/" sen_ID "/sh4"
//#define SH5_topic sen_location "/" sen_ID "/sh5"
#ifdef SH0_topic
const uint8_t SH0_len = 4;
#else
const uint8_t SH0_len = 0;
#endif
#ifdef SH1_topic
const uint8_t SH1_len = 4;
#else
const uint8_t SH1_len = 0;
#endif
#ifdef SH2_topic
const uint8_t SH2_len = 4;
#else
const uint8_t SH2_len = 0;
#endif
#ifdef SH3_topic
const uint8_t SH3_len = 4;
#else
const uint8_t SH3_len = 0;
#endif
#ifdef SH4_topic
const uint8_t SH4_len = 4;
#else
const uint8_t SH4_len = 0;
#endif
#ifdef SH5_topic
const uint8_t SH5_len = 4;
#else
const uint8_t SH5_len = 0;
#endif
const uint8_t dLen = (BL_len + BMP280_len + SI7006_len + AT_len + TCS3471_a_len + TCS3471_b_len + VEML6070_len + SH0_len + SH1_len + SH2_len + SH3_len + SH4_len + SH5_len);
// WiFi 80:7d:3a:3e:50:f7
const char *ssid = "xxxx"; //Your 2.4GHz network name
const char *password = "yyyy"; //Your 2.4GHz network password
// Mosquitto MQTT server credentials
const char* mqtt_server = "zz.zz.zz.zz";// IP of the MQTT broker
const char* mqtt_username = "JohnDoe"; // MQTT username
const char* mqtt_password = "JohnDoe!"; // MQTT password
const uint8_t msTime = 50;
//The end marker is not added to buffer
//Blue pill will transmit 34 bytes including markers
/*
BL_topic 0
AP_topic 4
AT_topic 8
AH_topic 12
SH0_topic 16
SH1_topic 20
SH2_topic 24
SH3_topic 28
SH4_topic 32
SH5_topic 36
UV_topic 40
has_TCS3471_a 42
R_topic0 42
G_topic0 44
B_topic0 46
C_topic0 48
has_TCS3471_b 50
R_topic1 50
G_topic1 52
B_topic1 54
C_topic1 56
*/
const uint8_t BL_pos = 0;//Battery level
const uint8_t AP_pos = 0;//Air pressure
const uint8_t AT_pos = 0;//Air Temperature
const uint8_t AH_pos = 0;//Air humidity
const uint8_t SH0_pos = 0;//Soil humidity
const uint8_t SH1_pos = 0;//Soil humidity
const uint8_t SH2_pos = 0;//Soil humidity
const uint8_t SH3_pos = 0;//Soil humidity
const uint8_t SH4_pos = 0;//Soil humidity
const uint8_t SH5_pos = 0;//Soil humidity
const uint8_t UV_pos = 0;//UV
const uint8_t R0_pos = 0;//Red sensor 1
const uint8_t G0_pos = 0;//Green sensor 1
const uint8_t B0_pos = 0;//Blue sensor 1
const uint8_t C0_pos = 0;//Clear sensor 1
const uint8_t R1_pos = 0;//Red sensor 2
const uint8_t G1_pos = 0;//Green sensor 2
const uint8_t B1_pos = 0;//Blue sensor 2
const uint8_t C1_pos = 0;//Clear sensor 2
const uint8_t sMarker = 60;//<
const uint8_t eMarker = 62;//>
//Messages we get from BP
const uint8_t BP_SYNK_1 = 125;//To get from BP when is ready for first synk
const uint8_t BP_SYNK_2 = 126;//To get from BP when is ready for second synk
//Messages we send to BP
const uint8_t ESP_READY = 100;//To send to BP when ESP is ready, first synk
const uint8_t ESP_WAIT = 101;//To send to BP when ESP is ready, second synk
const uint8_t ESP_DATA_I = 102;//To confirm the 32 bytes received
const uint8_t ESP_HTTP_IR = 103;//To send to BP when HTTP request is invalid
const uint8_t ESP_HTTP_RF = 104;//To send to BP when HTTP request failed
const uint8_t ESP_DATA_O = 105;//To send to BP when data is received
const uint8_t ESP_HTTP_OK = 106;//To send to BP when HTTP request is OK
const uint8_t ESP_SHORT = 0;//We are expecting a short message
const uint8_t ESP_LONG = 1;//We are expecting a Long message
uint8_t ESP_EXPECT = 0;//Variable to hold the size of expected message
//array to holde the data received from ESP
uint8_t BP_DATA[dLen];
//variables that will hold the sensors values receive from ESP
boolean ESP_Reading = false;
uint8_t ESP_Msg = 0;
uint8_t MsgLen = 0;
uint32_t MsgTime = 0;
WiFiClient wifi_Client;
PubSubClient mqtt_Client(mqtt_server, 1883, wifi_Client);
float battery = 1.0f; //for testing
void setup(){
pinMode(LED_BUILTIN, OUTPUT);
pinMode(0, OUTPUT);
//Serial.setRxBufferSize(256); //require ESP8266 >= 2.4.0 https://github.com/esp8266/Arduino/releases/tag/2.4.0-rc1
Serial.begin(115200);
delay(msTime);
//Static IP address configuration
IPAddress staticIP(10, 0, 1, 125); //ESP static ip
IPAddress gateway(10, 0, 1, 1); //IP Address of your WiFi Router (Gateway)
IPAddress subnet(255, 255, 255, 0); //Subnet mask
IPAddress dns(10, 0, 1, 1); //DNS
//Static IP address configuration
WiFi.disconnect();
WiFi.config(staticIP, subnet, gateway, dns);
WiFi.mode(WIFI_STA);
//WiFi.persistent(false);
WiFi.hostname("MQTT_1");
WiFi.begin(ssid, password);
MsgTime = millis();
while (WiFi.status() != WL_CONNECTED) {
delay(msTime);
}
// Connect to MQTT Broker
if (mqtt_Client.connect(clientID, mqtt_username, mqtt_password)) {
Serial.println("Connected to MQTT Broker!");
}
else {
Serial.println("Connection to MQTT Broker failed...");
}
digitalWrite(LED_BUILTIN, HIGH);
Serial.print("WiFi connected in ");
Serial.print((millis() - MsgTime)/1000);
Serial.println(" seconds");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
ClearBuffer();
//we are expecting short messages
ESP_EXPECT = ESP_SHORT;
sendDataToBluePill(ESP_READY);//let Blue pill know that ESP is ready to first synk
//wait for BluePill to respond
// while(ESP_Msg != BP_SYNK_1){
// CheckBluePillData();
// }
ClearBuffer();
MsgTime = millis();
}
void loop() {
//get in synk with BP
// while(ESP_Msg != BP_SYNK_2){
// CheckBluePillData();
// //sendDataToBluePill(ESP_WAIT);//let Blue pill know that ESP is ready to get 32 bytes
// }
// ESP_EXPECT = ESP_LONG;
//
// //wait to get the 32bytes from BP
// while(ESP_Msg != ESP_DATA_I){
// //Check data fron serialport
// CheckBluePillData();
// }
// //turn ON the LED for transmission
// digitalWrite(LED_BUILTIN, LOW);
//for(uint8_t i = 0; i < 100; i++){
// sendDataToBluePill(ESP_DATA_O);
//}
//prepare the data to be sent to server
//R, G, B, C bytes for each value, so 8 bytes per sensor
//UV 2 bytes
//Pressure, temperature, humidity, temperture, soil humidity will have 4 bypes per value
if(millis() > MsgTime){
battery += 0.1f;
if(battery > 100.0f) battery = 1.0f;
String val = String(battery);
if (!mqtt_Client.publish(BL_topic, String(val).c_str())) {
mqtt_Client.connect(clientID, mqtt_username, mqtt_password);
delay(10); // This delay ensures that client.publish doesn't clash with the client.connect call
mqtt_Client.publish(BL_topic, String(val).c_str());
}
//SendData();
Serial.print("Sent : ");Serial.println(val);
MsgTime = millis() + 10000;
}
//Turn OFF the LED to signal end transmission
//digitalWrite(LED_BUILTIN, HIGH);
//Serial.println();
//Serial.print("T2=");Serial.println(millis() - MsgTime);
//Serial.println();
// while(1) {
// sendDataToBluePill(ESP_Msg);
// }
}
void sendInterrupt(void){
digitalWrite(0, HIGH);
delayMicroseconds(100);
digitalWrite(0, LOW);
}
void sendDataToBluePill(uint8_t data){
uint8_t arrBP[3] = {sMarker, data, eMarker};
Serial.write(arrBP, 3);
//delay(msTime);
}
void CheckBluePillData() {
// receive data from BluePill and save it into BP_DATA
if(Serial.available() > 0) {
uint8_t DataIn = Serial.read();
// the order of these IF clauses is significant
//Do we have the end marker?
if (DataIn == eMarker) {
//we have the end marker,do we expect more data?
//if we expect 3 bytes then
if(!ESP_EXPECT) {
//if we have 1 byte in the message
if(MsgLen == 1) {
ESP_Reading = false;
ESP_Msg = BP_DATA[0];
//Serial.print("3Bytes in:");
//Serial.println(millis() - MsgTime);
}
} else {
//if we have 32 bytes in buffer
if(MsgLen == dLen) {
ESP_Reading = false;
ESP_Msg = ESP_DATA_I;
//Serial.print("32Bytes in:");
//Serial.println(millis() - MsgTime);
}
}
}
//if we are reading
if(ESP_Reading) {
BP_DATA[MsgLen] = DataIn;
MsgLen ++;
}
//if we read the start marker and we are not reading
if ((DataIn == sMarker) && !ESP_Reading) {
MsgLen = 0;
ESP_Reading = true;
//MsgTime = millis();
}
}
}
void SendData() {
//Publishto the MQTT Broker
//Battery level
#ifdef BL_topic
publishMQTT(BL_topic, BL_pos, float_data);
#endif
//Air Pressure
#ifdef AP_topic
publishMQTT(AP_topic, AP_pos, float_data);
#endif
//Air Temperature
#ifdef AT_topic
publishMQTT(AT_topic, AT_pos, float_data);
#endif
//Air Humidity
#ifdef AH_topic
publishMQTT(AH_topic, AH_pos, float_data);
#endif
//Soil humidity 0
#ifdef SH0_topic
publishMQTT(SH0_topic, SH0_pos, float_data);
#endif
//Soil humidity 1
#ifdef SH1_topic
publishMQTT(SH1_topic, SH1_pos, float_data);
#endif
//Soil humidity 2
#ifdef SH2_topic
publishMQTT(SH2_topic, SH2_pos, float_data);
#endif
//Soil humidity 3
#ifdef SH3_topic
publishMQTT(SH3_topic, SH3_pos, float_data);
#endif
//Soil humidity 4
#ifdef SH4_topic
publishMQTT(SH4_topic, SH4_pos, float_data);
#endif
//Soil humidity 5
#ifdef SH5_topic
publishMQTT(SH5_topic, SH5_pos, float_data);
#endif
//UV level
#ifdef UV_topic
publishMQTT(UV_topic, UV_pos, int_data);
#endif
//R0 level
#ifdef R_topic0
publishMQTT(R_topic0, R0_pos, int_data);
#endif
//G0 level
#ifdef G_topic0
publishMQTT(G_topic0, G0_pos, int_data);
#endif
//B0 level
#ifdef B_topic0
publishMQTT(B_topic0, B0_pos, int_data);
#endif
//C0 level
#ifdef C_topic0
publishMQTT(C_topic0, C0_pos, int_data);
#endif
//R1 level
#ifdef R_topic1
publishMQTT(R_topic1, R1_pos, int_data);
#endif
//G1 level
#ifdef G_topic1
publishMQTT(G_topic1, G1_pos, int_data);
#endif
//B1 level
#ifdef B_topic1
publishMQTT(B_topic1, B1_pos, int_data);
#endif
//C1 level
#ifdef C_topic1
publishMQTT(C_topic1, C1_pos, int_data);
#endif
}
void publishMQTT(char* topic, uint8_t position, data_type myType){
String val;
if(!myType) {
val = String(getInt(position));
}else {
val = String(getFloat(position));
}
if (!mqtt_Client.publish(topic, String(val).c_str())) {
mqtt_Client.connect(clientID, mqtt_username, mqtt_password);
delay(10); // This delay ensures that client.publish doesn't clash with the client.connect call
mqtt_Client.publish(topic, String(val).c_str());
}
}
//Serial.flush() function does not empty the input buffer. It is only relevant when the Arduino
//is sending data and its purpose is to block the Arduino until all outgoing the data has been sent.
void ClearBuffer(){
while (Serial.available() > 0) {
Serial.read();
}
}
void Blink_Led(void) {
digitalWrite(LED_BUILTIN, LOW);
delay (msTime);
digitalWrite(LED_BUILTIN, HIGH);
delay (msTime);
}
uint16_t getInt(uint8_t pos){
uint16_t retVal = ((uint16_t)BP_DATA[pos] << 8);
retVal |= BP_DATA[pos + 1];
return retVal;
}
float getFloat(uint8_t pos){
int32_t newVal = ((uint32_t)BP_DATA[pos] << 24);
newVal |= ((uint32_t)BP_DATA[pos + 1] << 16);
newVal |= ((uint32_t)BP_DATA[pos + 2] << 8);
newVal |= BP_DATA[pos + 3];
return (float)newVal/100.0f;
}
Comments powered by CComment