środa, 8 czerwca 2016

Sterowanie bramą wjazdową i garażową z Arduino - errata 1

Gotowy układ sterowania bramami zainstalowany u odbiorcy końcowego działa pięknie ..... tylko się wiesza! Po 24 do 48 h gaśnie żółty led a cały sterownik jest głuchy jak pień. Pomaga ostry reset tzn. wyjęcie wtyczki zasilania. I znowu pięknie mruga przez kilkanaście godzin do kolejnego zwisu. Co jest do cholery. Układ przez miesiąc na stole nie wysypał ani razu a tu na wejściu taki obciach. Jak w akademickim dowcipie. Wiem, że teoretycznie wszystko jest OK a nie działa - w praktyce na stole działa wzorcowo i nie wiem dlaczego - połączenie teorii z praktyką w układzie dla odbiorcy dało wynik oczywisty - nie działa i nie wiem dlaczego!

Na pierwszy ognień poszedł ESP-01 jako najbardziej podejrzany za zawieszanie komunikacji (zgaszony LED!). Jeśli się wiesza to pewnie i zatrzymuje cały program w pierwszej pętli

  while (Blynk.connect() == false) {}   // Wait until Blynk is connected

 Dorabiam więc na szybko reset ESP podpinając jego RST do portu A3 (przy resecie wachdogiem procesora, ESP się nie resetuje) i dodaję na starcie procedurę resetu układu sieciowego.

const int resetesp = A3;
void setup()
{

 pinMode(resetesp, OUTPUT);
 digitalWrite(resetesp, LOW); //reset esp
 delay(2000);
 digitalWrite(resetesp, HIGH);

 delay(2000); //odczekanie na stany przejściowe w ESP
.......... 

To oczywiście nie gwarantuje mi jeszcze niczego. Jeśli zawieszanie jest w trakcie nawiązywania komunikacji w pętli setup() to dobrze byłoby zrobić reset wszystkiego jeśli nie nastąpi połączenie z BLYNK powiedzmy przez minutę lub dwie. Watchdog używany dalej w programie odpada bo maksymalny czas możliwy do ustawienia to 8 sek. Pozostaje pętla programowa

int xx = 0;
int xxold = 0;

const int dzielnik = 1000; //do ustalenia czasu czekania na połączenie BLYNK
 xx = millis() / dzielnik;
 xxold = xx;
  while ((xx - xxold) < 100) { 
    xx = millis() / dzielnik;
    if (Blynk.connect() == true) { //jeśli jest połączenie to wyjdz z pętli
    xx = (xx + 200);
     }
    }
    if (Blynk.connected() == false) {  //jeśli nie ma połączenia to resetuj

    Watchdog.enable(2000);
 }  //koniec - jeśli nie ma połączenia to reset

Jeśli ESP nie nawiąże połączenia w setup() przez 100 sek to program zostanie zresetowany, jeśli straci połączenie w trakcie pracy - zresetuje go watchdog w pętli głównej loop(). Sprawdzimy jak to działa.
..................
NIE DZIAŁA

Jest jeszcze gorzej - program działa do momentu resetu i a chwilę później przestaje dawać jakiekolwiek oznaki życia. To NANO jest w tym momencie głuche jak pień. NIE podnosi się nawet po RESETcie przyciskiem na płytce. Dopiero odłączenie zasilania........  Zaraz zaraz to może nie ESP ale NANO jest winne całego bigosu z wieszaniem. Może biblioteka  #include <Adafruit_SleepyDog.h> szwankuje? Ale przecież pięknie działa na stole w projekcie pompa.

5 min w internecie wyjaśnia wszystko. Winne jest i NANO i biblioteka watchdoga a dokładnie sam fakt odblokowania programowego funkcji watchdog. Problem został opisany na przykładzie Arduino PRO Mini ale jak się okazuje dotyka on także NANO.  Natomiast z UNO działa prawidłowo.
W skrócie problem jest w tym, że reset watchdogiem nie dezaktywuje funkcji watchdog - jest ona wciąż aktywna i co gorsza po resecie ustawiona z krótkim czasem resetu. Bootloader winien zaraz na początku zatrzymać funkcję watchdog ale tego nie robi w wersjach  na MINI i NANO. Należy wgrać poprawiony bootloader by ten błąd usunąć.
Nic z tego - nie będę na razie grzebał w systemie NANO szczególnie, że jest już wlutowane w płytkę - spróbujemy inaczej zresetować procesor.

Sposób 1
Najłatwiej podłączyć jakiś port NANO do pinu RST i ustawić go na "0" w momencie resetu.
Trzeba tylko jak najwcześniej w programie zadeklarować port jako wyjście i ustawić na 1. Ale UWAGA kolejność tych dwu kroków musi być dokładnie taka - odwrotnie NIE DZIAŁA
void setup()
{
digitalWrite(resetnano, HIGH); //no reset nano

pinMode(resetnano, OUTPUT);

Potem już w programie możemy wywoływać reset procesora wpisem 0 na port resetnano.
Wgrałem program i połączyłem port 3 z RST. Działa i resetuje bez problemu tylko trzeba rozwierać to połączenie na moment wgrywania programu bo zawiesza się komunikacja z IDE :(.  A więc ten sposób odpada.

Sposób nr 2
Wymusić skok programu do adresu 0000 czyli rozpocząć program od początku. Jest tylko jeden niuans - taki "reset" nie czyści rejestrów i komórek więc jeśli jakieś zmienne nie są wprost zadeklarowane  z określonymi wartościami na początku programu to mogą dziać się różne rzeczy. Ale nie bardzo mam inne wyjście - więcej sposobów resetu już nie znam.
Deklaruję więc przed sekcją setup() funkcję skoku do adresu 0000

void(* resetFunc) (void) = 0;//declare reset function at address 0

a wywołanie tej funkcji  resetFunc(); //call reset  powinno udawać reset.

DZIAŁA !!!

Oczywiście to proteza by sprawdzić czy układ ruszy i czy pozbędę się tych cholernych wieszań. Docelowo bezwzględnie trzeba będzie wymienić bootloader jeśli chcę używać NANO jako podstawowego modułu do budowy układów sterowania.


I to na razie tyle z pola walki.

cdn...... co akurat w tym przypadku wcale mnie nie cieszy

Brak komentarzy:

Publikowanie komentarza