Hi! My biggest problem is that i don’t code myself (i’m about to change that soon), and the students i found for the coding part of this project have dissolved in summer holidays. They ignore my FB/Skype messages for over o month, and now i’m stuck with half-working piece of iron…
The purpose of this project is to remotely (as well as locally) control my mom’s electric stove. I live over a thousand miles from my elderly mother, who has senile dementia, and although she doesn’t cook herself, she needs to warm up her meals. Of course, she turns on the stove, and goes away to watch TV until the smell of burnt food reaches her bedroom… the apartment stinks, the electric bills are enormous, and buying a new stove is not an option - it is absolutely impossible to teach her to operate new equipment. She just rejects everything. So…
I came up with the idea of a 2-button stove controller that consists of two units, based on ESP8266. First part of the controller (STOVE) uses 2 physical buttons, 2 solid state relays, and 8x8 matrix [power mode] indicator.
SSRs control the power by switching 2 heating elements of the stove on and off in the following way: 25% means that the element is ON for 1 sec/OFF for 3 sec, 50% - 2 ON/2 OFF, and so on (5 levels: 0/25/50/75/100%). Regardless of the power mode, the controller switches off heating elements after 15 minutes, and sends ‘end of cycle’ signal to the second part of the controller - SCROLLER (via the Blynk Bridge) which is another ESP8266 (in my mom’s bedroom) with a 32x8 matrix display,
that displays pre-programmed message, saying ‘it’s time to check the stove’, blah-blah.
At the same time the SCROLLER serves as ‘pager’ - it receives text messages via the Terminal Widget (my mother is also hearing impaired, so for her it’s easier to understand written messages than speech), which i’m planning to use a lot.
The bugs are:
When SCROLLER is not powered, STOVE in Blynk shows ‘Project is offline’ approximately every second. After powering up SCROLLER, STOVE sends ‘end of cycle’ signal right upon connecting to Blynk Server, and SCROLLER starts displaying ‘end of cycle’ messages for both heating elements.
When both SCROLLER and STOVE are powered, i can not get SCROLLER to display messages that i send from Terminal Widget.
Can anyone help me fix the code, so that the Bridge(s) would work properly, and that i could use SCROLLER’s Terminal Widget in the same Blynk window as STOVE (on the picture)?
Currently it’s 2 different projects, and i have to switch between them…
So far only one thing works: SCROLLER displays text messages that i send from Blynk Terminal Widget, but only while the STOVE is not powered.
I realize that the algorithm of controlling power by switching the SSRs on and off is not the best, and that because of that, the STOVE code is probably more complex than it could be. So, i’m open to suggestions of how i can simplify the code by making the electric part more complex. One thing is for sure - i’m stuck with TRIAC SSRs. And as far as i understand, PWM is not recommended for SSRs because they have limited amount (it’s billion but still…) of on/off cycles (which i guess are minimised in my case by using seconds instead of milliseconds), and i assume that inertial load of heating elements won’t work well with PWM. Am i right?
Tech requirements (in Russian) of the project
Thanks a lot!
STOVE
#include <Sprite.h>
#include <Matrix.h>
Matrix myMatrix = Matrix(13, 14, 2);
Sprite one = Sprite(8, 8,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000001,
B01111111,
B00100001
);
Sprite two = Sprite(8, 8,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00111001,
B01000101,
B00100011
);
Sprite three = Sprite(8, 8,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00110110,
B01001001,
B00100010
);
Sprite four = Sprite(8, 8,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B01111111,
B00000100,
B01111100
);
Sprite one1 = Sprite(8, 8,
B00000001,
B01111111,
B00100001,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000
);
Sprite two1 = Sprite(8, 8,
B00111001,
B01000101,
B00100011,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000
);
Sprite three1 = Sprite(8, 8,
B00110110,
B01001001,
B00100010,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000
);
Sprite four1 = Sprite(8, 8,
B01111111,
B00000100,
B01111100,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000
);
Sprite one_one = Sprite(8, 8,
B00000001,
B01111111,
B00100001,
B00000000,
B00000000,
B00000001,
B01111111,
B00100001
);
Sprite one_two = Sprite(8, 8,
B00111001,
B01000101,
B00100011,
B00000000,
B00000000,
B00000001,
B01111111,
B00100001
);
Sprite one_three = Sprite(8, 8,
B00110110,
B01001001,
B00100010,
B00000000,
B00000000,
B00000001,
B01111111,
B00100001
);
Sprite one_four = Sprite(8, 8,
B01111111,
B00000100,
B01111100,
B00000000,
B00000000,
B00000001,
B01111111,
B00100001
);
Sprite two_one = Sprite(8, 8,
B00000001,
B01111111,
B00100001,
B00000000,
B00000000,
B00111001,
B01000101,
B00100011
);
Sprite two_two = Sprite(8, 8,
B00111001,
B01000101,
B00100011,
B00000000,
B00000000,
B00111001,
B01000101,
B00100011
);
Sprite two_three = Sprite(8, 8,
B00110110,
B01001001,
B00100010,
B00000000,
B00000000,
B00111001,
B01000101,
B00100011
);
Sprite two_four = Sprite(8, 8,
B01111111,
B00000100,
B01111100,
B00000000,
B00000000,
B00111001,
B01000101,
B00100011
);
Sprite three_one = Sprite(8, 8,
B00000001,
B01111111,
B00100001,
B00000000,
B00000000,
B00110110,
B01001001,
B00100010
);
Sprite three_two = Sprite(8, 8,
B00111001,
B01000101,
B00100011,
B00000000,
B00000000,
B00110110,
B01001001,
B00100010
);
Sprite three_three = Sprite(8, 8,
B00110110,
B01001001,
B00100010,
B00000000,
B00000000,
B00110110,
B01001001,
B00100010
);
Sprite three_four = Sprite(8, 8,
B01111111,
B00000100,
B01111100,
B00000000,
B00000000,
B00110110,
B01001001,
B00100010
);
Sprite four_one = Sprite(8, 8,
B00000001,
B01111111,
B00100001,
B00000000,
B00000000,
B01111111,
B00000100,
B01111100
);
Sprite four_two = Sprite(8, 8,
B00111001,
B01000101,
B00100011,
B00000000,
B00000000,
B01111111,
B00000100,
B01111100
);
Sprite four_three = Sprite(8, 8,
B00110110,
B01001001,
B00100010,
B00000000,
B00000000,
B01111111,
B00000100,
B01111100
);
Sprite four_four = Sprite(8, 8,
B01111111,
B00000100,
B01111100,
B00000000,
B00000000,
B01111111,
B00000100,
B01111100
);
int wd1=0;
int wtt=0;
int over =30000;
int tt=0;
int d1=0;
long ptime12 =0;
long weq=0;
long wt1=0;
long t1=0;
long t12=0;
long eq1=0;
long wt12=0;
long weq1=0;
long time12;
long ptime1=0;
long wptime1=0;
long pwtime12 =0;
long wptime12=0;
long wtime12;
int x = 0;
int val;
int sr=0;
int m;
int key = 0;
int key1 = 0;
int ke=0;
int ke1=0;
int val1;
int sr1=0;
int z;
long t=0;
long wt=0;
int eq=0;
String c;
long time1;
long wtime1;
int flag=0;
int flag2=0;
int flag3=0;
int wflag2=0;
int wflag=0;
int wflag3=0;
int wflag4=0;
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
char auth[] = "xxx";
WidgetBridge bridge(V11);
void setup() {
Serial.begin(9600);
pinMode(15,INPUT);
pinMode(12,OUTPUT);
pinMode(4,INPUT);
pinMode(5,OUTPUT);
WiFi.persistent(false);
Blynk.begin(auth, "xxx", "xxx");
}
BLYNK_CONNECTED() {
bridge.setAuthToken("xxx");
}
//Reset
BLYNK_WRITE(V31){
if(param.asInt()==1){
ke=0;
ke1=0;
Blynk.virtualWrite(2,0);
Blynk.virtualWrite(3,0);
myMatrix.clear();
}
}
void loop() {
//first button
if(digitalRead(15) == HIGH && key == 0) {
ke ++;
key = 1;
t=0;
eq1=0;
tt=0;
if(ke > 4)
ke = 0;
eq=0;
}
if(digitalRead(15) == LOW && key == 1)
{
key = 0;
}
//second button
if(digitalRead(4) == HIGH && key1 == 0)
{
ke1 ++;
key1 = 1;
wt=0;
weq1=0;
tt=0;
eq=0;
if(ke1 >4)
ke1 = 0;
}
if(digitalRead(4) == LOW && key1 == 1)
{
key1 = 0;
}
//timers
if(ke == 0){
eq1=0;
tt=0;
time12=0;
ptime12=0;
Blynk.virtualWrite(2,0);
if(ke1==0){
myMatrix.clear();
}
bridge.virtualWrite(12,1);
d1=1;
analogWrite(12,0);
Blynk.virtualWrite(0, 0);
//send over to ESP-line
bridge.virtualWrite(12,1);
}
if(ke == 1){
if(eq1<=over){
//////////////timer
time12=millis();
if(tt ==1){
eq1+=time12-ptime12;
}
ptime12=time12;
tt=1;
////////////////////
if(flag==4){
flag=0;
}
if(flag==0){
analogWrite(12,255);
Blynk.virtualWrite(0, 255);
}
//////////////timer
time1=millis();
if(t ==1){
eq+=time1-ptime1;
}
ptime1=time1;
t=1;
if(eq>=1000){
analogWrite(12,0);
Blynk.virtualWrite(0, 0);
flag+=1;
eq=0;
}
}else{
ke=0;
}
}
if(ke == 2){
if(eq1<=over){
//////////////timer
time12=millis();
if(tt ==1){
eq1+=time12-ptime12;
}
ptime12=time12;
tt=1;
////////////////////
if(flag2==2||flag2==3){
analogWrite(12,0);
Blynk.virtualWrite(0, 0);
}
if(flag2==4){
flag2=0;
}
if(flag2<=1){
analogWrite(12,255);
Blynk.virtualWrite(0, 255);
}//////////////timer
time1=millis();
if(t ==1){
eq+=time1-ptime1;
}
ptime1=time1;
t=1;
if(eq>=1000){
flag2+=1;
eq=0;
}
}else{
ke=0;
}
}
if(ke == 3){
if(eq1<over){
//////////////timer
time12=millis();
if(tt ==1){
eq1+=time12-ptime12;
}
ptime12=time12;
tt=1;
////////////////////
if(flag3==3){
analogWrite(12,0);
Blynk.virtualWrite(0, 0);
}
if(flag3==4){
flag3=0;
}
if(flag3<=2){
analogWrite(12,255);
Blynk.virtualWrite(0, 255);
}//////////////timer
time1=millis();
if(t ==1){
eq+=time1-ptime1;
}
ptime1=time1;
t=1;
if(eq>=1000){
flag3+=1;
eq=0;
}
}else{
ke=0;
}
}
if(ke == 4){
if(eq1<=over){
//////////////timer
time12=millis();
if(tt ==1){
eq1+=time12-ptime12;
}
ptime12=time12;
tt=1;
////////////////////
analogWrite(12,255);
Blynk.virtualWrite(0, 255);
}else{
ke=0;
}
}
/////////////////////Second stove module
if(ke1 == 0){
weq1=0;
wtt=0;
wtime12=0;
wptime12=0;
Blynk.virtualWrite(3,0);
if(ke==0){
myMatrix.clear();
}
wd1=1;
analogWrite(5,0);
Blynk.virtualWrite(1, 0);
//send over
bridge.virtualWrite(12,2);
}
if(ke1 == 1){
if(weq1<=over){
//////////////timer
wtime12=millis();
if(wtt ==1){
weq1+=wtime12-wptime12;
}
wptime12=wtime12;
wtt=1;
////////////////////
if(wflag==4){
wflag=0;
}
if(wflag==0){
analogWrite(5,255);
Blynk.virtualWrite(1, 255);
}
//////////////timer
wtime1=millis();
if(wt ==1){
weq+=wtime1-wptime1;
}
wptime1=wtime1;
wt=1;
if(weq>=1000){
analogWrite(5,0);
Blynk.virtualWrite(1, 0);
wflag+=1;
weq=0;
}
}else{
ke1=0;
}
}
if(ke1 == 2){
if(weq1<=over){
//////////////timer
wtime12=millis();
if(wtt ==1){
weq1+=wtime12-wptime12;
}
wptime12=wtime12;
wtt=1;
////////////////////
if(wflag2==2||wflag2==3){
analogWrite(5,0);
Blynk.virtualWrite(1, 0);
}
if(wflag2==4){
wflag2=0;
}
if(wflag2<=1){
analogWrite(5,255);
Blynk.virtualWrite(1, 255);
}//////////////timer
wtime1=millis();
if(wt ==1){
weq+=wtime1-wptime1;
}
wptime1=wtime1;
wt=1;
if(weq>=1000){
wflag2+=1;
weq=0;
}
}else{
ke1=0;
}
}
if(ke1 == 3){
if(weq1<over){
//////////////timer
wtime12=millis();
if(wtt ==1){
weq1+=wtime12-wptime12;
}
wptime12=wtime12;
wtt=1;
////////////////////
if(wflag3==3){
analogWrite(5,0);
Blynk.virtualWrite(1, 0);
}
if(wflag3==4){
wflag3=0;
}
if(wflag3<=2){
analogWrite(5,255);
Blynk.virtualWrite(1, 255);
}//////////////timer
wtime1=millis();
if(wt ==1){
weq+=wtime1-wptime1;
}
wptime1=wtime1;
wt=1;
if(weq>=1000){
wflag3+=1;
weq=0;
}
}else{
ke1=0;
}
}
if(ke1 == 4){
if(weq1<=over){
//////////////timer
wtime12=millis();
if(wtt ==1){
weq1+=wtime12-wptime12;
}
wptime12=wtime12;
wtt=1;
////////////////////
analogWrite(5,255);
Blynk.virtualWrite(1, 255);
}else{
ke1=0;
}
}
//matrices & power display
if(ke==1&&ke1==0){
myMatrix.write(0, 0, one);
Blynk.virtualWrite(2, 25);
Blynk.virtualWrite(3, 0);
}
if(ke==2&&ke1==0){
myMatrix.write(0, 0, two);
Blynk.virtualWrite(2, 50);
Blynk.virtualWrite(3, 0);
}
if(ke==3&&ke1==0){
myMatrix.write(0, 0, three);
Blynk.virtualWrite(2, 75);
Blynk.virtualWrite(3, 0);
}
if(ke==4&&ke1==0){
myMatrix.write(0, 0, four);
Blynk.virtualWrite(2, 100);
Blynk.virtualWrite(3, 0);
}
if(ke==0&&ke1==1){
myMatrix.write(0, 0, one1);
Blynk.virtualWrite(2, 0);
Blynk.virtualWrite(3, 25);
}
if(ke==0&&ke1==2){
myMatrix.write(0, 0, two1);
Blynk.virtualWrite(2, 0);
Blynk.virtualWrite(3, 50);
}
if(ke==0&&ke1==3){
myMatrix.write(0, 0, three1);
Blynk.virtualWrite(2, 0);
Blynk.virtualWrite(3, 75);
}
if(ke==0&&ke1==4){
myMatrix.write(0, 0, four1);
Blynk.virtualWrite(2, 0);
Blynk.virtualWrite(3, 100);
}
if(ke==1&&ke1==1){
myMatrix.write(0, 0, one_one);
Blynk.virtualWrite(2, 25);
Blynk.virtualWrite(3, 25);
}
if(ke==1&&ke1==2){
myMatrix.write(0, 0, one_two);
Blynk.virtualWrite(2, 25);
Blynk.virtualWrite(3, 50);
}
if(ke==1&&ke1==3){
myMatrix.write(0, 0, one_three);
Blynk.virtualWrite(2, 25);
Blynk.virtualWrite(3, 75);
}
if(ke==1&&ke1==4){
myMatrix.write(0, 0, one_four);
Blynk.virtualWrite(2, 25);
Blynk.virtualWrite(3, 100);
}
if(ke==2&&ke1==1){
myMatrix.write(0, 0, two_one);
Blynk.virtualWrite(2, 50);
Blynk.virtualWrite(3, 25);
}
if(ke==2&&ke1==2){
myMatrix.write(0, 0, two_two);
Blynk.virtualWrite(2, 50);
Blynk.virtualWrite(3, 50);
}
if(ke==2&&ke1==3){
myMatrix.write(0, 0, two_three);
Blynk.virtualWrite(2, 50);
Blynk.virtualWrite(3, 75);
}
if(ke==2&&ke1==4){
myMatrix.write(0, 0, two_four);
Blynk.virtualWrite(2, 50);
Blynk.virtualWrite(3, 100);
}
if(ke==3&&ke1==1){
myMatrix.write(0, 0, three_one);
Blynk.virtualWrite(2, 75);
Blynk.virtualWrite(3, 25);
}
if(ke==3&&ke1==2){
myMatrix.write(0, 0, three_two);
Blynk.virtualWrite(2, 75);
Blynk.virtualWrite(3, 50);
}
if(ke==3&&ke1==3){
myMatrix.write(0, 0, three_three);
Blynk.virtualWrite(2, 75);
Blynk.virtualWrite(3, 75);
}
if(ke==3&&ke1==4){
myMatrix.write(0, 0, three_four);
Blynk.virtualWrite(2, 75);
Blynk.virtualWrite(3, 100);
}
if(ke==4&&ke1==1){
myMatrix.write(0, 0, four_one);
Blynk.virtualWrite(2, 100);
Blynk.virtualWrite(3, 25);
}
if(ke==4&&ke1==2){
myMatrix.write(0, 0, four_two);
Blynk.virtualWrite(2, 100);
Blynk.virtualWrite(3, 50);
}
if(ke==4&&ke1==3){
myMatrix.write(0, 0, four_three);
Blynk.virtualWrite(2, 100);
Blynk.virtualWrite(3, 75);
}
if(ke==4&&ke1==4){
myMatrix.write(0, 0, four_four);
Blynk.virtualWrite(2, 100);
Blynk.virtualWrite(3, 100);
}
Blynk.run();
}
SCROLLER
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Max72xxPanel.h>
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
char auth[] = "xxxx";
int pinCS = 16;
int numberOfHorizontalDisplays = 1;
int numberOfVerticalDisplays = 4;
Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);
String tape = "";
int wait = 50; // In milliseconds
int spacer = 1; //
int width = 5 + spacer; // The font width is 5 pixels
/* Recode russian fonts from UTF-8 to Windows-1251 */
String utf8rus(String source)
{
int i,k;
String target;
unsigned char n;
char m[2] = { '0', '\0' };
k = source.length(); i = 0;
while (i < k) {
n = source[i]; i++;
if (n >= 0xC0) {
switch (n) {
case 0xD0: {
n = source[i]; i++;
if (n == 0x81) { n = 0xA8; break; }
if (n >= 0x90 && n <= 0xBF) n = n + 0x2F;
break;
}
case 0xD1: {
n = source[i]; i++;
if (n == 0x91) { n = 0xB7; break; }
if (n >= 0x80 && n <= 0x8F) n = n + 0x6F;
break;
}
}
}
m[0] = n; target = target + String(m);
}
return target;
}
String Serial_Read() {
unsigned char c; //
String Serial_string = ""; //
while (Serial.available() > 0) { //
c = Serial.read(); //
//Serial.print(c,HEX); Serial.print(" "); Serial.print(c);
if (c == '\n') { //
return Serial_string; //
}
if (c == 0xB8) c = c - 0x01; //
if (c >= 0xBF && c <= 0xFF) c = c - 0x01;
Serial_string = Serial_string + String(char(c)); //
}
return Serial_string;
}
WidgetTerminal terminal(V5);
void setup() {
Serial.begin(9600);
matrix.setIntensity(3); // Use a value between 0 and 15 for brightness
matrix.setRotation(matrix.getRotation()+1); //1 - 90 2 - 180 3 - 270
matrix.fillScreen(LOW);
matrix.write(); // Send bitmap to display
WiFi.persistent(false);
Blynk.begin(auth, "xxx", "xxx");
while (Blynk.connect() == false) {
}
terminal.println(F("Blynk v" BLYNK_VERSION ": WeMosD1mini is online"));
terminal.println("--------------------------------------");
terminal.println("Набрать текст и нажат ВВОД");
terminal.flush();
}
BLYNK_WRITE(V12){
if(param.asInt()==1){
tape=utf8rus("yellow желтая");
}if(param.asInt()==2){
tape=utf8rus("blue синяя");
}
}
BLYNK_WRITE(V5){
tape=utf8rus(param.asStr());
terminal.flush();
}
BLYNK_WRITE(V1){
terminal.flush();
}
void loop() {
if (Serial.available()){
tape=Serial_Read();
}
for ( int i = 0 ; i < width * tape.length() + matrix.width() - 1 - spacer; i++ )
{
matrix.fillScreen(LOW);
int letter = i / width; //
int x = (matrix.width() - 1) - i % width;
int y = (matrix.height() - 8) / 2; // center the text vertically
while ( x + width - spacer >= 0 && letter >= 0 ) {
if ( letter < tape.length() ) {
matrix.drawChar(x, y, tape[letter], HIGH, LOW,1);
}
letter--;
x -= width;
}
matrix.write(); // Send bitmap to display
delay(wait);
}
Blynk.run();
}