Hello,
I have a created a aquarium dosing and motoring program using a Wemos D1 mini. The main light is only controllable via I.R. It all works using I.R.; however, I would like a way to be able to tell in my Blynk app that the signal was received and/or whether the light is currently on. Any ideas?
/* Wemos D1 mini R1
D0 heater relay
D1 empty (mosfet)
D2 IR
D4 water temp sensor
D5 aux light
D6 pump relay
D7 CO2 relay
BLYNK VIRTUAL PINS
MISC V0-V9
V0 water Temp
V1 time
V2 activeLED
V3 CO2LED
V4 heaterLED
V5 blynkLCD
Lights V10-V29
Pumps/Sliders V30-V39
V40 Dose Counter Reset
*/
//#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <BlynkSimpleEsp8266.h>
#include <EEPROM.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <IRremoteESP8266.h>
#include <IRsend.h>
#include <TimeLib.h>
#include <WidgetRTC.h>
#define heaterPin D0
#define lightPin D1
#define IR_LED D2
#define ONE_WIRE_BUS D4
#define motorPin D6
#define CO2Pin D7
#define lightButton V20
#define pumpButton V30
char auth[] = "XXXXXXXXXXXXX";
const char* ssid = "XXXXX";
const char* pass = "XXXXXX";
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature DS18B20(&oneWire);
BlynkTimer timer;
WidgetRTC rtc;
WidgetLED activeLED(V2);
WidgetLED CO2LED(V3);
WidgetLED heaterLED (V4);
WidgetLCD blynkLCD(V5);
IRsend irsend(IR_LED); // Set the GPIO to be used to sending the message.
////variables
float waterTemp = 0;
int pumpCount = 0;
float mlsGiven = 0;
float pumpml;
float correctionFactor = 1; //correction factor for pump
String lastRunDate = ""; //for LCD to Print the Date Pump ran
String lastRunTime = ""; //for LCD to Print the Time Pump ran
/////////////////////CLOCK/////////////////////////////
String getTime() {
String currentTime = String(hour()) + ":" + minute() + ":" + second();
return currentTime;
}
String getDate() {
String currentDate = String(month()) + "/" + day() ;
return currentDate;
}
BLYNK_CONNECTED() {// Synchronize time, widgets on connection
rtc.begin();
Blynk.syncVirtual(V20); //rear light button
Blynk.syncVirtual(V31); //fertilizer slide
Blynk.syncVirtual(V30); //pump
}
//////////////////////PUMPS///////////////////////////
BLYNK_WRITE(V31) {// Pump 1 slider
pumpml = param.asFloat();
Serial.println(String("Pump 1 slider value = ") + pumpml );
}
void primePump() {
digitalWrite(motorPin, HIGH);
blynkLCD.clear();
Serial.println("PRIMING PUMP");
blynkLCD.print(0, 0, " PRIMING PUMP");
Blynk.virtualWrite(V30, 1);
timer.setTimeout(2000, LCDWriteCounts);
}
BLYNK_WRITE(pumpButton) {// Prime button
int motorButtonValue = param.asInt();
if (motorButtonValue == 1) {
primePump();
}
else {
pumpOff();
}
}
void pumpOff() {
digitalWrite(motorPin, LOW);
Blynk.virtualWrite(pumpButton, LOW);
}
void runPump() {
Serial.println(String("Dosing ThriveS") + pumpml + (" mls"));
Blynk.virtualWrite(V30, 1);
blynkLCD.clear();
blynkLCD.print(0, 0, "Dosing ThriveS");
blynkLCD.print(4, 1, pumpml);
blynkLCD.print(10, 1, "ml");
Blynk.virtualWrite(pumpButton, HIGH);
Blynk.setProperty(pumpButton, "onLabel", "DOSING");
digitalWrite(motorPin, HIGH);
delay(pumpml * (1000 * correctionFactor)); // set how long you want the motor to run... 1000 = aprox 1ml
pumpOff();
delay(1000);// for doses < one second long
pumpCount ++;
lastRunTime = getTime();
lastRunDate = getDate();
mlsGiven = (mlsGiven + pumpml);
EEPROM.write(0, pumpCount);
EEPROM.write(1, hour());
EEPROM.write(2, minute());
EEPROM.write(3, second());
EEPROM.write(4, month());
EEPROM.write(5, day());
EEPROM.put(6, mlsGiven);
EEPROM.commit();
timer.setTimeout(2000, LCDWriteCounts);
}
void LCDWriteCounts() {
blynkLCD.clear();
blynkLCD.print(0, 0, "#");
blynkLCD.print(1, 0, pumpCount);
blynkLCD.print(4, 0, "t.ml: ");
blynkLCD.print(10, 0, mlsGiven);
//Line 2
blynkLCD.print(0, 1, lastRunDate);
blynkLCD.print(8, 1, lastRunTime);
}
void resetCounts() {
for (int a = 0; a < 1; a++) {
pumpCount = 0;
mlsGiven = 0;
lastRunDate = "";
lastRunTime = "";
}
for (int i = 0 ; i < 30 ; i++) {
EEPROM.write(i, 0);
}
EEPROM.commit();
blynkLCD.clear();
Serial.println("EEPROM ERASED");
Serial.println("counts reset");
blynkLCD.print(0, 0, " EEPROM ERASED");
blynkLCD.print(0, 1, " COUNTS RESET");
timer.setTimeout(2000, LCDWriteCounts);
}
BLYNK_WRITE(V40) {// Count reset
int resetButton = param.asInt();
if (resetButton == 1) {
resetCounts();
}
}
void getPumpData() { // Read pump EEPROM data and write to variables
pumpCount = EEPROM.read(0);
lastRunTime = String(EEPROM.read(1)) + ":" + EEPROM.read(2) + ":" + EEPROM.read(3);
lastRunDate = String(EEPROM.read(4)) + "/" + EEPROM.read(5);
float f = 0.00f;
mlsGiven = EEPROM.get(6, f);
}
//////////////////////CO2//////////////////////////
void CO2ON() {
digitalWrite(CO2Pin, HIGH);
Serial.println("CO2 ON");
CO2LED.on();
}
void CO2OFF() {
digitalWrite(CO2Pin, LOW);
Serial.println("CO2 OFF");
CO2LED.off();
}
//////////////////////LIGHTS//////////////////////////
void rearLightOn() {
Blynk.virtualWrite(lightButton, HIGH);
digitalWrite(lightPin, HIGH);
Serial.println(String("light on"));
}
void rearLightOff() {
Blynk.virtualWrite(lightButton, LOW);
digitalWrite(lightPin, LOW);
Serial.println(String("light off"));
}
void powerWhite() {
irsend.sendNEC(0xF7C03F, 32);
}
void maxWhite() {
for (int i = 0; i < 10; i++) {
irsend.sendNEC(0xF7E01F, 32);
}
}
void minWhite() {
for (int i = 0; i < 10; i++) {
irsend.sendNEC(0xF7D02F, 32);
}
}
void upWhite(int p) {
for (int i = 0; i < p; i++) {
irsend.sendNEC(0xF7E01F, 32);
}
}
void downWhite(int p) {
for (int i = 0; i < p; i++) {
irsend.sendNEC(0xF7D02F, 32);
}
}
void maxRGB() {
for (int i = 0; i < 10; i++) {
irsend.sendNEC(0xF700FF, 32);
}
}
void minRGB() {
for (int i = 0; i < 10; i++) {
irsend.sendNEC(0xF7807F, 32);
}
}
void upRGB(int p) {
for (int i = 0; i < p; i++) {
irsend.sendNEC(0xF700FF, 32);
}
}
void downRGB(int p) {
for (int i = 0; i < p; i++) {
irsend.sendNEC(0xF7807F, 32);
}
}
void red() {
irsend.sendNEC(0xF720DF, 32);
}
void red1() {
irsend.sendNEC(0xF710EF, 32);
}
void red2() {
irsend.sendNEC(0xF730CF, 32);
}
void red3() {
irsend.sendNEC(0xF708F7, 32);
}
void red4() {
irsend.sendNEC(0xF728D7, 32);
}
void green1() {
irsend.sendNEC(0xF710EF, 32);
}
void green2() {
irsend.sendNEC(0xF730CF, 32);
}
void green3() {
irsend.sendNEC(0xF708F7, 32);
}
void green4() {
irsend.sendNEC(0xF728D7, 32);
}
void blue() {
irsend.sendNEC(0xF7609F, 32);
}
void blue1() {
irsend.sendNEC(0xF750AF, 32);
}
void blue2() {
irsend.sendNEC(0xF7708F, 32);
}
void blue3() {
irsend.sendNEC(0xF748B7, 32);
}
void blue4() {
irsend.sendNEC(0xF76897, 32);
}
BLYNK_WRITE(lightButton) { // Rear Light
int ltButton = param.asInt();
if (ltButton == HIGH) {
rearLightOn();
}
else {
rearLightOff();
}
}
BLYNK_WRITE(V10) { // White Power
int pinData = param.asInt();
if (pinData == HIGH) {
irsend.sendNEC(0xF7C03F, 32);
}
}
BLYNK_WRITE(V11) { // White Max
int pinData = param.asInt();
if (pinData == HIGH) {
maxWhite();
}
}
BLYNK_WRITE(V12) { // White Min
int pinData = param.asInt();
if (pinData == HIGH) {
minWhite();
}
}
BLYNK_WRITE(V13) { // RGB Power
int pinData = param.asInt();
if (pinData == HIGH) {
irsend.sendNEC(0xF740BF, 32);
}
}
BLYNK_WRITE(V14) { // RGB Max
int pinData = param.asInt();
if (pinData == HIGH) {
maxRGB();
}
}
BLYNK_WRITE(V15) { // RGB Min
int pinData = param.asInt();
if (pinData == HIGH) {
minRGB();
}
}
BLYNK_WRITE(V17) { // Moonlight
int pinData = param.asInt();
if (pinData == HIGH) {
irsend.sendNEC(0xF7F00F, 32);
}
}
BLYNK_WRITE(V18) { // Thunderstorm
int pinData = param.asInt();
if (pinData == HIGH) {
irsend.sendNEC(0xF7C837, 32);
}
}
BLYNK_WRITE(V19) { // RGB cycle
int pinData = param.asInt();
if (pinData == HIGH) {
irsend.sendNEC(0xF7E817, 32);
}
}
void blinkactiveLED() {
//LED
if (activeLED.getValue()) {
activeLED.off();
Serial.println("Status LED on V2: off");
} else {
activeLED.on();
Serial.println("Status LED on V2: on");
}
//CLOCK
Blynk.virtualWrite(V1, getTime());
}
void checkTemperature() {
DS18B20.requestTemperatures();
waterTemp = DS18B20.toFahrenheit(DS18B20.getTempCByIndex(0));
if (isnan(waterTemp)) {
Serial.println("Failed to read from DS18B20 sensor!");
return;
}
Blynk.virtualWrite(V0, waterTemp); //water
Serial.print(" DS18B20 F: "),
Serial.println(waterTemp);
}
void checkHeater() {
DS18B20.requestTemperatures();
waterTemp = DS18B20.toFahrenheit(DS18B20.getTempCByIndex(0));
if (isnan(waterTemp)) {
digitalWrite(heaterPin, LOW);
Blynk.setProperty(V4, "color", "#D3435C");
heaterLED.on();
Serial.println("temp sensor not working, heater OFF");
blynkLCD.clear();
blynkLCD.print(0, 0, "Temp Error");
return;
}
else if (waterTemp < 78) {
digitalWrite(heaterPin, HIGH);
Serial.println("Heater ON");
Blynk.setProperty(V4, "color", "#23C48E");
heaterLED.on();
}
else if (waterTemp >= 79) {
digitalWrite(heaterPin, LOW);
Serial.println("Heater OFF");
heaterLED.off();
}
}
void checkSchedules() {
if (hour() == 00 && minute() == 00 && second() == 00) {
CO2OFF();
blue();
downRGB(1);
rearLightOff();
}
if (hour() == 01 && minute() == 00 && second() == 00) {
CO2OFF();
blue();
downRGB(1);
rearLightOff();
}
if (hour() == 02 && minute() == 00 && second() == 00) {
CO2OFF();
blue();
downRGB(1);
rearLightOff();
}
if (hour() == 03 && minute() == 00 && second() == 00) {
CO2OFF();
blue();
minRGB();
rearLightOff();
}
if (hour() == 04 && minute() == 00 && second() == 00) {
CO2OFF();
blue1();
minRGB();
upRGB(2);
rearLightOff();
}
if (hour() == 05 && minute() == 00 && second() == 00) {
CO2OFF();
green2();
minRGB();
upRGB(7);
rearLightOn();
}
if (hour() == 06 && minute() == 00 && second() == 00) {
CO2OFF();
red4();
minRGB();
upRGB(4);
powerWhite();
Blynk.virtualWrite(V13, "ON: 1");
minWhite();
rearLightOn();
}
if (hour() == 07 && minute() == 00 && second() == 00) {
CO2OFF();
red4();
maxRGB();
upWhite(1);
Blynk.virtualWrite(V13, "ON: 3");
rearLightOn();
}
if (hour() == 8 && minute() == 00 && second() == 00) {
CO2ON();
red3();
maxRGB();
upWhite(1);
Blynk.virtualWrite(V13, "ON: 5");
rearLightOn();
}
if (hour() == 9 && minute() == 00 && second() == 00) {
runPump();//////daily fertilizer
CO2ON();
red2();
maxRGB();
upWhite(2);
Blynk.virtualWrite(V13, "ON: 8");
rearLightOn();
}
if (hour() == 10 && minute() == 00 && second() == 00) {
CO2ON();
red1();
maxRGB();
maxWhite();
Blynk.virtualWrite(V13, "ON: 10");
rearLightOn();
}
if (hour() == 11 && minute() == 00 && second() == 00) {
CO2ON();
red();
maxRGB();
maxWhite();
Blynk.virtualWrite(V13, "ON: 10");
rearLightOn();
}
if (hour() == 12 && minute() == 00 && second() == 00) {
CO2ON();
red();
maxRGB();
maxWhite();
Blynk.virtualWrite(V13, "ON: 10");
rearLightOn();
}
if (hour() == 13 && minute() == 00 && second() == 00) {
CO2ON();
red();
maxRGB();
maxWhite();
Blynk.virtualWrite(V13, "ON: 10");
rearLightOn();
}
if (hour() == 14 && minute() == 22 && second() == 00) {
CO2ON();
red();
maxRGB();
maxWhite();
Blynk.virtualWrite(V13, "ON: 10");
rearLightOn();
}
if (hour() == 15 && minute() == 00 && second() == 00) {
CO2ON();
red();
maxRGB();
downWhite(1);
Blynk.virtualWrite(V13, "ON: 8");
rearLightOn();
}
if (hour() == 16 && minute() == 00 && second() == 00) {
CO2ON();
red();
maxRGB();
downWhite(2);
Blynk.virtualWrite(V13, "ON: 5");
rearLightOn();
}
if (hour() == 17 && minute() == 00 && second() == 00) {
CO2OFF();
red1();
maxRGB();
downWhite(1);
Blynk.virtualWrite(V13, "ON: 3");
rearLightOn();
}
if (hour() == 18 && minute() == 00 && second() == 00) {
red1();
maxRGB();
minWhite();
Blynk.virtualWrite(V13, "ON: 1");
rearLightOn();
}
if (hour() == 19 && minute() == 00 && second() == 00) {
CO2OFF();
blue1();
maxRGB();
minWhite();
Blynk.virtualWrite(V13, "ON: 1");
rearLightOn();
}
if (hour() == 20 && minute() == 00 && second() == 00) {
CO2OFF();
blue1();
maxRGB();
powerWhite();
Blynk.virtualWrite(V13, "OFF");
rearLightOn();
}
if (hour() == 21 && minute() == 00 && second() == 00) {
CO2OFF();
blue();
maxRGB();
rearLightOn();
}
if (hour() == 22 && minute() == 00 && second() == 00) {
CO2OFF();
blue();
maxRGB();
downRGB(8);
rearLightOff();
}
if (hour() == 23 && minute() == 00 && second() == 00) {
CO2OFF();
blue();
downRGB(2);
rearLightOff();
}
}
void OTASetup() {
Serial.println("Booting");
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, pass);
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("Connection Failed! Rebooting...");
delay(5000);
ESP.restart();
}
ArduinoOTA.setHostname("15 Gallon Tank");
ArduinoOTA.onStart([]() {
Serial.println("Start");
});
ArduinoOTA.onEnd([]() {
Serial.println("\nEnd");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: % u % % \r", (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("Error[ % u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
else if (error == OTA_END_ERROR) Serial.println("End Failed");
});
ArduinoOTA.begin();
Serial.println("Ready");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void setup() {
Serial.begin(9600);
Blynk.config(auth, IPAddress(192, 168, 1, 70), 8080);
OTASetup();
blynkLCD.clear();
irsend.begin();
DS18B20.begin();
pinMode(lightPin, OUTPUT);
pinMode(motorPin, OUTPUT);
pinMode(CO2Pin, OUTPUT);
pinMode(heaterPin, OUTPUT);
EEPROM.begin(512);
getPumpData();// reads pump data from EEPROM and writes to variables
timeStatus(), setSyncInterval(10 * 60);// every
timer.setInterval(1000L, blinkactiveLED);// every 1 second
timer.setInterval(1000 * 60, checkTemperature); // every 1 minute
timer.setInterval(1000 * 60, LCDWriteCounts);// every 1 minute
timer.setInterval(10000 * 60, checkHeater);// every 10 minutes
}
void loop() {
ArduinoOTA.handle();
Blynk.run();
timer.run();
checkSchedules();
yield();
}