Relais Erweiterung mit MCP23017

@Vincent Kanst du mir bitte erklären, was es sich mit den functions "match relays w/ labels auf sich hat, also wie diese funktionieren?
Ich wollte über einen weiteren MCP23017 weitere Relais hinzufügen, die auch die Eigenschaften / Funktionen bekommen sollen, wie die von euch.
Ohne, daß ich in eure Flows eingreife.
Leider klappt das an der Stelle mit dem Namen nicht.
Danke, Stefan

Anbei Mein Flow
S-IO OUT.json (146.5 KB)

@range4200t Diese Funktion ist dazu da, die Labels der Switches anzupassen, wenn diese ihren Status ändern, sodass dann die Auto-Off Zeiten mit angezeigt werden.

function numberToWord(num) {
    const words = ["nine","ten","eleven","twelve","thirteen","fourteen","fiveteen","sixteen","seventeen","eighteen","nineteen","twenty","twenty-one","twenty-two","twenty-three","twenty-four"];
    return words[num];
}

if (msg.status.shape == "dot" && msg.status.fill == "blue" && msg.status.text == "1") {
    let relayNumber = msg.status.source.name.charAt(msg.status.source.name.length - 1);
    let relayNumberWord = numberToWord(relayNumber)
    msg.relayNumber = relayNumber
    let offtime = flow.get("offtime"+relayNumber)
    msg.offtime = offtime
    msg.relayname = offtime != null ? global.get("N"+relayNumberWord) + "<br><font size='-1'>(turn off at: " + flow.get("offtime"+relayNumber) + ")" : global.get("N"+relayNumberWord)

    // Prepare the output array, initializing all outputs to null
    let outputs = Array(16).fill(null);
    
    // Set the message to the appropriate output
    outputs[relayNumber - 1] = msg; // Subtract 1 because array index is 0-based
    
    // Send the message to the selected output
    return outputs;
}

Also, die Status Node überprüft die delays, die wir benannt haben nach den Relaynummern. Diese Nummern stehen dann an letzter Stelle von msg.status.source.name.
Wir extrahieren dann diese Zahl aus dem String mit .charAt(msg.status.source.name.length - 1), damit würde also nur noch die letzte Position des Names (nämlich die Zahl) weitergegeben werden. Jetzt wissen wir, dass diese Zahl immer einstellig ist, deswegen nehmen wir einfach das letzte Zeichen. Bei dir kann es aber auch zweistellig sein. Deswegen musst du die Funktion etwas umschreiben:

let relayNumber = msg.status.source.name.match(/\d+$/);
relayNumber = relayNumber[0]

Damit hast du eine “regular expression”, dabei sucht \d nach einer Nummer (0-9), das + stellt sicher, dass eine oder alls vorhanden zwei Zahlen genommen werden und $ ist dafür, dass das Ganze am Ende vom String sein muss. Das Ergebnis wird dann in ein Array geschrieben dass wir mit relayNumber[0] (= erste Stelle des Arrays) wieder rausfiltern.

Jetzt haben wir in relayNumber eine Zahl drinstehen und mit let relayNumberWord = numberToWord(relayNumber) wird die Function numberToWord aufgerufen, wobei relayNumber als Argument mitgegeben wird. Also am Beispiel von delay13. Die regular expression holt sich die 13 und danach wird numberToWord(13) aufgerufen.
In der Function wird dann mit return words[num] (in dem Fall return words[13] die dreizehnte Stelle (EDIT: die vierzehnte Stelle, array fängt bei 0 an) des arrays words ausgelesen, das wäre in deinem Fall “twenty-one”

Danach wird mit flow.get("offtime"+relayNumber) die flow Variable “offtime13” ausgelesen, ist diese undefined, kommt wahrscheinlich ein Fehler.

Die Zeile danach versucht global.get("N"+relayNumberWord) auszulesen, das wäre in deinem Fall die globale Variable “Ntwenty-one”. Und da ist dann dein Fehler, weil wir sind ja bei Relay 13 grade. Das heißt, die Art und Weise wie du auf das Array zugreifst ist falsch, weil wir dort die Position raussuchen. also TL:DR: Erweiter dein Array um die Wörter von den Zahlen davor zero one two three… (Bei null anfangen weil der Index bei 0 los geht).

Dann musst du sicherstellen, dass alle Variablen die aufgerufen werden auch existieren. Und dann sollte es eigentlich schon funktionieren :smiley:

Wow,wow,wow…
Vince ich danke dir.
Muss das erst einmal durcharbeiten und verstehen.
Warum werden die Namen nicht in MQTT geschrieben und von dort abgeholt?
Oder in einzelne Dateien? ( werden sie glaube ich sogar, oder ?)
Deine Lösung erscheint mir sehr aufwändig.
Gruß Stefan

Irgenwo stimmt noch etwas nicht.
Sosieht die erste function aus:
function numberToWord(num) {
const words = [“zero”, “one”, “two”, “three”, “four”, “five”, “six”, “seven”, “eight”,“nine”,“ten”,“eleven”,“twelve”,“thirteen”,“fourteen”,“fiveteen”,“sixteen”,“seventeen”,“eighteen”,“nineteen”,“twenty”,“twenty-one”,“twenty-two”,“twenty-three”,“twenty-four”];
return words[num];
}

if (msg.status.shape == “dot” && msg.status.fill == “blue” && msg.status.text == “1”) {
let relayNumber = msg.status.source.name.match(/\d+$/);
let relayNumberWord = numberToWord(relayNumber)
relayNumber = relayNumber[0]
// let relayNumber = msg.status.source.name.charAt(msg.status.source.name.length - 1);
// let relayNumberWord = numberToWord(relayNumber)
msg.relayNumber = relayNumber
let offtime = flow.get(“offtime”+relayNumber)
msg.offtime = offtime
msg.relayname = offtime != null ? global.get(“N”+relayNumberWord) + "
(turn off at: " + flow.get(“offtime”+relayNumber) + “)” : global.get(“N”+relayNumberWord)

// Prepare the output array, initializing all outputs to null
let outputs = Array(16).fill(null);

// Set the message to the appropriate output
outputs[relayNumber - 1] = msg; // Subtract 1 because array index is 0-based

// Send the message to the selected output
return outputs;

}

else if (msg.status.shape == “dot” && msg.status.fill == “blue” && msg.status.text == “0”) {
let relayNumber = msg.status.source.name.charAt(msg.status.source.name.length - 1);
let relayNumberWord = numberToWord(relayNumber)
msg.relayNumber = relayNumber
let offtime = flow.get(“offtime”+relayNumber)
msg.offtime = offtime
msg.relayname = global.get(“N”+relayNumberWord)

// Prepare the output array, initializing all outputs to null
let outputs = Array(16).fill(null);

// Set the message to the appropriate output
outputs[relayNumber - 1] = msg; // Subtract 1 because array index is 0-based

// Send the message to the selected output
return outputs;

}

und so die zweite:
function numberToWord(num) {
const words = [“zero”, “one”, “two”, “three”, “four”, “five”, “six”, “seven”, “eight”,“nine”,“ten”,“eleven”,“twelve”,“thirteen”,“fourteen”,“fiveteen”,“sixteen”,“seventeen”,“eighteen”,“nineteen”,“twenty”,“twenty-one”,“twenty-two”,“twenty-three”,“twenty-four”];
return words[num];
}

// Initialize an array to store messages for each output
let outputs = ;

// Iterate from 1 to 24 (corresponding to relay numbers 1 to 24)
for (let i = 1; i < 24; i++) {
let relayNumberWord = numberToWord(i);

let offtime = flow.get("offtime"+i)
let relayname = offtime != null ? global.get("N"+relayNumberWord) + "<br><font size='-1'>(turn off at: " + flow.get("offtime"+i) + ")" : global.get("N"+relayNumberWord)

// Prepare the message object
let msg = {
    relayname: relayname,
    payload: global.get(relayNumberWord)
};

// Assign the message to the correct index in the outputs array
outputs[i-1] = msg;

}

// Send all messages using node.send
node.send(outputs);

Die Relais EIngabe sieht gut aus:

Aber bei den Switchen sieht es so aus:

Ausserdem wird Relais 9+10 immer eingeschaltet.
Ich habe auch schon probiert die Schleife hoch zu setzen:

for (let i = 9; i < 23; i++) {

Aber es kommen von allen Relais folgende Fehler:
grafik

Ich habe die Ausgänge der Functions allerdings 9-14 bezeichnet, könnte das der Fehler sein?

Jetzt sieht es so aus:

Dadurch, daß ich die anderen globalen Variabeln setze:

@Vincent Was bedeutet diese Zeile :
if (msg.status.shape == “dot” && msg.status.fill == “blue” && msg.status.text == “1”) {

Denn das Programm wird nicht angesprochen, sondern verwendet den “else” Teil.

if (msg.status.shape == “dot” && msg.status.fill == “blue” && msg.status.text == “1”) ...

Die Status Node überprüft ja die delay Nodes, die das Relay automatisch wieder abschalten nach einer gewissen Zeit. Wir filtern also danach, dass das der Status der Node blue, dot und 0 oder 1 hat. Eigentlich interessiert uns nur 0 oder 1, die anderen Abfragen sind nur zur Sicherheit, falls man mal eine Falsche node zur Überprüfung angeklickt hat.
Wenn die delay Node also eine 1 hat wissen wir, dass grade ein delay läuft. Dann passen wir den Titel (Label) vom jeweiligen Relay an, sodass da steht “Relay X geht aus …” Wenn die delay Node eine 0 ausgibt, dann läuft sie nicht und wir können das Label wieder zurückändern.

Ich habe ein Problem mit der 8fach Relais Karte:

Ich möchte diese ja mit einem MCP23017 steuern.
+5V ist an JD-VCC angeschlossen, der Jumper entfernt.
GND an GND vom J9 auf dem Relais Board. 3.3V vom Relais Board zum MCP23017+SCA+SDA
Ich kann alle Ports ohne die 5V problemlos ein- und aus schalten.(LEDs leuchten).
Sobald aber die 5V für die Relais angeschlossen werden, kann ich nur ein Relais zur Zeit schalten. Wenn zwei relais gleichzeit an sind, stürtzt Node-Red ab.
Muss ich den MCP23017 mit 5V betreiben anstatt den 3,3V ?

Den mcp23017 solltest du mir 3,3 volt versorgen können, ist ja auf dem Relayboard auch


Kannst du mal ne Zeichnung oder ein Foto von der Verdrahtung schicken

Schaltplan:


0


Ich hatte es auch schon probiert GND vom Reöaismoard mit GND vom Spannungswandler zusammen, bringt auch keine Verbesserung.

Guten Morgen Stefan
ich habe auch nur diese Beschreibung gefunden, und demnach bist du ja richtig.
das einzige sind die Wiederstände um den Strom zu begrenzen.


ist auf dem
Relayboard ja auch so gemacht. Vor dem Optokoppler ein Wiederstand.
oder ist der beim 8 Kanal Relay schon drauf???

Hi Arno, danke dir.
Ich habe einen Schaltplan von dem Relais Modul gefunden.
Hat einen Vorwiderstand mit 1KOhm (R9) in der VCC Leitung, aber nicht in der IN(1-8) Leitung. Wird ja gegen aktiv low geschaltet.

Evtl. liegt es doch an der Gesamtleistung des MCP23017 ?
Relais Board Verbrauch: ca. 20mA/ je Kanal = 160mA wenn alle 8Ports EIN

Der MCP23017 kann eine maximale Stromstärke von 25mA pro Pin und insgesamt 150mA für das gesamte IC liefern. Wenn der MCP23017 im Betrieb warm oder heiß wird, könnte das ein Anzeichen dafür sein, dass zu viel Strom durch den IC fließt. Es ist wichtig, die Stromversorgung zu beachten und sicherzustellen, dass die maximale Stromstärke nicht überschritten wird.
Aus dem Grund wird ein Tiefpassfilter empfohlen


und auch den MCP23017 mit 5V zu betreiben.

Was ich aber aber nicht verstehe ist, warum Node-Red abstürzt?

Ich gebe es auf!
Ich kann machen, was ich will.
Sobald die Betriebsspannung der Relais (JD-VCC), oder GND von den Relais anliegt,und mind. ein Relais an geht, verabschiedet sich NodeRed.

Es wurde auch folgendes versucht:

  • MCP23017 und das Relaisboard mit 5V
  • MCP23017 mit 3.3V, Relaisboard mit 5V
  • Diode in +
  • Diode in -
  • Diode in Steuerleitung
  • Widerstand in Steuerleitung