Hallo Zusammen, ich suche jemand der mir den passenden Sketch für die Steuerung der Relaiskarte schreibt. Diese ist simpel...
Es soll ein Shelly das Eingangssignal ON/OFF liefern.
Die 16 Relais sollen der Reihe nach sich Einschslten, mit jedem weiteren ON Zustand soll das nächste Relais Einschalten und so lange an bleiben, wie das ON Signal vom Shelly kommt(alle anderen Relais sollen aus sein). Es soll nur 1 Relais an sein.
Hintergrund: es soll der 6 fach Wasserverteiler von Gardena durch einzelne Magnetventile ersetz werden. Der Wasserverteiler ist eine Art Revolver und setzt immer eine Stufe weiter mit dem Wasserhahn AUF und ZU Signal, was durch den Shelly (Funksteckdose) und Magnetventil realisiert wird
Ja, der Shelly schaltet aktuell das 24V AC Netzteil für das Rainbird Magnetventil und das Magnetventil schaltet nur wenn Spannung anliegt, oder fällt ab, wenn keine Spannung anliegt.
Das ist im prinzip ganz einfach, mit jedem EIN-schalten erhöhst Du einen Zähler um 1 und das jeweilige Relais wird damit ausgewählt.
Was mir fehlt: Was passiert, wenn das Shelly länger aus bleibt?
Soll dann der Wert erhalten bleiben oder dann zurück auf 0?
-> Hintergrund: Wenn Du mit länger Pause den Kanal zurücksetzt, könntest Du zwischendurch einfach anhalten und neu starten - sonst müsstest Du immer bis 16 durchschalten um wieder auf 0 zu kommen.
Schön wäre natürlich, wenn man den Sketch für 16 Schreibt aber im Sketch eine Option einbaut wenn man nur mit 4 Magnetventilen arbeitet, quasie nur von 1 bis 4 durch arbeitet.
Aber sonst wäre es auch kein Problem, da man ja die Relais am Ende auf das gleich Magnetventil legen kann, sodaß quasie bei 4 Verlauten, daß 1 und das 5 und das 9 und das 13 Relais das gleiche Magnetventil schaltet.
Wenn der Shelly länger aus bleibt äre es ein geniales Feature, daß er z.B. nach 4Stunden wieder beim 1 Relais anfängt.
Die Vorgabe kann man in die Software giessen oder z.B. mit 2 Eingangspins aka 2 bit auflösen.
Ich kann Dir schnell die 20 zeilen zusammenschreiben. Aber ich hab keinen ESP.
Du bist doch sonst auch nicht so unbewandert.
Der Shelly kommt mit einem NO zwischen GND und einem Pin.
Dann kommt ein debounce von 100ms rein und ein Timer auf millis()-basis für den reset und ein Zähler der den Umlauf mitzählt.
Gesteuert wird als Ausgabe ein array mit den Pins - fettig.
Den obolus spar Dir für ein gutes C++ Buch.
Den Zähler bau ich, testen lässt sich das bestimmt mit irgendeinem NodeMCU oder so; Da findet sich vielleicht jemand.
// forensketch - simpler Zähler und out auf Array
// Relaisplatine schalten - erster Anlauf mit 16 Relais
// https://forum.arduino.cc/t/sketch-fur-esp8266-16-relay/1123972/17
constexpr uint8_t inputPin = 2; // Eingang
constexpr uint8_t relais[] = {3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}; // Alle relaispins
constexpr uint8_t relaisNums = sizeof(relais) / sizeof(relais[0]); // errechnet die Anzahl der relais
constexpr uint32_t debounceTime = 100; // großzügig ;)
constexpr uint32_t resetTime = 1000UL * 60 * 60 * 4; // 1000ms = 1sek * 60 = 1Min *60 = 1Std * 4 = 4 Std
constexpr bool OFF = LOW; // Sollten die relais LOW-Aktiv sein, kommt hier HIGH rein.
uint32_t switchTime; // Merker für letzten Schaltzustand
uint8_t zaehler; //
void setup()
{
pinMode(inputPin, INPUT_PULLUP); // Pin schaltet nach GND
for (uint8_t b = 0; b < relaisNums; b++) // durch alle relais zaehlen
{
pinMode(relais[b], OUTPUT); //
digitalWrite(relais[b], OFF); //
}
}
void loop()
{
switch2Zaehler();
timer2Zaehler();
setRelais();
}
void switch2Zaehler() // Die Funktion löst bei Eingangsflanke HIGH/LOW aus
{
static bool lastSwitch = false; // Merker letzter Zustand
if (!digitalRead(inputPin)) // wenn ausgelöst
{
if (!lastSwitch) // und vorher nicht
{
lastSwitch = true; // merken das ausgelöst
zaehler++; // zaehler erhöhen
if (zaehler > relaisNums) // Grenze überschritten?
{ zaehler = 0; } // dann zurücksetzen
switchTime = millis(); // zeit merken
}
}
else if (millis() - switchTime > debounceTime) // Entprellt
{
lastSwitch = false; // und losgelassen
}
}
void timer2Zaehler()
{
if (millis() - switchTime > resetTime) // Zeit abgelaufen
{
zaehler = 0; // Vergessenen Shelly...
//switchTime=millis();
}
}
void setRelais()
{
static uint8_t lastZaehler = 0;
if (lastZaehler != zaehler) // Zaehlerstand hat sich geändert
{
for (uint8_t b = 0; b < relaisNums; b++) // Durch alle zaehlen
{
digitalWrite(relais[b], OFF); // und aus machen
}
lastZaehler = zaehler; // zaehler merken
}
if (zaehler != 0)
{ digitalWrite(zaehler - 1, !OFF); } // aktuellen zaehler einschalten
}
Das schlimmste sind immer die Kommentare verständlich zu schreiben...
Der hier würde jetzt mit/auf einem UNO laufen.
Das auf den ESP zu bringen, ist Kleinkram. Da müssen nur die Pins angepasst werden - fertig.
Noch'n Nachtrag:
Offensichtlich ist es das Board - Da ist die komplette Anschlussbelegung für die Schieberegister drin.
Also nur umschreiben und gut ist.
du könntest dir eine Funktion schreiben, die statt an digitalWrite auf die shift register ausgibt. Da du eh immer nur ein Relais einschalten willst, sollte das eigentlich ziemlich einfach sein.
edit mal zum testen:
/*
expand outputs with shift registers
activate one output after another
https://forum.arduino.cc/t/sketch-fur-esp8266-16-relay/1123972
2023-05-07 by noiasca
sketch in tread
*/
const uint8_t buttonPin = 19; // a button
const uint8_t stcpPin = 12; // GPIO12 74x595 RCLK/STCP
const uint8_t shcpPin = 13; // GPIO13 74x595 SRCLK/SHCP
const uint8_t serPin = 14; // GPIO14 74x595 SER/DS
const uint8_t oePin = 5; // GPIO05 74x595 OE/output enable active low
const uint8_t output[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; // the used outputs, can also be used to change the order of the outputs
//const uint8_t output[] {0, 8, 7, 15};
int actual = -1; // the actual output. -1 = all off
// generic shift out to two 74HC595 shift registers
void hc595Write(uint8_t pin, uint8_t val) {
if (pin > 15) return; // sanitize input
static uint16_t state = 0; // remember the state of all outputs in a bitmask
if (val == HIGH) {
state |= (1 << pin); // activate the pin in the bitmask
}
else {
state &= ~(1 << pin); // deactivate the pin in the bitmask
}
digitalWrite(stcpPin, LOW);
shiftOut(serPin, shcpPin, MSBFIRST, state >> 8); // send the higher nibble to second 74HC595
shiftOut(serPin, shcpPin, MSBFIRST, state & 0xFF); // send the lower nibble to first 74HC595
digitalWrite(stcpPin, HIGH);
}
// switch on next output
void next() {
actual++;
if (actual >= sizeof(output)) {
actual = 0; // wrap around
}
hc595Write(output[actual], HIGH); // switch on new
Serial.println(output[actual]);
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("Hello, ESP32!");
pinMode(buttonPin, INPUT);
pinMode(stcpPin, OUTPUT);
pinMode(shcpPin, OUTPUT);
pinMode(serPin, OUTPUT);
pinMode(oePin, OUTPUT);
digitalWrite(oePin, LOW); // enable the output
/*
// only testing
hc595Write(0, HIGH); // single write
delay(500);
hc595Write(0, LOW);
delay(500);
hc595Write(8, HIGH);
delay(500);
hc595Write(0, LOW);
*/
}
void loop() {
//"state change detection" taken from the IDE example and modified for this sketch
static int lastButtonState = HIGH; // needs to be static as it must survive the local scope of loop
// read the pushbutton input pin:
int buttonState = digitalRead(buttonPin); // a local variable is ok as we read in each iteration of loop
// compare the buttonState to its previous state
if (buttonState != lastButtonState) {
// if the state has changed, increment the counter
if (buttonState == HIGH) {
// if the current state is HIGH then the button went from off to on:
//Serial.println("on");
next();
} else {
// if the current state is LOW then the button went from on to off:
// switch off old
hc595Write(output[actual], LOW);
}
// Delay a little bit to avoid bouncing
delay(50);
}
// save the current state as the last state, for next time through the loop
lastButtonState = buttonState;
//delay(10); // only for this simulator!!!
}
So soll es funktionieren., Ah, nein nicht ganz, der Input Knopf, soll nur bei Dauernter Betätigung, die LED Abschalten, wenn der Knopf los gelassen wird, muss auch die LED ausgehen.