Code Wizards:
I am hoping to extend a long working project to control 12 relays using a scheduler and Blynk. I’m sure my coding is primitive, however working well with original 4 relay controller mostly from Hagary et.al.
Hardware is:
LOLIN D1 Mini Pro
LOLIN OLED Shield 64 X 48 (plugs directly to Lolin D1)
Adafruit_MCP23017 port extender using I2C on Lolin D1 SCL/SDA (1,2)
Power from proto board supply 3.3VDC-700 ma
Albeit, there a probably several bugs remaining in the “time, day, schedule routines”, I can’t seem to get past an exception causing MCU resets about every 10 seconds,
From Exception Decoder:
**Exception 0: Illegal instruction** PC: 0x4000e25d EXCVADDR: 0x00000000 *Decoding stack results* 0x402042cd: **BlynkTimer::run()** at C:\Users\xxxxxxxx\Documents\Arduino\libraries\blynk-library-master\src\utility\**BlynkTimer.cpp** line **60** 0x40203ff0: **setup()** at C:\Users\lawalter\Documents\Arduino\libraries\Adafruit_GFX_Library/**Adafruit_GFX.h** line **141** 0x40203c4f: **loop()** at C:\Users\lawalter\Documents\Arduino\sketch_jun15a/**sketch_jun15a.ino** line **551** 0x4020865c: **loop_wrapper()** at C:\Users\xxxxxxxx\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.0\cores\esp8266\**core_esp8266_main.cpp** line **201**
From hardware behavior it seems the OLED display never has time to get booted/reset, and a blinky red LED on MCU. From Serial monitor I observe the resets at time-stamp of very close to 10 seconds.
After 10’s of hours of searching, testing, focused small changes, this reset behavior and exceptions remain identical, and I am lost in what is probably something simple.
The crude code compiles well and occupies; “…Sketch uses 308977 bytes (29%) of program storage space. Maximum is 1044464 bytes…”
Code follows:
/* MODIFIED C:\Users\xxxxxxx\Documents\Arduino\libraries\Blynk\src WidgetTimeInput.h
replace “-1” of the code “mWeekdays = -1;” by “0”. You can find the code in line “33” of file “WidgetTimeInput.h” (Version: Aug 2016, respectively 14 Sep 2016).*/
#define BLYNK_PRINT Serial
#define WIFI_LED 10
// define configuration (number of switches and number of timers)
#define SWITCH_CNT 12
#define TIME_CNT 4
//#include <ESP8266_Lib.h>
#include <BlynkSimpleEsp8266.h>
#include <TimeLib.h>
#include <WidgetRTC.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#include <Adafruit_MCP23017.h>
Adafruit_MCP23017 mcp;
byte mcp_pin_PA0=0;
byte mcp_pin_PA1=1;
byte mcp_pin_PA2=2;
byte mcp_pin_PA3=3;
byte mcp_pin_PA4=4;
byte mcp_pin_PA5=5;
byte mcp_pin_PA6=6;
byte mcp_pin_PA7=7;
byte mcp_pin_PB0=8;
byte mcp_pin_PB1=9;
byte mcp_pin_PB2=10;
byte mcp_pin_PB3=11;
byte mcp_pin_PB4=12;
byte mcp_pin_PB5=13;
byte mcp_pin_PB6=14;
byte mcp_pin_PB7=15;
//char auth[] = "hX7p4aL29tlmIrxpFPQxN8i8uriF9rWj"; //LOLIN D1 Mini
char auth[] = "aGx-6GnTSyissGnwCZJGWHQsa_JujVaJ"; //LOLIN D1 Mini
char ssid[] = "2WIRE505_AP";
char pass[] = "1248345632";
#define SCREEN_WIDTH 64 // OLED display width, in pixels
#define SCREEN_HEIGHT 48 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET 0 // Default OLED Shield
Adafruit_SSD1306 display(OLED_RESET);
byte switch_pins[] = {mcp_pin_PA0 , mcp_pin_PA1, mcp_pin_PA2 , mcp_pin_PA3 ,mcp_pin_PA4 , mcp_pin_PA5, mcp_pin_PA6 , mcp_pin_PA7 , mcp_pin_PB0 , mcp_pin_PB1, mcp_pin_PB2 , mcp_pin_PB3 }; // number of MCP23017 "gpio" to be used as switch/relay control
bool switch_default[] = {HIGH, HIGH, HIGH, HIGH ,HIGH, HIGH, HIGH, HIGH , HIGH, HIGH, HIGH, HIGH}; // switches that use reverse polarity should be set to HIGH here
////////////////////////////////////////////////////////////////////////////////////////
// This code can control up to 12 switches //
// For each switch up to 1 schedule start and end times can be configured - (V0..V11) //
// A default duration can be defined per switch - (V12..V23)//
// If an end time is not defined at the app the default duration is used //
// default duration is also used when manually activating the switch - (V36..V47)//
// for each switch when start time is reached the switch turns on for the duration //
// //
// maximum duration is used for safety (to limit activation time) - (V24..V35)//
////////////////////////////////////////////////////////////////////////////////////////
int start_time_sec[SWITCH_CNT][TIME_CNT]; // array of 4 start times (in seconds) for 12 switches [switch number][schedual timer number]
bool start_valid[SWITCH_CNT][TIME_CNT]; // is the start time valid ?
bool weekdays[SWITCH_CNT][TIME_CNT][8]; // array of 8 days (day 0 not used) for each schedual time
int active_duration[SWITCH_CNT][TIME_CNT + 1]; // duration per switch per time(in sec)
bool end_valid[SWITCH_CNT][TIME_CNT]; // is the end time valid ?
int max_duration[SWITCH_CNT]; // max duration per switch
int auto_off = 1; // 1 is auto or on
char zone ; // HOPEFUL GLOBAL VARIABLE TO DISPLAY ON OLED, I ATTEMPT TO CHANGE VALUE AND ASSIGN TO "ZONE" IN THE "handle switch state" loop
// when activating a switch a timer is set for the configured duration
// when the duration ends the switch is turned off by the timer
// the id of the timer is saved using end_timer_id
// if switch is manually turned off the end_timer_id is used to stop the timer.
// end_timer_id is initialized to 32 (per entry) at the setup section
int end_timer_id[SWITCH_CNT];
// timer object declaration
BlynkTimer timer;
// this code use Real Time Clock widget in the blynk app to keep the clock updated from net
WidgetRTC rtc;
BLYNK_CONNECTED() {
// Synchronize time on connection
rtc.begin();
Blynk.syncAll();
}
WidgetLED led1(V55);
bool ledStatus = auto_off;
// V55 LED Widget is ON or OFF
void LedWidget()
{ ledStatus = auto_off;
if (ledStatus) {
led1.on();
} else {
led1.off();
}
}
//////////////////////////////////////////////////////////
// get schedual parameters from App //
//////////////////////////////////////////////////////////
void set_time(BlynkParam param, byte switch_no, byte time_no) {
TimeInputParam t(param);
// Process start time
if (t.hasStartTime())
{
Serial.println(String("Start: ") +
t.getStartHour() + ":" +
t.getStartMinute() + ":" +
t.getStartSecond());
Serial.println(String("Start in sec: ") + param[0].asLong() + String(" for switch") + switch_no + String(" time_no: ") + time_no);
start_time_sec[switch_no][time_no] = param[0].asLong();
start_valid[switch_no][time_no] = true;
}
else
{
// Do nothing
Serial.println(String("No Start Time Given for switch: ") + switch_no + String(" time_no: ") + time_no);
start_valid[switch_no][time_no] = false;
}
//////////////////////////////////////////////////////////////////////////////
// check if end time is received convert and save it as day time in seconds //
//////////////////////////////////////////////////////////////////////////////
if (t.hasStopTime())
{
Serial.println(String("Stop: ") +
t.getStopHour() + ":" +
t.getStopMinute() + ":" +
t.getStopSecond());
Serial.println(String("Stop in sec: ") + param[1].asLong() + String(" for switch") + switch_no + String(" time_no: ") + time_no);
active_duration[switch_no][time_no] = (param[1].asLong() - start_time_sec[switch_no][time_no]);
// if end time is smaller than start time this means end time is at next day
if (active_duration[switch_no][time_no] < 0) active_duration[switch_no][time_no] = 86400 + active_duration[switch_no][time_no];
Serial.println(String("Stop duration: ") + active_duration[switch_no][time_no]);
end_valid[switch_no][time_no] = true;
}
else // if end time is not defined //
{
// Do nothing
Serial.println(String("No Stop Time Given for switch: ") + switch_no + String(" time_no: ") + time_no);
end_valid[switch_no][time_no] = false;
}
// Process weekdays (1. Mon, 2. Tue, 3. Wed, ...)
for (int i = 1; i <= 7; i++) {
if (t.isWeekdaySelected(i)) {
Serial.println(String("Day ") + i + " is selected");
weekdays[switch_no][time_no][i] = true;
}
else {
weekdays[switch_no][time_no][i] = false;
}
}
Serial.println();
}
//this reads status of on/off mode and displays on screen
BLYNK_WRITE(V50) {
int Vpin50 = param.asInt();
auto_off = Vpin50;
}
// V0..V3 for switch 0, V4..V7 for switch 1 ...
BLYNK_WRITE(V0) { set_time(param, 0, mcp_pin_PA0); }
BLYNK_WRITE(V1) { set_time(param, 1, mcp_pin_PA1); }
BLYNK_WRITE(V2) { set_time(param, 2, mcp_pin_PA2); }
BLYNK_WRITE(V3) { set_time(param, 3, mcp_pin_PA3); }
BLYNK_WRITE(V4) { set_time(param, 4, mcp_pin_PA4); }
BLYNK_WRITE(V5) { set_time(param, 5, mcp_pin_PA5); }
BLYNK_WRITE(V6) { set_time(param, 6, mcp_pin_PA6); }
BLYNK_WRITE(V7) { set_time(param, 7, mcp_pin_PA7); }
BLYNK_WRITE(V8) { set_time(param, 8, mcp_pin_PB0); }
BLYNK_WRITE(V9) { set_time(param, 9, mcp_pin_PB1); }
BLYNK_WRITE(V10) { set_time(param, 10, mcp_pin_PB2); }
BLYNK_WRITE(V11) { set_time(param, 11, mcp_pin_PB3); }
// use a slider to define default activation duration (slider count in minute)
BLYNK_WRITE(V12) { active_duration[mcp_pin_PA0][TIME_CNT] = param.asInt() * 60; }
BLYNK_WRITE(V13) { active_duration[mcp_pin_PA1][TIME_CNT] = param.asInt() * 60; }
BLYNK_WRITE(V14) { active_duration[mcp_pin_PA2][TIME_CNT] = param.asInt() * 60; }
BLYNK_WRITE(V15) { active_duration[mcp_pin_PA3][TIME_CNT] = param.asInt() * 60; }
BLYNK_WRITE(V16) { active_duration[mcp_pin_PA4][TIME_CNT] = param.asInt() * 60; }
BLYNK_WRITE(V17) { active_duration[mcp_pin_PA5][TIME_CNT] = param.asInt() * 60; }
BLYNK_WRITE(V18) { active_duration[mcp_pin_PA6][TIME_CNT] = param.asInt() * 60; }
BLYNK_WRITE(V19) { active_duration[mcp_pin_PA7][TIME_CNT] = param.asInt() * 60; }
BLYNK_WRITE(V20) { active_duration[mcp_pin_PB0][TIME_CNT] = param.asInt() * 60; }
BLYNK_WRITE(V21) { active_duration[mcp_pin_PB1][TIME_CNT] = param.asInt() * 60; }
BLYNK_WRITE(V22) { active_duration[mcp_pin_PB2][TIME_CNT] = param.asInt() * 60; }
BLYNK_WRITE(V23) { active_duration[mcp_pin_PB3][TIME_CNT] = param.asInt() * 60; }
// use a slider to define default max duration (slider count in minute) ***HARD CODE THIS*** NL
BLYNK_WRITE(V24) { max_duration[mcp_pin_PA0] = param.asInt() * 60; }
BLYNK_WRITE(V25) { max_duration[mcp_pin_PA1] = param.asInt() * 60; }
BLYNK_WRITE(V26) { max_duration[mcp_pin_PA2] = param.asInt() * 60; }
BLYNK_WRITE(V27) { max_duration[mcp_pin_PA3] = param.asInt() * 60; }
BLYNK_WRITE(V28) { max_duration[mcp_pin_PA4] = param.asInt() * 60; }
BLYNK_WRITE(V29) { max_duration[mcp_pin_PA5] = param.asInt() * 60; }
BLYNK_WRITE(V30) { max_duration[mcp_pin_PA6] = param.asInt() * 60; }
BLYNK_WRITE(V31) { max_duration[mcp_pin_PA7] = param.asInt() * 60; }
BLYNK_WRITE(V32) { max_duration[mcp_pin_PB0] = param.asInt() * 60; }
BLYNK_WRITE(V33) { max_duration[mcp_pin_PB1] = param.asInt() * 60; }
BLYNK_WRITE(V34) { max_duration[mcp_pin_PB2] = param.asInt() * 60; }
BLYNK_WRITE(V35) { max_duration[mcp_pin_PB3] = param.asInt() * 60; }
/////////////////////////////////////////////////////////////////
// Handle switch events (from app or from scheduler ) //
/////////////////////////////////////////////////////////////////
// turn off switch after active duration ends
// duration number is not important here
void turn_off_switch_no_0() { turn_on_off(0, mcp_pin_PA0, 0); Blynk.virtualWrite(V36, 0); Serial.println(String("timer turn off switch 0 ") ); }
void turn_off_switch_no_1() { turn_on_off(0, mcp_pin_PA1, 0); Blynk.virtualWrite(V37, 0); Serial.println(String("timer turn off switch 1 ") ); }
void turn_off_switch_no_2() { turn_on_off(0, mcp_pin_PA2, 0); Blynk.virtualWrite(V38, 0); Serial.println(String("timer turn off switch 2 ") ); }
void turn_off_switch_no_3() { turn_on_off(0, mcp_pin_PA3, 0); Blynk.virtualWrite(V39, 0); Serial.println(String("timer turn off switch 3 ") ); }
void turn_off_switch_no_4() { turn_on_off(0, mcp_pin_PA4, 0); Blynk.virtualWrite(V40, 0); Serial.println(String("timer turn off switch 4 ") ); }
void turn_off_switch_no_5() { turn_on_off(0, mcp_pin_PA5, 0); Blynk.virtualWrite(V41, 0); Serial.println(String("timer turn off switch 5 ") ); }
void turn_off_switch_no_6() { turn_on_off(0, mcp_pin_PA6, 0); Blynk.virtualWrite(V42, 0); Serial.println(String("timer turn off switch 6 ") ); }
void turn_off_switch_no_7() { turn_on_off(0, mcp_pin_PA7, 0); Blynk.virtualWrite(V43, 0); Serial.println(String("timer turn off switch 7 ") ); }
void turn_off_switch_no_8() { turn_on_off(0, mcp_pin_PB0, 0); Blynk.virtualWrite(V44, 0); Serial.println(String("timer turn off switch 8 ") ); }
void turn_off_switch_no_9() { turn_on_off(0, mcp_pin_PB1, 0); Blynk.virtualWrite(V45, 0); Serial.println(String("timer turn off switch 9 ") ); }
void turn_off_switch_no_10() { turn_on_off(0, mcp_pin_PB2, 0); Blynk.virtualWrite(V46, 0); Serial.println(String("timer turn off switch 10 ") ); }
void turn_off_switch_no_11() { turn_on_off(0, mcp_pin_PB3, 0); Blynk.virtualWrite(V47, 0); Serial.println(String("timer turn off switch 11 ") ); }
// handle switch state
void turn_on_off(int on_off, byte switch_no , byte time_no) {
long active_duration_ms ;
char Time_print[16];
if ((on_off == 1) && (auto_off == 1)) //auto_off is a slider in app to shut off the program
{
// create time as string to print on activation button
sprintf(Time_print, "%02d:%02d", hour(), minute());
// turn on the switch (or off if default is on)
mcp.digitalWrite(switch_pins[switch_no], !switch_default[switch_no]);
// if end time is valid use the active duration assigned to this time
// (change to msec will be done later)
if (end_valid[switch_no][time_no])
active_duration_ms = ((long)active_duration[switch_no][time_no]);
else // otherwise use the general time duration
active_duration_ms = ((long)active_duration[switch_no][4]);
// max duration smaller than two min is not valid
if ( (max_duration[switch_no] < 120) | (max_duration[switch_no] > active_duration_ms) )
active_duration_ms = active_duration_ms * 1000;
else
active_duration_ms = ((long)max_duration[switch_no]) * 1000;
// if new timer is set before another one ended then disable previous timer
if (end_timer_id[switch_no] != 32) timer.deleteTimer(end_timer_id[switch_no]);
// turn on switch and set timer
switch (switch_no) {
case 0:
Blynk.setProperty(V36, "onLabel", String(Time_print));
Blynk.virtualWrite(V36, 1);
end_timer_id[0] = timer.setTimeout(active_duration_ms, turn_off_switch_no_0);
zone = 1;
break;
case 1:
Blynk.setProperty(V37, "onLabel", String(Time_print));
Blynk.virtualWrite(V37, 1);
end_timer_id[1] = timer.setTimeout(active_duration_ms, turn_off_switch_no_1);
zone = 2;
break;
case 2:
Blynk.setProperty(V38, "onLabel", String(Time_print));
Blynk.virtualWrite(V38, 1);
end_timer_id[2] = timer.setTimeout(active_duration_ms, turn_off_switch_no_2);
zone = 3;
break;
case 3:
Blynk.setProperty(V39, "onLabel", String(Time_print));
Blynk.virtualWrite(V39, 1);
end_timer_id[3] = timer.setTimeout(active_duration_ms, turn_off_switch_no_3);
zone = 4;
break;
case 4:
Blynk.setProperty(V40, "onLabel", String(Time_print));
Blynk.virtualWrite(V40, 1);
end_timer_id[4] = timer.setTimeout(active_duration_ms, turn_off_switch_no_4);
zone = 5;
break;
case 5:
Blynk.setProperty(V41, "onLabel", String(Time_print));
Blynk.virtualWrite(V41, 1);
end_timer_id[5] = timer.setTimeout(active_duration_ms, turn_off_switch_no_5);
zone = 6;
break;
case 6:
Blynk.setProperty(V42, "onLabel", String(Time_print));
Blynk.virtualWrite(V42, 1);
end_timer_id[6] = timer.setTimeout(active_duration_ms, turn_off_switch_no_6);
zone = 7;
break;
case 7:
Blynk.setProperty(V43, "onLabel", String(Time_print));
Blynk.virtualWrite(V43, 1);
end_timer_id[7] = timer.setTimeout(active_duration_ms, turn_off_switch_no_7);
zone = 8;
break;
case 8:
Blynk.setProperty(V44, "onLabel", String(Time_print));
Blynk.virtualWrite(V44, 1);
end_timer_id[8] = timer.setTimeout(active_duration_ms, turn_off_switch_no_8);
zone = 9;
break;
case 9:
Blynk.setProperty(V45, "onLabel", String(Time_print));
Blynk.virtualWrite(V45, 1);
end_timer_id[9] = timer.setTimeout(active_duration_ms, turn_off_switch_no_9);
zone = 10;
break;
case 10:
Blynk.setProperty(V46, "onLabel", String(Time_print));
Blynk.virtualWrite(V46, 1);
end_timer_id[10] = timer.setTimeout(active_duration_ms, turn_off_switch_no_10);
zone = 11;
break;
case 11:
Blynk.setProperty(V47, "onLabel", String(Time_print));
Blynk.virtualWrite(V47, 1);
end_timer_id[11] = timer.setTimeout(active_duration_ms, turn_off_switch_no_11);
zone =12;
break;
}
Serial.println(String("turn ON switch: ") + switch_no + String(" for duration: ") + active_duration_ms / 60000 + String("min "));
}
else
{
mcp.digitalWrite(switch_pins[switch_no], switch_default[switch_no]);
timer.deleteTimer(end_timer_id[switch_no]);
end_timer_id[switch_no] = 32;
Serial.println(String("turn OFF switch: ") + switch_no);
zone = '\0';
}
}
// set switch state from APP
BLYNK_WRITE(V36) { turn_on_off(param.asInt(), mcp_pin_PA0, TIME_CNT); }
BLYNK_WRITE(V37) { turn_on_off(param.asInt(), mcp_pin_PA1, TIME_CNT); }
BLYNK_WRITE(V38) { turn_on_off(param.asInt(), mcp_pin_PA2, TIME_CNT); }
BLYNK_WRITE(V39) { turn_on_off(param.asInt(), mcp_pin_PA3, TIME_CNT); }
BLYNK_WRITE(V40) { turn_on_off(param.asInt(), mcp_pin_PA4, TIME_CNT); }
BLYNK_WRITE(V41) { turn_on_off(param.asInt(), mcp_pin_PA5, TIME_CNT); }
BLYNK_WRITE(V42) { turn_on_off(param.asInt(), mcp_pin_PA6, TIME_CNT); }
BLYNK_WRITE(V43) { turn_on_off(param.asInt(), mcp_pin_PA7, TIME_CNT); }
BLYNK_WRITE(V44) { turn_on_off(param.asInt(), mcp_pin_PB0, TIME_CNT); }
BLYNK_WRITE(V45) { turn_on_off(param.asInt(), mcp_pin_PB1, TIME_CNT); }
BLYNK_WRITE(V46) { turn_on_off(param.asInt(), mcp_pin_PB2, TIME_CNT); }
BLYNK_WRITE(V47) { turn_on_off(param.asInt(), mcp_pin_PB3, TIME_CNT); }
/////////////////////////////////////////////////////////////////////////////////////////////
// the following function is called every 60 seconds by a timer //
// the function checks if a start time is reached and if yes it will call //
// the turn_on_off function (to turn on the switch and set timer for turning off switch) //
/////////////////////////////////////////////////////////////////////////////////////////////
void activetoday() { // check if schedule #1 should run today
if (Blynk.connected()) // set wifi led if no connection
{
mcp.digitalWrite(WIFI_LED, LOW);
}
else
{
mcp.digitalWrite(WIFI_LED, HIGH);
}
if (year() != 1970) {
unsigned int nowseconds = ((hour() * 3600) + (minute() * 60) + second());
int dayadjustment = -1;
if (weekday() == 1) {
dayadjustment = 6; // needed for Sunday Time library is day 1 and Blynk is day 7
}
for (int switch_cnt = 0; switch_cnt < SWITCH_CNT; switch_cnt++) {
for (int timer_cnt = 0; timer_cnt < TIME_CNT; timer_cnt++) {
if (start_valid[switch_cnt][timer_cnt] == true) {
if (weekdays[switch_cnt][timer_cnt][weekday() + dayadjustment] == true) {
if (nowseconds >= start_time_sec[switch_cnt][timer_cnt]) {
if (nowseconds < start_time_sec[switch_cnt][timer_cnt] + 90) {
turn_on_off(1, switch_cnt, timer_cnt);
Serial.println(String("turn ON switch: ") + switch_cnt);
}
}
}
}
}
}
}
}
/////////////////////////////////////
// Digital clock display of the time
void clockDisplay()
{
// You can call hour(), minute(), ... at any time
// Please see Time library examples for details
String currentTime = String(hour()) + ":" + minute() + ":" + second();
String currentDate = String(month()) + "." + day() + "." + year();
Serial.print("Current time: ");
Serial.print(currentTime);
Serial.print(" ");
Serial.print(currentDate);
Serial.println();
// Send DATE and DATE to Blynk APP
Blynk.virtualWrite(V101, currentTime);
// Send date to the App--Not used but is available--this will show processor date if it is important to you
Blynk.virtualWrite(V102, currentDate);
}
void OLED_SSD1306() {
// clear display
display.clearDisplay();
//display
display.setTextSize(1);
display.setCursor(0, 0);
display.print("TIME");
display.setTextSize(1);
display.setCursor(0, 10);
display.print(String(hour()) + ":" + minute() + ":" + second());
display.print(" ");
display.setTextSize(1);
display.setCursor(0, 30);
display.print("ZONE");
display.setTextSize(2);
display.setCursor(34, 25);
display.printf("%2d", zone);
display.display();
}
void setup() {
// Wire.begin(0,2); //SDA, SCL
Serial.begin(115200);
// Initialize the MCP23017
mcp.begin(7); // use hardware default address 7
mcp.pinMode(mcp_pin_PA0, OUTPUT);
mcp.pullUp(mcp_pin_PA0, HIGH); // turn on a 100K pullup internally
mcp.digitalWrite(mcp_pin_PA0, HIGH);
mcp.pinMode(mcp_pin_PA1, OUTPUT);
mcp.pullUp(mcp_pin_PA1, HIGH); // turn on a 100K pullup internally
mcp.digitalWrite(mcp_pin_PA1, HIGH);
mcp.pinMode(mcp_pin_PA2, OUTPUT);
mcp.pullUp(mcp_pin_PA2, HIGH); // turn on a 100K pullup internally
mcp.digitalWrite(mcp_pin_PA2, HIGH);
mcp.pinMode(mcp_pin_PA3, OUTPUT);
mcp.pullUp(mcp_pin_PA3, HIGH); // turn on a 100K pullup internally
mcp.digitalWrite(mcp_pin_PA3, HIGH);
mcp.pinMode(mcp_pin_PA4, OUTPUT);
mcp.pullUp(mcp_pin_PA4, HIGH); // turn on a 100K pullup internally
mcp.digitalWrite(mcp_pin_PA4, HIGH);
mcp.pinMode(mcp_pin_PA5, OUTPUT);
mcp.pullUp(mcp_pin_PA5, HIGH); // turn on a 100K pullup internally
mcp.digitalWrite(mcp_pin_PA5, HIGH);
mcp.pinMode(mcp_pin_PA6, OUTPUT);
mcp.pullUp(mcp_pin_PA6, HIGH); // turn on a 100K pullup internally
mcp.digitalWrite(mcp_pin_PA6, HIGH);
mcp.pinMode(mcp_pin_PA7, OUTPUT);
mcp.pullUp(mcp_pin_PA7, HIGH); // turn on a 100K pullup internally
mcp.digitalWrite(mcp_pin_PA7, HIGH);
mcp.pinMode(mcp_pin_PB0, OUTPUT);
mcp.pullUp(mcp_pin_PB0, HIGH); // turn on a 100K pullup internally
mcp.digitalWrite(mcp_pin_PB0, HIGH);
mcp.pinMode(mcp_pin_PB1, OUTPUT);
mcp.pullUp(mcp_pin_PB1, HIGH); // turn on a 100K pullup internally
mcp.digitalWrite(mcp_pin_PB1, HIGH);
mcp.pinMode(mcp_pin_PB2, OUTPUT);
mcp.pullUp(mcp_pin_PB2, HIGH); // turn on a 100K pullup internally
mcp.digitalWrite(mcp_pin_PB2, HIGH);
mcp.pinMode(mcp_pin_PB3, OUTPUT);
mcp.pullUp(mcp_pin_PB3, HIGH); // turn on a 100K pullup internally
mcp.digitalWrite(mcp_pin_PB3, HIGH);
// reset output pins used and system variables
for (int i = 0; i < SWITCH_CNT ; i++) {
mcp.digitalWrite(switch_pins[i], switch_default[i]); // set switch to default
end_timer_id[i] = 32; // reset end timer id's
for (int j = 0; j < TIME_CNT ; j++)
{
end_valid[i][j] = false; // reset end valid array
}
}
ayr
Blynk.begin(auth, ssid, pass);
rtc.begin(); // Begin synchronizing time
timer.setInterval(10000L, clockDisplay); // check every 10s
timer.setInterval(60000L, activetoday); // check every 60s if ON / OFF trigger time has been reached
setSyncInterval(5 * 60); // Sync interval in seconds (5 minutes)
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 64x48)
delay(5000);
display.clearDisplay();
display.setTextColor(WHITE);
}
void loop()
{
Blynk.run();
timer.run();
LedWidget();
OLED_SSD1306();
}
Coaching is sincerely appreciated as possible,