Your Arduino went offline

For now I use about 16+2 Analog pins and all digital ones of an uno as well as all 32 VP. Already are shot of some (as well as Widget Space). Might also be expanded later…
but the Shift register usage allows for flexible scaling in case I build a bigger one later. So I perfer this over bridging, since I anyway need to etch a pcb later for this.

Just going for a dogwalk and got my ESP-13f in the Mail, so I might test with them later.

Hmmm…
Same if not even more problems with ESP-12F

Probably neet to switch to ESP Standalone…

So how many of those Pins are really available as output for my program Costas?
I saw GPIO 0 and 15 at least cant be used. I also read on some pages GPIO2 has to be + I believe…

Do you know which really can be used?

I’d neet 5 pins for my analog multiplexing and 3 I believe for the 595 shift register right? So there would be 8 without any further consideration.

On the WeMos D1 Mini our main project uses all the pins except GPIO 0, 2 & 15.

On an ESP-07 project we use GPIO 0 as a swtich.

GPIO 2 and 15 need to be tied to ground for flashing but I suspect they can be used in your project.

You can even use the TX pin (GPIO 1) if you are running short of pins but obviously it has to be available for the initial sketch upload.

Ok, thanks, thats what I expected.

You could use GPIO0 as well for what I think since it as well as 15 just have to be pulled at start as far as I know.

So it should work out…

Btw… JUst cant connect to blynk, is there a server problem at the moment?
did work before and can manually connect to other servers.

This is the code which won,'t connect since I added Timer functions yesterday.

I did mark what I added since yesterday with ----->

As soon as I remove this Timer stuff it can connect to Blynk again!

Also this Timer Usage did really use much program and varable memory, no idea why. I belive it was around 20% more than before.

Any Idea? Why do these lines avoid connection?

// #define BLYNK_PRINT Serial                                      // Blynk Debug Messages (muss vor dem Includes kommen) - Auskommentieren wenn nicht mehr gebraucht.
#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>
#include <SimpleTimer.h>

ESP8266 wifi(&Serial);


// ********  VOREINSTELLUNGEN  *****************************************************************************************************************

// ACHTUNG! ESP8266 auf 57600 Baud stellen, für diesen Sketch - Dann gibts scheinbar keine Buffer overflow Fehler!

// WLAN Einstellungen
#define WLANname "****"                                // WLAN Name
#define WLANpw "****"                                       // WLAN Passwort

// Email Einstellungen
#define EMAILto "****"                                  // Email Empfänger für Warn und Error Mails

// Blynk Token
#define authToken "****"            // Blynk Token

// Sonstige Einstellungen
byte shutdowntime = 30;                                         //Zeit(s) bis Pumpe zwangsweise gestoppt wird
//int SensorMin = 10;                                             // Minimale Schwelle Sensor bevor Fehler gemeldet wird
//int SensorMax = 1013;                                           // Maximale Schwelle Sensor bevor Fehler gemeldet wird

// ********  ENDE VOREINSTELLUNGEN  ************************************************************************************************************


// Restliches Setup
// Pumpen
#define pumpWass 6                // Pumpe1 für Wasser (gießen)
#define pumpwd 9                  // Pumpe2 für Wasser zum Düngermix-Tank
#define pumpdueng 10              // Pumpe3 für Dünger
#define pumpDWass 11              // Pumpe4 für Düngerwasser (gießen)

// Select Pins des 4051 Alalog Multiplexer (Sensoren)
#define IC4051S0 2
#define IC4051S1 3
#define IC4051S2 4
#define IC4051ENa 5
#define IC4051ENb 7

// LEDs
#define HWarnLED 12               // Warn LED
#define HErrLED 8                 // Error LED
#define PowWifiLED 13             // Power/Wlan LED (aktiv nachdem Wlan Verbindung erstmalig aufgebaut)

// Analoge Eingänge
#define SensTopf A0               // Feuchtigkeitssensor Töpfe
#define SensWass A1               // Wasserstandssensor Wassertank
#define SensDWass A2              // Wasserstandssensor Düngerwasser Tank
#define SensTemp A3               // Temperatursensor
#define SensLight A4              // Helligkeitssensor

// Error und Warnmeldungen
#define ErrorNr1 "Pflanzen: Fehler Feuchtigkeitsmessung! Dringend handeln! - Pumpen deaktiviert!"
#define ErrorNr2 "Pflanzen: Fehler Wasserstandssmessung! Dringend handeln! - Pumpen deaktiviert!"
#define ErrorNr3 "Pflanzen: Fehler Düngerwassermessung! Dringend handeln! - Pumpen deaktiviert!"
#define ErrorNr4 "Pflanzen: Fehler Pumpen-Timeout! Dringend handeln! - Pumpen deaktiviert!"
#define ErrorNr5 "Pflanzen: Fehler Kalibration notwendig! Dringend handeln! - Pumpen deaktiviert!"

#define WarnNr1 "Pflanzen: Warnung! 30% Wasserstand!"
#define WarnNr2 "Pflanzen: Warnung! 20% Wasserstand!"
#define WarnNr3 "Pflanzen: Warnung! 10% Wasserstand!"
#define WarnNr4 "Pflanzen: Wassertank befüllt!"

// Blynk Widget Pins
// Widget LEDs
#define WidWarnLED V17            // Warn LED setzen
#define WidErrLED V18             // Error LED setzen 

// Programmvariablen
//byte AnzToepfe = 0;             // Topfanzal initialisieren (wird später aus App/EEprom ausgelesen)
int FeuchtigkeitRAW[16] = {};     // Gemessene RAW Werte der Feuchtigkeit aller Töpfe
int FeuchtigkeitMAP[16] = {};     // Gemappte Feuchtigkeit aller Töpfe 0-100%
int FeuchtigkeitCALIB[32] = {};   // Kalibrationswert Feuchtigkeit 0-15 = LOW Werte 16-32 = HIGH Werte
int MoistLowHighRAW[2] = {};      // Niedrigster und höchster RAW Feuchtigkeitswert
int MoistLowHighMAP[2] = {};      // Niedrigster und höchster Gemappter Feuchtigkeitswert 0-100%
int WassCALIB[2] = {};            // Kalibrationswert Sensor Wassertank 0 = Leer 1= Voll
int DuengWassCALIB[2] = {};       // Kalibrationswert Sensor DüngewasserMix 0 = Leer 1= Voll
byte ErrorNr = 0;                 // Fehlerspeicher (wird durch Error Routine gesetzt) 0 = Kein Fehler, 1 = Feuchtigkeit Topf, 2 = Problem Wasserstandsmessung, 3= Wasser leer, 4 = Problem DüngeWasserMix Messung, 5 = Gieß-Timeout
byte WarnNr = 0;                  // Warnungsspeicher (wird durch Warn Routine gesetzt) 0 = Keine Warnung, 1 = Gießwasser 30%, 2 = Gießwasser 20%, 3 = Gießwasser 10%, 4 = Kalibration notwendig, 5 = Wassertank befüllt

// Timer definieren
 ----->  SimpleTimer ErrLEDtimer;
 ----->  int ErrLEDtimerID = 0;
 ----->   SimpleTimer WarnLEDtimer;
 ----->   int WarnLEDtimerID = 0;



// FOR TESTING PURPOSES
// ZUM TESTEN, LÖSCHEN !!!!
byte topf = 0;
byte AnzToepfe = 16;      // ALTEN WIEDER AKTIVIEREN!
int SensorMin = 0;       // ALTEN WIEDER AKTIVIEREN!
int SensorMax = 1023;     // ALTEN WIEDER AKTIVIEREN!
//int FeuchtigkeitRAW[] = {270,400,600,770,270,400,600,770,270,400,600,770,270,400,600,770,}; // TEST !! ALTEN AKTIVIEREN !!!!!!!!!!!!!!!!!
//int FeuchtigkeitCALIB[]= {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800}; // TEST !! ALTEN AKTIVIEREN !!!!!!!!!!!!!!!!!





void ReadWass()
{
  // analogRead(SensWass);
  // Warnung wenn 30,20,10% / Error wenn 0
  // Wenn Wasserstand wieder über 30% weil aufgefüllt wurde, Warnung LED Timer löschen, Error löschen (falls richtige Nummer), Nachricht
}

void ReadDWass()
{
  //  analogRead(SensDWass);
  // Fehler wenn DW Tank keine 100% erreicht
}

void Giessen()
{
  // ***** Routine Gießen oder Düngen (Variable für rythmus in Voreinstellungen setzen und Wert nach Gießen/Düngen in EEprom)
}
void DuengerMix()
{
  // Düngerwasser anmischen
}

void Duengen()
{
  // ***** Routine Gießen oder Düngen (Variable für rythmus in Voreinstellungen setzen und Wert nach Gießen/Düngen in EEprom)
}
void Reset()
{
  // ***** RESET durch App
  // Errorflag im EEprom löschen, danach Reset
}

void CheckCalib()
{
  // Checke Kalibration ob ein Wert = 0
  // Wenn einer gleich = Dann Error5
}

void Calib()
{
  // Am Ende CheckCalib und Error 5 löschen
  // Werte ins EEprom
}

void Error(byte Nr)
{
  // Pumpen deaktivieren
  analogWrite(pumpWass, 0);
  analogWrite(pumpwd, 0);
  analogWrite(pumpdueng, 0);
  analogWrite(pumpDWass, 0);

----->      ErrLEDtimerID = ErrLEDtimer.setInterval(300L, blinkErrLED);           // Error LED Timer setzen
----->      ErrLEDtimer.enable(ErrLEDtimerID);
----->      WarnLEDtimer.disable(WarnLEDtimerID);                  // Warn LED Timer deaktivieren
----->      digitalWrite(HWarnLED, LOW);                           // Hardware Warn LED aus
----->      Blynk.virtualWrite(WidWarnLED, 0);                     // Widget Warn LED aus

  if (ErrorNr != Nr)                                     // Wenn neuer, anderer Fehler aufgetreten
  {
    ErrorNr = Nr;
    // *************** WarnNr ins EEprom schreiben
    if (Nr == 1)
    {
      Blynk.notify(ErrorNr1);
      Blynk.email(EMAILto, ErrorNr1, " ");
    }
    else if (Nr == 2)
    {
      Blynk.notify(ErrorNr2);
      Blynk.email(EMAILto, ErrorNr2, " ");
    }
    else if (Nr == 3)
    {
      Blynk.notify(ErrorNr3);
      Blynk.email(EMAILto, ErrorNr3, " ");
    }
    else if (Nr == 4)
    {
      Blynk.notify(ErrorNr4);
      Blynk.email(EMAILto, ErrorNr4, " ");
    }
    else if (Nr == 4)
    {
      Blynk.notify(ErrorNr4);
      Blynk.email(EMAILto, ErrorNr4, " ");
    }
    //  ***** Error Flag in EEprom setzen (löschbar durch Arduino Reset per App)
  }
  while (1)                                              // Programm stoppen,weiter messen und Error LED blinken lassen
  {
    Blynk.run();
----->        ErrLEDtimer.run();
    MesseToepfe();
    // Messe Wasser
    // Messe Temperatur
    // Messe Licht
    // Wenn Reset zur Resetroutine
  }
}

void Warn(byte Nr)
{
----->      WarnLEDtimerID = WarnLEDtimer.setInterval(800L, blinkWarnLED);          // Warn LED Timer setzen
----->      WarnLEDtimer.enable(WarnLEDtimerID);                                    // Warn LED Timer aktivieren

  if (WarnNr != Nr)                                                       // Wenn neue, andere Warnung aufgetreten
  {
    WarnNr = Nr;
    // *************** WarnNr ins EEprom schreiben
    if (Nr == 1)
    {
      Blynk.notify(WarnNr1);
      Blynk.email(EMAILto, WarnNr1, " ");
    }
    else if (Nr == 2)
    {
      Blynk.notify(WarnNr2);
      Blynk.email(EMAILto, WarnNr2, " ");
    }
    else if (Nr == 3)
    {
      Blynk.notify(WarnNr3);
      Blynk.email(EMAILto, WarnNr3, " ");
    }
    else if (Nr == 4)                                    // Tank aufgefüllt Nachricht senden Warnung zurücksetzen und LED stoppen
    {
      Blynk.notify(WarnNr4);
      Blynk.email(EMAILto, WarnNr4, " ");
----->          WarnNr = 0;
      // ***************** WarnNr im EEprom löschen
----->          WarnLEDtimer.disable(WarnLEDtimerID);              // Warn LED Timer deaktivieren
----->          digitalWrite(HWarnLED, LOW);                       // Hardware Warn LED aus
----->          Blynk.virtualWrite(WidWarnLED, 0);                 // Widget Warn LED aus
    }
  }
}




// FERTIGE FUNKTIONEN


int ReadPot(byte i)     // Misst einzelenen Topf (Topfnummer 1-16 an Funktion übergeben)
{
  if (i > 0 && i <= 16)
  {
    i--;                               // Topf 1-16 in 0-15 wandeln
    i <<= 2;                           // 2 nach links verschieben, damit die Zahl im Register bei Pin 2 beginnt
    byte TopfENb = i & 0b100000;       // Enable Bit B per UND rausfiltern
    TopfENb ^= 0b100000;               // Enable Bit B per XOR invertieren
    TopfENb <<= 2;                     // Enable Bit B 2 nach links damit es auf 7 liegt
    i |= TopfENb;                      // Enable Bit für 4051b hinzufügen
    PORTD = (PORTD & 0b01000011) | i;  // Ports setzen - PORTD per UND mit inv. Maske (Vorhandene Bits löschen), dann mit ODER Bits setzen
    int Wert = analogRead(SensTopf);
    if (Wert >= SensorMin && Wert <= SensorMax)
    {
      return (Wert);
    }
    else
    {
      return (-1);
    }
  }
  else
  {
    return (-1);
  }
}

int MesseToepfe()     // Misst Feuchtigkeit aller Töpfe bis zur angegebenen Anzahlund mappt danach 0-100 via MapPots()
{
  MoistLowHighRAW[0] = 1023;                   // Niedrigsten Wert mit max Wert füllen für Vergleich später
  MoistLowHighRAW[1] = 0;                      // Höchsten Wert mit min Wert füllen für Vergleich später
  for (byte i = 1; i <= AnzToepfe; i++)
  {
    if (ReadPot(i) != -1)
    {
      FeuchtigkeitRAW[i - 1] = ReadPot(i);
      if (FeuchtigkeitRAW[i - 1] < MoistLowHighRAW[0])     // Niedrigsten und höchsten RAW Wert ermitteln
      {
        MoistLowHighRAW[0] = FeuchtigkeitRAW[i - 1];
      }
      if (FeuchtigkeitRAW[i - 1] > MoistLowHighRAW[1])
      {
        MoistLowHighRAW[1] = FeuchtigkeitRAW[i - 1];
      }
      MapPots();
    }
    else
    {
      Error(1);                                // Error Routine Feuchtigkeitsmessung aufrufen (Error 1)
    }
  }
}

void MapPots()        // Map Feuchtigkeit  -- Negative Werte bedeuten trockener als Minimum, über 100 bedeutet feuchter als Maximum
{
  MoistLowHighMAP[0] = 1023;                   // Niedrigsten Wert mit max Wert füllen für Vergleich später
  MoistLowHighMAP[1] = 0;                      // Höchsten Wert mit min Wert füllen für Vergleich später
  for (byte i = 1; i <= AnzToepfe; i++)
  {
    FeuchtigkeitMAP[i - 1] = map(FeuchtigkeitRAW[i - 1], FeuchtigkeitCALIB[i - 1], FeuchtigkeitCALIB[i + 15], 0, 100);
    if (FeuchtigkeitMAP[i - 1] < MoistLowHighMAP[0])     // Niedrigsten und höchsten gemappten Wert ermitteln
    {
      MoistLowHighMAP[0] = FeuchtigkeitMAP[i - 1];
    }
    if (FeuchtigkeitMAP[i - 1] > MoistLowHighMAP[1])
    {
      MoistLowHighMAP[1] = FeuchtigkeitMAP[i - 1];
    }
  }
}

void blinkErrLED()
{
  if (digitalRead(HErrLED) == 1)
  {
    Blynk.virtualWrite(WidErrLED, 0);
    digitalWrite(HErrLED, LOW);
  }
  else
  {
    Blynk.virtualWrite(WidErrLED, 255);
    digitalWrite(HErrLED, HIGH);
  }
}

void blinkWarnLED()
{
  if (digitalRead(HWarnLED) == 1)
  {
    Blynk.virtualWrite(WidWarnLED, 0);
    digitalWrite(HWarnLED, LOW);
  }
  else
  {
    Blynk.virtualWrite(WidWarnLED, 255);
    digitalWrite(HWarnLED, HIGH);
  }
}


void setup()
{
  // Outputs deklarieren   (PWM Pins werden automatisch bei analogWrite() deklariert)
  pinMode(IC4051S0, OUTPUT);
  pinMode(IC4051S1, OUTPUT);
  pinMode(IC4051S2, OUTPUT);
  pinMode(IC4051ENa, OUTPUT);
  pinMode(IC4051ENb, OUTPUT);
  pinMode(PowWifiLED, OUTPUT);
  pinMode(HErrLED, OUTPUT);
  pinMode(HWarnLED, OUTPUT);


  // Ausgänge initialisieren
  analogWrite(pumpWass, 0);
  analogWrite(pumpwd, 0);
  analogWrite(pumpdueng, 0);
  analogWrite(pumpDWass, 0);


  // ***** EEPROM auslesen
  // ***** (Anzahl Töpfe (Erst EEprom, dann App),Dünger-Rhytmus-Counter (Erst EEprom, dann App), ErrorNr und WarnNr Flag, Kalibration Töpfe/Wasser/Düngerwasser)
  // Wenn Errorflag Error Routine aufrufen
  //  digitalWrite(HErrLED, 0);
  //  digitalWrite(HWarnLED, 0);


  // Seriellen Port starten
  Serial.begin(115200);

  // Verbindungsaufbau WLAN
  Blynk.begin(authToken, wifi, WLANname, WLANpw);
  while (Blynk.connect() == false) {}

  digitalWrite(PowWifiLED, HIGH);     // Power / Wifi-LED an (nach erstem Verbindungsaufbau)

----->      if (ErrorNr != 0)                   // Wenn Error vorhanden vor Beginn des Programms zur Error Routine springen
----->      {
----->        Error(ErrorNr);
----->      }
----->      if (WarnNr != 0)                    // Wenn Warnung vorhanden vor Beginn des Programms zur Warn Routine springen
----->      {
----->        Warn(WarnNr);
----->      }
}


void loop()
{
  Blynk.run();
----->      WarnLEDtimer.run();
  // BIS HIER FERTIGE LOOP!



 /*
      // TESTROUTINE RAW MESSWERT TÖPFE
      if (MesseToepfe() != -1)
      {
      Serial.print("Feuchte RAW      ");
      for (byte i = 0; i <= AnzToepfe - 1; i++)
      {
        Serial.print(FeuchtigkeitRAW[i]);
        Serial.print(" ");
      }
      Serial.print("  Low: ");
      Serial.print(MoistLowHighRAW[0]);
      Serial.print("  High: ");
      Serial.print(MoistLowHighRAW[1]);
      Serial.print("\n");
      }
      else
      {
      Serial.print("Error\n");
      Error(1);
      }
      delay(2000);
*/

  /*
      // TESTROUTINE MAPPED MESSWERT TÖPFE
       // MesseToepfe();                            // AUSKOMMENTIEREN wenn Nur Mapping getestet werden soll, enthält MapPots
        MapPots();                                // AUSKOMMENTIEREN wenn Messwert zum Testen gemappt werden soll
        Serial.print("Feuchte GEMAPPED ");
        for (byte i = 0; i <= AnzToepfe - 1; i++)
        {
          Serial.print(FeuchtigkeitMAP[i]);
          Serial.print(" ");
        }
        Serial.print("  Low: ");
        Serial.print(MoistLowHighMAP[0]);
        Serial.print("  High: ");
        Serial.print(MoistLowHighMAP[1]);
        Serial.print("\n");
        delay(2000);

    /*
        // TESTROUTINE MESSWERT TOPF MIT EINGABE
        if (topf == 0)
        {
          // Testeingabe Serieller Monitor
          Serial.println("Topfnummer eingeben:");
          while (Serial.available() == 0);
          topf = Serial.parseInt();
        }
        Serial.print(ReadPot(topf));
        Serial.print("\n");
  */
}

I would say your problems relate to the huge delays you have in the main loop.

4 seconds plus overhead.

I don’t know what you are doing in the loop but I would remove the lot and just leave Blynk.run() and calls to the timer.

That’s just test routines and they are commented out. the main routine is just

Blynk.run()
WarnLEDtimer.run();

nothing else.


Something unrelated to the problem (just so you don’t think I’m totally stupid when you look over the code):

I just saw my stupid [i-1] stuff and changed it now :wink:
Could do that way simpler but didn’t see it…

Have you you tried a basic sketch to see if that goes offline? If it doesn’t then you know there is a problem with your code in the main project.

Sure, with the short code it works most of the time.

But the longer the code the more often it disconnects.

This and the buffer overflow is in my opinion a clear sign there must be a flaw in the library about memory.

This sketch uses over 50% memory and it can’t even connect at all, even there’s just variable definition, connection and the 2 in the main loop.

Anyway, already decided to change to ESP Standalone but I would like to know the reason anyway…

what is this doing ?

this is your code in “magic” code tags:

// #define BLYNK_PRINT Serial                                      // Blynk Debug Messages (muss vor dem Includes kommen) - Auskommentieren wenn nicht mehr gebraucht.
#include &lt;ESP8266_Lib.h&gt;
#include &lt;BlynkSimpleShieldEsp8266.h&gt;
#include &lt;SimpleTimer.h&gt;

ESP8266 wifi(&Serial);


// ********  VOREINSTELLUNGEN  *****************************************************************************************************************

// ACHTUNG! ESP8266 auf 57600 Baud stellen, für diesen Sketch - Dann gibts scheinbar keine Buffer overflow Fehler!

// WLAN Einstellungen
#define WLANname "****"                                // WLAN Name
#define WLANpw "****"                                       // WLAN Passwort

// Email Einstellungen
#define EMAILto "****"                                  // Email Empfänger für Warn und Error Mails

// Blynk Token
#define authToken "****"            // Blynk Token

// Sonstige Einstellungen
byte shutdowntime = 30;                                         //Zeit(s) bis Pumpe zwangsweise gestoppt wird
//int SensorMin = 10;                                             // Minimale Schwelle Sensor bevor Fehler gemeldet wird
//int SensorMax = 1013;                                           // Maximale Schwelle Sensor bevor Fehler gemeldet wird

// ********  ENDE VOREINSTELLUNGEN  ************************************************************************************************************


// Restliches Setup
// Pumpen
#define pumpWass 6                // Pumpe1 für Wasser (gießen)
#define pumpwd 9                  // Pumpe2 für Wasser zum Düngermix-Tank
#define pumpdueng 10              // Pumpe3 für Dünger
#define pumpDWass 11              // Pumpe4 für Düngerwasser (gießen)

// Select Pins des 4051 Alalog Multiplexer (Sensoren)
#define IC4051S0 2
#define IC4051S1 3
#define IC4051S2 4
#define IC4051ENa 5
#define IC4051ENb 7

// LEDs
#define HWarnLED 12               // Warn LED
#define HErrLED 8                 // Error LED
#define PowWifiLED 13             // Power/Wlan LED (aktiv nachdem Wlan Verbindung erstmalig aufgebaut)

// Analoge Eingänge
#define SensTopf A0               // Feuchtigkeitssensor Töpfe
#define SensWass A1               // Wasserstandssensor Wassertank
#define SensDWass A2              // Wasserstandssensor Düngerwasser Tank
#define SensTemp A3               // Temperatursensor
#define SensLight A4              // Helligkeitssensor

// Error und Warnmeldungen
#define ErrorNr1 "Pflanzen: Fehler Feuchtigkeitsmessung! Dringend handeln! - Pumpen deaktiviert!"
#define ErrorNr2 "Pflanzen: Fehler Wasserstandssmessung! Dringend handeln! - Pumpen deaktiviert!"
#define ErrorNr3 "Pflanzen: Fehler Düngerwassermessung! Dringend handeln! - Pumpen deaktiviert!"
#define ErrorNr4 "Pflanzen: Fehler Pumpen-Timeout! Dringend handeln! - Pumpen deaktiviert!"
#define ErrorNr5 "Pflanzen: Fehler Kalibration notwendig! Dringend handeln! - Pumpen deaktiviert!"

#define WarnNr1 "Pflanzen: Warnung! 30% Wasserstand!"
#define WarnNr2 "Pflanzen: Warnung! 20% Wasserstand!"
#define WarnNr3 "Pflanzen: Warnung! 10% Wasserstand!"
#define WarnNr4 "Pflanzen: Wassertank befüllt!"

// Blynk Widget Pins
// Widget LEDs
#define WidWarnLED V17            // Warn LED setzen
#define WidErrLED V18             // Error LED setzen 

// Programmvariablen
//byte AnzToepfe = 0;             // Topfanzal initialisieren (wird später aus App/EEprom ausgelesen)
int FeuchtigkeitRAW[16] = {};     // Gemessene RAW Werte der Feuchtigkeit aller Töpfe
int FeuchtigkeitMAP[16] = {};     // Gemappte Feuchtigkeit aller Töpfe 0-100%
int FeuchtigkeitCALIB[32] = {};   // Kalibrationswert Feuchtigkeit 0-15 = LOW Werte 16-32 = HIGH Werte
int MoistLowHighRAW[2] = {};      // Niedrigster und höchster RAW Feuchtigkeitswert
int MoistLowHighMAP[2] = {};      // Niedrigster und höchster Gemappter Feuchtigkeitswert 0-100%
int WassCALIB[2] = {};            // Kalibrationswert Sensor Wassertank 0 = Leer 1= Voll
int DuengWassCALIB[2] = {};       // Kalibrationswert Sensor DüngewasserMix 0 = Leer 1= Voll
byte ErrorNr = 0;                 // Fehlerspeicher (wird durch Error Routine gesetzt) 0 = Kein Fehler, 1 = Feuchtigkeit Topf, 2 = Problem Wasserstandsmessung, 3= Wasser leer, 4 = Problem DüngeWasserMix Messung, 5 = Gieß-Timeout
byte WarnNr = 0;                  // Warnungsspeicher (wird durch Warn Routine gesetzt) 0 = Keine Warnung, 1 = Gießwasser 30%, 2 = Gießwasser 20%, 3 = Gießwasser 10%, 4 = Kalibration notwendig, 5 = Wassertank befüllt

// Timer definieren
 -----&gt;  SimpleTimer ErrLEDtimer;
 -----&gt;  int ErrLEDtimerID = 0;
 -----&gt;   SimpleTimer WarnLEDtimer;
 -----&gt;   int WarnLEDtimerID = 0;



// FOR TESTING PURPOSES
// ZUM TESTEN, LÖSCHEN !!!!
byte topf = 0;
byte AnzToepfe = 16;      // ALTEN WIEDER AKTIVIEREN!
int SensorMin = 0;       // ALTEN WIEDER AKTIVIEREN!
int SensorMax = 1023;     // ALTEN WIEDER AKTIVIEREN!
//int FeuchtigkeitRAW[] = {270,400,600,770,270,400,600,770,270,400,600,770,270,400,600,770,}; // TEST !! ALTEN AKTIVIEREN !!!!!!!!!!!!!!!!!
//int FeuchtigkeitCALIB[]= {200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800, 800}; // TEST !! ALTEN AKTIVIEREN !!!!!!!!!!!!!!!!!





void ReadWass()
{
  // analogRead(SensWass);
  // Warnung wenn 30,20,10% / Error wenn 0
  // Wenn Wasserstand wieder über 30% weil aufgefüllt wurde, Warnung LED Timer löschen, Error löschen (falls richtige Nummer), Nachricht
}

void ReadDWass()
{
  //  analogRead(SensDWass);
  // Fehler wenn DW Tank keine 100% erreicht
}

void Giessen()
{
  // ***** Routine Gießen oder Düngen (Variable für rythmus in Voreinstellungen setzen und Wert nach Gießen/Düngen in EEprom)
}
void DuengerMix()
{
  // Düngerwasser anmischen
}

void Duengen()
{
  // ***** Routine Gießen oder Düngen (Variable für rythmus in Voreinstellungen setzen und Wert nach Gießen/Düngen in EEprom)
}
void Reset()
{
  // ***** RESET durch App
  // Errorflag im EEprom löschen, danach Reset
}

void CheckCalib()
{
  // Checke Kalibration ob ein Wert = 0
  // Wenn einer gleich = Dann Error5
}

void Calib()
{
  // Am Ende CheckCalib und Error 5 löschen
  // Werte ins EEprom
}

void Error(byte Nr)
{
  // Pumpen deaktivieren
  analogWrite(pumpWass, 0);
  analogWrite(pumpwd, 0);
  analogWrite(pumpdueng, 0);
  analogWrite(pumpDWass, 0);

-----&gt;      ErrLEDtimerID = ErrLEDtimer.setInterval(300L, blinkErrLED);           // Error LED Timer setzen
-----&gt;      ErrLEDtimer.enable(ErrLEDtimerID);
-----&gt;      WarnLEDtimer.disable(WarnLEDtimerID);                  // Warn LED Timer deaktivieren
-----&gt;      digitalWrite(HWarnLED, LOW);                           // Hardware Warn LED aus
-----&gt;      Blynk.virtualWrite(WidWarnLED, 0);                     // Widget Warn LED aus

  if (ErrorNr != Nr)                                     // Wenn neuer, anderer Fehler aufgetreten
  {
    ErrorNr = Nr;
    // *************** WarnNr ins EEprom schreiben
    if (Nr == 1)
    {
      Blynk.notify(ErrorNr1);
      Blynk.email(EMAILto, ErrorNr1, " ");
    }
    else if (Nr == 2)
    {
      Blynk.notify(ErrorNr2);
      Blynk.email(EMAILto, ErrorNr2, " ");
    }
    else if (Nr == 3)
    {
      Blynk.notify(ErrorNr3);
      Blynk.email(EMAILto, ErrorNr3, " ");
    }
    else if (Nr == 4)
    {
      Blynk.notify(ErrorNr4);
      Blynk.email(EMAILto, ErrorNr4, " ");
    }
    else if (Nr == 4)
    {
      Blynk.notify(ErrorNr4);
      Blynk.email(EMAILto, ErrorNr4, " ");
    }
    //  ***** Error Flag in EEprom setzen (löschbar durch Arduino Reset per App)
  }
  while (1)                                              // Programm stoppen,weiter messen und Error LED blinken lassen
  {
    Blynk.run();
-----&gt;        ErrLEDtimer.run();
    MesseToepfe();
    // Messe Wasser
    // Messe Temperatur
    // Messe Licht
    // Wenn Reset zur Resetroutine
  }
}

void Warn(byte Nr)
{
-----&gt;      WarnLEDtimerID = WarnLEDtimer.setInterval(800L, blinkWarnLED);          // Warn LED Timer setzen
-----&gt;      WarnLEDtimer.enable(WarnLEDtimerID);                                    // Warn LED Timer aktivieren

  if (WarnNr != Nr)                                                       // Wenn neue, andere Warnung aufgetreten
  {
    WarnNr = Nr;
    // *************** WarnNr ins EEprom schreiben
    if (Nr == 1)
    {
      Blynk.notify(WarnNr1);
      Blynk.email(EMAILto, WarnNr1, " ");
    }
    else if (Nr == 2)
    {
      Blynk.notify(WarnNr2);
      Blynk.email(EMAILto, WarnNr2, " ");
    }
    else if (Nr == 3)
    {
      Blynk.notify(WarnNr3);
      Blynk.email(EMAILto, WarnNr3, " ");
    }
    else if (Nr == 4)                                    // Tank aufgefüllt Nachricht senden Warnung zurücksetzen und LED stoppen
    {
      Blynk.notify(WarnNr4);
      Blynk.email(EMAILto, WarnNr4, " ");
-----&gt;          WarnNr = 0;
      // ***************** WarnNr im EEprom löschen
-----&gt;          WarnLEDtimer.disable(WarnLEDtimerID);              // Warn LED Timer deaktivieren
-----&gt;          digitalWrite(HWarnLED, LOW);                       // Hardware Warn LED aus
-----&gt;          Blynk.virtualWrite(WidWarnLED, 0);                 // Widget Warn LED aus
    }
  }
}




// FERTIGE FUNKTIONEN


int ReadPot(byte i)     // Misst einzelenen Topf (Topfnummer 1-16 an Funktion übergeben)
{
  if (i &gt; 0 && i &lt;= 16)
  {
    i--;                               // Topf 1-16 in 0-15 wandeln
    i &lt;&lt;= 2;                           // 2 nach links verschieben, damit die Zahl im Register bei Pin 2 beginnt
    byte TopfENb = i & 0b100000;       // Enable Bit B per UND rausfiltern
    TopfENb ^= 0b100000;               // Enable Bit B per XOR invertieren
    TopfENb &lt;&lt;= 2;                     // Enable Bit B 2 nach links damit es auf 7 liegt
    i |= TopfENb;                      // Enable Bit für 4051b hinzufügen
    PORTD = (PORTD & 0b01000011) | i;  // Ports setzen - PORTD per UND mit inv. Maske (Vorhandene Bits löschen), dann mit ODER Bits setzen
    int Wert = analogRead(SensTopf);
    if (Wert &gt;= SensorMin && Wert &lt;= SensorMax)
    {
      return (Wert);
    }
    else
    {
      return (-1);
    }
  }
  else
  {
    return (-1);
  }
}

int MesseToepfe()     // Misst Feuchtigkeit aller Töpfe bis zur angegebenen Anzahlund mappt danach 0-100 via MapPots()
{
  MoistLowHighRAW[0] = 1023;                   // Niedrigsten Wert mit max Wert füllen für Vergleich später
  MoistLowHighRAW[1] = 0;                      // Höchsten Wert mit min Wert füllen für Vergleich später
  for (byte i = 1; i &lt;= AnzToepfe; i++)
  {
    if (ReadPot(i) != -1)
    {
      FeuchtigkeitRAW[i - 1] = ReadPot(i);
      if (FeuchtigkeitRAW[i - 1] &lt; MoistLowHighRAW[0])     // Niedrigsten und höchsten RAW Wert ermitteln
      {
        MoistLowHighRAW[0] = FeuchtigkeitRAW[i - 1];
      }
      if (FeuchtigkeitRAW[i - 1] &gt; MoistLowHighRAW[1])
      {
        MoistLowHighRAW[1] = FeuchtigkeitRAW[i - 1];
      }
      MapPots();
    }
    else
    {
      Error(1);                                // Error Routine Feuchtigkeitsmessung aufrufen (Error 1)
    }
  }
}

void MapPots()        // Map Feuchtigkeit  -- Negative Werte bedeuten trockener als Minimum, über 100 bedeutet feuchter als Maximum
{
  MoistLowHighMAP[0] = 1023;                   // Niedrigsten Wert mit max Wert füllen für Vergleich später
  MoistLowHighMAP[1] = 0;                      // Höchsten Wert mit min Wert füllen für Vergleich später
  for (byte i = 1; i &lt;= AnzToepfe; i++)
  {
    FeuchtigkeitMAP[i - 1] = map(FeuchtigkeitRAW[i - 1], FeuchtigkeitCALIB[i - 1], FeuchtigkeitCALIB[i + 15], 0, 100);
    if (FeuchtigkeitMAP[i - 1] &lt; MoistLowHighMAP[0])     // Niedrigsten und höchsten gemappten Wert ermitteln
    {
      MoistLowHighMAP[0] = FeuchtigkeitMAP[i - 1];
    }
    if (FeuchtigkeitMAP[i - 1] &gt; MoistLowHighMAP[1])
    {
      MoistLowHighMAP[1] = FeuchtigkeitMAP[i - 1];
    }
  }
}

void blinkErrLED()
{
  if (digitalRead(HErrLED) == 1)
  {
    Blynk.virtualWrite(WidErrLED, 0);
    digitalWrite(HErrLED, LOW);
  }
  else
  {
    Blynk.virtualWrite(WidErrLED, 255);
    digitalWrite(HErrLED, HIGH);
  }
}

void blinkWarnLED()
{
  if (digitalRead(HWarnLED) == 1)
  {
    Blynk.virtualWrite(WidWarnLED, 0);
    digitalWrite(HWarnLED, LOW);
  }
  else
  {
    Blynk.virtualWrite(WidWarnLED, 255);
    digitalWrite(HWarnLED, HIGH);
  }
}


void setup()
{
  // Outputs deklarieren   (PWM Pins werden automatisch bei analogWrite() deklariert)
  pinMode(IC4051S0, OUTPUT);
  pinMode(IC4051S1, OUTPUT);
  pinMode(IC4051S2, OUTPUT);
  pinMode(IC4051ENa, OUTPUT);
  pinMode(IC4051ENb, OUTPUT);
  pinMode(PowWifiLED, OUTPUT);
  pinMode(HErrLED, OUTPUT);
  pinMode(HWarnLED, OUTPUT);


  // Ausgänge initialisieren
  analogWrite(pumpWass, 0);
  analogWrite(pumpwd, 0);
  analogWrite(pumpdueng, 0);
  analogWrite(pumpDWass, 0);


  // ***** EEPROM auslesen
  // ***** (Anzahl Töpfe (Erst EEprom, dann App),Dünger-Rhytmus-Counter (Erst EEprom, dann App), ErrorNr und WarnNr Flag, Kalibration Töpfe/Wasser/Düngerwasser)
  // Wenn Errorflag Error Routine aufrufen
  //  digitalWrite(HErrLED, 0);
  //  digitalWrite(HWarnLED, 0);


  // Seriellen Port starten
  Serial.begin(115200);

  // Verbindungsaufbau WLAN
  Blynk.begin(authToken, wifi, WLANname, WLANpw);
  while (Blynk.connect() == false) {}

  digitalWrite(PowWifiLED, HIGH);     // Power / Wifi-LED an (nach erstem Verbindungsaufbau)

-----&gt;      if (ErrorNr != 0)                   // Wenn Error vorhanden vor Beginn des Programms zur Error Routine springen
-----&gt;      {
-----&gt;        Error(ErrorNr);
-----&gt;      }
-----&gt;      if (WarnNr != 0)                    // Wenn Warnung vorhanden vor Beginn des Programms zur Warn Routine springen
-----&gt;      {
-----&gt;        Warn(WarnNr);
-----&gt;      }
}


void loop()
{
  Blynk.run();
-----&gt;      WarnLEDtimer.run();
  // BIS HIER FERTIGE LOOP!



 /*
      // TESTROUTINE RAW MESSWERT TÖPFE
      if (MesseToepfe() != -1)
      {
      Serial.print("Feuchte RAW      ");
      for (byte i = 0; i &lt;= AnzToepfe - 1; i++)
      {
        Serial.print(FeuchtigkeitRAW[i]);
        Serial.print(" ");
      }
      Serial.print("  Low: ");
      Serial.print(MoistLowHighRAW[0]);
      Serial.print("  High: ");
      Serial.print(MoistLowHighRAW[1]);
      Serial.print("\n");
      }
      else
      {
      Serial.print("Error\n");
      Error(1);
      }
      delay(2000);
*/

  /*
      // TESTROUTINE MAPPED MESSWERT TÖPFE
       // MesseToepfe();                            // AUSKOMMENTIEREN wenn Nur Mapping getestet werden soll, enthält MapPots
        MapPots();                                // AUSKOMMENTIEREN wenn Messwert zum Testen gemappt werden soll
        Serial.print("Feuchte GEMAPPED ");
        for (byte i = 0; i &lt;= AnzToepfe - 1; i++)
        {
          Serial.print(FeuchtigkeitMAP[i]);
          Serial.print(" ");
        }
        Serial.print("  Low: ");
        Serial.print(MoistLowHighMAP[0]);
        Serial.print("  High: ");
        Serial.print(MoistLowHighMAP[1]);
        Serial.print("\n");
        delay(2000);

    /*
        // TESTROUTINE MESSWERT TOPF MIT EINGABE
        if (topf == 0)
        {
          // Testeingabe Serieller Monitor
          Serial.println("Topfnummer eingeben:");
          while (Serial.available() == 0);
          topf = Serial.parseInt();
        }
        Serial.print(ReadPot(topf));
        Serial.print("\n");
  */
}
1 Like

Magic code tags?

The Line dies run the Warning LED Timer once set.
Its doing nothing now since the timer is sez in the warning routine which isn’t called

So what do you want to tell me?
I still don’t understand your sentence

Ahhh… Ok uf I press code 3 times it gets highlighted you do mean that?

Thanks, didn’t know

Makes it easier to read :slight_smile:

@Gorkde are you using the correct basic sketch for your hardware?

This is the example provided by Blynk for Arduinos with ESP shield, specifically the Uno with just one hardware serial port. It does recommend using hard serial but I’m not sure that is still available from the latest Blynk examples provided in the Arduino IDE:

/**************************************************************
 
 * This example shows how to use ESP8266 Shield via  to connect your project to Blynk.
 *
 * Note: Ensure a stable serial connection to ESP8266!
 *       Firmware version 1.0.0 (AT v0.22) is needed.
 *       You can change ESP baud rate. Connect to AT console and call:
 *           AT+UART_DEF=9600,8,1,0,0
 *       In general, Soft Serial may be unstable.
 *       It is highly recommended to switch to Hard Serial.
 *
 * Change WiFi ssid, pass, and Blynk auth token to run :)
 * Feel free to apply it to any other example. It's simple!
 *
 **************************************************************/

#define BLYNK_PRINT Serial    // Comment this out to disable prints and save space
#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "YourAuthToken";


// Hardware Serial on Mega, Leonardo, Micro...
//#define EspSerial Serial1

// or Software Serial on Uno, Nano...
#include <SoftwareSerial.h>
SoftwareSerial EspSerial(2, 3); // RX, TX

// Your ESP8266 baud rate:
#define ESP8266_BAUD 9600

ESP8266 wifi(&EspSerial);

void setup()
{
  // Set console baud rate
  Serial.begin(9600);
  delay(10);
  // Set ESP8266 baud rate
  EspSerial.begin(ESP8266_BAUD);
  delay(10);

  Blynk.begin(auth, wifi, "ssid", "pass");
}

void loop()
{
  Blynk.run();
}

You really need to get this running ALL the time, not most of the time, before moving on to an actual project. I know you plan to move to standalone but if you want to know what your problems are with ESP as a shield you should take a step back.

Things to note in the sketch. The version of the AT firmware is IMPORTANT.

Baud rates are IMPORTANT and it is recommended to stick with 9600 for testing purposes.

If I was able to get this working I would then add SimpleTimer to Blink an LED and then move on to do a real project.

1 Like

With basic sketch it worked for over half an hour without disconnect but sometimes it disconnects one time after another even with this.

I dit try to update the ESP-14 but couldn’t I believe it had 0.20 Firmware and the ESP-12F has 0.40 Firmware. I didn’t see you need an old Firmware until now. I did assume my FW is too old.

That could be the reason maybe but since I’m running out of time I think I’ll switch now, maybe I’ll try later since I’ll keep my test Board and build another on another breadboard anyway.

But why do we need old firmware to get it working?
Hasn’t the Blynk library not been updated for that long?

Sounds like the Uno with ESP wasn’t running that well then.

How did you power the ESP as the Uno has enough power to flash an ESP but not enough for the ESP to operate in running mode?

I was never sure about the AT firmware, sometimes I thought Blynk meant you must have at least version 0.22 but I believe the references to it meant exactly version 0.22.

I did power it by an external 3.3V voltage regulator which was connected to an additional power source.