hardlog
12. Februar 2025 um 15:29
1
Hallo,
ich brauche mal eine Einstiegshilfe modbus.
Ich will ein 8-Kanalrelais-Module (waveshare Modbus POE ETH Relay) ansteuern. Über das vom waveshare verlinke tool (SSCOM) habe ich mit viel Gefummel erreichen können, das die ein Relais via modbus TCP schalten kann.
Nun wollte ich das mal „auf die Schnelle“ in IPS umsetzen, scheitere jedoch kläglich.
Kann mir da bei der grundlegenden modbus-Nutzung in IPS jemand Hilfe leisten?
Die Einstellungen am Geräte (via virCom) sehen wie folgt aus:
Mit dem tool (mit dem ich es hinbekomme zu schalten) sieht es so aus:
In Symcon habe ich nun folgendes ohne Erfolgt (im Debugfenster kommt auch nichts an versucht:
Im Wiki von waveshare steht folgendes:
Gruß hardlog
hardlog
12. Februar 2025 um 18:02
2
Nach viel Probieren komme ich der Sache selbst näher:
der Modus war falsch (nicht RTU über TCP) sondern „einfach“ Modbus TCP …
Jetzt lassen sich die Relais schonmal mit Modbus Coil schalten:
hardlog
Helmut
12. Februar 2025 um 18:44
3
Lesen könnte auch nicht schaden
Edit:
Damit keine Missverständnisse entstehen: Lesen per Modbus Instance war gemeint, nicht die Augen
1 „Gefällt mir“
hardlog
19. Februar 2025 um 16:13
5
Hallo,
ich mache meine ersten Schritte in Modbus TCP. Ich will eine 8-Kanal-Relaiskarte (waveshare) steuern. Soweit so gut. Einzelne Relais per Instanz WriteSingleCoil bekomme ich hin. Hab ich aber auch die Möglichkeit per „MultipeCoil“ z.B. die Relais 1,3,5 und 7 gleichzeitig einzuschalten?
$startAddress = 0; // Startadresse für Relais
$numberOfCoils = 4; // Anzahl der zu schaltenden Relais
$data = chr(0x55); // Daten für Relais 1, 3, 5 und 7 ein
Gruß hardlog
paule
19. Februar 2025 um 18:38
6
Abend,
du kannst mit dem Functionscode 15 nur zusammenhängende Blöcke schreiben.
Wenn du Relais 1,3,5 und 7 schalten willst musst du 4 und 6 mit senden.
Wenn du diese nicht benutzt kannst du sie einfach auf 0 senden.
Mfg
Paul
Helmut
19. Februar 2025 um 18:41
7
Für Michael: Glaube nicht, dass das in die Modbus Einsteighilfe passt…
Also, da Modbus Multiple Coils (15) zwar angeboten wird, aber kein Feld für die Nachfolgenden Coil da sind, gehe ich davon aus, dass das ein Fake ist. Angefragt hatte ich es schon…
Ich habe mal das Prg qModbus Master gestartet und auf mein Pokeys57E die Funktion Modbus Multiple Coils (15) geschrieben.
Im Debug Fenster habe ich mir dann die Hex Codes raus geschrieben und in ein PHP Script gepackt.
$str=chr(0x00).chr(0x0C).chr(0x00).chr(0x00).chr(0x00).chr(0x08).chr(0x01).chr(0x0F).chr(0x00).chr(0x12).chr(0x00).chr(0x08).chr(0x01).chr(0xA7);
CSCK_SendText (14098,$str);
Warum? Geht doch noch immer um die gleiche Hardware.
Michael
Helmut
19. Februar 2025 um 20:20
9
Ein wenig Recht gebe ich Dir, eigentlich ist es eine Frage, die in Anleitungen gehört.
Aber schau Dir den Ordner an …
Anleitungen sind überall zu finden in den Fragen und Antworten von Usern.
Irgendwie unbefriedigend, wo fragt man gezielt was zu einer Funktion, gib mal ein Tip
hardlog
20. Februar 2025 um 12:05
10
Hallo, ich traue mich kaum noch mal nachzufragen, aber wie könnte es gehen?
Welche Instanz ist dann die 14098 bei Dir?? bzw wie nutze ich in der ModbusCoil - Instanz die Funktion 15?
Helmut
20. Februar 2025 um 14:06
11
Trau Dich
Das ist die Client Socket Instanz ( i/O ) an der Dein Relais-Gerät hängt.
Nutzen… das Problem ist, ich weiß nicht wie man die CRC-Prüfsumme am Schluss berechnet.
Wenn mir jemand das aufzeigt, könnte ich Dir den Befehlsstring besser aufdrösseln.
Bin nun mal ein Copy and Paste Typ.
hardlog
21. Februar 2025 um 14:40
12
Hallo Helmut,
ich habe mal die „KI“ gefragt und die hat mir zum berechnen der Checksumme folgenden PHP-Schnipsel vorgeschlagen.
<?php
function calculate_crc($data) {
$crc = 0xFFFF; // Initialwert für CRC
// Durchlaufe jedes Byte im Datenarray
for ($i = 0; $i < strlen($data); $i++) {
$crc ^= ord($data[$i]); // XOR mit dem aktuellen Byte
// Verarbeite jedes Bit des aktuellen Bytes
for ($j = 0; $j < 8; $j++) {
if ($crc & 0x0001) { // Prüfe, ob das niederwertigste Bit gesetzt ist
$crc = ($crc >> 1) ^ 0xA001; // Rechtsverschiebung und XOR mit Polynom
} else {
$crc >>= 1; // Nur Rechtsverschiebung
}
}
}
return $crc;
}
// Beispiel: Modbus-Daten als String (ohne Checksumme)
//$data = "\x01\x0F\x00\x13\x00\x0A\x02\xCD\x01"; // Beispiel-Daten (Slave-Adresse, Funktion, usw.)
$data = "\x00\x00\x00\x00\x00\x06\x01\x03\x80\x00\x00\x01"; //
// CRC berechnen
$crc = calculate_crc($data);
// CRC in Low- und High-Byte aufteilen
$lowByte = $crc & 0xFF;
$highByte = ($crc >> 8) & 0xFF;
echo "CRC Low Byte: " . dechex($lowByte) . PHP_EOL;
echo "CRC High Byte: " . dechex($highByte) . PHP_EOL;
?>
Mit den Beispielen auf der Wiki von waveshare (https://www.waveshare.com/wiki/Modbus_POE_ETH_Relay#Modbus_TCP_Development_Protocol ) scheint es zu stimmen. Ich kann damit trotzdem nicht soviel anfangen. Kannst du mir damit weiterhelfen?
Gruß
Florian
Helmut
21. Februar 2025 um 14:41
13
Im Moment nicht, aber ich setze mich heute Abend mal hin.
Helmut
21. Februar 2025 um 22:56
15
Wie gesagt, ich bin eher der Copy and Paste.
Ich habe noch einen Fehler: der Wert „$AlleRelays“ bringt nicht die richtigen Bit Zuweisung.
Finde den Fehler nicht, Es solten die Bit0 bis Bit 7 gesetzt werden, nach dem Muster:
Bit stelle wird mit dem ganz rechtem Hex Wert gesetzt
Bit …hier
0000 0000[TCP]>Tx > 20:31:28:320 - 00 01 00 00 00 08 01 0F 00 11 00 08 01 00
0000 0001[TCP]>Tx > 20:24:29:253 - 00 01 00 00 00 08 01 0F 00 11 00 08 01 80
0000 0010[TCP]>Tx > 20:24:45:472 - 00 01 00 00 00 08 01 0F 00 11 00 08 01 40
0000 0100[TCP]>Tx > 20:27:08:874 - 00 01 00 00 00 08 01 0F 00 11 00 08 01 60
0000 1000[TCP]>Tx > 20:27:58:644 - 00 01 00 00 00 08 01 0F 00 11 00 08 01 10
0001 0000[TCP]>Tx > 20:28:31:419 - 00 01 00 00 00 08 01 0F 00 11 00 08 01 08
0010 0000[TCP]>Tx > 20:29:38:692 - 00 01 00 00 00 08 01 0F 00 11 00 08 01 04
0100 0000[TCP]>Tx > 20:30:13:762 - 00 01 00 00 00 08 01 0F 00 11 00 08 01 06
1000 0000[TCP]>Tx > 20:30:50:973 - 00 01 00 00 00 08 01 0F 00 11 00 08 01 01
Hier mein Script, der fast fertig ist, die Relays sind im Code fest, zum Test
<?php
function calculate_crc($data) {
$crc = 0xFFFF; // Initialwert für CRC
// Durchlaufe jedes Byte im Datenarray
for ($i = 0; $i < strlen($data); $i++) {
$crc ^= ord($data[$i]); // XOR mit dem aktuellen Byte
// Verarbeite jedes Bit des aktuellen Bytes
for ($j = 0; $j < 8; $j++) {
if ($crc & 0x0001) { // Prüfe, ob das niederwertigste Bit gesetzt ist
$crc = ($crc >> 1) ^ 0xA001; // Rechtsverschiebung und XOR mit Polynom
} else {
$crc >>= 1; // Nur Rechtsverschiebung
}
}
}
return $crc;
}
//$Relay1 = GetValueBoolean(39702);
$Relay1 = 1;
//$Relay2 = GetValueBoolean(59657);
$Relay2 = 1;
//$Relay3 = GetValueBoolean(17035);
$Relay3 = 1;
//$Relay4 = GetValueBoolean(51025);
$Relay4 = 1;
//$Relay5 = GetValueBoolean(31769);
$Relay5 = 1;
//$Relay6 = GetValueBoolean(47090);
$Relay6 = 1;
//$Relay7 = GetValueBoolean(46043);
$Relay7 = 1;
//$Relay8 = GetValueBoolean(49724);
$Relay8 = 1;
$Low = (($Relay4 <<= 3) + ($Relay3 <<= 2) + ($Relay2 <<1) + $Relay1);
$Low = dechex($Low);
echo " Low ". $Low;
$High = (($Relay8 <<= 3) + ($Relay7 <<= 2) + ($Relay6 <<1) + $Relay5);
$High = dechex($High);
echo " High ". $High;
$AlleRelays = ($High . $Low);
echo " Alle Relays ".$AlleRelays;
$data = chr(0x00).chr(0x01).chr(0x00).chr(0x00).chr(0x00).chr(0x08).chr(0x01).chr(0x0F).chr(0x00).chr(0x10).chr(0x00).chr(0x08).chr(0x01).$AlleRelays; ///dechex($High).dechex($Low ); //.chr(0x18);
// CRC berechnen
$crc = calculate_crc($data);
// CRC in Low- und High-Byte aufteilen
$lowByte = $crc & 0xFF;
$highByte = ($crc >> 8) & 0xFF;
echo " CRC Low Byte: " . dechex($lowByte) . PHP_EOL;
echo " CRC High Byte: " . dechex($highByte) . PHP_EOL;
//$data = chr(0x00).chr(0x01).chr(0x00).chr(0x00).chr(0x00).chr(0x08).chr(0x01).chr(0x0F).chr(0x00).chr(0x11).chr(0x00).chr(0x08).chr(0x01).chr(0x80).$highByte.$lowByte;
CSCK_SendText (14098, $data);
//*//$data = hexToStr ($data); //. hexToStr($highByte) . hexToStr($lowByte) ;
// $str = dechex($hexNum);
//echo $data;
?>