Hi I am trying to incorporate an LCD Widget with my project. It is an Automatic Water Change System. It draines the water into a bucket using a solenoid valve and another bucket filled with new water to replace the water that was removed. Anyway I tried adding messages to tell me what is happening when I start the water change process. Example when I the Aquarium was drained I would go in the Blynk app and see the Message on the lcd. Now my problem is that the Water Change is written in a loop. So now the Message is sent but it flickers because the message is sent over and over again. What can I do to prevent this from happening?
Start by showing us your script. Please format it properly…
Void Water is the loop I was referring to. This code also includes Temperature reading and Led control. Ignore Those.
#include <ArduinoOTA.h>
#define BLYNK_PRINT Serial // Comment this out to disable prints and save space
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <Wire.h>
#include "Adafruit_MCP23008.h"
#include <TimeLib.h>
#include <WidgetRTC.h>
WidgetTerminal terminal(V13);
#include <OneWire.h>
#include <DallasTemperature.h>
OneWire oneWire (14); //esp
DallasTemperature sensors(&oneWire);
WidgetLCD lcd(V13);
WidgetRTC rtc;
Adafruit_MCP23008 mcp;
#define white 12 //esp
#define blue 13 //esp
#define SUNRISE 9*60 + 0
#define DAWN 10*60 + 0
#define DUSK 16*60 + 0
#define SUNSET 17*60 + 0
#define drain_bucket_full 4 //mcp
#define fill_bucket_empty 6 //mcp
#define aquarium_empty 5 //mcp
#define aquarium_full 1 //mcp
#define Fill_Pump 2 //mcp
#define solenoid 0 //mcp
#define watersensor 3
int sensor = 0;
WidgetLED Pump(V2);
WidgetLED Solenoid_valve(V7);
WidgetLED Done(V8);
WidgetLED Auto(V9);
WidgetLED error(V10);
WidgetLED blueled(V12);
WidgetLED whiteled(V11);
BlynkTimer timer;
unsigned long previousMillis = 0;
boolean fill;
boolean drain;
boolean emergencystop = 0;
boolean automatic = 0;
boolean refilling = 0;
boolean draining = 0;
boolean filling = 0;
boolean start = 0;
boolean filled;
int state;
char auth[] = "501xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx071a2";
char ssid[] = "Clzxxxxxxxxxxxxxxxxxxxxxxxxxxxi";
char pass[] = "clxxxxxxxxxxxxxxxx3";
BLYNK_WRITE(V0) // At global scope (not inside of the function)
{
if ( param.asInt() == 1 )
{
fill = 1;
}
else
{
fill = 0;
filled = 0;
}
}
BLYNK_WRITE(V1) // At global scope (not inside of the function)
{
if ( param.asInt() == 1 )
{
drain = 1;
}
else
{
drain = 0;
}
}
BLYNK_WRITE(V5) // At global scope (not inside of the function)
{
if ( param.asInt() == 1 )
{
automatic = 1;
Auto.on();
state = 0;
}
else
{
automatic = 0;
Auto.off();
Done.off();
lcd.clear(); //Use it to clear the LCD Widget
}
}
BLYNK_WRITE(V6) // At global scope (not inside of the function)
{
if ( param.asInt() == 1 )
{
emergencystop = 1;
}
else
{
emergencystop = 0;
}
}
BLYNK_WRITE(V3) // At global scope (not inside of the function)
{
if ( param.asInt() == 1 )
{
int D7 = mcp.digitalRead(drain_bucket_full);
int D6 = mcp.digitalRead(aquarium_empty);
int D5 = mcp.digitalRead(fill_bucket_empty);
int D8 = mcp.digitalRead(aquarium_full);
sensor = mcp.digitalRead(watersensor);
BLYNK_LOG("");
BLYNK_LOG("drain bucket full (%d) = %d, aquarium_empty (%d) = %d, fill_bucket_empty (%d) = %d , aquarium_full (%d) = %d , watersensor = %d ", drain_bucket_full, D7, aquarium_empty, D6, fill_bucket_empty, D5, aquarium_full, D8, sensor);
BLYNK_LOG("fill = %d , drain = %d, emergency Stop = %d, Automatic = %d, Refilling = %d, Draning = %d, start = %d", fill, drain, emergencystop, automatic, refilling, draining, start);
BLYNK_LOG("");
/*terminal.flush();
terminal.println("drain bucket full () = " drain_bucket_full);
///terminal.println("fill = %d , drain = %d, emergency Stop = %d, Automatic = %d, Refilling = %d, Draning = %d, start = %d", fill, drain, emergencystop, automatic, refilling, draining, start);
*/
}
}
void water() {
if (mcp.digitalRead(watersensor) == 1) {
sensor = 0;
}
else
{
sensor = 1;
}
//Aquarium Filling
//---------------------------------------------------------------------------------------------------------------------
if (filled == 0 && sensor == 0 && automatic == 0 && fill == 1 && mcp.digitalRead(fill_bucket_empty) == HIGH && mcp.digitalRead(aquarium_full) == LOW)
{
mcp.digitalWrite(Fill_Pump, HIGH);
Pump.on();
//Done.off();
filling = 1;
}
else if (automatic == 0 && fill == 0 || mcp.digitalRead(fill_bucket_empty) == LOW || mcp.digitalRead(aquarium_full) == HIGH)
{
mcp.digitalWrite(Fill_Pump, LOW);
Pump.off();
filling = 0;
}
/*
if (fill == 1 && mcp.digitalRead(aquarium_full) == HIGH) {
filled = 1;
}*/
//---------------------------------------------------------------------------------------------------------------------
//Aquarium Draining
//--------------------------------------------------------------------------------------------------------------------
if (sensor == 0 && automatic == 0 && drain == 1 && mcp.digitalRead(drain_bucket_full) == LOW && mcp.digitalRead(aquarium_empty) == HIGH) {
mcp.digitalWrite(solenoid, HIGH);
Solenoid_valve.on();
//Done.off();
draining = 1;
}
else if (automatic == 0 && drain == 0 || mcp.digitalRead(drain_bucket_full) == HIGH || mcp.digitalRead(aquarium_empty) == LOW) {
mcp.digitalWrite(solenoid, LOW);
Solenoid_valve.off();
draining = 0;
}
//------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------AUTOMATIC------------------------------------------------------
if (state == 0 && fill == 0 && drain == 0 && automatic == 1 && sensor == 0) {
if (mcp.digitalRead(drain_bucket_full) == LOW && mcp.digitalRead(aquarium_empty) == HIGH) {
mcp.digitalWrite(solenoid, HIGH);
lcd.clear(); //Use it to clear the LCD Widget
lcd.print(0, 0, "Automatic Mode" ); // use: (position X: 0-15, position Y: 0-1, "Message you want to print")
lcd.print(0, 1, "Draining Water");
Solenoid_valve.on();
state = 1;
}
if (state == 1 && mcp.digitalRead(aquarium_empty) == LOW) {
lcd.clear(); //Use it to clear the LCD Widget
lcd.print(0, 0, "Water Drained" ); // use: (position X: 0-15, position Y: 0-1, "Message you want to print")
lcd.print(0, 1, "Proceeding to fill again");
state = 2;
}
if (state = 2 && mcp.digitalRead(fill_bucket_empty) == HIGH && mcp.digitalRead(aquarium_empty) == LOW && mcp.digitalRead(aquarium_full) == LOW)
{
lcd.clear(); //Use it to clear the LCD Widget
lcd.print(0, 0, "Filling with Water" ); // use: (position X: 0-15, position Y: 0-1, "Message you want to print")
mcp.digitalWrite(Fill_Pump, HIGH);
start = 1;
Pump.on();
if (state == 2 && mcp.digitalRead(aquarium_empty) == HIGH && mcp.digitalRead(aquarium_full) == HIGH) {
state = 3;
Done.on();
lcd.clear(); //Use it to clear the LCD Widget
lcd.print(0, 0, "WaterChangeDone"); // use: (position X: 0-15, position Y: 0-1, "Message you want to print")
}
}
}
if (state == 1 && mcp.digitalRead(drain_bucket_full) == HIGH || mcp.digitalRead(aquarium_empty) == LOW) {
mcp.digitalWrite(solenoid, LOW);
Solenoid_valve.off();
}
if (state == 1 && mcp.digitalRead(drain_bucket_full) == HIGH) {
lcd.clear(); //Use it to clear the LCD Widget
lcd.print(0, 0, "DraningBucketisFull"); // use: (position X: 0-15, position Y: 0-1, "Message you want to print")
//lcd.print(0, 1, "Waiting for the bucket to be empty");
}
if (state == 2 && (mcp.digitalRead(fill_bucket_empty) == LOW || mcp.digitalRead(aquarium_full) == HIGH))
{
mcp.digitalWrite(Fill_Pump, LOW);
Pump.off();
}
if (state == 2 && mcp.digitalRead(fill_bucket_empty) == LOW) {
lcd.clear(); //Use it to clear the LCD Widget
lcd.print(0, 0, "FillingBucketisEmpty"); // use: (position X: 0-15, position Y: 0-1, "Message you want to print")
//lcd.print(0, 1, "Waiting for the bucket to be ");
}
if (automatic == 0 && fill == 0 && drain == 0) {
mcp.digitalWrite(Fill_Pump, LOW);
Pump.off();
mcp.digitalWrite(solenoid, LOW);
Solenoid_valve.off();
}
/*
if (automatic == 1 && mcp.digitalRead(aquarium_full) == HIGH && mcp.digitalRead(solenoid) == LOW && mcp.digitalRead(Fill_Pump) == LOW )
{
Done.on();
}
else {
Done.off();
}
*/
//-----------------------------------------------------------------------------------------------------------------------------------------------
if (sensor == 1)
{
lcd.clear(); //Use it to clear the LCD Widget
lcd.print(0, 0, "Water was detected and process was Stopped"); // use: (position X: 0-15, position Y: 0-1, "Message you want to print")
error.on();
automatic = 0;
fill = 0;
drain = 0;
}
else
{
error.off();
}
if (emergencystop == 1)
{
automatic = 0;
fill = 0;
drain = 0;
Pump.off();
Solenoid_valve.off();
Auto.off();
Done.off();
}
}
void temp() {
sensors.requestTemperatures();
float currentTemp;
currentTemp = sensors.getTempCByIndex(0);
Blynk.virtualWrite(V4, currentTemp); // Virtual 0
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= 14400000 ) {
// save the last time you blinked the LED
previousMillis = currentMillis;
if (currentTemp > 30)
{
Blynk.notify("Temperature Exceeded 30°C");
}
else if (currentTemp < 26)
{
Blynk.notify("Temerature is Below 26°C");
}
}
}
void turn_on() {
int value = 0;
int msm = hour() * 60 + minute(); //minutes since midnight
if ( msm < SUNRISE ) {
value = 0;
} else if (msm < DAWN) {
value = map(msm, SUNRISE, DAWN, 0, 1024);
} else if (msm < DUSK ) {
value = 1024;
} else if (msm < SUNSET ) {
value = map(msm, DUSK, SUNSET, 1024, 0);
} else {
value = 0;
}
int brightness = map(value, 0, 1024, 0, 255);
whiteled.setValue(brightness);
blueled.setValue(brightness);
BLYNK_LOG("Time: %d %d - setting lights to %d", hour(), minute(), value);
analogWrite(blue, value);
analogWrite(white, value);
}
void setup() {
WiFi.mode(WIFI_STA);
Serial.begin(9600);
mcp.begin(); // use default address 0
Blynk.begin(auth, ssid, pass);
while (Blynk.connect() == false) {}
ArduinoOTA.setHostname("Aquarium"); // OPTIONAL
ArduinoOTA.begin();
pinMode(white, OUTPUT);
pinMode(blue, OUTPUT);
mcp.pinMode(drain_bucket_full, INPUT);
mcp.pinMode(fill_bucket_empty, INPUT);
mcp.pinMode(aquarium_empty, INPUT);
mcp.pinMode(watersensor, INPUT);
mcp.pinMode(aquarium_full, INPUT);
mcp.pullUp(drain_bucket_full, HIGH); // turn on a 100K pullup internally
mcp.pullUp(fill_bucket_empty, HIGH);
mcp.pullUp(aquarium_empty, HIGH);
mcp.pullUp(aquarium_full, HIGH);
mcp.pinMode(Fill_Pump, OUTPUT);
mcp.pinMode(solenoid, OUTPUT);
mcp.digitalWrite(Fill_Pump, LOW);
mcp.digitalWrite(solenoid, LOW);
// Begin synchronizing time
rtc.begin();
fill = 0;
drain = 0;
timer.setInterval(10000L, turn_on);
// timer.setInterval(1000L, clockDisplay);
timer.setInterval(10000L, temp);
timer.setInterval(1000L, water);
}
void loop() {
Blynk.run();
ArduinoOTA.handle();
timer.run();
}
Hmm, a bit bigger script than I anticipated… lots of logic to go through, but I think I see a “flicker free” solution:
Limit your lcd.clear();
commands only to places where you actually need a clear screen. Then, when overwriting a longer message with a shorter one, just add spaces to overwrite past characters.
This will not limit the amount of lcd writes (that would probably require more counters, flags and if-then logic), but it will prevent the flicker.
PS, I still had to edit your post to add in the required backticks for proper code viewing. Now I am done for the night