an genau sowas probiere ich mich auch gerade, mit Hilfe von KI, aber leider bekomme ich keine Verbindung zur Z21 (schwarz)hin.
Wäre es möglich den Code aus dem Video zu bekommen? Perfekt wäre für Adruino IDE.
Ich hatte allerdings für jede LED einen separaten PIN genutzt so brauch man keine NPN / PNP. Aber vielleicht spart man bei deiner Methode ja PINS ein und brauch keine Erweiterung aller MCP23017.
Ich stelle mal meinen Code ein, vielleicht findet ja jemand den Fehler.
Der Webserver ist erstmal ein „nice to have“, und nicht wirklich nötig.
Fehler stecken sicher irgendwo im "Z21 Weichenbefehl senden" (void sendWeiche). Aber wir (KI und ich) haben es an einen ganzen Nachmittag nicht hinbekommen eine Verbindung aufzubauen.
Folgende Funktion sind im Code:
-4 Weichen (Adressen 120–123)
-Entprellung (Taster)
-LED-Update
-Z21-Rückmeldung
-Start-Synchronisation
-Weichenbefehl senden
Loop:
-Z21 Rückmeldungen empfangen
-Taster entprellen
-Weichen schalten
-LEDs aktualisieren
Quelltext:
Code: Alles auswählen
#include <wifi_config.h> //WLAN Login
#include <WiFi.h>
#include <WiFiUdp.h>
#include <WebServer.h>
#include <EEPROM.h>
IPAddress z21(192,168,0,111);
WiFiUDP udp;
WebServer server(80);
#define EEPROM_SIZE 64
// -----------------------------
// Weichen-Struct
// -----------------------------
struct Weiche {
uint16_t adresse; // DCC-Adresse
uint8_t tasterPin; // Taster-Pin
uint8_t ledGerade; // LED für "gerade"
uint8_t ledAbzweig; // LED für "abzweig"
bool state; // Weichenstellung (false = gerade)
bool lastState; // letzter Rohwert
bool stableState; // entprellter Zustand
unsigned long lastChangeTime;
};
// -----------------------------
// 4 Weichen
// Adresse, Taster, Led1, LED2
// -----------------------------
Weiche weichen[] = {
{ 120, 15, 18, 19, false, HIGH, HIGH, 0 },
{ 121, 4, 21, 22, false, HIGH, HIGH, 0 },
{ 122, 13, 23, 25, false, HIGH, HIGH, 0 },
{ 123, 14, 26, 27, false, HIGH, HIGH, 0 }
};
const int anzahlWeichen = sizeof(weichen) / sizeof(weichen[0]);
const unsigned long debounceTime = 50;
// -----------------------------
// LED-Update
// -----------------------------
void updateLEDs(Weiche &w) {
if (w.state == false) { // gerade
digitalWrite(w.ledGerade, HIGH);
digitalWrite(w.ledAbzweig, LOW);
} else { // abzweig
digitalWrite(w.ledGerade, LOW);
digitalWrite(w.ledAbzweig, HIGH);
}
}
// -----------------------------
// EEPROM: Weichen speichern
// -----------------------------
void saveWeichenToEEPROM() {
Serial.println("Speichere Weichen in EEPROM...");
for (int i = 0; i < anzahlWeichen; i++) {
EEPROM.write(i, weichen[i].state ? 1 : 0);
Serial.print(" Weiche ");
Serial.print(weichen[i].adresse);
Serial.print(" -> ");
Serial.println(weichen[i].state ? "Abzweig" : "Gerade");
}
EEPROM.commit();
}
// -----------------------------
// EEPROM: Weichen laden
// -----------------------------
void loadWeichenFromEEPROM() {
Serial.println("Lade Weichen aus EEPROM...");
for (int i = 0; i < anzahlWeichen; i++) {
uint8_t v = EEPROM.read(i);
weichen[i].state = (v != 0);
updateLEDs(weichen[i]);
Serial.print(" Weiche ");
Serial.print(weichen[i].adresse);
Serial.print(" -> ");
Serial.println(weichen[i].state ? "Abzweig" : "Gerade");
}
}
// -----------------------------
// Z21 Weichenbefehl senden
// -----------------------------
void sendWeiche(uint16_t addr, bool gerade) {
uint8_t buf[6];
buf[0] = 0x04;
buf[1] = 0x00;
buf[2] = 0x40;
buf[3] = 0x00;
buf[4] = (addr >> 8) & 0xFF;
buf[5] = (addr & 0xFF) << 1;
buf[5] |= 0x02;
if (!gerade) buf[5] |= 0x01;
udp.beginPacket(z21, 21105);
udp.write(buf, 6);
udp.endPacket();
Serial.print("Z21 SEND: Weiche ");
Serial.print(addr);
Serial.print(" -> ");
Serial.println(gerade ? "Gerade" : "Abzweig");
}
// -----------------------------
// Z21 Rückmeldungen empfangen
// -----------------------------
void empfangeZ21() {
int packetSize = udp.parsePacket();
if (packetSize <= 0) return;
uint8_t buf[20];
udp.read(buf, packetSize);
if (buf[2] == 0x40 && buf[3] == 0x00 && packetSize >= 6) {
uint16_t addr = (buf[4] << 8) | (buf[5] >> 1);
bool gerade = !(buf[5] & 0x01);
Serial.print("Z21 RECV: Weiche ");
Serial.print(addr);
Serial.print(" -> ");
Serial.println(gerade ? "Gerade" : "Abzweig");
for (int i = 0; i < anzahlWeichen; i++) {
if (weichen[i].adresse == addr) {
weichen[i].state = !gerade;
updateLEDs(weichen[i]);
saveWeichenToEEPROM();
}
}
}
}
// -----------------------------
// Z21 Status beim Start anfordern
// -----------------------------
void requestZ21WeichenStatus() {
uint8_t buf[5] = {0x05, 0x00, 0x40, 0x00, 0xF0};
udp.beginPacket(z21, 21105);
udp.write(buf, 5);
udp.endPacket();
Serial.println("Z21: Statusanforderung gesendet.");
}
// -----------------------------
// Webinterface HTML
// -----------------------------
String buildPage() {
String html = "<html><head><meta name='viewport' content='width=device-width, initial-scale=1'>";
html += "<style>body{font-family:sans-serif;}button{width:120px;height:40px;font-size:18px;margin:10px;}</style></head><body>";
html += "<h2>Weichensteuerung</h2>";
for (int i = 0; i < anzahlWeichen; i++) {
html += "Weiche ";
html += weichen[i].adresse;
html += ": ";
html += "<a href='/toggle?i=" + String(i) + "'>";
html += "<button>";
html += (weichen[i].state ? "Abzweig" : "Gerade");
html += "</button></a><br>";
}
html += "</body></html>";
return html;
}
void handleRoot() {
server.send(200, "text/html", buildPage());
}
void handleToggle() {
int i = server.arg("i").toInt();
Serial.print("WEB: Weiche ");
Serial.print(weichen[i].adresse);
Serial.println(" getoggelt.");
weichen[i].state = !weichen[i].state;
sendWeiche(weichen[i].adresse, !weichen[i].state);
updateLEDs(weichen[i]);
saveWeichenToEEPROM();
server.sendHeader("Location", "/");
server.send(303);
// -----------------------------
// Setup
// -----------------------------
void setup() {
Serial.begin(115200);
Serial.println();
Serial.println("Starte ESP32 Weichensteuerung...");
Serial.print("Verbinde mit WLAN: ");
Serial.println(ssid);
WiFi.begin(ssid, pass);
int counter = 0;
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
counter++;
if (counter % 10 == 0) {
Serial.print(" (warte ");
Serial.print(counter / 2);
Serial.println(" Sekunden)");
}
}
Serial.println();
Serial.println("WLAN verbunden!");
Serial.print("IP-Adresse: ");
Serial.println(WiFi.localIP());
Serial.println("--------------------------------------");
udp.begin(21105);
EEPROM.begin(EEPROM_SIZE);
for (int i = 0; i < anzahlWeichen; i++) {
pinMode(weichen[i].tasterPin, INPUT_PULLUP);
pinMode(weichen[i].ledGerade, OUTPUT);
pinMode(weichen[i].ledAbzweig, OUTPUT);
}
loadWeichenFromEEPROM();
delay(300);
requestZ21WeichenStatus();
server.on("/", handleRoot);
server.on("/toggle", handleToggle);
server.begin();
}
// -----------------------------
// Loop
// -----------------------------
void loop() {
server.handleClient();
empfangeZ21(); // Z21 Rückmeldungen verarbeiten
for (int i = 0; i < anzahlWeichen; i++) {
bool reading = digitalRead(weichen[i].tasterPin);
if (reading != weichen[i].lastState) {
weichen[i].lastChangeTime = millis();
weichen[i].lastState = reading;
}
if ((millis() - weichen[i].lastChangeTime) > debounceTime) {
if (reading != weichen[i].stableState) {
weichen[i].stableState = reading;
if (reading == LOW) {
weichen[i].state = !weichen[i].state;
Serial.print("TASTER: Weiche ");
Serial.print(weichen[i].adresse);
Serial.print(" -> ");
Serial.println(weichen[i].state ? "Abzweig" : "Gerade");
sendWeiche(weichen[i].adresse, !weichen[i].state);
updateLEDs(weichen[i]);
saveWeichenToEEPROM();
}
}
}
}
}