28-05-2020, 11:28
Cześć,
mam 2 różna projekty na nodemcu oba podpięte do tej samej sieci WIFI i oba resetują się co jakiś czas.
Wiem że w przypadku sieciowych modułów powinienem w pętlach używać "yield()" - będę to poprawiać.
Ale problem jest chyba bardziej złożony.
Resety "samorzutne" mogę zrzucić winę na moje błędy w kodzie, ale czemu co jakiś czas obie płytki resetują się w tym samym momencie?
Co wykluczyłem?
-zasilanie (różna źródła)
-"cykl" płytki (włączane w różnym czasie)
moje podejrzenie:
jako połączone do sieci WiFi płytki dostają sygnał który je resetuje, albo odpowiedź sieci(czas??) powodują błąd i reset.
Reasumując czy ktoś wie czy jest jakiś "pakiet" który może rozsyłać router powodujący reset?
Płytki resetują się w bardzo losowych odstępach czasu (czasem kilka razy z rzędu w cyklu max 5s, a zazwyczaj 1 na 1-2h)
Będę wdzięczy za każdą podpowiedź
Załączam kod prostszego projektu.
Cechy wspólne projektów:
1) ta sama sieć WIFI
2) Bibliotekiwszystkie najnowsze)
<DallasTemperature.h>
<ESP8266WiFi.h>
<ESP8266WebServer.h>
<ZBK_Interval.h> - autorska w oparciu o wiele projektów z sieci (poniżej załączę)
mam 2 różna projekty na nodemcu oba podpięte do tej samej sieci WIFI i oba resetują się co jakiś czas.
Wiem że w przypadku sieciowych modułów powinienem w pętlach używać "yield()" - będę to poprawiać.
Ale problem jest chyba bardziej złożony.
Resety "samorzutne" mogę zrzucić winę na moje błędy w kodzie, ale czemu co jakiś czas obie płytki resetują się w tym samym momencie?
Co wykluczyłem?
-zasilanie (różna źródła)
-"cykl" płytki (włączane w różnym czasie)
moje podejrzenie:
jako połączone do sieci WiFi płytki dostają sygnał który je resetuje, albo odpowiedź sieci(czas??) powodują błąd i reset.
Reasumując czy ktoś wie czy jest jakiś "pakiet" który może rozsyłać router powodujący reset?
Płytki resetują się w bardzo losowych odstępach czasu (czasem kilka razy z rzędu w cyklu max 5s, a zazwyczaj 1 na 1-2h)
Będę wdzięczy za każdą podpowiedź
Załączam kod prostszego projektu.
Kod:
//#include <OneWire1.h>//DS1820
//#include <DS18B20.h>//DS1820
#include <DallasTemperature.h>//DS1820
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h> // Include the WebServer library
#include <ZBK_Interval.h>
/*
static const uint8_t D0 = 16;
static const uint8_t D1 = 5;
static const uint8_t D2 = 4;
static const uint8_t D3 = 0;
static const uint8_t D4 = 2;
static const uint8_t D5 = 14;
static const uint8_t D6 = 12;
static const uint8_t D7 = 13;
static const uint8_t D8 = 15;
static const uint8_t D9 = 3;
static const uint8_t D10 = 1;
*/
/* Konfiguracja sieci */
const char* ssid = "#SIEC#"; //your WiFi Name
const char* password = "#HASŁO#"; //Your Wifi Password
const char* login="#LOGIN#";
const char* haslo="#HASŁO#";
const char* klucz="#KLUCZ#";
int IloscBlednychLogowan=0;
const int PinPrzek1 = D0;
const int PinPrzek2 = D1;
const int PinPrzek3 = D2;
const int PinPrzek4 = D4; //D3 przy włączaniu "pstryka"
const int PinPowerLed=D5;
byte StanPrzek1=51;
byte StanPrzek2=51;
byte StanPrzek3=51;
byte StanPrzek4=51;
byte stan=HIGH;
float Temp=-126;
const float TempON=32.0;
const float TempOFF=25.0;
const int OpoznienieWylaczania =100000; //ms
#define ONE_WIRE_BUS 0 //D3
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
ZBK_Interval Interval(3);
ESP8266WebServer server(80); // Create a webserver object that listens for HTTP request on port 80
void handleRoot(); // function prototypes for HTTP handlers
void handleNotFound();
void handlePrzekaznik();
void handlePOWER();
void setup() {
pinMode(PinPrzek1, OUTPUT);
pinMode(PinPrzek2, OUTPUT);
pinMode(PinPrzek3, OUTPUT);
pinMode(PinPrzek4, OUTPUT);
digitalWrite(PinPrzek1, HIGH);
digitalWrite(PinPrzek2, HIGH);
digitalWrite(PinPrzek3, HIGH);
digitalWrite(PinPrzek4, HIGH);
pinMode(PinPowerLed, INPUT);
StanPrzek1=HIGH;
StanPrzek2=61;
StanPrzek3=61;
StanPrzek4=61;
Serial.begin(115200);
Serial.print("Connecting to ");
Serial.println(ssid);
Interval.set(1, 1000, TempOdczyt);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
server.begin();
Serial.println("Server started");
Serial.print("Use this URL to connect: ");
Serial.print("http://");
Serial.print(WiFi.localIP());
Serial.println("/");
server.on("/", HTTP_GET, handleLOGIN);
server.on("/zalogowany", HTTP_POST, handleRoot);
server.on("/przekaznik", HTTP_POST, handlePrzekaznik);
server.on("/power", HTTP_POST, handlePOWER);
server.onNotFound(handleNotFound);
}
void wlaczaniewiatrakow()
{
if(StanPrzek2!=2){StanPrzek2=0;digitalWrite(PinPrzek2, StanPrzek2);};
if(StanPrzek2!=2){StanPrzek3=0;digitalWrite(PinPrzek3, StanPrzek3);};
}
void wylaczaniewiatrakow()
{
if(StanPrzek2!=2){StanPrzek2=1;digitalWrite(PinPrzek2, StanPrzek2);};
if(StanPrzek3!=2){StanPrzek3=1;digitalWrite(PinPrzek3, StanPrzek3);};
}
void TempOdczyt()
{
sensors.requestTemperatures();
Temp=sensors.getTempCByIndex(0);
if(Temp<-100){Temp=127;}
if(Temp>TempON){wlaczaniewiatrakow();}else{if(Temp<TempOFF){Interval.set(3, (OpoznienieWylaczania*-1), wylaczaniewiatrakow);}}
}
void handleLOGIN() {
Serial.println("LOGIN");
String html = "<!DOCTYPE html> <html>\n";
html +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
html +="<title>TEST</title>\n";
html +="<meta charset=\"utf-8\">";
html +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
html +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n";
html +="</style>\n";
html +="</head>\n";
html +="<body>\n";
html +="<div id=\"webpage\">\n";
html +="<h1>Logowanie:)</h1><form action='/zalogowany' method='POST'><div>Login:<input type='text' name='login' value=''></div><div>Hasło:<input type='password' name='haslo' value=''></div><input type='submit' value='Zaloguj'></form></br>";
html +="</div></body></html>";
server.send(200,"text/html", html); // Send HTTP status 200 (Ok) and send some text to the browser/client
}
void handleRoot() {
Serial.println("ROOT");
if(((! server.hasArg("login"))||(! server.hasArg("haslo")))&&(! server.hasArg("klucz"))){ Serial.println("."); server.sendHeader("Location","/"); server.send(303); }
else
{
if(((server.arg("login")!=login)||(server.arg("haslo")!=haslo))&&(server.arg("klucz")!=klucz)){ Serial.println(".."); server.sendHeader("Location","/"); server.send(303); }
else{
Serial.println(":)");
stan=digitalRead(PinPowerLed);
String html = "<!DOCTYPE html> <html>\n";
html +="<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
html +="<title>Zdalny kontroler</title>\n";
html +="<meta charset=\"utf-8\">";
html +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
html +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;}\n";
html +="p {font-size: 24px;color: #444444;margin-bottom: 10px;}\n";
html +=".s1{display:inline-block; width:100px;height:25px;background-color:#5f5;}";
html +=".s0{display:inline-block; width:100px;height:25px;background-color:#f55;}";
html +="</style>\n";
html +="</head>\n";
html +="<body>\n";
html +="<div id=\"webpage\">\n";
html +="<h1>Komputer</h1>\n";
html +="Przekażnik 1: ";
if (stan == LOW) {html +="<span class='s1'>Włączony</span>";}else{html +="<span class='s0'>Wyłączony</span>";}
html +="<form action='/power' method='POST'><input type='hidden' name='klucz' value='";html+=klucz;html+="'><input type='hidden' name='przekaznik' value='1'><input type='submit' value='POWER'><select name='czas'> <option value='1000' selected>1s</option><option value='2000'>2s</option><option value='5000'>5s</option><option value='10000'>10s</option><option value='15000'>15s</option></select></form></br>";
html +="<h1>Temperatura</h1>\n";
html +=Temp;
html +=" °C \n";
html +="<h1>Stan Przekazników</h1>\n";
html +="Przekażnik 2: ";
if ((StanPrzek2%2)==0) {html +="<span class='s1'>Włączony</span>";}else{html +="<span class='s0'>Wyłączony</span>";}
html +="<form action='/przekaznik' method='POST'><input type='hidden' name='klucz' value='";html+=klucz;html+="'><input type='hidden'name='przekaznik' value='2'><input type='submit' value='Zmień' title='";
html +=StanPrzek2;
html +="'></form></br>";
html +="Przekażnik 3: ";
if ((StanPrzek3%2)==0) {html +="<span class='s1'>Włączony</span>";}else{html +="<span class='s0'>Wyłączony</span>";}
html +="<form action='/przekaznik' method='POST'><input type='hidden' name='klucz' value='";html+=klucz;html+="'><input type='hidden' name='przekaznik' value='3'><input type='submit' value='Zmień' title='";
html +=StanPrzek3;
html +="'></form></br>";
html +="Przekażnik 4: ";
if ((StanPrzek4%2)==0) {html +="<span class='s1'>Włączony</span>";}else{html +="<span class='s0'>Wyłączony</span>";}
html +="<form action='/przekaznik' method='POST'><input type='hidden' name='klucz' value='";html+=klucz;html+="'><input type='hidden'name='przekaznik' value='4'><input type='submit' value='Zmień' title='";
html +=StanPrzek4;
html +="'></form></br>";
html +="<hr><form action='/zalogowany' method='POST'><input type='hidden' name='klucz' value='";html+=klucz;html+="'><input type='submit' value='Odśwież'></form></br>";
html +="</div></body></html>";
server.send(200,"text/html", html); // Send HTTP status 200 (Ok) and send some text to the browser/client
}
}
}
//StanPrzek (dla 2-3) 0- włączny przez terostat 1 wyłączony ptzez teromostat 2 włączony ręzcnie 3 wyłączony ręcznie
void handlePrzekaznik() {
Serial.println("Przekaznik");
if(((! server.hasArg("login"))||(! server.hasArg("haslo")))&&(! server.hasArg("klucz"))){ Serial.println("."); server.sendHeader("Location","/"); server.send(303); }
else
{
if(((server.arg("login")!=login)||(server.arg("haslo")!=haslo))&&(server.arg("klucz")!=klucz)){ Serial.println(".."); server.sendHeader("Location","/"); server.send(303); }
else{
Serial.println(":)");
if(server.hasArg("przekaznik")){
Serial.println(server.arg("przekaznik"));
if(server.arg("przekaznik")=="1"){if(StanPrzek1==HIGH){StanPrzek1=LOW;}else{StanPrzek1=HIGH;};digitalWrite(PinPrzek1, StanPrzek1%2);}
if(server.arg("przekaznik")=="2"){if((StanPrzek2%2)==1){StanPrzek2=2;}else{if(StanPrzek2==2){StanPrzek2=3;}}digitalWrite(PinPrzek2, StanPrzek2%2);}
if(server.arg("przekaznik")=="3"){if((StanPrzek3%2)==1){StanPrzek3=2;}else{if(StanPrzek3==2){StanPrzek3=3;}}digitalWrite(PinPrzek3, StanPrzek3%2);}
if(server.arg("przekaznik")=="4"){if((StanPrzek4%2)==1){StanPrzek4=2;}else{if(StanPrzek4==2){StanPrzek4=3;}}digitalWrite(PinPrzek4, StanPrzek4%2);}
}
// server.sendHeader("Location","/zalogowany");
// server.send(303);
handleRoot() ;
}}}
void handlePOWER() {
Serial.println("POWER");
if(((! server.hasArg("login"))||(! server.hasArg("haslo")))&&(! server.hasArg("klucz"))){ Serial.println("."); server.sendHeader("Location","/"); server.send(303); }
else
{
if(((server.arg("login")!=login)||(server.arg("haslo")!=haslo))&&(server.arg("klucz")!=klucz)){ Serial.println(".."); server.sendHeader("Location","/"); server.send(303); }
else{
Serial.println(":)");
digitalWrite(PinPrzek1, LOW);
if(server.hasArg("czas"))
{
int czas=server.arg("czas").toInt();
if((czas>99)&&(czas<30000)){Interval.set(0, (server.arg("czas").toInt()*-1), koniecPOWER);}else{ Interval.set(0, -1000, koniecPOWER);}
}else{ Interval.set(0, -1000, koniecPOWER);}
// server.sendHeader("Location","/zalogowany");
//server.send(303);
handleRoot() ;
}}}
void koniecPOWER()
{
Serial.println("-POWER-");
digitalWrite(PinPrzek1, HIGH);
}
void handleNotFound(){
server.send(404, "text/plain", "404: Not found"); // Send HTTP status 404 (Not Found) when there's no handler for the URI in the request
}
void loop() {
Interval.update();
server.handleClient(); // Listen for HTTP requests from clients
}
Cechy wspólne projektów:
1) ta sama sieć WIFI
2) Bibliotekiwszystkie najnowsze)
<DallasTemperature.h>
<ESP8266WiFi.h>
<ESP8266WebServer.h>
<ZBK_Interval.h> - autorska w oparciu o wiele projektów z sieci (poniżej załączę)
Kod:
#include "ZBK_Interval.h"
//v 0.7
/*
Inicjacja ZBK_Interval(byte slots) // deklarujemy ile slotów potrzebujemy (możemy je dynamicznie zmieniać ale nie można dodać nowych...)
update(void) // funkcja wywołująca funkcjonalność powinna być w loop
delay(long time) //funkcja podobna do zwykłego delay z tą różnicą że w trakcie trwania działą zegar - UWAGA! jeśli pod koniec czasu wywołana zosstanie "długa" funkcja może się okazać że czas trawnia przerwy będzie dłuższy niż oczekiwano
set(byte slot, long interval, intervalFunc func) //funkcja przypisująca czas i funkcje do slotu - funkcje są przekazywane bez zmiennych
interval //zmienna częstotliwości. jeśli <0 zdarzenie tylko raz wywołane jeśli >0 zdażenie cykliczne jeśli 0 to wyłączone
funkcje start i stop dzaiłają tylko dla dodatnich intervałow
*/
ZBK_Interval::ZBK_Interval(byte slots)
{
_slots = slots;
_elements = (IntervalElement *) malloc(sizeof(IntervalElement)*slots);
for (byte slot=0; slot<_slots; slot++)
{
_elements[slot].interval = 0;
}
}
ZBK_Interval::~ZBK_Interval()
{
free(_elements);
}
void ZBK_Interval::set(byte slot, long interval, intervalFunc func)
{
set(slot,interval,func,true);
}
void ZBK_Interval::set(byte slot, long interval, intervalFunc func, bool active)
{
_elements[slot].func = func;
//_elements[slot].active=false;
if(active){
_elements[slot].interval = interval;
_elements[slot].exetute_time = millis()+abs(interval);
}
else{
_elements[slot].exetute_time = 0xffffffff-interval;//ponieważ interval zazwyczaj jest mały to żeby execute był wysoki
_elements[slot].interval = 0;
}
}
void ZBK_Interval::setInterval(byte slot, long interval)
{
//w wersji exetute_time dodatkowe działania
//long interval_old=_elements[slot].interval;
//przypisuję nowy czas wykonania
/*if(interval>0){
_elements[slot].exetute_time = millis()+interval;
}else{
_elements[slot].exetute_time = millis()-interval;
}
*/
_elements[slot].exetute_time = millis()+abs(interval);
_elements[slot].interval = interval;
//w wersji begin_time wystarczy
if(interval==0){_elements[slot].exetute_time =0xffffffff;}///żeby tylko raz na "cyklu" robić więcej kroków
}
void ZBK_Interval::stop(byte slot)
{
_elements[slot].exetute_time = 0xffffffff-_elements[slot].interval;//ponieważ interval zazwyczaj jest mały to żeby execute był wysoki
_elements[slot].interval = 0;
}
void ZBK_Interval::start(byte slot)
{
_elements[slot].interval = 0xffffffff-_elements[slot].exetute_time;
_elements[slot].exetute_time = millis()+_elements[slot].interval;
}
/*
void ZBK_Interval::setTime(byte slot)
{
_elements[slot].begin_time = millis();
}
*/
void ZBK_Interval::delay(long time)
{
unsigned long exetute_time= millis()+time;
if(exetute_time<time){//przepełnienie execute_time
while((millis()>5000))///mogło by być while((millis()>0)) ale wstawiam 5000 żeby uniknąć zbubienia (
{
update();
}
}
while((millis()<exetute_time))
{
update();
}
}
void ZBK_Interval::update(void)
{
unsigned long actual_time = millis();
unsigned long interval_memory = 0;
for (byte slot=0; slot<_slots; slot++)
{
if(actual_time>=_elements[slot].exetute_time)
{//prawdopodobnie wykonać - trzeba zweryfikować czy przypadkiem exetute_time nie "przeskoczył" granicy
//if(_elements[slot].active==true){}//jeśli funkcja aktywna to nie można uruchomić nowej... (blokada dodana na potrzeby "wielowątkowości"
//else{
if(_elements[slot].interval>0){
if((actual_time-_elements[slot].exetute_time)<0x0fffffff)//skoro różnica nie jest tak duża że prawie na pewno zegar nie "przeskoczył"
{
//_elements[slot].active=true;
_elements[slot].exetute_time = _elements[slot].interval;
interval_memory=_elements[slot].interval;
_elements[slot].interval=0;//wyłączam
_elements[slot].func();
//_elements[slot].active=false;
if(interval_memory==_elements[slot].exetute_time){//na wypadek gdyby ktoś w funkcji zmienił itererval- czyli z poziomu wywołanej funkcji edytował wartość danego slotu
_elements[slot].interval=_elements[slot].exetute_time;//włączam spowrotem
_elements[slot].exetute_time = actual_time+_elements[slot].interval;
}
}
}else{
//if((_elements[slot].exetute_time-_elements[slot].interval)<actual_time){}//skoro execute + interval jest mniejsze to coś się .....
if((actual_time-_elements[slot].exetute_time)<0x0fffffff)//skoro różnica nie jest tak duża że prawie na pewno zegar nie "przeskoczył"
{
if(_elements[slot].interval<0){//wykluczam 0
//_elements[slot].active=true;
_elements[slot].interval=0;//wyłączam
_elements[slot].func();
//_elements[slot].active=false;
if(_elements[slot].interval==0){//na wypadek gdyby ktoś w funkcji zmienił itererval- czyli że ma działać dalej
_elements[slot].exetute_time =0xffffffff;///żeby tylko raz na "cyklu" robić więcej kroków
}
}
}
}
//}
}
}
}