RIP UNO Wifi Rev2 - Alternative?

Hallo zusammen,

gerade hat es meinen ersten UNO WIFI Rev 2 zerlegt. Der Chip in der Mitte wird knülle heiß und die orange LED blinkt schnell. Mehr passiert nicht mehr. Da scheint der Chip wohl durchgeknallt zu sein.

Schade, war das ging knapp 2 Jahre alt. Ich steuere damit zwei Schrittmotoren, die Solarpanels mit der Sonne mit drehen.

Ich suche jetzt eine Alternative für den Nachfolger. Könntet ihr mir eine Empfehlung geben?

Was brauche ich: Mindestens 5 Digital PWM Pins. Ich hatte aktuell 2,4, 8 und 12 genutzt.
Dazu die beiden GND bei Power.

WLAN muss dabei sein und wenn OTA funktionieren würde, wäre das schon sehr gut.
Fast schon zwingend sind die Steckpins.

Ich hatte das damals empfohlen bekommen. Wäre aber über eine Alternative sehr dankbar.

Auf dem Uno WiFi sind:

  • Atmega4809
  • Esp32
  • ATECC608A
  • LSM6DS3TR

Was benutzt du davon?
Brauchst du 5V Logic oder geht auch 3V?

1 Like

Hallo,

den um 45° verdrehten meinst du? Das ist der ATmega4809, der Controller den man selbst auf dem Board programmiert. Ich würde erstmal abklären warum es ihn zerlegt hat. Einfach so geht er nicht kaputt. Ansonsten wechselst du ständig Boards aus.

1 Like

ESP32 DevKit hat das bis auf die Steckpins, aber die lassen sich separat kaufen, wobei ich Löten besser fände.

Problematisch könnten die 3,3 V an den digitalen Pins werden, das mag nicht jede nachfolgende Elektronik. Aber auch dafür gibt es Lösungen wie Pegelwandler.

Mit einem Fingerschnipps ist die Umstellung nicht gemacht, aber sicherlich möglich.

1 Like

ESP32 DEV 4 sind aktuell meine Favoriten. Wenn man Glück hat unter 8 Euro. Einziger Nachteil : Es gibt sogut wie keine Shield dafür weil kleinere Bauform.

Genug Speicherplatz, Genug Schnittstellen + Pins.

Bei meinen waren die Steckpins extra, was bedeutet ich kann (und habe) sie angelötet. Man kann es aber auch lassen. Da löten Geld kostet sind die mit Pins dabei liegen i.d.R. ein Tick preiswerter.

Gruß

Pucki
1 Like

Bevor Du eine andere Platine in Deine Schaltung steckst, wäre es gut zu verstehen wieso das Ding draufgegangen ist, weil sonst ereilt dem neuen Teil das gleiche Schicksal.

Grüße Uwe

1 Like

Also Standard ESP32, so lange man nimmt kein C, S machen die keine Probleme.

1 Like

Eine schöne Seite über alle ESP32.

3 Likes

Danke euch allen für die Antworten.

Die Fehlerursache wird schwierig und wohl nur im Realbetrieb zu finden sein. Das werde ich dann wohl mit einem neuem Board herausfinden müssen. Das Board steuert halt einen Treiber, der dann die Motoren bewegt.

Das Gerät ist quasi im Dauerbetrieb und lief jetzt fast 2 Jahre mit kurzen Unterbrechungen durch.

Programmiert habe ich dort den ATmega4809. Das wäre natürlich wieder gut, wenn der da drauf ist. Dann kann alles 1:1 übernommen werden. Auch die runde Powerbuchse wäre gut, dann muss ich dort nicht alles umbauen (geteiltes Netzteil für den Antrieb).

Die 5V müsste ich wieder haben. OTA wäre zwar nett, aber ist kein Muss!

Schön wäre so wenig wie möglich neue Bastelei. Am einfachsten wäre natürlich wieder einen Uno Wifi Rev 2 zu erwerben. Mögliche Upgrades wären jetzt aber natürlich sinnvoll, wenn eh schon neugekauft werden muss.

Alles andere als ein WiFi Rev2 wird ziemlich viel neue Bastelei bedeuten ...

Ich hatte schon nach dem Uno Wifi Rev 4 geguckt.

Wenn ich das richtig gelesen habe, müsste ich hier den kompletten Code anpassen, aber sonst klappt es?

Ist auch was anderes, wen Du zeigst dein Sketch, schauen sich das hier so einige an. danach erst kann man sagen wie die Lage ist. Ich nutze keinen UNO mit WLAN, nur reine ESP.
Dein defekter UNO Wifi Rev 2 ist reiner 5V. R4 ist 5V für den ARM und 3,3v für den ESP und arbeitet ganz anders als der R2.
Wurde sagen wahrscheinlich ohne großem umbau wird es nicht gehen. Es sind ganz andere Familien, wo dazu nicht alle Lib sind noch portiert auf die Renesas RA4M1 (Arm® Cortex®-M4) MCU.
Ja so eine Endscheidung ist immer schwer, wo der R2 ist nicht ganz günstig, der R4 ja auch nicht.

1 Like

Der Uno Wifi Rev 2 hatte halt viele Vorteile. Steckpins, WLAN die runde Powerbuchse....alles auf einem Board.

Den Sketch kann ich gerne hinzufügen. Vielleicht hilft das bei der Unterstützung.

#include <WiFiNINA.h>
#include <AccelStepper.h>
#include <TimeLib.h>
#include <WiFiUdp.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include "secrets.h"

#define dirPin 2
#define stepPin 4
#define motorInterfaceType 1
#define PIN_BUTTON 12

#define SECRET_MQTT_USER "MQTT_USER"
#define SECRET_MQTT_PW "MQTT_PASSWORD"

const char* mqtt_server = "192.168.2.2"; // IP-Adresse oder Domain des MQTT-Brokers
const int mqtt_port = 1883; // MQTT-Port (standardmäßig 1883)
const char* mqtt_user = MQTT_USER; // MQTT-Benutzername
const char* mqtt_password = MQTT_PASSWORD; // MQTT-Passwort

unsigned long WindschutzTimer;
boolean Warteposition_aktiv = false;

unsigned long WindWartezeit_ms = 900000;

const long Startposition = 17000;
const long Vormittag1 = 9000;
const long Vormittag2 = 2000;
const long Mittag1 = 0;
const long Mittag2 = -6000;
const long Nachmittag1 = -12000;
const long Nachmittag2 = -15000;
const long Nachmittag3 = -18000;
const long Endposition = -24000;
const long Windschutz = 0;

const int timeZoneOffset = 1;  // Winterzeit (UTC+1)

AccelStepper stepper(motorInterfaceType, stepPin, dirPin);

char ssid[] = WIFI_SSID; // WLAN-SSID aus SECRETS.h
char pass[] = WIFI_PASSWORD; // WLAN-Passwort aus SECRETS.h
int timeZone = 2;

unsigned long currentTimestamp = 0;  // Variable für den aktuellen Zeitstempel
time_t currentTime;                  // Variable für die aktuelle Zeit

WiFiUDP ntpUDP;
IPAddress timeServerIP;
//########################
WiFiUDP udp;
WiFiClient wifiClient;
PubSubClient client(wifiClient);

WiFiServer server(80);

#define WIFI_CHECK_INTERVAL 600000  // Intervall für die Überprüfung der WLAN-Verbindung (10 Minuten)

unsigned long wifiCheckTimer = 0;  // Timer für die WLAN-Verbindung

bool isDaylightSavingTime(time_t currentTime);

int getLastSundayDay(int year, int month);

bool isDaylightSavingTime(time_t currentTime);

int getLastSundayDay(int year, int month);

bool isDaylightSavingTime(time_t currentTime) {
  int currentYear = year(currentTime);
  int currentMonth = month(currentTime);
  int currentDay = day(currentTime);

  // Letzter Sonntag im März
  int lastSundayMarch = getLastSundayDay(currentYear, 3);
  Serial.print("Letzter Sonntag im März: ");
  Serial.println(lastSundayMarch);

  // Letzter Sonntag im Oktober
  int lastSundayOctober = getLastSundayDay(currentYear, 10);
  Serial.print("Letzter Sonntag im Oktober: ");
  Serial.println(lastSundayOctober);

  // Sommerzeit beginnt am letzten Sonntag im März und endet am letzten Sonntag im Oktober
  bool isDST = ((currentMonth > 3 && currentMonth < 10) || 
                (currentMonth == 3 && currentDay > lastSundayMarch) || 
                (currentMonth == 10 && currentDay <= lastSundayOctober));
  
  if (isDST) {
    Serial.println("Es ist Sommerzeit.");
  } else {
    Serial.println("Es ist Winterzeit.");
  }

  return isDST;
}

int getLastSundayDay(int year, int month) {
  const int lastDays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // Tage in jedem Monat

  int lastSunday = lastDays[month - 1]; // Annahme: Monat hat maximal 31 Tage
  tmElements_t timeInfo;

  // Bestimme den letzten Tag des Monats
  while (lastSunday > 0) {
    timeInfo.Year = year - 1970; // Year offset from 1970
    timeInfo.Month = month;
    timeInfo.Day = lastSunday;

    time_t time = makeTime(timeInfo);
    int dayOfWeek = weekday(time);

    if (dayOfWeek == 1) { // Sonntag hat den Wert 1, unabhängig davon, wann die Woche beginnt
      return lastSunday;
    }

    lastSunday--;
  }

  return -1; // Fehler, falls der letzte Sonntag nicht gefunden wird
}


void setup() {
  Serial.begin(9600);
  while (!Serial)
    ;
  Serial.println("#### SETUP - START ####");
  Serial.println("");
  Serial.println("#### MOTOR - Geschwindigkeit eingestellen ####");
  stepper.setMaxSpeed(1400);
  stepper.setAcceleration(550);
  Serial.println("#### MOTOR - Geschwindigkeit eingestellen - ERFOLGREICH ####");
  Serial.println("");
  Serial.println("#### PIN-Belegung wird hinterlegt ####");
  pinMode(PIN_BUTTON, INPUT_PULLUP);
  pinMode(LED_BUILTIN, OUTPUT);  // Pin für die eingebaute LED
  Serial.println("#### PIN-Belegung wird hinterlegt - ERFOLGREICH ####");
  Serial.println("");
  Serial.println("#### WLAN-Verbindung####");
  connectWiFi();
  Serial.println("#### WLAN-Verbindung - ERFOLGREICH ####");
  Serial.println("");
  Serial.println("#### ZEIT ####");
  setSyncProvider(getNtpTime);
  setSyncInterval(3600);  // Synchronisiere die Zeit alle 1 Stunde
  Serial.println("#### ZEIT - ERFOLGREICH ####");
  Serial.println("");
  //server.begin();

  // Verbindung zum MQTT-Broker herstellen, einschließlich Benutzername und Passwort
  Serial.println("#### MQTT - Server-Verbindung herstellen ####");
  client.setServer(mqtt_server, mqtt_port);
  Serial.println("#### MQTT - Server-Verbindung herstellen - ERFOLGREICH ####");
  Serial.println("");
  Serial.println("#### MQTT - Callback-Funktion initialisieren ####");
  client.setCallback(callback);
  if (!client.connected()) {
    reconnect();
  }
  Serial.println("#### MQTT - Callback-Funktion initialisieren - ERFOLGREICH ####");
  Serial.println("");
  // Abonnement für das gewünschte Topic einrichten
  Serial.println("#### MQTT - Steuerungstopic Abo ####");
  client.subscribe("solar/bkw-steuerung/app");
  Serial.println("#### MQTT - Steuerungstopic Abo - ERFOLGREICH ####");
  Serial.println("");
  // Sende Autodiscovery-Nachrichten
  sendMQTTAutoDiscovery();
  Serial.println("");
  Serial.println("#### MQTT - Loop aktivieren ####");
  client.loop();
  Serial.println("#### MQTT - Loop aktivieren - ERFOLGREICH ####");
  Serial.println("");
  Serial.println("#### Setup - ENDE ####");
  Serial.println("");
}

void loop() {
  checkWiFiConnection();
  checkWindsensor();
  //handleRoot();

  // Daten an Home Assistant senden
  sendMQTTData();
  // MQTT Auto Discovery
  // MQTT-Verbindung und Verarbeitung von Nachrichten in einer separaten Funktion
  //mqttLoop();
  client.loop();
}


void checkWiFiConnection() {
  if (millis() - wifiCheckTimer >= WIFI_CHECK_INTERVAL) {
    wifiCheckTimer = millis();  // Timer zurücksetzen

    // Überprüfe die WLAN-Verbindung
    if (WiFi.status() != WL_CONNECTED) {
        Serial.println("");
        Serial.println("#### WLAN - Verbindungstest ####");
        Serial.println("");
        Serial.println("WLAN - Verbinung - NICHT AKTIV (Verbinde neu)");
        Serial.println("");
        Serial.println("#### WLAN - Verbindungstest ####");
        Serial.println("");

      // Trenne WLAN-Verbindung
      WiFi.disconnect();

      // Warte, um sicherzustellen, dass die Verbindung getrennt wurde
      delay(1000);

      // Stelle die WLAN-Verbindung neu her
      connectWiFi();
    } else {
      Serial.println("");
      Serial.println("#### WLAN - Verbindungstest ####");
      Serial.println("");
      Serial.println("WLAN - Verbindung - AKTIV.");
      Serial.println("");
      Serial.println("#### WLAN - Verbindungstest ####");
      Serial.println("");
    }
  }
}

void connectWiFi() {
  int connectAttempts = 0;

  while (connectAttempts < 10) {
    WiFi.begin(ssid, pass);
    unsigned long startTime = millis();

    while (WiFi.status() != WL_CONNECTED && millis() - startTime < 30000) {
      delay(1000);
    }

    if (WiFi.status() == WL_CONNECTED) {
      Serial.println("Verbindung hergestellt");
      IPAddress ip = WiFi.localIP();
      Serial.print("IP-Adresse: ");
      Serial.println(ip);
      return;  // Verbindung erfolgreich, beende die Funktion
    }

    // Verbindung nicht erfolgreich, trenne die Verbindung
    WiFi.disconnect();

    // Warte 30 Sekunden vor dem nächsten Versuch
    delay(30000);

    connectAttempts++;
  }

  Serial.println("WiFi-Verbindung fehlgeschlagen");
}

time_t getNtpTime() {
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
  }

  WiFi.hostByName("pool.ntp.org", timeServerIP);
  Serial.println("Zeitserver IP-Adresse erhalten");

  const int NTP_PACKET_SIZE = 48;
  byte packetBuffer[NTP_PACKET_SIZE];

  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  packetBuffer[0] = 0b11100011;
  packetBuffer[1] = 0;
  packetBuffer[2] = 6;
  packetBuffer[3] = 0xEC;
  packetBuffer[12] = 49;
  packetBuffer[13] = 0x4E;
  packetBuffer[14] = 49;
  packetBuffer[15] = 52;

  WiFiUDP udp;
  udp.begin(123);
  udp.beginPacket(timeServerIP, 123);
  udp.write(packetBuffer, NTP_PACKET_SIZE);
  udp.endPacket();

  uint32_t beginWait = millis();
  while (millis() - beginWait < 5000) {
    int size = udp.parsePacket();
    if (size >= NTP_PACKET_SIZE) {
      udp.read(packetBuffer, NTP_PACKET_SIZE);
      unsigned long secsSince1900 = (unsigned long)packetBuffer[40] << 24 | (unsigned long)packetBuffer[41] << 16 | (unsigned long)packetBuffer[42] << 8 | (unsigned long)packetBuffer[43];

      time_t ntpTime = secsSince1900 - 2208988800UL;

      // Hier wird die DST-Offset-Korrektur angewendet
      ntpTime += (isDaylightSavingTime(ntpTime) ? 3600 : 0);
      ntpTime += (timeZoneOffset * 3600);  // Zeitzonenverschiebung hinzufügen

      // Aktuelles Datum und Uhrzeit ausgeben
      Serial.print("Datum: ");
      Serial.print(day(ntpTime));
      Serial.print("-");
      Serial.print(month(ntpTime));
      Serial.print("-");
      Serial.print(year(ntpTime));
      Serial.println(" ");
      Serial.print("Uhrzeit: ");
      Serial.print(hour(ntpTime));
      Serial.print(":");
      Serial.print(minute(ntpTime));
      Serial.print(":");
      Serial.println(second(ntpTime));

      return ntpTime;
    }
    delay(10);
  }

  Serial.println("Keine Antwort vom Zeitserver");
  return 0;
}

void moveStepper(int position) {
  Serial.println("#### MOTOR - BEWEGUNG - START ####");
  Serial.println("");
  if (stepper.currentPosition() != position) {
    stepper.moveTo(position);
    stepper.runToPosition();
  }
  Serial.println("#### MOTOR - BEWEGUNG - ENDE ####");
  Serial.println("");
}

void managePositions() {
  Serial.println("#### MOTOR - POSITIONEN - START ####");
  Serial.println("");
  currentTime = now();  // Aktualisiere den Wert der globalen Variable currentTime
  int currentMonth = month(currentTime);
  int currentDay = day(currentTime);
  int currentHour = hour(currentTime);
  int currentMinute = minute(currentTime);
  int currentSecond = second(currentTime);
  int currentTimeInSeconds = currentHour * 3600 + currentMinute * 60;

  Serial.print("Zeit: ");
  Serial.print(day(currentTime));
  Serial.print(".");
  Serial.print(month(currentTime));
  Serial.print(".");
  Serial.print(year(currentTime));
  Serial.print(" ");
  // Führende Null für einstellige Stunden
  Serial.print(currentHour < 10 ? "0" + String(currentHour) : String(currentHour));
  Serial.print(":");
  // Führende Null für einstellige Minuten
  Serial.print(currentMinute < 10 ? "0" + String(currentMinute) : String(currentMinute));
  Serial.print(":");
  // Führende Null für einstellige Sekunden
  Serial.println(currentSecond < 10 ? "0" + String(currentSecond) : String(currentSecond));
  Serial.println("");
  // Überprüfe, ob Sommerzeit oder Winterzeit aktiv ist
  bool isDST = isDaylightSavingTime(currentTime);

  struct PositionThreshold {
    int thresholdHour;
    int thresholdMinute;
    long position;
  };

  PositionThreshold PositionenSommer[] = {
    { 6, 0, Startposition },
    { 11, 0, Vormittag1 },
    { 12, 0, Vormittag2 },
    { 12, 30, Mittag1 },
    { 13, 0, Mittag2 },
    { 13, 30, Nachmittag1 },
    { 14, 0, Nachmittag2 },
    { 15, 0, Nachmittag3 },
    { 16, 0, Endposition },
    { 21, 0, Windschutz }
  };

  PositionThreshold PositionenWinter[] = {
    { 8, 0, Vormittag1 },
    { 10, 30, Vormittag2 },
    { 12, 0, Mittag1 },
    { 12, 30, Mittag2 },
    { 13, 0, Nachmittag1 },
    { 14, 0, Nachmittag2 },
    { 15, 0, Nachmittag3 },
    { 17, 30, Windschutz }
  };

  PositionThreshold PositionenZwischen[] = {
    { 7, 0, Startposition },
    { 9, 0, Vormittag1 },
    { 11, 0, Vormittag2 },
    { 12, 0, Mittag1 },
    { 13, 0, Mittag2 },
    { 14, 0, Nachmittag1 },
    { 15, 0, Nachmittag2 },
    { 16, 0, Nachmittag3 },
    { 17, 0, Endposition },
    { 18, 30, Windschutz }
  };

  int numThresholds;
  PositionThreshold *thresholds;

  if (currentMonth == 1 || currentMonth == 2 || currentMonth == 11 || currentMonth == 12) {
    thresholds = PositionenWinter;
    numThresholds = sizeof(PositionenWinter) / sizeof(PositionenWinter[0]);
  } else if (currentMonth == 3 || currentMonth == 4 || currentMonth == 9 || currentMonth == 10) {
    thresholds = PositionenZwischen;
    numThresholds = sizeof(PositionenZwischen) / sizeof(PositionenZwischen[0]);
  } else if (currentMonth >= 5 && currentMonth <= 8) {
    thresholds = PositionenSommer;
    numThresholds = sizeof(PositionenSommer) / sizeof(PositionenSommer[0]);
  } else {
    // Standardpositionen oder eine andere Logik hier einfügen, wenn erforderlich
    thresholds = PositionenSommer;
    numThresholds = sizeof(PositionenSommer) / sizeof(PositionenSommer[0]);
  }

  long position = Startposition;  // Standardposition

  for (int i = 0; i < numThresholds; i++) {
    if (currentHour > thresholds[i].thresholdHour || (currentHour == thresholds[i].thresholdHour && currentMinute >= thresholds[i].thresholdMinute)) {
      position = thresholds[i].position;
    } else {
      break;  // Schleife abbrechen, da der Rest der Schwellenwerte nicht mehr relevant ist
    }
  }

  moveStepper(position);
  Serial.println("");
  Serial.print("Aktive Positionen: ");
  if (currentMonth == 1 || currentMonth == 2 || currentMonth == 11 || currentMonth == 12) {
    Serial.println("Winterpositionen");
  } else if (currentMonth == 3 || currentMonth == 4 || currentMonth == 9 || currentMonth == 10) {
    Serial.println("Zwischenpositionen");
  } else if (currentMonth >= 5 && currentMonth <= 8) {
    Serial.println("Sommerpositionen");
  } else {
    Serial.println("Standardpositionen");  // Standardpositionen oder eine andere Bezeichnung hier einfügen, wenn erforderlich
  }
  Serial.print("Position: ");
  Serial.println(stepper.currentPosition());

  Serial.println("#### MOTOR - POSITIONEN - ENDE ####");
  Serial.println("");
}

void checkWindsensor() {
  //currentTime = now(); // Aktualisiere den Wert der globalen Variable currentTime
  Serial.println("");
  Serial.println("#### WINDSENSOR - CHECK - START ####");
  Serial.println("");
  if (digitalRead(PIN_BUTTON) == HIGH) {
    Warteposition_aktiv = true;
    WindschutzTimer = millis();
    Serial.println("WINDSENSOR - AUSGELÖST");
    Serial.print("WINDSENSOR - ");
    Serial.println(WindschutzTimer);
    Serial.println("");
    stepper.moveTo(Windschutz);
    stepper.runToPosition();
    Serial.print("WINDSENSOR - AKTIVIERT - Position: ");
    Serial.println(stepper.currentPosition());
    Serial.println("");
  }

  if (millis() - WindschutzTimer >= WindWartezeit_ms) {
    Warteposition_aktiv = false;
    Serial.println("");
    Serial.println("Windsensor deaktiviert");
    Serial.println("");
  }
  Serial.println("#### WINDSENSOR - CHECK - ENDE ####");
  Serial.println("");
  if (!Warteposition_aktiv) {
    managePositions();  // Nur wenn der Windsensor nicht aktiv ist, rufe managePositions auf
  }
}

void handleRoot() {
  WiFiClient client = server.available();
  if (client) {
    String request = client.readStringUntil('\r');
    client.flush();

    if (request.indexOf("/deaktivieren") != -1) {
      // Logik zum Deaktivieren des Windsensors hier
      Warteposition_aktiv = false;
      Serial.println("Windsensor deaktiviert");
    } else if (request.indexOf("/aktivieren") != -1) {
      // Logik zum Aktivieren des Windsensors hier
      Warteposition_aktiv = true;
      WindschutzTimer = millis();
      Serial.println("Windsensor aktiviert");

      // Setze die Zielposition für den Windschutz und bewege den Motor zur Windschutzposition
      stepper.moveTo(Windschutz);
      stepper.runToPosition();
      Serial.print(stepper.currentPosition());
    } else if (request.indexOf("/position_setzen") != -1) {
      // Logik zum Setzen der Windschutzposition hier
      Warteposition_aktiv = true;
      WindschutzTimer = millis();
      Serial.println("Windsensor aktiviert");

      // Setze die Zielposition für den Windschutz und bewege den Motor zur Windschutzposition
      stepper.moveTo(Endposition);
      stepper.runToPosition();
      Serial.print(stepper.currentPosition());
    } else if (request.indexOf("/startposition_setzen") != -1) {
      // Logik zum Setzen der Startposition hier
      Warteposition_aktiv = true;
      WindschutzTimer = millis();
      Serial.println("Windsensor aktiviert");

      // Setze die Zielposition für den Motor zur Startposition und bewege den Motor dorthin
      stepper.moveTo(Startposition);
      stepper.runToPosition();
      Serial.print(stepper.currentPosition());
    } else if (request.indexOf("/drehen_plus_1000") != -1) {
      // Logik zum Drehen des Motors um +1000 Schritte hier
      stepper.move(1000); // Motor um 1000 Schritte erhöhen
      stepper.runToPosition(); // Motor zur neuen Position bewegen
      Serial.print("Motor um 1000 Schritte erhöht. Aktuelle Position: ");
      Serial.println(stepper.currentPosition());

      // Aktiviere den Windsensor, um die neue Position zu halten
      Warteposition_aktiv = true;
      WindschutzTimer = millis();
      Serial.println("Windsensor aktiviert");
    } else if (request.indexOf("/drehen_minus_1000") != -1) {
      // Logik zum Drehen des Motors um -1000 Schritte hier
      stepper.move(-1000); // Motor um 1000 Schritte reduzieren
      stepper.runToPosition(); // Motor zur neuen Position bewegen
      Serial.print("Motor um 1000 Schritte reduziert. Aktuelle Position: ");
      Serial.println(stepper.currentPosition());

      // Aktiviere den Windsensor, um die neue Position zu halten
      Warteposition_aktiv = true;
      WindschutzTimer = millis();
      Serial.println("Windsensor aktiviert");
    }

    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: text/html");
    client.println();
    client.println("<html><body>");
    client.println("<h1><strong>Balkonkraftwerk</strong></h1>");
    // IP-Adresse
    client.print("<p><strong>IP-Adresse:</strong> ");
    client.print(WiFi.localIP());
    client.println("</p>");

    // Datum und Uhrzeit
    client.print("<strong>Datum:</strong> ");
    client.print(day(currentTime));
    client.print(".");
    client.print(month(currentTime));
    client.print(".");
    client.print(year(currentTime));
    client.print("<br>");

    client.print("<strong>Uhrzeit:</strong> ");
    client.print((hour(currentTime) < 10 ? "0" : ""));
    client.print(hour(currentTime));
    client.print(":");
    client.print((minute(currentTime) < 10 ? "0" : ""));
    client.print(minute(currentTime));
    client.print(":");
    client.print((second(currentTime) < 10 ? "0" : ""));
    client.print(second(currentTime));
    client.print("<br>");

    // Sommer- oder Winterzeit
    client.print("<strong>S/W-Zeit:</strong> ");
    client.print(isDaylightSavingTime(currentTime) ? "Sommerzeit" : "Winterzeit");
    client.print("");

    // Aktuelle Position
    client.print("<p><strong>Aktuelle Position:</strong> ");
    client.print(stepper.currentPosition());
    client.print("<br>");

    // Positionsset
    int currentMonth = month(currentTime);  // Den aktuellen Monat holen
    client.print("<strong>Positionsset:</strong> ");
    if (currentMonth == 1 || currentMonth == 2 || currentMonth == 11 || currentMonth == 12) {
      client.print("Winter");
    } else if (currentMonth == 3 || currentMonth == 4 || currentMonth == 9 || currentMonth == 10) {
      client.print("Zwischen");
    } else if (currentMonth >= 5 and currentMonth <= 8) {
      client.print("Sommer");
    } else {
      client.print("Standard");
    }
    client.print("<br>");

    // Status des Windsensors
    client.print("<p><strong>Windsensor:</strong> ");
    if (Warteposition_aktiv) {
      // Wenn der Windsensor aktiviert ist, den Text in Rot anzeigen
      client.print("<span style='color:red;'>Aktiviert</span>");
    } else {
      // Wenn der Windsensor deaktiviert ist, den Text in Grün anzeigen
      client.print("<span style='color:green;'>Deaktiviert</span>");
    }

    // Zeitdauer des aktiven Windsensors
    if (Warteposition_aktiv) {
      unsigned long currentTimeInSeconds = (millis() - WindschutzTimer) / 1000;
      int minutes = currentTimeInSeconds / 60;
      int seconds = currentTimeInSeconds % 60;
      client.print(" - ");
      // Wenn der Windsensor aktiviert ist, die Zeit in Rot anzeigen
      client.print("<span style='color:red;'>");
      client.print(minutes);
      client.print(" Min ");
      client.print(seconds);
      client.print(" Sek");
      client.print("</span>");
    }

    // Formular zum Deaktivieren und Aktivieren des Windsensors
    client.println("<div style='display: flex;'><form action='/deaktivieren' method='get'><input type='submit' value='Windsensor deaktivieren'></form>");
    client.println("<form action='/aktivieren' method='get' style='margin-left: 10px;'><input type='submit' value='Windsensor aktivieren'></form></div>");
    client.println("<form action='/position_setzen' method='get' style='margin-left: 10px;'><input type='submit' value='Endposition'></form>");
    client.println("<form action='/startposition_setzen' method='get' style='margin-left: 10px;'><input type='submit' value='Startposition'></form>");
    client.println("<form action='/drehen_plus_1000' method='get' style='margin-left: 10px;'><input type='submit' value='Motor um +1000 erhöhen'></form>");
    client.println("<form action='/drehen_minus_1000' method='get' style='margin-left: 10px;'><input type='submit' value='Motor um -1000 reduzieren'></form>");

    client.println("</body></html>");
    client.stop();
  }
}

void reconnect() {
  // Loop, bis eine Verbindung hergestellt wird
  while (!client.connected()) {
    Serial.print("MQTT - Broker - ");
    // Verbindung mit MQTT-Broker herstellen, einschließlich Benutzername und Passwort
    if (client.connect("ArduinoClient", mqtt_user, mqtt_password)) {
      Serial.println("verbunden");
    } else {
      Serial.print("Fehlgeschlagen, rc=");
      Serial.print(client.state());
      Serial.println(" Versuche es in 5 Sekunden erneut");
      // 5 Sekunden warten und erneut versuchen
      delay(5000);
    }
  }
}

unsigned long lastSendTime = 0; // Variable, um die Zeit des letzten Sendens zu speichern

void sendMQTTData() {
  // Überprüfe, ob eine Verbindung zum MQTT-Broker besteht
  //if (!client.connected()) {
  //  reconnect();
  //}
    // Erfasse die aktuellen Zeit
  unsigned long currentTime = millis();

  // Sende die MQTT-Nachrichten nur, wenn seit dem letzten Senden mehr als 5 Sekunden vergangen sind
  if (currentTime - lastSendTime >= 15000) {
    // Erfasse die Daten, die du übertragen möchtest
    int motorPosition = stepper.currentPosition();
    String windsensorStatus = Warteposition_aktiv ? "Aktiviert" : "Deaktiviert";
    String zeitzone = isDaylightSavingTime(currentTime) ? "Sommerzeit" : "Winterzeit";
    String positionsset;
    int currentMonth = month(currentTime);
    if (currentMonth == 1 || currentMonth == 2 || currentMonth == 11 || currentMonth == 12) {
      positionsset = "Winter";
    } else if (currentMonth == 3 || currentMonth == 4 || currentMonth == 9 || currentMonth == 10) {
      positionsset = "Zwischen";
    } else if (currentMonth >= 5 && currentMonth <= 8) {
      positionsset = "Sommer";
    } else {
      positionsset = "Standard";
    }
    // Erfasse die aktuelle Uhrzeit
    String currentTimeStr = String(hour()) + ":" + minute() + ":" + second();

    // Debugging-Ausgabe, um sicherzustellen, dass der Codeabschnitt erreicht wird
    Serial.println("");
    Serial.println("");
    Serial.println("##### MQTT-Nachrichtenversand #####");

    // Veröffentliche die MQTT-Nachrichten mit den erfassten Daten
    Serial.print("Motorposition: ");
    Serial.println(motorPosition);
    client.publish("solar/bkw-steuerung/motorposition", String(motorPosition).c_str());

    Serial.print("Windsensor-Status: ");
    Serial.println(windsensorStatus);
    client.publish("solar/bkw-steuerung/windsensor", windsensorStatus.c_str());

    Serial.print("Zeitzone: ");
    Serial.println(zeitzone);
    client.publish("solar/bkw-steuerung/zeitzone", zeitzone.c_str());

    Serial.print("Positionsset: ");
    Serial.println(positionsset);
    client.publish("solar/bkw-steuerung/positionsset", positionsset.c_str());

    Serial.print("Aktuelle Uhrzeit: ");
    Serial.println(currentTimeStr);
    client.publish("solar/bkw-steuerung/uhrzeit", currentTimeStr.c_str());

    Serial.println("##### MQTT-Nachrichtenversand - ERFOLGREICH #####");
    Serial.println("");
    Serial.println("");
    // Setze die Zeit des letzten Sendens auf die aktuelle Zeit
    lastSendTime = currentTime;
  }
}

void sendDiscoveryMessage(const char* topic, const char* name, const char* stateTopic, const char* stateClass = "") {
  // Erstelle die Entdeckungsnachricht im JSON-Format
  String discoveryMessage = "{";
  discoveryMessage += "\"name\":\"" + String(name) + "\",";
  discoveryMessage += "\"state_topic\":\"" + String(stateTopic) + "\"";
  
  // Füge den state_class-Parameter hinzu, wenn er übergeben wurde
  if (strlen(stateClass) > 0) {
    discoveryMessage += ",\"state_class\":\"" + String(stateClass) + "\"";
  }
  
  discoveryMessage += "}";

  // Sende die Entdeckungsnachricht
  client.publish(("homeassistant/sensor/bkw-steuerung/" + String(name) + "/config").c_str(), discoveryMessage.c_str(), true);
}

void sendMQTTAutoDiscovery() {
  Serial.println("#### AutoDiscovery-Nachricht - Versand ####");
  sendDiscoveryMessage("solar/BKW-Steuerung/motorposition", "Motorposition", "solar/bkw-steuerung/motorposition", "measurement");
  sendDiscoveryMessage("solar/BKW-Steuerung/windsensor", "Windsensor", "solar/bkw-steuerung/windsensor");
  sendDiscoveryMessage("solar/BKW-Steuerung/zeitzone", "Zeitzone", "solar/bkw-steuerung/zeitzone");
  sendDiscoveryMessage("solar/BKW-Steuerung/positionsset", "Positionsset", "solar/bkw-steuerung/positionsset");
  sendDiscoveryMessage("solar/BKW-Steuerung/uhrzeit", "Uhrzeit", "solar/bkw-steuerung/uhrzeit");
  Serial.println("#### AutoDiscovery-Nachricht - Versand - ERFOLGREICH ####");
}

void callback(char* topic, byte* payload, unsigned int length) {
  // Debugging-Ausgabe, um sicherzustellen, dass die callback-Funktion aufgerufen wird
  Serial.println("Callback-Funktion wurde aufgerufen!");

  Serial.print("Nachricht empfangen [");
  Serial.print(topic);
  Serial.print("] ");

  String message = "";
  for (int i = 0; i < length; i++) {
    message += (char)payload[i]; // Füge jeden Byte des Payloads zum String hinzu
  }

  message.trim(); // Entferne führende und abschließende Leerzeichen

  Serial.println(message);

if (strcmp(topic, "solar/bkw-steuerung/app") == 0) {
  if (message.equals("Windsensor aktivieren")) {
    // Führe Logik zum Bewegen des Motors in die Windschutzposition durch
    // Hier können Sie die entsprechenden Stepper-Motorbefehle einfügen
    stepper.moveTo(Windschutz);
    stepper.runToPosition();
    Serial.println("Motor fährt in die Windschutzposition.");
    Warteposition_aktiv = true; // Setze die Warteposition auf aktiv
  } else if (message.equals("Windsensor deaktivieren")) {
    Warteposition_aktiv = false; // Setze die Warteposition auf inaktiv
    Serial.println("Windsensor wurde deaktiviert.");
    // Führen Sie hier den normalen Programmablauf fort
  } else if (message.equals("position_setzen")) {
    // Logik zum Setzen der Windschutzposition hier
    // Hier könnte zusätzliche Logik zur Handhabung der Position gesetzt werden
    Warteposition_aktiv = true; // Setze die Warteposition auf aktiv
  } else if (message.equals("Startposition")) {
    stepper.moveTo(Startposition);
    stepper.runToPosition();
    Serial.println("Motor fährt zur Startposition.");
    Warteposition_aktiv = true; // Setze die Warteposition auf aktiv
  } else if (message.equals("Endposition")) {
    stepper.moveTo(Endposition);
    stepper.runToPosition();
    Serial.println("Motor fährt zur Endposition.");
    Warteposition_aktiv = true; // Setze die Warteposition auf aktiv
  } else if (message.equals("+1000")) {
    int newPos = stepper.currentPosition() + 1000;
    stepper.moveTo(newPos);
    stepper.runToPosition();
    Serial.println("Motor fährt um +1000 Positionen.");
    Warteposition_aktiv = true; // Setze die Warteposition auf aktiv
  } else if (message.equals("-1000")) {
    int newPos = stepper.currentPosition() - 1000;
    stepper.moveTo(newPos);
    stepper.runToPosition();
    Serial.println("Motor fährt um -1000 Positionen.");
    Warteposition_aktiv = true; // Setze die Warteposition auf aktiv
  } else if (message.equals("-17000")) {
    int newPos = stepper.currentPosition() - 17000;
    stepper.moveTo(newPos);
    stepper.runToPosition();
    Serial.println("Motor fährt um -17500 Positionen.");
    Warteposition_aktiv = true; // Setze die Warteposition auf aktiv
  } else if (message.equals("+24000")) {
    int newPos = stepper.currentPosition() + 24000;
    stepper.moveTo(newPos);
    stepper.runToPosition();
    Serial.println("Motor fährt um +24000 Positionen.");
    Warteposition_aktiv = true; // Setze die Warteposition auf aktiv
  }
  // Aktualisiere den Status und die Zeit für den Windschutz außerhalb der Windsensor-Abfrage
  WindschutzTimer = millis();
  }
}


Hallo,

um das mit dem Arduino Uno R4 WiFi zu testen muss man ihn nicht zwangsweise kaufen. Richte die IDE dafür ein und kompiliere den Sketch. Dann kann man im Trockendock ausprobieren und ggf. Anpassungen vornehmen. Aber ob jemand dann helfen kann wenn es klemmt ist die Frage. Im Unterforum hier zum Board wäre dann wohl die beste Stelle dafür. Ich weiß nicht wieviel Deutsche hier so ein Board haben und damit wirklich etwas machen.

1 Like

Wie gesagt, muss ja nicht das Board werden. Genau deshalb habe ich mich ja ans Forum gewandt um da Unterstützung zu bekommen. Also welches Board als Alternative am meisten Sinn macht.

AccelStepper soll noch nicht kompatibel mit dem R4 sein...

1 Like

Gerade die hasse wie die Pest bei mir ist alles oder geschraubt oder gelötet. Für Displays und Sachen mit mehr als 4 Pins nutze nur mehrpolige Verbinder ( Beispiel) was werden auf anderer Seite verschraubt die "Sitzen" wenigsten vernünftig.
Nur wie im Leben das ist, jeder macht wie er Gut findet.

Hallo,

wegen deinem Board Sterben nochmal. Wie wird das denn versorgt? Wie ist alles miteinander verbunden? Gibt es einen echten Schaltplan bzw. Beschaltungsplan dafür?

Thema Kabelverbindungen. Wenn es irgendwie möglich nimmt man Federklemme, danach Schraubverbindungen. Federklemme ist die sicherste Kontaktart. Löten würde ich nicht mehr. Das Risiko das es bricht ist ziemlich hoch. Dafür muss dann mindestens eine zusätzliche Zugentlastung herhalten. Bspw. wenn es im Gehäuse gelötet ist und nach außen flexibel bleiben soll.

Einen Plan gibt es so nicht. Am Ende steuert der Arduino den Stepper-Treiber an. :-/

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.