That did the trick. The W5100 didn’t hold things up this time. I tested twice to make sure I was fully awake. I disconnect everything, reinstate power only and within about 5 seconds it gets right out into the loop of timered functions as my relays illuminated their onboard LEDs in accordance with my schedule.
#include <SPI.h> // Used by Blynk
#include <Ethernet.h> // Used by Blynk
#include <BlynkSimpleEthernet.h> // Used by Blynk
//#include <UIPEthernet.h>
//#include <BlynkSimpleUIPEthernet.h>
#include <Wire.h> // I2c
#include <WidgetRTC.h>
#include <DHT.h> // DHT data wire connected to I/O pin with a 10k pullup resistor to 5V
#include <RTClib.h> // RealTimeClock Library for DS1307 and DS3231
#define BLYNK_PRINT Serial
char auth[] = "AUTH";
unsigned int port = 8442;
byte arduino_mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; //DE:ED:BA:FE:FE:ED
char server[] = "blynk-cloud.com"; // can use "blynk-cloud.com" or an IP address
IPAddress arduino_ip ( 10, 0, 0, 120);
IPAddress dns_ip ( 10, 0, 0, 1);
IPAddress gateway_ip ( 10, 0, 0, 1);
IPAddress subnet_mask(255, 255, 255, 0);
unsigned int myEthernetTimeout = 20000; // 5.0s Ethernet Connection Timeout (ECT)
unsigned int blynkInterval = 30000; // 25.0s Check Server Frequency (CSF)
unsigned long startConnecting = millis();
// DHT Reference Values - CHANGE THESE TO MANAGE YOUR ROOM'S CLIMATE - //
byte hiMaxTemp = 80; // temp that triggers heat removal device(s) on
byte lowMaxTemp = 70; // temp that triggers heat removal device(s) off
byte hiMinTemp = 55; // temp that triggers heater on
byte lowMinTemp = 65; // temp that triggers heater off
byte hiHum = 58; // High humidity value that triggers dehumidifier on
byte lowHum = 40; // Low humidity value that triggers dehumidifier off
//-Digital Pins - Peristaltic Pump Variables - 00 Series Pins
const int pumpPin[8] = { 2, 3, 4, 5, 6, 7, 8, 9 };
int dosingLEDs[8] = { V14, V15, V16, V17, V18, V19, V20, V21 };
uint32_t multiplier[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; //ms per ml
uint32_t startPump = 0;
uint32_t runCount;
bool pumpRunning;
const char *nuteType[8] = { "GH Armor Si", "GH Flora Blend", "GH CALiMAGic", "GH Kool Bloom",
"GH Flora Gro", "GH Flora Micro", "GH Flora Bloom", "GH pH Down"
}; //Text Printed to Terminal Widget^^
float DOSEml; //Step Widget (0.25 per step, send step/NO, loop values ON)
int button = 0; //Button Widget set to Switch
int x; //Correlates Array Positions with Pump Motor Pins
int calibration;
BLYNK_WRITE(V4) {
x = param.asInt() - 1;
}
BLYNK_WRITE(V5) {
DOSEml = param.asFloat();
}
BLYNK_WRITE(V6) {
button = param.asInt();
}
BLYNK_WRITE(V13) {
calibration = param.asInt();
}
//
uint32_t msPerGallon = 33000; //ms per gallon
uint32_t ROstart = 0;
uint32_t countGallons;
boolean runningRO = false;
int pumpAon; //Blynk Override to turn pumpA back on
int pumpBon; //Blynk Override to turn pumpB back on
int ROpumpOn = 0; //Blynk Triggered RO Pump
float totalGallons; //Number of RO Gallons Selected in Widget
BLYNK_WRITE(V9) {
pumpAon = param.asInt(); // pumpA remote
}
BLYNK_WRITE(V10) {
pumpBon = param.asInt(); // pumpB remote
}
BLYNK_WRITE(V11) {
ROpumpOn = param.asInt(); // ROpump remote
}
BLYNK_WRITE(V12) {
totalGallons = param.asFloat(); // ROpump remote
}
// Digital Pin 10 is <RESERVED> for W5100 Wiznet chip
// Digital Pins - 8 Channel Relay Assignments - 20 Series Pins - 120VAC~ switching
#define lightA 22 //Relay 1/a
#define lightB 23 //Relay 2/b
#define pumpA 24 //Relay 3/c
#define pumpB 25 //Relay 4/d
#define ROpump 26 //Relay 5/e
#define scrubberFan 27 //Relay 6/f
#define VentA 28 //Relay 7/g
#define VentB 29 //Relay 8/h
//-Digital Pins - 8 Channel Relay Assignments - 30 Series Pins - 120VAC~ switching
// -Dpins 30-37 are reserved for another bank of Relays.
//Digital Pin Valves Assignments - 40 Series Pins - Hi/Lo Solenoid Valves
//const byte valve[13] = { 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52 };
#define TURN_ON LOW // TURN_ON and TURN_OFF are defined to account for Active LOW relays
#define TURN_OFF HIGH // Used to switch relay states for on/off of 120VAC~ devices
RTC_DS1307 RTC;
float UTCOffset = -5.0; // Your timezone relative to UTC (http://en.wikipedia.org/wiki/UTC_offset)
WidgetLCD lcdA(V7); //Set LCD widget to Advanced Mode - Widget to display project clock
WidgetTerminal terminal(V8);
DHT dhtA(A0, DHT22); // DHT instance named dhtA, (I/O pin, sensor type)
DHT dhtB(A2, DHT22); // DHT instance named dhtB, (I/O pin, sensor type)
BlynkTimer timer; // SimpleTimer instance named timer
WidgetRTC rtcWidget; // requires RTC widget in app
#define W5100_CS 10
#define SDCARD_CS 4
//**********************Functions***************************//
//**********************************************************//
// This is called for all virtual pins that do not have BLYNK_WRITE handler
BLYNK_WRITE_DEFAULT()
{
Serial.println("BLYNK_WRITE_DEFAULT()");
terminal.print("BLYNK_WRITE for pin ");
terminal.print(request.pin);
terminal.println(" not defined.");
terminal.println("Values: ");
for (auto i = param.begin(); i < param.end(); ++i) {
terminal.print("* ");
terminal.println(i.asString());
}
terminal.flush();
}
// This is called for all virtual pins that do not have BLYNK_READ handler
BLYNK_READ_DEFAULT()
{
Serial.println("BLYNK_READ_DEFAULT");
terminal.print("BLYNK_READ for pin ");
terminal.print(request.pin);
terminal.println(" not defined.");
terminal.flush();
}
// This is called when Blynk has successfully connected
BLYNK_CONNECTED()
{
Serial.println("BLYNK_CONNECTED");
rtcWidget.begin(); // Synchronize with widget (server) time on connection
setSyncInterval(5 * 60); // subsequent time sync interval in seconds (5 minutes)
for (int i = V4; i <= V6; i++)
for (int j = V9; j <= V21; j++)
{
Blynk.virtualWrite(i, j, 0);
}
}
void myfunction() {
Serial.println("\tLook, no Blynk block.");
if (Blynk.connected()) {
Serial.println("\tEthernet still connected.");
Blynk.virtualWrite(V22, millis() / 1000);
}
}
void checkBlynk() {
while (!Blynk.connected()) {
Blynk.connect();
if (millis() > startConnecting + myEthernetTimeout) {
Serial.print("\tUnable to connect to server. ");
break;
}
}
Serial.println("Checking again in 30s.");
}
void displayDateTime()
{
Serial.println("displayDateTime");
DateTime now = RTC.now(); // reads time at beginning of loop
byte HOUR = now.hour();
byte twelveHour = now.hour() - 12; // Variable used to display 13+ hours in 12 hour format
byte zeroHour = 12; // Variable use to convert "0" zero hour to display it as 12:00+
byte displayHour;
byte MIN = now.minute();
byte SEC = now.second();
char* meridian;
if (now.hour() == 0) // First we test if the hour reads "0"
{
displayHour = zeroHour;
meridian = "AM";
}
else if (now.hour() >= 13) // if no, Second we test if the hour reads "13 or more"
{
displayHour = twelveHour;
meridian = "PM";
}
else
{
displayHour = now.hour();
meridian = "AM";
}
if (Blynk.connected())
{
char stamp[16];
lcdA.clear();
sprintf(stamp, "%02d:%02d:%02d-%02s", displayHour, MIN, SEC, meridian);
lcdA.print(3, 0, stamp);
sprintf(stamp, "%02d/%02d/%04d", now.month(), now.day(), now.year());
lcdA.print(3, 1, stamp);
}
}
// synchronize the RTC hardware device with our server provided date/time values
void syncRTCHardware()
{
if (!Blynk.connected())
{
Serial.println("Blynk not connected. Exiting syncRTCHardware.");
return;
}
Serial.println("syncRTCHardware");
DateTime now = RTC.now(); // reads time at beginning of loop
char currentTime[16];
char currentDate[16];
sprintf(currentDate, "%02d/%02d/%04d", month(), day(), year());
sprintf(currentTime, "%02d:%02d:%02d", hour(), minute(), second());
Serial.print("Server Time: ");
Serial.print(currentDate);
Serial.print (" ");
Serial.println(currentTime);
// time library is synchronized by the Blynk WidgetRTC
if (Blynk.connected())
{
bool syncClocks;
if (now.hour() != hour() && now.minute() != minute()) syncClocks = true;
if (syncClocks == true)
{
syncClocks = false;
Serial.println("Resynching RTC Time...");
terminal.println("Resynching RTC Time...");
RTC.adjust(DateTime(year(), month(), day(), hour(), minute(), second()));
terminal.flush();
}
}
}
// checks connection to Blynk server and attempts reconnect if disconnectedd checkBlynkConnection()
void checkBlynkConnection()
{
Serial.println("Attempting to Connect");
if (!Blynk.connected())
{
Serial.println("checkBlynkConnection");
Blynk.connect(); // try to connect to server with default timeout
}
}
void climateRoutine()
{
byte h1 = dhtA.readHumidity(); // f1 and h1 are fahrenheit and humidity readings
byte f1 = dhtA.readTemperature(true); // from DHT/A
byte h2 = dhtB.readHumidity(); // f2 and h2 are fahrenheit and humidity readings
byte f2 = dhtB.readTemperature(true); // from DHT/B
if (isnan(f1) || isnan(f2) || isnan(h1) || isnan(h2)) {
terminal.println("Failed to read from a DHT sensor");
terminal.flush();
return;
}
Blynk.virtualWrite(V0, f1); // Set Virtual Pin 0 frequency to PUSH in Blynk app
Blynk.virtualWrite(V1, h1); // Set Virtual Pin 1 frequency to PUSH in Blynk app
Blynk.virtualWrite(V2, f2); // Set Virtual Pin 2 frequency to PUSH in Blynk app
Blynk.virtualWrite(V3, h2); // Set Virtual Pin 3 frequency to PUSH in Blynk app
//-------------------Bloom A Temp Test---------------------------------------//
if (f1 >= hiMaxTemp) //if "f1" is greater than or equal to hiMaxTemp,
{
digitalWrite(VentA, TURN_ON); // TURN_ON heatVentA (fan).
terminal.println("Exhausting the heat from Bloom A"); // Text printed to terminal monitor
}
else if (f1 <= lowMaxTemp) // or else if "f1" is less than or equal to lowMaxTemp
{
digitalWrite(VentA, TURN_OFF); // TURN_OFF relay E.
}
//-----------------------Bloom A Humidity Test-------------------------//
if (h1 >= hiHum) //if "h2" is greater than or equal to hiHum,
{
digitalWrite(VentA, TURN_ON); // TURN_ON heatVentA (fan).
terminal.println("Exhausting the RH from Bloom A"); // Text printed to terminal monitor
}
else if (h1 <= lowHum) // or else if "h1" is less than or equal to lowHum
{
digitalWrite(VentA, TURN_OFF);
}
//-----------------------Bloom B Temp Test-----------------------------//
if (f2 >= hiMaxTemp) //if "f2" is greater than or equal to hiMaxTemp,
{
digitalWrite(VentB, TURN_ON); // TURN_ON heatVentA (fan).
terminal.println("Exhausting the heat from Bloom B"); // Text printed to terminal monitor
}
else if (f2 <= lowMaxTemp) // or else if "f2" is less than or equal to lowMaxTemp
{
digitalWrite(VentB, TURN_OFF);
}
//-----------------------Bloom B Humidity Test-------------------------//
if (h2 >= hiHum) //if "h2" is greater than or equal to hiHum,
{
digitalWrite(scrubberFan, TURN_ON); // TURN_ON heatVentA (fan).
terminal.println("Exhausting the RH from Bloom B"); // Text printed to terminal monitor
}
else if (h2 <= lowHum) // or else if "h2" is less than or equal to lowHum
{
digitalWrite(scrubberFan, TURN_OFF);
}
terminal.flush();
}
void timeRoutine()
{
DateTime now = RTC.now(); // reads time at beginning of loop
//------------------12/12 BloomA Light - 5AM-5PM
//Adjust hours and minutes in accordance with 24 hour time format.
//Create tests where true is ON time and false is OFF time.
boolean lightAstate = false;
if (now.hour() >= 5 && now.hour() <= 16) lightAstate = true;
if (lightAstate == true)
{
digitalWrite(lightA, TURN_ON);
terminal.println("Lights On In Bloom A"); // Text printed to terminal monitor
}
else
{
digitalWrite(lightA, TURN_OFF);
}
//--------------------12/12 Bloom B Light - 5PM-5AM
//lightB is lit during the opposing 12 hours to lightA to conserve current draw from HID ballasts.
boolean lightBstate = false;
if (lightAstate == false) lightBstate = true;
if (lightBstate == true)
{
digitalWrite(lightB, TURN_ON);
terminal.println("Lights On In Bloom B"); // Text printed to terminal monitor
}
else
{
digitalWrite(lightB, TURN_OFF);
}
//---------------Bloom A Feed Times------------------------
boolean pumpAstate = false;
if (pumpAon == 1) pumpAstate = true;
if (now.hour() == 6 && now.minute() >= 0 && now.minute() < 10) pumpAstate = true; //6:00 am - 10 mins
if (now.hour() == 8 && now.minute() >= 30 && now.minute() < 40) pumpAstate = true; //8:30 am - 10 mins
if (now.hour() == 11 && now.minute() >= 00 && now.minute() < 10) pumpAstate = true; //11:00 am - 10 mins
if (now.hour() == 13 && now.minute() >= 30 && now.minute() < 40) pumpAstate = true; //1:30 pm - 10 mins
if (now.hour() == 16 && now.minute() >= 0 && now.minute() < 10) pumpAstate = true; //4:00 pm - 10 mins
if (pumpAstate == true)
{
Blynk.virtualWrite(V9, 1);
digitalWrite(pumpA, TURN_ON);
terminal.println("Pump A Is On"); // Text printed to terminal monitor
}
else
{
pumpAon = 0;
Blynk.virtualWrite(V9, 0);
digitalWrite(pumpA, TURN_OFF);
}
//---------------------------Bloom B Feed Times-------------------------------------
boolean pumpBstate = false;
if (pumpBon == 1) pumpBstate = true;
if (now.hour() == 18 && now.minute() >= 0 && now.minute() < 10) pumpBstate = true; //6:00 pm - 10 mins -//- 1 hour after light on
if (now.hour() == 20 && now.minute() >= 30 && now.minute() < 40) pumpBstate = true; //8:30 pm - 10 mins
if (now.hour() == 23 && now.minute() >= 0 && now.minute() < 10) pumpBstate = true; //11:00 pm - 10 mins
if (now.hour() == 1 && now.minute() >= 30 && now.minute() < 40) pumpBstate = true; //1:30 am - 10 mins
if (now.hour() == 4 && now.minute() >= 0 && now.minute() < 10) pumpBstate = true; //4:00 am - 10 mins
if (pumpBstate == true)
{
Blynk.virtualWrite(V10, 1);
digitalWrite(pumpB, TURN_ON);
terminal.println("Pump B Is On"); // Text printed to terminal monitor
}
else
{
pumpBon = 0;
Blynk.virtualWrite(V10, 0);
digitalWrite(pumpB, TURN_OFF);
}
terminal.flush();
}
void ROcheck() //RO Pump = 34 seconds on time per gallon
{
if (ROpumpOn == 1 && runningRO == false) // Activates when Blynk button is toggled
{
digitalWrite(ROpump, TURN_ON);
Blynk.virtualWrite(V11, 255); // Illuminates Blynk button widget
runningRO = true;
ROstart = millis();
countGallons = msPerGallon * totalGallons; // Calculates length of runtime for pump
Blynk.virtualWrite(V12, 0);
terminal.print("Pumping:");
terminal.print(totalGallons);
terminal.println(" Gallons of RO");
}
if (millis() - ROstart > countGallons) // Determines when runtime ends
{
ROpumpOn = 0;
runningRO = false;
digitalWrite(ROpump, TURN_OFF);
Blynk.virtualWrite(V11, 0);
//Blynk.virtualWrite(V22, 0);
}
terminal.flush();
}
void dosingPumps()
{
if (button == 1 && pumpRunning == false)
{
multiplier[x] = calibration; // Gets the value in [x] position from Blynk
Blynk.virtualWrite(V4, 0);
Blynk.virtualWrite(V5, 0);
Blynk.virtualWrite(V6, 0); // Keeps button ON until fully executed
pumpRunning = true;
digitalWrite(pumpPin[x], HIGH);
Blynk.virtualWrite(dosingLEDs[x], 255); // [x] position Blynk indicator LED
startPump = millis();
runCount = DOSEml * multiplier[x];
terminal.print("Dosing in: ");
terminal.print(DOSEml);
terminal.print(" milliliters of ");
terminal.println(nuteType[x]);
}
if (millis() - startPump > runCount)
{
digitalWrite(pumpPin[x], LOW);
Blynk.virtualWrite(dosingLEDs[x], 0);
pumpRunning = false;
button = 0;
}
terminal.flush();
}
void setup()
{
Serial.begin(9600);
Serial.println("setup start...");
Serial.println("dhtA.begin()...");
dhtA.begin();
Serial.println("dhtB.begin()...");
dhtB.begin();
Serial.println("setting DHT's...");
pinMode(A0, INPUT_PULLUP); // DHT22 use internal 20k pullup resistors
pinMode(A2, INPUT_PULLUP);
Serial.println("Wire.begin()...");
Wire.begin();
Serial.println("RTC.begin()...");
RTC.begin();
Serial.println("turning relays off...");
for (int allRelays = lightA; allRelays <= VentB; allRelays++)
{
pinMode(allRelays, OUTPUT);
digitalWrite(allRelays, TURN_OFF);
}
Serial.println("setting pump pinMode's...");
for (int p = 0; p <= 7; p++)
{
pinMode(pumpPin[p], OUTPUT);
}
pinMode(SDCARD_CS, OUTPUT);
digitalWrite(SDCARD_CS, HIGH); // Deselect the SD card
Serial.println("setting timers...");
timer.setInterval(2000L, timeRoutine); // 2 second intervals between timed routiness
timer.setInterval(5001L, climateRoutine); // 5 second intervals between climate routines
timer.setInterval(15000L, syncRTCHardware); // synchronize the RTC device with the server time every 15 seconds
timer.setInterval(5000L, displayDateTime); // update the LCD Widget every 5 seconds
timer.setInterval(15000L, checkBlynkConnection); // check Blynk connection every 15 seconds
timer.setInterval(207L, dosingPumps); // 0.2 second interval to maintain accuracy (+/- .25)
timer.setInterval(1003L, ROcheck); // 1 second interval between RO pump routines
timer.setInterval(myEthernetTimeout, myfunction);
timer.setInterval(blynkInterval, checkBlynk); // check connection to server per blynkInterval
Serial.println("beginning Blynk...");
// Blynk stuff after timers
//Blynk.config(auth, server, port);
//Blynk.begin(auth, server, port);
//while (Blynk.connect() == false) {}
Ethernet.begin(arduino_mac, arduino_ip, dns_ip, gateway_ip, subnet_mask );
Blynk.config(auth, server); // this is OK
Blynk.connect(); // this is OK
//Blynk.disconnect(); // skip connecting to the Blynk server until checkBlynkConnection timer fires
Serial.println("setup complete.");
}
void loop()
{
// only attempt Blynk-related functions when connected to Blynk
if (Blynk.connected())
{
Blynk.run();
}
timer.run();
}