Mähen nur jeden 2ten Tag?

Diskutiere Mähen nur jeden 2ten Tag? im Yardforce Forum im Bereich Mähroboter; Hallo, danke an Thorsten für die tolle Beschreibung der Shelly-Installation am Ferrex R800 Mähroboter. ich habe den Shelly dort eingebaut weil...
  • Mähen nur jeden 2ten Tag? Beitrag #181
H

huels4

Dabei seit
21.04.2021
Beiträge
3
Likes
0
Hallo,
Da ich noch einen Shelly rumliegen hatte, habe ich mich gestern an den Einbau gemacht. Zunächst bin ich genauso vorgegangen wie Du. + und - habe ich mir von der Hauptplatine unter dem Bedienfeld geholt. Die beiden Drähte lassen sich ohne Probleme durch die Gummitülle fädeln, wo auch der normale Kabelstrang vom Regensensor, Ladekabel, etc. von vorne ( Regensensor, Ladekontakte, Induktionsspulen) nach hinten zum Bedienfeld geht. Als + für den Shelly habe ich das Gelbe Kabel am Stecker der Hauptplatine genommen. -dieser ist ein geschaltetes +. Hat den Vorteil, dass der Shelly immer aktiv ist wenn der Robbi über den Hauptschalter eingeschaltet ist. (Somit kann ich mähen auch unterbrechen wenn er nicht in der Ladestation steht).
Alternativ könnte man den Shelly auch über das Blaue und Braune Kabel anschließen, dann bekommt der Shelly aber nur Strom wenn er in der LS steht. Suboptimal, finde ich. Letzte Möglichkeit wäre noch den Shelly am Akku direkt anzuschließen, das würde aber bedeuten, dass der Shelly den Akku belastet, unabhängig davon ob der Hauptschalter aus ist, oder der Robbi in der LS steht. Das birgt die Gefahr dass der Shelly den Akku im Winter leer saugt, obwohl der Hauptschlalter ausgeschaltet ist :)
Den Regensensor habe ich am Shelly genauso wie Du angeschlossen. Einfach parallel. Ohne Gehäuse des Shelly passt der Shelly prima vorne in die kleine Box, wo die Anschlüsse des Regensensors sind. :) Fand ich etwas eleganter als Deine Lösung, den Shelly auf die Box mit Tape zu kleben. Somit kommen nämlich nur 2 zusätzliche Kabel ( +/-) in die Box.

Jetzt kommt aber ein großes ABER!!!!

Montiert man den Shelly in der Box, schließt alles korrekt an und baut alles zusammen meldet der Robbi einen Fehler. Die W-Lan Leute des Robbi leuchtet DAUERHAFT Rot und der Robbi erkennt kein Begrenzungsfeld. Diese Fehlerbeschreibung ( W-Lan LED leuchtet Dauerhaft Rot) gibt es in der Bedienungsanleitung eigentlich nicht.
Ich vermute, dass es zu Interferenzen zwischen Shellly und Induktionsspulen kommt, wenn dieser zu nah an der Platine für den Regensensor und den Induktionsspulen sitzt.

Lösung:
Den Robbi nochmals aufgemmacht. Shelly wieder ausgebaut. Die beiden Drähte, die vorher als +/- von der Hauptplatine zum Shelly als Spannungsversorgung gezogen hatte, an parallel an die Kabel des Regensensors angeschlossen. Somit habe ich das Signal für den Sensor nun auch hinten unter dem Bedienfeld. Dann den Shelly hinten unter das Bedienfeld gepackt ( Da passt er auch mit Gehäuse rein) . Dort die beiden Kabel an I/O des Shelly angeschlossen und den Shelly mit dem Gelben und dem Schwarzen Kabel des Steckers (POWER) verbunden, der auf die Hauptplatine geht. Und Voila.... Alles geht wie es soll.
Beim Shelly ist es noch wichtig in der App "Toggle Switch" zu wählen, also Kippschalter An/Aus.
Und man muss drauf achten dass der Standardmodus auf "Power-Off" steht. Das heißt wenn ich den Robbi über den Hauptschalter aus und wieder einschalte, gauckelt der Shelly dem Robbi kein Regen vor. Erst wenn ich den Shelly über die App schalte ( Shclater in der App leuchtet Blau) schalte, denkt der Robbi es regnet und fährt in die LS wenn er gerade mäht. Oder er bleibt eben in der LS wenn er nicht mähen soll.

Jetzt muss ich nur noch den Weekly Timer richtig einstellen, damit der Robbi eben nur dann mäht weann er soll.

Gruß Thorsten
Hallo,
danke an Thorsten für die tolle Beschreibung der Shelly-Installation am Ferrex R800 Mähroboter. ich habe den Shelly dort eingebaut weil unser Rasen einfach zu klein ist (ca. 200 qm) für 4 Std. mähen. Nach dem 2. Versuch ist es mir auch gelungen ihn z.B. nur 1 Std. mähen zu lassen. Ich hatte den Shelly auch vorne installiert. Da fand er das Begrenzungssignal nicht. Jetzt sitzt er hinten und es klappt. Der Shelly läuft übrigen mit Tasmota.
Gruß Jürgen
 
  • Mähen nur jeden 2ten Tag? Beitrag #182
J

Jojo66

Dabei seit
20.05.2019
Beiträge
2
Likes
0
Ich hatte ein paar Problemen mit der Stabilität der WLAN-Verbindung und dem Autoconnect. Deshalb habe ich dann doch mal mehr Aufwand getrieben und jetzt eine stabile Lösung mit der ich sehr zufrieden bin.
Code:
#include <Arduino.h>

//#include <ESP_WiFiManager.h>              //https://github.com/khoih-prog/ESP_WiFiManager
#define NDEBUG
#include "debuglog.h"
#include "autoconnect.h"
#include <ArduinoOTA.h>
#include <PubSubClient.h>

const char *mqtt_server = "littlezero.fritz.box";
const unsigned long status_interval = 30000; //Statusmeldung alle x millisekunden;
const unsigned long wlan_check_interval = 10000;  //check_WLAN alle x millisekunden;


//LED-PINs:
const int LED_SIGNAL_PIN = 5; //WANNENSTECKER (40pol) PIN5 (Anzeige Schleifensignal vorhanden)
const int LED_AKKU_PIN = 16;  //WANNENSTECKER (40pol) PIN6 (Anzeige Akku schwach)
const int LED_HEBEN_PIN = 17; //WANNENSTECKER (40pol) PIN3 (Anzeige Hebensensor Mäher)
const int LED_LADEN_PIN = 19; //WANNENSTECKER (40pol) PIN7 (Anzeige Akku lädt "blinken", Akku voll "dauernd")
const int LED_SPERR_PIN = 26; //WANNENSTECKER (40pol) PIN16 (Anzeige Mäher gesperrt, "Schlosssymbol")
//Transistor-PINs:
const int HOME_PIN = 13;  //Transistor zur Überbrückung Taster "HOME" am Mäher, WANNENSTECKER (40pol) PIN29
const int START_PIN = 14; //Transistor zur Überbrückung Taster "START" am Mäher, WANNENSTECKER (40pol) PIN22
const int STOP_PIN = 15;  //Relais zur Unterbrechung der Verbindungsleitung zu STOP-Schaltern am Mäher (Simulation Durck auf STOP-Taste)
const int H_PIN = 32;     //Transistor zur Überbrückung Taster "4H" am Mäher (Mähzeit 4 Stunden), WANNENSTECKER (40pol) PIN11
const int SPERR_PIN = 33; //Transistor zur Überbrückung Taster "SCHLOSS" am Mäher (Sperren), WANNENSTECKER (40pol) PIN25
//Optokoppler-PIN:
const int STATION_PIN = 34; //Docking in Ladestation (Präsenz) durch Optokoppler CNY17-3


String topic_prefix;
bool state_led_heben = 0;
bool state_led_akku = 0;
bool state_led_signal = 0;
bool state_led_sperr = 0;
bool state_led_laden = 0;
bool state_station = 0;
bool last_state_led_heben = 0;
bool last_state_led_akku = 0;
bool last_state_led_signal = 0;
bool last_state_led_sperr = 0;
bool last_state_led_laden = 0;
bool last_state_station = 0;

bool state_btn_home = 0;
bool state_btn_start = 0;
bool state_sw_stop = 0;
bool state_btn_h = 0;
bool state_btn_sperr = 0;

bool initialization = 0;

bool send_status = 0;
unsigned long last_status = 0;
unsigned long last_check_wlan = 0;


WiFiClient espClient;
PubSubClient client(espClient);

void callback(char *topic, byte *payload, unsigned int length)
{
  DEBPrint("Message arrived [");
  DEBPrint(topic);
  DEBPrint("] ");
  String str_payload = "";
  for (int i = 0; i < length; i++)
  {
    str_payload += (char)payload[i];
  }
  DEBPrintln(str_payload);
  DEBPrintln(String(topic).substring(topic_prefix.length() + 1));
  if ((topic_prefix + String("/getstatus")).equals(String(topic)))
  {
    send_status = true;
  }
  if ((str_payload.length() == 1) && ((str_payload == "0") || (str_payload == "1")))
  {
    if ((topic_prefix + String("/home_pin")).equals(String(topic)))
    {
      state_btn_home = (str_payload == "0" ? false : true);
      digitalWrite(HOME_PIN, state_btn_home);
      DEBPrint(topic_prefix);DEBPrint(topic);DEBPrint("\t= ");DEBPrintln(str_payload);
    }
    if ((topic_prefix + String("/start_pin")).equals(String(topic)))
    {
      state_btn_start = (str_payload == "0" ? false : true);
      digitalWrite(START_PIN, state_btn_start);
      DEBPrint(topic_prefix);DEBPrint(topic);DEBPrint("\t= ");DEBPrintln(str_payload);
    }
    if ((topic_prefix + String("/stop_pin")).equals(String(topic)))
    {
      state_sw_stop = (str_payload == "0" ? false : true);
      digitalWrite(STOP_PIN, state_sw_stop);
      DEBPrint(topic_prefix);DEBPrint(topic);DEBPrint("\t= ");DEBPrintln(str_payload);
    }
    if ((topic_prefix + String("/4h_pin")).equals(String(topic)))
    {
      state_btn_h = (str_payload == "0" ? false : true);
      digitalWrite(H_PIN, state_btn_h);
      DEBPrint(topic_prefix);DEBPrint(topic);DEBPrint("\t= ");DEBPrintln(str_payload);
    }
    if ((topic_prefix + String("/sperr_pin")).equals(String(topic)))
    {
      state_btn_sperr = (str_payload == "0" ? false : true);
      digitalWrite(SPERR_PIN, state_btn_sperr);
      DEBPrint(topic_prefix);DEBPrint(topic);DEBPrint("\t= ");DEBPrintln(str_payload);
    }
  }
}

void reconnect()
{
  // Loop until we're reconnected
  uint8_t cnt_tries = 0;
  while (!client.connected())
  {
    DEBPrint("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "Maehroboter-";
    clientId += String(random(0xffff), HEX);
    clientId += String(uint32_t(ESP.getEfuseMac()), HEX);
    clientId += String(uint32_t(ESP.getEfuseMac() >> 32), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str()))
    {
      String topic = topic_prefix;
      topic += "/online";
      DEBPrintln("connected");
      // Once connected, publish an announcement...
      client.publish(topic.c_str(), "true");
      // ... and resubscribe
      topic = topic_prefix;
      topic += "/home_pin";
      client.subscribe(topic.c_str());
      topic = topic_prefix;
      topic += "/start_pin";
      client.subscribe(topic.c_str());
      topic = topic_prefix;
      topic += "/stop_pin";
      client.subscribe(topic.c_str());
      topic = topic_prefix;
      topic += "/4h_pin";
      client.subscribe(topic.c_str());
      topic = topic_prefix;
      topic += "/sperr_pin";
      client.subscribe(topic.c_str());
      topic = topic_prefix;
      topic += "/getstatus";
      client.subscribe(topic.c_str());
    }
    else
    {
      DEBPrint("failed, rc=");
      DEBPrint(client.state());
      DEBPrintln(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      cnt_tries++;
      if (cnt_tries>10) {
#if ESP8266      
        ESP.reset();
#else
        ESP.restart();
#endif     
       }
      delay(5000);
    }
  }
}

void read_leds()
{
  last_state_led_akku = state_led_akku;
  last_state_led_heben = state_led_heben;
  last_state_led_laden = state_led_laden;
  last_state_led_signal = state_led_signal;
  last_state_led_sperr = state_led_sperr;
  last_state_station = state_station;
  state_led_akku = digitalRead(LED_AKKU_PIN);
  state_led_heben = digitalRead(LED_HEBEN_PIN);
  state_led_laden = digitalRead(LED_LADEN_PIN);
  state_led_signal = digitalRead(LED_SIGNAL_PIN);
  state_led_sperr = digitalRead(LED_SPERR_PIN);
  state_station = !digitalRead(STATION_PIN);
}

void writeoutputs()
{
  digitalWrite(HOME_PIN, state_btn_home);
  digitalWrite(START_PIN, state_btn_start);
  digitalWrite(STOP_PIN, state_sw_stop);
  digitalWrite(H_PIN, state_btn_h);
  digitalWrite(SPERR_PIN, state_btn_sperr);
}

void states2mqtt()
{
  String topic;
  String value;
  if ((last_state_led_akku != state_led_akku) || initialization)
  {
    topic = topic_prefix + "/led_akku";
    value = state_led_akku ? "1" : "0";
    client.publish(topic.c_str(), value.c_str());
    DEBPrint(topic);
    DEBPrint("\t= ");
    DEBPrintln(value);
  }
  if ((last_state_led_heben != state_led_heben) || initialization)
  {
    topic = topic_prefix + "/led_heben";
    value = state_led_heben ? "1" : "0";
    client.publish(topic.c_str(), value.c_str());
    DEBPrint(topic);
    DEBPrint("\t= ");
    DEBPrintln(value);
  }
  if ((last_state_led_laden != state_led_laden) || initialization)
  {
    topic = topic_prefix + "/led_laden";
    value = state_led_laden ? "1" : "0";
    client.publish(topic.c_str(), value.c_str());
    DEBPrint(topic);
    DEBPrint("\t= ");
    DEBPrintln(value);
  }
  if ((last_state_led_signal != state_led_signal) || initialization)
  {
    topic = topic_prefix + "/led_signal";
    value = state_led_signal ? "1" : "0";
    client.publish(topic.c_str(), value.c_str());
    DEBPrint(topic);
    DEBPrint("\t= ");
    DEBPrintln(value);
  }
  if ((last_state_led_sperr != state_led_sperr) || initialization)
  {
    topic = topic_prefix + "/led_sperr";
    value = state_led_sperr ? "1" : "0";
    client.publish(topic.c_str(), value.c_str());
    DEBPrint(topic);
    DEBPrint("\t= ");
    DEBPrintln(value);
  }
  if ((last_state_station != state_station) || initialization)
  {
    topic = topic_prefix + "/station";
    value = state_station ? "1" : "0";
    client.publish(topic.c_str(), value.c_str());
    DEBPrint(topic);
    DEBPrint("\t= ");
    DEBPrintln(value);
  }
  initialization = false;
}
/*
typedef struct
{
  bool state_btn_home;
  bool state_btn_start;
  bool state_sw_stop;
  bool state_btn_h;
  bool state_btn_sperr;
} Status_rec;
Status_rec status_rec;

#define  STATUS_FILENAME              F("/laststatus.dat")

void save_status()
{
  File file = FileFS.open(STATUS_FILENAME, "w");
  if (file)
  {
    file.write((uint8_t*) &status_rec, sizeof(status_rec));
    file.close();
  }
}

bool load_status()
{
  File file = FileFS.open(STATUS_FILENAME, "r");

  memset((void *) &status_rec,       0, sizeof(status_rec));

  if (file)
  {
    file.readBytes((char *) &status_rec,   sizeof(status_rec));
    file.close();
    return true;
  }
  else
  {
    return false;
  }
}
*/

void sendstatus()
{
  if (send_status){
    send_status = false;
/*
    status_rec.state_btn_home   = state_btn_home;
    status_rec.state_btn_start  = state_btn_start;
    status_rec.state_sw_stop    = state_sw_stop;
    status_rec.state_btn_h      = state_btn_h;
    status_rec.state_btn_sperr  = state_btn_sperr;
    save_status();
*/
    last_status = millis();
    String payload = "{";
    payload += "\"home_pin\":";
    payload += String(state_btn_home);
    payload += ",";
    payload += "\"start_pin\":";
    payload += String(state_btn_start);
    payload += ",";
    payload += "\"stop_pin\":";
    payload += String(state_sw_stop);
    payload += ",";
    payload += "\"4h_pin\":";
    payload += String(state_btn_h);
    payload += ",";
    payload += "\"sperr_pin\":";
    payload += String(state_btn_sperr);
    payload += ",";
    payload += "\"led_akku\":";
    payload += String(state_led_akku);
    payload += ",";
    payload += "\"led_heben\":";
    payload += String(state_led_heben);
    payload += ",";
    payload += "\"led_laden\":";
    payload += String(state_led_laden);
    payload += ",";
    payload += "\"led_signal\":";
    payload += String(state_led_signal);
    payload += ",";
    payload += "\"led_sperr\":";
    payload += String(state_led_sperr);
    payload += ",";
    payload += "\"station\":";
    payload += String(state_station);
    payload += ",";
    payload += "\"initialization\":";
    payload += String(initialization);
    payload += "}";
    String topic = topic_prefix;
    topic += "/status";
    client.publish(topic.c_str(),payload.c_str());
  }
  if ((millis()>last_status+status_interval)||millis()<last_status) {
    send_status = true;
  }
}

void setup()
{
  DEBInitSerial(1115000);
  topic_prefix = "Maehroboter-";
  topic_prefix += String(uint32_t(ESP.getEfuseMac()), HEX);
  topic_prefix += String(uint32_t(ESP.getEfuseMac() >> 32), HEX);
  // put your setup code here, to run once:
  setupautoconnect(topic_prefix.c_str());
/*
  if (load_status())
  {
    state_btn_home = status_rec.state_btn_home;
    state_btn_start = status_rec.state_btn_start;
    state_sw_stop = status_rec.state_sw_stop;
    state_btn_h = status_rec.state_btn_h;
    state_btn_sperr = status_rec.state_btn_sperr;
  }
*/
  ArduinoOTA.setHostname("Maehroboter");
  ArduinoOTA.begin();

  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);

  //GPIOs
  pinMode(LED_SIGNAL_PIN, INPUT);
  pinMode(LED_AKKU_PIN, INPUT);
  pinMode(LED_HEBEN_PIN, INPUT);
  pinMode(LED_LADEN_PIN, INPUT);
  pinMode(LED_SPERR_PIN, INPUT);
  pinMode(STATION_PIN, INPUT);
  read_leds();
  state_sw_stop = state_station; //Wenn sich der Maeher beim Start des ESP in der Station befindet, dann Stop einschalten 
  pinMode(HOME_PIN, OUTPUT);
  digitalWrite(HOME_PIN, state_btn_home);
  pinMode(START_PIN, OUTPUT);
  digitalWrite(START_PIN, state_btn_start);
  pinMode(STOP_PIN, OUTPUT);
  digitalWrite(STOP_PIN, state_sw_stop);
  pinMode(H_PIN, OUTPUT);
  digitalWrite(H_PIN, state_btn_h);
  pinMode(SPERR_PIN, OUTPUT);
  digitalWrite(SPERR_PIN, state_btn_sperr);
  initialization = true;
}

void loop()
{
  // put your main code here, to run repeatedly:
  if (!client.connected())
  {
    reconnect();
  }
  client.loop();
  read_leds();
  sendstatus();
  states2mqtt();
  ArduinoOTA.handle();
  check_WiFi();
}
Code:
#if !( defined(ESP8266) ||  defined(ESP32) )
  #error This code is intended to run on the ESP8266 or ESP32 platform! Please check your Tools->Board setting.
#endif

#define ESP_WIFIMANAGER_VERSION_MIN_TARGET     "ESP_WiFiManager v1.7.3"

// Use from 0 to 4. Higher number, more debugging messages and memory usage.
#ifndef NDEBUG
#define _WIFIMGR_LOGLEVEL_    3
#endif

//Ported to ESP32
#ifdef ESP32
  #include <esp_wifi.h>
  #include <WiFi.h>
  #include <WiFiClient.h>

  // From v1.1.0
  #include <WiFiMulti.h>
  WiFiMulti wifiMulti;

  // LittleFS has higher priority than SPIFFS
  #if ( ARDUINO_ESP32C3_DEV )
    // Currently, ESP32-C3 only supporting SPIFFS and EEPROM. Will fix to support LittleFS
    #define USE_LITTLEFS          false
    #define USE_SPIFFS            true
  #else
    #define USE_LITTLEFS    true
    #define USE_SPIFFS      false
  #endif

  #if USE_LITTLEFS
    // Use LittleFS
    #include "FS.h"

    // The library has been merged into esp32 core release 1.0.6
     #include <LITTLEFS.h>             // https://github.com/lorol/LITTLEFS
    
    FS* filesystem =      &LITTLEFS;
    #define FileFS        LITTLEFS
    #define FS_Name       "LittleFS"
  #elif USE_SPIFFS
    #include <SPIFFS.h>
    FS* filesystem =      &SPIFFS;
    #define FileFS        SPIFFS
    #define FS_Name       "SPIFFS"
  #else
    // Use FFat
    #include <FFat.h>
    FS* filesystem =      &FFat;
    #define FileFS        FFat
    #define FS_Name       "FFat"
  #endif
  //////
  
  #define ESP_getChipId()   ((uint32_t)ESP.getEfuseMac())
  
  #define LED_ON      HIGH
  #define LED_OFF     LOW
  
#else

  #include <ESP8266WiFi.h>          //https://github.com/esp8266/Arduino
  //needed for library
  #include <DNSServer.h>
  #include <ESP8266WebServer.h>

  // From v1.1.0
  #include <ESP8266WiFiMulti.h>
  ESP8266WiFiMulti wifiMulti;

  #include <FS.h>

  #define USE_LITTLEFS      true
  
  #if USE_LITTLEFS
    #include <LittleFS.h>
    FS* filesystem = &LittleFS;
    #define FileFS    LittleFS
    #define FS_Name       "LittleFS"
  #else
    FS* filesystem = &SPIFFS;
    #define FileFS    SPIFFS
    #define FS_Name       "SPIFFS"
  #endif
  //////
  
  #define ESP_getChipId()   (ESP.getChipId())
  
  #define LED_ON      LOW
  #define LED_OFF     HIGH
#endif

// You only need to format the filesystem once
//#define FORMAT_FILESYSTEM       true
#define FORMAT_FILESYSTEM         false

// SSID and PW for your Router
String Router_SSID;
String Router_Pass;

// From v1.1.0
#define MIN_AP_PASSWORD_SIZE    8

#define SSID_MAX_LEN            32
//From v1.0.10, WPA2 passwords can be up to 63 characters long.
#define PASS_MAX_LEN            64

typedef struct
{
  char wifi_ssid[SSID_MAX_LEN];
  char wifi_pw  [PASS_MAX_LEN];
}  WiFi_Credentials;

typedef struct
{
  String wifi_ssid;
  String wifi_pw;
}  WiFi_Credentials_String;

#define NUM_WIFI_CREDENTIALS      2

// Assuming max 491 chars
#define TZNAME_MAX_LEN            50
#define TIMEZONE_MAX_LEN          50

typedef struct
{
  WiFi_Credentials  WiFi_Creds [NUM_WIFI_CREDENTIALS];
  char TZ_Name[TZNAME_MAX_LEN];     // "America/Toronto"
  char TZ[TIMEZONE_MAX_LEN];        // "EST5EDT,M3.2.0,M11.1.0"
  uint16_t checksum;
} WM_Config;

WM_Config         WM_config;

#define  CONFIG_FILENAME              F("/wifi_cred.dat")

// Indicates whether ESP has WiFi credentials saved from previous session, or double reset detected
bool initialConfig = false;
//////

// Use false if you don't like to display Available Pages in Information Page of Config Portal
// Comment out or use true to display Available Pages in Information Page of Config Portal
// Must be placed before #include <ESP_WiFiManager.h>
#define USE_AVAILABLE_PAGES     false

// From v1.0.10 to permit disable/enable StaticIP configuration in Config Portal from sketch. Valid only if DHCP is used.
// You'll loose the feature of dynamically changing from DHCP to static IP, or vice versa
// You have to explicitly specify false to disable the feature.
#define USE_STATIC_IP_CONFIG_IN_CP          false

// Use false to disable NTP config. Advisable when using Cellphone, Tablet to access Config Portal.
// See Issue 23: On Android phone ConfigPortal is unresponsive (https://github.com/khoih-prog/ESP_WiFiManager/issues/23)
#define USE_ESP_WIFIMANAGER_NTP     true

// Just use enough to save memory. On ESP8266, can cause blank ConfigPortal screen
// if using too much memory
#define USING_AFRICA        false
#define USING_AMERICA       true
#define USING_ANTARCTICA    false
#define USING_ASIA          false
#define USING_ATLANTIC      false
#define USING_AUSTRALIA     false
#define USING_EUROPE        false
#define USING_INDIAN        false
#define USING_PACIFIC       false
#define USING_ETC_GMT       false

// Use true to enable CloudFlare NTP service. System can hang if you don't have Internet access while accessing CloudFlare
// See Issue #21: CloudFlare link in the default portal (https://github.com/khoih-prog/ESP_WiFiManager/issues/21)
#define USE_CLOUDFLARE_NTP          false

// New in v1.0.11
#define USING_CORS_FEATURE          true
//////

// Use USE_DHCP_IP == true for dynamic DHCP IP, false to use static IP which you have to change accordingly to your network
#if (defined(USE_STATIC_IP_CONFIG_IN_CP) && !USE_STATIC_IP_CONFIG_IN_CP)
  // Force DHCP to be true
  #if defined(USE_DHCP_IP)
    #undef USE_DHCP_IP
  #endif
  #define USE_DHCP_IP     true
#else
  // You can select DHCP or Static IP here
  //#define USE_DHCP_IP     true
  #define USE_DHCP_IP     false
#endif

#if ( USE_DHCP_IP )
// Use DHCP
  #warning Using DHCP IP
  IPAddress stationIP   = IPAddress(0, 0, 0, 0);
  IPAddress gatewayIP   = IPAddress(192, 168, 2, 1);
  IPAddress netMask     = IPAddress(255, 255, 255, 0);
#else
  // Use static IP
  #warning Using static IP
  
  #ifdef ESP32
    IPAddress stationIP   = IPAddress(192, 168, 2, 232);
  #else
    IPAddress stationIP   = IPAddress(192, 168, 2, 186);
  #endif
  
  IPAddress gatewayIP   = IPAddress(192, 168, 2, 1);
  IPAddress netMask     = IPAddress(255, 255, 255, 0);
#endif

#define USE_CONFIGURABLE_DNS      true

IPAddress dns1IP      = gatewayIP;
IPAddress dns2IP      = IPAddress(8, 8, 8, 8);

#define USE_CUSTOM_AP_IP          false

// New in v1.4.0
IPAddress APStaticIP  = IPAddress(192, 168, 100, 1);
IPAddress APStaticGW  = IPAddress(192, 168, 100, 1);
IPAddress APStaticSN  = IPAddress(255, 255, 255, 0);
//////

#include <ESP_WiFiManager.h>              //https://github.com/khoih-prog/ESP_WiFiManager

// Function Prototypes
uint8_t connectMultiWiFi();

///////////////////////////////////////////
// New in v1.4.0
/******************************************
 * // Defined in ESPAsync_WiFiManager.h
typedef struct
{
  IPAddress _ap_static_ip;
  IPAddress _ap_static_gw;
  IPAddress _ap_static_sn;
}  WiFi_AP_IPConfig;
typedef struct
{
  IPAddress _sta_static_ip;
  IPAddress _sta_static_gw;
  IPAddress _sta_static_sn;
#if USE_CONFIGURABLE_DNS  
  IPAddress _sta_static_dns1;
  IPAddress _sta_static_dns2;
#endif
}  WiFi_STA_IPConfig;
******************************************/

WiFi_AP_IPConfig  WM_AP_IPconfig;
WiFi_STA_IPConfig WM_STA_IPconfig;

void initAPIPConfigStruct(WiFi_AP_IPConfig &in_WM_AP_IPconfig)
{
  in_WM_AP_IPconfig._ap_static_ip   = APStaticIP;
  in_WM_AP_IPconfig._ap_static_gw   = APStaticGW;
  in_WM_AP_IPconfig._ap_static_sn   = APStaticSN;
}

void initSTAIPConfigStruct(WiFi_STA_IPConfig &in_WM_STA_IPconfig)
{
  in_WM_STA_IPconfig._sta_static_ip   = stationIP;
  in_WM_STA_IPconfig._sta_static_gw   = gatewayIP;
  in_WM_STA_IPconfig._sta_static_sn   = netMask;
#if USE_CONFIGURABLE_DNS  
  in_WM_STA_IPconfig._sta_static_dns1 = dns1IP;
  in_WM_STA_IPconfig._sta_static_dns2 = dns2IP;
#endif
}

void displayIPConfigStruct(WiFi_STA_IPConfig in_WM_STA_IPconfig)
{
  LOGERROR3(F("stationIP ="), in_WM_STA_IPconfig._sta_static_ip, ", gatewayIP =", in_WM_STA_IPconfig._sta_static_gw);
  LOGERROR1(F("netMask ="), in_WM_STA_IPconfig._sta_static_sn);
#if USE_CONFIGURABLE_DNS
  LOGERROR3(F("dns1IP ="), in_WM_STA_IPconfig._sta_static_dns1, ", dns2IP =", in_WM_STA_IPconfig._sta_static_dns2);
#endif
}

void configWiFi(WiFi_STA_IPConfig in_WM_STA_IPconfig)
{
  #if USE_CONFIGURABLE_DNS  
    // Set static IP, Gateway, Subnetmask, DNS1 and DNS2. New in v1.0.5
    WiFi.config(in_WM_STA_IPconfig._sta_static_ip, in_WM_STA_IPconfig._sta_static_gw, in_WM_STA_IPconfig._sta_static_sn, in_WM_STA_IPconfig._sta_static_dns1, in_WM_STA_IPconfig._sta_static_dns2);  
  #else
    // Set static IP, Gateway, Subnetmask, Use auto DNS1 and DNS2.
    WiFi.config(in_WM_STA_IPconfig._sta_static_ip, in_WM_STA_IPconfig._sta_static_gw, in_WM_STA_IPconfig._sta_static_sn);
  #endif 
}

///////////////////////////////////////////

uint8_t connectMultiWiFi()
{
#if ESP32
  // For ESP32, this better be 0 to shorten the connect time.
  // For ESP32-S2/C3, must be > 500
  #if ( USING_ESP32_S2 || USING_ESP32_C3 )
    #define WIFI_MULTI_1ST_CONNECT_WAITING_MS           500L
  #else
    // For ESP32 core v1.0.6, must be >= 500
    #define WIFI_MULTI_1ST_CONNECT_WAITING_MS           800L
  #endif
#else
  // For ESP8266, this better be 2200 to enable connect the 1st time
  #define WIFI_MULTI_1ST_CONNECT_WAITING_MS             2200L
#endif

#define WIFI_MULTI_CONNECT_WAITING_MS                   500L

  uint8_t status;

  //WiFi.mode(WIFI_STA);

  LOGERROR(F("ConnectMultiWiFi with :"));

  if ( (Router_SSID != "") && (Router_Pass != "") )
  {
    LOGERROR3(F("* Flash-stored Router_SSID = "), Router_SSID, F(", Router_Pass = "), Router_Pass );
    LOGERROR3(F("* Add SSID = "), Router_SSID, F(", PW = "), Router_Pass );
    wifiMulti.addAP(Router_SSID.c_str(), Router_Pass.c_str());
  }

  for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++)
  {
    // Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8)
    if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) )
    {
      LOGERROR3(F("* Additional SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw );
    }
  }

  LOGERROR(F("Connecting MultiWifi..."));

  //WiFi.mode(WIFI_STA);

#if !USE_DHCP_IP
  // New in v1.4.0
  configWiFi(WM_STA_IPconfig);
  //////
#endif

  int i = 0;
  
  status = wifiMulti.run();
  delay(WIFI_MULTI_1ST_CONNECT_WAITING_MS);

  while ( ( i++ < 20 ) && ( status != WL_CONNECTED ) )
  {
    status = WiFi.status();

    if ( status == WL_CONNECTED )
      break;
    else
      delay(WIFI_MULTI_CONNECT_WAITING_MS);
  }

  if ( status == WL_CONNECTED )
  {
    LOGERROR1(F("WiFi connected after time: "), i);
    LOGERROR3(F("SSID:"), WiFi.SSID(), F(",RSSI="), WiFi.RSSI());
    LOGERROR3(F("Channel:"), WiFi.channel(), F(",IP address:"), WiFi.localIP() );
  }
  else
  {
    LOGERROR(F("WiFi not connected"));

#if ESP8266      
    ESP.reset();
#else
    ESP.restart();
#endif  
  }

  return status;
}

#if USE_ESP_WIFIMANAGER_NTP

void printLocalTime()
{
#if ESP8266
  static time_t now;
  
  now = time(nullptr);
  
  if ( now > 1451602800 )
  {
    DEBPrint("Local Date/Time: ");
    DEBPrint(ctime(&now));
  }
#else
  struct tm timeinfo;

  getLocalTime( &timeinfo );

  // Valid only if year > 2000. 
  // You can get from timeinfo : tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec
  if (timeinfo.tm_year > 100 )
  {
    DEBPrint("Local Date/Time: ");
    DEBPrint( asctime( &timeinfo ) );
  }
#endif
}

#endif

void heartBeatPrint()
{
#if USE_ESP_WIFIMANAGER_NTP
  printLocalTime();
#else
  static int num = 1;

  if (WiFi.status() == WL_CONNECTED)
    DEBPrint(F("H"));        // H means connected to WiFi
  else
    DEBPrint(F("F"));        // F means not connected to WiFi

  if (num == 80)
  {
    DEBPrintln();
    num = 1;
  }
  else if (num++ % 10 == 0)
  {
    DEBPrint(F(" "));
  }
#endif  
}

void check_WiFi()
{
  if ( (WiFi.status() != WL_CONNECTED) )
  {
    DEBPrintln(F("\nWiFi lost. Call connectMultiWiFi in loop"));
    connectMultiWiFi();
  }
}  

void check_status()
{
  static ulong checkstatus_timeout  = 0;
  static ulong checkwifi_timeout    = 0;

  static ulong current_millis;

#define WIFICHECK_INTERVAL    1000L

#if USE_ESP_WIFIMANAGER_NTP
  #define HEARTBEAT_INTERVAL    60000L
#else
  #define HEARTBEAT_INTERVAL    10000L
#endif

  current_millis = millis();
  
  // Check WiFi every WIFICHECK_INTERVAL (1) seconds.
  if ((current_millis > checkwifi_timeout) || (checkwifi_timeout == 0))
  {
    check_WiFi();
    checkwifi_timeout = current_millis + WIFICHECK_INTERVAL;
  }

  // Print hearbeat every HEARTBEAT_INTERVAL (10) seconds.
  if ((current_millis > checkstatus_timeout) || (checkstatus_timeout == 0))
  {
    heartBeatPrint();
    checkstatus_timeout = current_millis + HEARTBEAT_INTERVAL;
  }
}

int calcChecksum(uint8_t* address, uint16_t sizeToCalc)
{
  uint16_t checkSum = 0;
  
  for (uint16_t index = 0; index < sizeToCalc; index++)
  {
    checkSum += * ( ( (byte*) address ) + index);
  }

  return checkSum;
}

bool loadConfigData()
{
  File file = FileFS.open(CONFIG_FILENAME, "r");
  LOGERROR(F("LoadWiFiCfgFile "));

  memset((void *) &WM_config,       0, sizeof(WM_config));

  // New in v1.4.0
  memset((void *) &WM_STA_IPconfig, 0, sizeof(WM_STA_IPconfig));
  //////

  if (file)
  {
    file.readBytes((char *) &WM_config,   sizeof(WM_config));

    // New in v1.4.0
    file.readBytes((char *) &WM_STA_IPconfig, sizeof(WM_STA_IPconfig));
    //////

    file.close();
    LOGERROR(F("OK"));

    if ( WM_config.checksum != calcChecksum( (uint8_t*) &WM_config, sizeof(WM_config) - sizeof(WM_config.checksum) ) )
    {
      LOGERROR(F("WM_config checksum wrong"));
      
      return false;
    }
    
    // New in v1.4.0
    displayIPConfigStruct(WM_STA_IPconfig);
    //////

    return true;
  }
  else
  {
    LOGERROR(F("failed"));

    return false;
  }
}

void saveConfigData()
{
  File file = FileFS.open(CONFIG_FILENAME, "w");
  LOGERROR(F("SaveWiFiCfgFile "));

  if (file)
  {
    WM_config.checksum = calcChecksum( (uint8_t*) &WM_config, sizeof(WM_config) - sizeof(WM_config.checksum) );
    
    file.write((uint8_t*) &WM_config, sizeof(WM_config));

    displayIPConfigStruct(WM_STA_IPconfig);

    // New in v1.4.0
    file.write((uint8_t*) &WM_STA_IPconfig, sizeof(WM_STA_IPconfig));
    //////

    file.close();
    LOGERROR(F("OK"));
  }
  else
  {
    LOGERROR(F("failed"));
  }
}

void setupautoconnect(const char *iHostname = "")
{

  DEBPrint(F("\nStarting AutoConnectAP using ")); DEBPrint(FS_Name);
  DEBPrint(F(" on ")); DEBPrintln(ARDUINO_BOARD);
  DEBPrintln(ESP_WIFIMANAGER_VERSION);

  if ( String(ESP_WIFIMANAGER_VERSION) < ESP_WIFIMANAGER_VERSION_MIN_TARGET )
  {
    DEBPrint(F("Warning. Must use this example on Version equal or later than : "));
    DEBPrintln(ESP_WIFIMANAGER_VERSION_MIN_TARGET);
  }
  
  if (FORMAT_FILESYSTEM) 
    FileFS.format();

  // Format FileFS if not yet
#ifdef ESP32
  if (!FileFS.begin(true))
#else
  if (!FileFS.begin())
#endif
  {
#ifdef ESP8266
    FileFS.format();
#endif

    DEBPrintln(F("SPIFFS/LittleFS failed! Already tried formatting."));
  
    if (!FileFS.begin())
    {     
      // prevents debug info from the library to hide err message.
      delay(100);
      
#if USE_LITTLEFS
      DEBPrintln(F("LittleFS failed!. Please use SPIFFS or EEPROM. Stay forever"));
#else
      DEBPrintln(F("SPIFFS failed!. Please use LittleFS or EEPROM. Stay forever"));
#endif

      while (true)
      {
        delay(1);
      }
    }
  }

#ifndef NDEBUG
  unsigned long startedAt = millis();
#endif

  // New in v1.4.0
  initAPIPConfigStruct(WM_AP_IPconfig);
  initSTAIPConfigStruct(WM_STA_IPconfig);
  //////

  // Use this to default DHCP hostname to ESP8266-XXXXXX or ESP32-XXXXXX
  //ESP_WiFiManager ESP_wifiManager;
  // Use this to personalize DHCP hostname (RFC952 conformed)
  ESP_WiFiManager ESP_wifiManager(iHostname);

  ESP_wifiManager.setDebugOutput(true);

  //reset settings - for testing
  //ESP_wifiManager.resetSettings();

#if USE_CUSTOM_AP_IP
  //set custom ip for portal
  // New in v1.4.0
  ESP_wifiManager.setAPStaticIPConfig(WM_AP_IPconfig);
  //////
#endif

  ESP_wifiManager.setMinimumSignalQuality(-1);

  // From v1.0.10 only
  // Set config portal channel, default = 1. Use 0 => random channel from 1-13
  ESP_wifiManager.setConfigPortalChannel(0);
  //////
  
#if !USE_DHCP_IP    
    // Set (static IP, Gateway, Subnetmask, DNS1 and DNS2) or (IP, Gateway, Subnetmask). New in v1.0.5
    // New in v1.4.0
    ESP_wifiManager.setSTAStaticIPConfig(WM_STA_IPconfig);
    //////
#endif

  // New from v1.1.1
#if USING_CORS_FEATURE
  ESP_wifiManager.setCORSHeader("Your Access-Control-Allow-Origin");
#endif

  // We can't use WiFi.SSID() in ESP32 as it's only valid after connected.
  // SSID and Password stored in ESP32 wifi_ap_record_t and wifi_config_t are also cleared in reboot
  // Have to create a new function to store in EEPROM/SPIFFS for this purpose
  Router_SSID = ESP_wifiManager.WiFi_SSID();
  Router_Pass = ESP_wifiManager.WiFi_Pass();

  //Remove this line if you do not want to see WiFi password printed
  DEBPrintln("ESP Self-Stored: SSID = " + Router_SSID + ", Pass = " + Router_Pass);

  bool configDataLoaded = false;

  // From v1.1.0, Don't permit NULL password
  if ( (Router_SSID != "") && (Router_Pass != "") )
  {
    LOGERROR3(F("* Add SSID = "), Router_SSID, F(", PW = "), Router_Pass);
    wifiMulti.addAP(Router_SSID.c_str(), Router_Pass.c_str());
    
    ESP_wifiManager.setConfigPortalTimeout(120); //If no access point name has been previously entered disable timeout.
    DEBPrintln(F("Got ESP Self-Stored Credentials. Timeout 120s for Config Portal"));
  }
  
  if (loadConfigData())
  {
    configDataLoaded = true;
    
    ESP_wifiManager.setConfigPortalTimeout(120); //If no access point name has been previously entered disable timeout.
    DEBPrintln(F("Got stored Credentials. Timeout 120s for Config Portal")); 

#if USE_ESP_WIFIMANAGER_NTP      
    if ( strlen(WM_config.TZ_Name) > 0 )
    {
      LOGERROR3(F("Current TZ_Name ="), WM_config.TZ_Name, F(", TZ = "), WM_config.TZ);

  #if ESP8266
      configTime(WM_config.TZ, "pool.ntp.org"); 
  #else
      //configTzTime(WM_config.TZ, "pool.ntp.org" );
      configTzTime(WM_config.TZ, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org");
  #endif   
    }
    else
    {
      DEBPrintln(F("Current Timezone is not set. Enter Config Portal to set."));
    } 
#endif
  }
  else
  {
    // Enter CP only if no stored SSID on flash and file
    DEBPrintln(F("Open Config Portal without Timeout: No stored Credentials."));
    initialConfig = true;
  }

  String chipID = String(ESP_getChipId(), HEX);
  chipID.toUpperCase();

  // SSID and PW for Config Portal
  String AP_SSID = "Maehroboter_" + chipID + "_AutoConnectAP";
  String AP_PASS = "";//"MyESP_" + chipID;

  if (initialConfig)
  {
    DEBPrint(F("Starting configuration portal @ "));
    
#if USE_CUSTOM_AP_IP    
    DEBPrint(APStaticIP);
#else
    DEBPrint(F("192.168.4.1"));
#endif

    DEBPrint(F(", SSID = "));
    DEBPrint(AP_SSID);
    DEBPrint(F(", PWD = "));
    DEBPrintln(AP_PASS);

    initialConfig = true;

    // Starts an access point
    //if (!ESP_wifiManager.startConfigPortal((const char *) ssid.c_str(), password))
    if ( !ESP_wifiManager.startConfigPortal(AP_SSID.c_str(), AP_PASS.c_str()) )
      DEBPrintln(F("Not connected to WiFi but continuing anyway."));
    else
      DEBPrintln(F("WiFi connected...yeey :)"));

    // Stored  for later usage, from v1.1.0, but clear first
    memset(&WM_config, 0, sizeof(WM_config));
    
    for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++)
    {
      String tempSSID = ESP_wifiManager.getSSID(i);
      String tempPW   = ESP_wifiManager.getPW(i);
  
      if (strlen(tempSSID.c_str()) < sizeof(WM_config.WiFi_Creds[i].wifi_ssid) - 1)
        strcpy(WM_config.WiFi_Creds[i].wifi_ssid, tempSSID.c_str());
      else
        strncpy(WM_config.WiFi_Creds[i].wifi_ssid, tempSSID.c_str(), sizeof(WM_config.WiFi_Creds[i].wifi_ssid) - 1);

      if (strlen(tempPW.c_str()) < sizeof(WM_config.WiFi_Creds[i].wifi_pw) - 1)
        strcpy(WM_config.WiFi_Creds[i].wifi_pw, tempPW.c_str());
      else
        strncpy(WM_config.WiFi_Creds[i].wifi_pw, tempPW.c_str(), sizeof(WM_config.WiFi_Creds[i].wifi_pw) - 1);  

      // Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8)
      if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) )
      {
        LOGERROR3(F("* Add SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw );
        wifiMulti.addAP(WM_config.WiFi_Creds[i].wifi_ssid, WM_config.WiFi_Creds[i].wifi_pw);
      }
    }

#if USE_ESP_WIFIMANAGER_NTP      
    String tempTZ   = ESP_wifiManager.getTimezoneName();

    if (strlen(tempTZ.c_str()) < sizeof(WM_config.TZ_Name) - 1)
      strcpy(WM_config.TZ_Name, tempTZ.c_str());
    else
      strncpy(WM_config.TZ_Name, tempTZ.c_str(), sizeof(WM_config.TZ_Name) - 1);

    const char * TZ_Result = ESP_wifiManager.getTZ(WM_config.TZ_Name);
    
    if (strlen(TZ_Result) < sizeof(WM_config.TZ) - 1)
      strcpy(WM_config.TZ, TZ_Result);
    else
      strncpy(WM_config.TZ, TZ_Result, sizeof(WM_config.TZ_Name) - 1);
         
    if ( strlen(WM_config.TZ_Name) > 0 )
    {
      LOGERROR3(F("Saving current TZ_Name ="), WM_config.TZ_Name, F(", TZ = "), WM_config.TZ);

  #if ESP8266
      configTime(WM_config.TZ, "pool.ntp.org"); 
  #else
      //configTzTime(WM_config.TZ, "pool.ntp.org" );
      configTzTime(WM_config.TZ, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org");
  #endif
    }
    else
    {
      LOGERROR(F("Current Timezone Name is not set. Enter Config Portal to set."));
    }
#endif

    // New in v1.4.0
    ESP_wifiManager.getSTAStaticIPConfig(WM_STA_IPconfig);
    //////
    
    saveConfigData();
  }
  else
  {
    wifiMulti.addAP(Router_SSID.c_str(), Router_Pass.c_str());
  }

#ifndef NDEBUG
  startedAt = millis();
#endif

  if (!initialConfig)
  {
    // Load stored data, the addAP ready for MultiWiFi reconnection
    if (!configDataLoaded)
      loadConfigData();

    for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++)
    {
      // Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8)
      if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) )
      {
        LOGERROR3(F("* Add SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw );
        wifiMulti.addAP(WM_config.WiFi_Creds[i].wifi_ssid, WM_config.WiFi_Creds[i].wifi_pw);
      }
    }

    if ( WiFi.status() != WL_CONNECTED ) 
    {
      DEBPrintln(F("ConnectMultiWiFi in setup"));
     
      connectMultiWiFi();
    }
  }

  DEBPrint(F("After waiting "));
  DEBPrint((float) (millis() - startedAt) / 1000L);
  DEBPrint(F(" secs more in setup(), connection result is "));

  if (WiFi.status() == WL_CONNECTED)
  {
    DEBPrint(F("connected. Local IP: "));
    DEBPrintln(WiFi.localIP());
  }
  else
    DEBPrintln(ESP_wifiManager.getStatus(WiFi.status()));
}
Code:
#ifndef NDEBUG  
    #define DEBPrint(...) (Serial.print(__VA_ARGS__))
    #define DEBPrintln(...) (Serial.println(__VA_ARGS__))

    void DEBInitSerial(unsigned long baudrate = 115000)
    {
    Serial.begin(baudrate);
    while (!Serial)
        ;
    delay(200);
    }
#else
    #define DEBPrint(...) 
    #define DEBPrintln(...) 
    #define DEBInitSerial(...)
#endif
 
  • Mähen nur jeden 2ten Tag? Beitrag #184
G

gg123456

Dabei seit
16.05.2021
Beiträge
4
Likes
2
Thanks Robotuino for help. As promised - I post my changes to your files.


Changes:
1. Added BMI160 Gyroscope (for detecting lawnmower stuck)
2. Added NEO-6M GPS (for positioning stucked lawnmower)
3. Added DS18B20 temperature sensor (monitor inside temperature)
4. Additional BC547 (for LED Strobe Lamp)
5. ESP32 change to ESP32-DEVKITC-32U (version U have U.FL external antenna connector)

I will post software soon.

d2.jpg

d1.jpg

Den Anhang Roboterplatine.pdf betrachten
Den Anhang Platine.zip betrachten
 
  • Mähen nur jeden 2ten Tag? Beitrag #185
R

Robotuino

Dabei seit
02.05.2021
Beiträge
34
Likes
4
gg123456
That looks really good. :thumbsup::thumbsup:

I have some easy question: What is the connector j6 for? Is it the output for theLED? When does the LED starts blinking?

But: My lawn is not so large that i have to search the mower by GPS ;). Although it is hot outside the mower never give up his job depending on high temperature. Very interesting ist the sensor if the mower stucks. This could be a reason to start again this projekt.

The PCB looks great. I think J1 und J2 are dangerous close together. I had some problems with the near-by connectors.

Good job!
Regards Robotuino
 
  • Mähen nur jeden 2ten Tag? Beitrag #186
G

gg123456

Dabei seit
16.05.2021
Beiträge
4
Likes
2
Thanks Robotuino

My answers:
1. Yes, J6 is for LED. LED is blinking, when lawnmower is stucked somewhere in garden.
2. My lawn is also not so large, but it's easier to find, when you know where to search. This class of GPS have 1.5m of HDOP.
3. Highest temperature which I registered was 62°C. It's only for monitoring. I noticed that the temperature rises a lot while charging,
4. It's very usefull. Sometimes, especially after rain, my LM stuck some inside the border wire, digging a hole with the wheel.
5. J1 and J2 are close together but the plugs fit perfectly.

I'm doing some refactoring in Arduino code, I will post it in few days.


Max temperatures
t1.jpg


Temperatures with station sensor
t5.jpg


First hour of mowing
t3.jpg


All day of mowing
t2.jpg
 
  • Mähen nur jeden 2ten Tag? Beitrag #187
R

Robotuino

Dabei seit
02.05.2021
Beiträge
34
Likes
4
gg123456
That gives you 12 points out of 10 !!!!

Really good. Did you ordered a printed circuit board?

Regards Robotuino
 
  • Mähen nur jeden 2ten Tag? Beitrag #188
G

gg123456

Dabei seit
16.05.2021
Beiträge
4
Likes
2
Yes, I ordered a PCB. I soldered everything and started it.
 
  • Mähen nur jeden 2ten Tag? Beitrag #189
G

gg123456

Dabei seit
16.05.2021
Beiträge
4
Likes
2
My Arduino code based on some post above
 

Anhänge

  • Lawnmower.zip
    5,8 KB · Aufrufe: 3
Thema:

Mähen nur jeden 2ten Tag?

Mähen nur jeden 2ten Tag? - Ähnliche Themen

Yardforce SA650 Eco, S1+S2 blinken wenn Mäher in der Station ist: Hallo zusammen, heute habe ich einen neuen Yardforce SA650 erhalten und nach Anleitung in Betrieb genommen. Mäher und Station sind auf S1...
Fragen zur PIN Eingabe 30 Tage: Moin zusammen! Ich habe jetzt bei dem neuen Sileno 600 die Sicherheit auf "schwach" eingestellt, so dass bei einem manuellen Start am Gerät die...
Sileno meldet "Offline": Moin zusammen! Nach jetzt 2 Jahren größtenteils problemlosen Betrieb des Sileno Life 1000, meldet das SmartSystem derzeit alle paar Tage, dass...
Mowapp Yardforce: Hallo glückliche Appbesitzer von Mowapp! Für mich ist die App eine interessante Erfahrung. Einige Male deinstalliert und wieder neu versucht...
Agrarshop Trockenrasen vor 14 Tagen nachgesät, kommt spärlich: Vor gut 14 Tagen habe ich frische Erde verfüllt und mit Agrarshop Trockenrasen nachgesät und regelmäßig bewässert. Nun nach 14 Tagen kommen...
Beiträge
188
Erstellt
2018
Aktualisiert

Top Poster

  • R

    Robotuino

    Beiträge: 34
  • E

    eavel

    Beiträge: 26
  • M

    MasterDiesel

    Beiträge: 18
  • T

    Terabyte

    Beiträge: 10

Häufigste Beiträge

Beliebte Beiträge

N
NetFritz
Hallo Endschalter werden auch in der Insdustrie eingesetzt, sie konnen schon einigemal Schalten. Ich habe so einen um 90 Grad verdreht auf der...
E
eavel
Yard Force SA650 ECO (MIT Regensensor) Moin, habe heute mal den Robo-Mäher etwas genauer angeschaut und stelle die Bilder für alle...
E
eavel
....hier noch weitere Bilder... Viel Erfolg beim Basteln und Schrauben :)
N
NetFritz
Hallo Das ist aber Mega Klasse, vielen Dank. Liegt den in der Box vor den Vorderrädern an den Blau/Brauen die Akku Spannung an wenn er nicht...
Oben