NEWS
Modbus RS485 Konfiguration
-
Modbus seriell (RS485) Konfiguration
Habe mich zum ersten Mal überhaupt bei einem Forum angemeldet, hoffentlich mache ich nicht zu viele Formfehler.
Möchte per RS485 Daten zwischen IO-Broker (Raspi4) und einem Microcontroller (Arduino Mega) austauschen. IO-Broker ist aktuell, ebenso der Modbus Adapter (V5.0.11).
Datenübertragung vom MC zum IOB funktioniert mit Funktion 4 in die Eingangsregister.
Datenübertragung mit Funktion 3 in die Holdingregister funktioniert auch, benötige ich eigentlich nicht. Wenn ich die "Abfrage" in der Konfig Holdingregister abschalte, kommt kein Protokoll 3 mehr an. Allerdings auch kein Protokoll 6 (bzw.16) je nach Auswahl in der allgemeinen Instanzeinstellung. Nach meinem Verständnis erwarte ich bei der Konfiguration der Holdingregister "Abfrage" nein und "CW" ja entsprechene Anfragen vom Master (IOB) mit Funktion 6 bzw. 16. Leider gelingt mir die gewünschte Datenübertragung nicht.
Bei der Konfiguration "Abfrage" ja und "CW" ja erscheint das von mir nicht benötigte Protokoll 3 und auch 4 Protokolle 6 (bzw.16 je nach Konfig) für die 4 konfigurierten Holdingregister, allerdings alle mit dem Inhalt 0. siehe Monitorausschrift vom Arduino:Kann mir bitte jemand Hinweise zur Konfiguration des Modbusadapters geben, um die gewünschten Protokolle 6 bzw. 16 mit Dateninhalt zu erhalten?
hier noch die Log Einträge:
Danke, Jörg -
@jg sagte in Modbus RS485 Konfiguration:
hoffentlich mache ich nicht zu viele Formfehler.
naja, den ArduinoCode und das log bitte als Text in code-tags
hast du eine Beschreibung der Register für den Arduino?
BTW RS485 ist nicht Modbus!
-
@homoran
hier der komplette Arduino Code, sollte an sich kein Problem im Code sein, die Protokolle muß ja der IOB als Master initiieren, der Arduino antwortet nur, ist auch einiges nicht notwendiges im Code, da aus einem anderen eigenen Programm kopiert!// für Arduino Mega im schmalen Hutschienengehäuse 6 * 4-polig RS485 an tx: 18, rx: 19, txEnabRs485: 17 #define debugCycle 0 #define debugLoop 1 #define debugRs485 1 #define modBaud 115200 // Modbus Baudrate #define modAdr 1 // Modbus Geräteadresse Master #define SoftRxPin 31 // RS485 Rx Software Seriell #define SoftTxPin 21 // RS485 Tx Software Seriell #define SoftTxEnab 15 // RS485 Transmit Enable Pin Software Seriell //#define SoftSerial 1 // soft seriell verwenden #ifdef SoftSerial #include <SoftwareSerial.h> SoftwareSerial mySerial(SoftRxPin, SoftTxPin, false); // RX, TX, inversLogic #endif /* Pinbelegung Hutschienengehäuse 24 polig (6 * 4 polig): Stand 22/01 * Pin 1.1, 2.1, 3.1, 4.1, 5.1, 6.1: // Masse * Pin 1.4, 2.4, 3.4, 4.4, 5.4, 6.4: // Versorgungsspannung + 5V * Pin 1.2: D20 // I2C SDA * Pin 1.3: D21 // I2C SCL * Pin 2.2: D2 // frei Interruptfähig * Pin 2.3: D9 // frei * Pin 3.2: // Versorgungsspannung + 24V (9..30V) besser nicht benutzen! * Pin 3.3: D16 // Tx2 * Pin 4.2: D18 // Tx1 * Pin 4.3: D19 // Rx1 * Pin 5.2: D31 // frei mit Diode Anode, Diode Katode an Pin D30 für Onewire * Pin 5.3: D17 // Rx2 * Pin 6.2: D27 // frei mit Diode Anode, Diode Katode an Pin D26 für Onewire * Pin 6.3: D15 // Masse * Onewire an D30/31 und D27/26: D31, 27 Eingang mit Pullup, D30, D26 Ausgang * 24 V Eingang: Schaltregler auf 5V mit Supressordiode 6V ohne Sicherung! * Achtung: 4polige Stecker vertauschen Pins bei Verwendung auf anderer Gehäuseseite! 1,2,3 sind gleich, 4,5,6 auch */ //storage variables //Definitionen E/A: //Pin 0 Rx USB //Pin 1 Tx USB #define resLan 42 // Reset ethernet shield (MEGA2560) #define taste 44 // Taste Pullup gegen Masse #define ledR 45 // LED 3Color Rot #define ledG 46 // LED 3Color Grün #define ledB 47 // LED 3Color Blau #define csSd 48 // ChipSelect SD card #define csLan 53 // ChipSelect ethernet shield (MEGA2560) #define rd485send 17 // Umschaltung max485 auf Senden #define solar600Ein 8 // Solarpumpe alt (600 Liter) ein #define heizungBadEin 7 // Heizungspumpe Bad / Terrasse ein #define nachheizung2Ein 22 // Nachheizungspumpe Speicher alt (600 Liter) ein //SPI wird z.B. von LAN und SD-card extern verwendet //Pins 10(SPI_CS), 11(MOSI), 12(MISO) & 13(SCK) werden vom ethernet shield verwendet (UNO, NANO) //Pins 53(SPI_CS), 51(MOSI), 50(MISO) & 52(SCK) werden vom ethernet shield verwendet (MEGA2560) //I2C wird z.B. von EEPROM extern per wire.h verwendet //Pin A4(SDA) und A5(SCL) (UNO, NANO) //Pin D20(SDA) und D21(SCL) (MEGA2560) // Variablen für Verwendung in Interrupt Service Routinen sind volatile zu vereinbaren unsigned int n; unsigned long milliAlt, diffLoop; bool writePar; int stunde; int minuten; int wochentag; int datum; int monat; int jahr; int inTag=255; int inStunde=16; int inMinute=30; int inTemp=200; // entspricht 20°C int x=0; int anzahl; // Anzahl Zeichen für Modbus Sendung bool tasteOld, tasteAct, tasteFp, tasteFn; bool t0sel,t1sel,t2sel,t3sel,t4sel,t5sel,t6sel,t7sel,t1min,t8min,t64min; bool t0done,t1done,t2done,t3done,t4done,t5done,t6done,t7done,t1minDone; //************************************************************************************************************************ // volatile zur Verwendung im Interrupt volatile int ledRms, ledGms, ledBms; volatile int intms, intsec, int10sec, intmin, intstunde, inttag; volatile bool boolsec, bool10sec, boolmin, boolstunde, booltag, boolwoche; bool impulsSec, impuls10Sec, impulsMin, impulsStunde, impulsTag, impulsWoche, rstrt; #define stx 2 //StartOfText #define etx 3 //EndOfText #define nul 0 //Null #define maxBuffer 64 //size of serial buffer char rcvBuffer1[maxBuffer+1], rcvBuffer2[maxBuffer+1], sendBuffer1[maxBuffer+1], readChar; bool serial1block2, enableSend03, enableSend04, enableSend06, enableSend16, timeoutMod; uint16_t serial1pointer, serial2pointer, recAnzZei, crcRcv; uint32_t timeMod; //************************* F U N K T I O N E N ************************************************************************** uint16_t crc1(byte *z, byte l) { uint16_t sum = 0xFFFF; // Startwert 0xFFFFh for (int i=0;i<l;i++) { // CRC16 berechnen nach Modbus RTU sum = sum ^ *z++; for (int j=8;j>0;j--) { if((sum & 0x01) == 0) { sum >>= 1; } // crc16 polynom (X16 + X15 + X2 + 1): else { sum >>= 1; sum ^= 0xA001; } // 0xA001 = 1010 0000 0000 0001 } // Berechnung vlnr oder vrnl!: } // 0x8005 = 1000 0000 0000 0101 return(sum); } uint16_t crc (byte *z, byte l) { static const word wCRCTable[] PROGMEM = { 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 }; uint16_t sum = 0xFFFF; while (l--) { byte nTemp = *z++ ^ sum; sum >>= 8; sum ^= pgm_read_word(&wCRCTable[nTemp]); } return (sum); } void intToAscii (int i, byte *z){ // integer Zahl in 4 ASCII Zeichen wandeln *z = (((i>>12) & 0xf) + 0x30); if(*z > 0x39) *z += 7; z++; *z = (((i>>8) & 0xf) + 0x30); if(*z > 0x39) *z += 7; z++; *z = (((i>>4) & 0xf) + 0x30); if(*z > 0x39) *z += 7; z++; *z = (((i>>0) & 0xf) + 0x30); if(*z > 0x39) *z += 7; } int asciiToInt (byte *z){ // 4 ASCII Zeichen in integer Zahl in wandeln int a, b; if(*z > 0x39) a = *z - 0x37; else a = *z - 0x30; z++; b = (a << 4); if(*z > 0x39) a = *z - 0x37; else a = *z - 0x30; z++; b = ((b + a) << 4); if(*z > 0x39) a = *z - 0x37; else a = *z - 0x30; z++; b = ((b + a) << 4); if(*z > 0x39) a = *z - 0x37; else a = *z - 0x30; return (b + a); } void hexByte(byte zeichen) { if (zeichen < 16) Serial.print('0'); Serial.print(highByte(unsigned(zeichen)), HEX); Serial.print(lowByte(unsigned(zeichen)), HEX); Serial.print(' '); } //************************* S E T U P ************************************************************************************ void setup(){ cli(); // stop interrupts // set timer1 interrupt TCCR1A = 0; // set entire TCCR1A register to 0 TCCR1B = 0; // same for TCCR1B TCNT1 = 0; // initialize counter value to 0 // set compare match register: 7999 entspricht 2KHz/prescaler OCR1A = 19999;// = (16*10^6) / (1*prescaler) - 1 (must be <65536) entspricht 1KHz // turn on CTC mode TCCR1B |= (1 << WGM12); // Set CS10, CS11 and CS12 bits for prescaler 1=1, 2=8, 3=64, 4=256, 5=1024 TCCR1B |= (0 << CS12) | (1 << CS11) | (0 << CS10); // enable timer compare interrupt TIMSK1 |= (1 << OCIE1A); sei(); // allow interrupts vor aufruf wire notwendig! pinMode(rd485send, OUTPUT); // pin als Ausgang deklarieren CS ADS1118 Modul digitalWrite(rd485send,LOW); // max485 empfangen Serial.begin(115200); Serial.println("Setup gestartet"); Serial1.begin(modBaud); // 250000 geht, getestet Serial.print("Modbus Baudrate: "); Serial.println(modBaud); //Serial2.begin(57600); #ifdef SoftSerial pinMode(SoftTxEnab, OUTPUT); digitalWrite(SoftTxEnab,LOW); // Freigabe Empfangen an Max485 mySerial.begin(2000); Serial.println("Setup SoftSerial beendet"); #endif rstrt = true; // Restart Merker setzen Serial.println("Setup beendet"); } //end setup //************************* I N T E R R U P T T I M E R 1 Z E I T 1 0 m s **************************************** ISR(TIMER1_COMPA_vect){ //timer 1 interrupt intms++; if (intms >= 100) {boolsec = true; intms = 0; intsec++; } if (intsec >= 10) {bool10sec = true; intsec = 0; bool10sec++; } if (int10sec >= 6) {boolmin = true; int10sec = 0; intmin++; } if (intmin >= 60) {boolstunde = true; intmin = 0; intstunde++; } if (intstunde >= 24) {booltag = true; intstunde = 0; inttag++; } if (inttag >= 7) {boolwoche = true; inttag = 0; } } //end isr timer 1 interrupt //********************************* M A I N ****************************************************************************** // O O O O O O O O O O O O O O // O O O O O O O O O O O O O O O O O // O O O O O O O O O O O O O O O O O O O O // O O O O O O O O O O O O O O O O O O // O O O O O O O O O O O O O O O O O O O O // O O O O O O O O O O O O O O O // O O O O O O O O O O O O O O O O void loop() { cli(); // stop interrupts if (boolsec) {impulsSec = true; boolsec = false;} if (bool10sec) {impuls10Sec = true; bool10sec = false;} if (boolmin) {impulsMin = true; boolmin = false;} if (boolstunde) {impulsStunde = true; boolstunde = false;} if (booltag) {impulsTag = true; booltag = false;} if (boolwoche) {impulsWoche = true; boolwoche = false;} sei(); // allow interrupts t0sel = (milliAlt & 0b00000000001110000000000) == 0b0; // 0 ms t1sel = (milliAlt & 0b00000000001110000000000) == 0b0010000000000; // 1024 ms t2sel = (milliAlt & 0b00000000001110000000000) == 0b0100000000000; // 2048 ms t3sel = (milliAlt & 0b00000000001110000000000) == 0b0110000000000; // 3072 ms t4sel = (milliAlt & 0b00000000001110000000000) == 0b1000000000000; // 4096 ms t5sel = (milliAlt & 0b00000000001110000000000) == 0b1010000000000; // 5120 ms t6sel = (milliAlt & 0b00000000001110000000000) == 0b1100000000000; // 6144 ms t7sel = (milliAlt & 0b00000000001110000000000) == 0b1110000000000; // 7188 ms t1min = (milliAlt & 0b00000001110000000000000) == 0; // 65,536 s t8min = (milliAlt & 0b00001111110000000000000) == 0; // 524,288 s t64min = (milliAlt & 0b1111111110000000000000) == 0; // 4194,304 s if (!t0sel) {t0done = false;} if (!t1sel) {t1done = false;} if (!t2sel) {t2done = false;} if (!t3sel) {t3done = false;} if (!t4sel) {t4done = false;} if (!t5sel) {t5done = false;} if (!t6sel) {t6done = false;} if (!t7sel) {t7done = false;} if (!t1min) {t1minDone = false;} // if (t4sel && t1min) {} // if (t5sel && t1min) {} /* Serial.println(milliAlt); Serial.print(t0sel); Serial.print(t1sel); Serial.print(t2sel); Serial.print(t3sel); Serial.print(t4sel); Serial.print(t5sel); Serial.print(t6sel); Serial.println(t7sel);*/ //************************* R E C E I V E 1 M O D B U S S E R I A L **************************************************** // if (Serial1.available() > 5) Serial.println(Serial1.available()); timeoutMod = (timeMod < (millis()-10)); while (Serial1.available()) { timeMod = millis(); if (serial1pointer >= maxBuffer) serial1pointer = maxBuffer - 1; readChar = Serial1.read(); if (timeoutMod) { serial1pointer = 0; recAnzZei = 12; } // Geräteadresse prüfen rcvBuffer1[serial1pointer] = readChar; if (serial1pointer > 2) { // if (rcvBuffer1[1] == 3) recAnzZei = 4; // if (rcvBuffer1[1] == 4) recAnzZei = 4; // if (rcvBuffer1[1] == 6) recAnzZei = 4; if (rcvBuffer1[1] == 16) recAnzZei = 7; else recAnzZei = 4; //Serial.println(recAnzZei); } if (debugRs485 && 0) {Serial.print(serial1pointer); Serial.print(": "); Serial.print(readChar); Serial.print(", "); Serial.println(readChar,HEX);} // read the incoming byte if (serial1pointer == recAnzZei + 3) { crcRcv = ((lowByte(rcvBuffer1[recAnzZei+3])<<8) + lowByte(rcvBuffer1[recAnzZei+2])); rcvBuffer1[serial1pointer+1] = nul; if (debugRs485) {Serial.print("Empfangen: "); // an Monitor for (int i=0; i<recAnzZei + 4; i++) { // Serial.print(highByte(unsigned(rcvBuffer1[i])), HEX); Serial.print(lowByte(unsigned(rcvBuffer1[i])), HEX); Serial.print(' '); hexByte(rcvBuffer1[i]); } Serial.print(", CRC Buffer: "); Serial.print(crcRcv,HEX); Serial.print(", CRC berechnet: "); Serial.print(crc(&rcvBuffer1[0],(recAnzZei+2)),HEX); Serial.print(", "); Serial.print(serial1pointer + 1); Serial.println(" Zeichen"); } if (crc(&rcvBuffer1[0],(recAnzZei+2))==crcRcv) { // hier empfangene Werte verarbeiten // if (debugRs485) {Serial.print(" rcv1 1 o.k., Funktionscode: "); Serial.println(rcvBuffer1[1], HEX);} // an Monitor if (rcvBuffer1[1] == 3) enableSend03 = true; // Funktionscode 03: senden Integerwerte if (rcvBuffer1[1] == 4) enableSend04 = true; // Funktionscode 04: senden Integerwerte if (rcvBuffer1[1] == 6) enableSend06 = true; // Funktionscode 06: empfangen Integerwerte if (rcvBuffer1[1] == 16) enableSend16 = true; // Funktionscode 16: empfangen Integerwerte } else { if (debugRs485) Serial.println(" rcv1: CRC n.o.k."); // an Monitor } } serial1pointer++; } //************************* S E N D ************************************************************************************** /* Modbus Beschreibungen ************************************************************************************************************************** Befehle: FUNKTIONSKODE WAS DIE FUNKTION TUT WERTTYP ZUGRIFFSTYP 01 (0x01) Liest DO Read Discrete Output Coil Diskret Lesen 02 (0x02) Liest DI Read Discrete Input Contact Diskret Lesen 03 (0x03) Liest AO Read Analog Output Holding Register 16 Bit Lesen 04 (0x04) Liest AI Read Analog Input Register 16 Bit Lesen 05 (0x05) Schreibt ein DO Setzen einer Discrete Output Coil Diskret Schreiben 06 (0x06) Schreibt ein AO Setzen eines Analog Output Holding Registers 16 Bit Schreiben 15 (0x0F) Aufzeichnung mehrerer DOs Setzen mehrerer Discrete Output Coil Diskret Schreiben 16 (0x10) Aufzeichnung mehrerer AOs Setzen mehrerer Analog Output Holding Registers 16 Bit Schreiben ************************************************************************************************************************** REGISTERNUMMER REGISTERADRESSE HEX TYP NAME TYP 1-9999 0000 to 270E lesen-schreiben Discrete Output Coils DO 10001-19999 0000 to 270E lesen Discrete Input Contacts DI 30001-39999 0000 to 270E lesen Analog Input Registers AI 40001-49999 0000 to 270E lesen-schreiben Analog Output Holding Registers AO ************************************************************************************************************************** BYTE ANFRAGE BYTE ANTWORT (Hex) Feldname (Hex) Feldname 11 Geräteadresse 11 Geräteadresse 01 Funktionaler Code 01 Funktionaler Code 00 Adresse des ersten Registers Hi Bytes 05 Anzahl der Antwortbytes 13 Adresse des ersten Registers Lo Bytes CD Registerwert DO 27-20 (1100 1101) 00 Anzahl der Register Hi Bytes 6B Registerwert DO 35-28 (0110 1011) 25 Anzahl der Register Lo Bytes B2 Registerwert DO 43-36 (1011 0010) 0E Prüfsumme CRC 0E Registerwert DO 51-44 (0000 1110) 84 Prüfsumme CRC 1B Registerwert DO 56-52 (0001 1011) 45 Prüfsumme CRC E6 Prüfsumme CRC ************************************************************************************************************************** BYTE ANFRAGE BYTE ANTWORT (Hex) Feldname (Hex) Feldname 11 Geräteadresse 11 Geräteadresse 02 Funktionaler Code 02 Funktionaler Code 00 Adresse des ersten Registers Hi Bytes 03 Anzahl der Antwortbytes C4 Adresse des ersten Registers Lo Bytes AC Registerwert DI 10204-10197 (1010 1100) 00 Anzahl der Register Hi Bytes DB Registerwert DI 10212-10205 (1101 1011) 16 Anzahl der Register Lo Bytes 35 Registerwert DI 10218-10213 (0011 0101) BA Prüfsumme CRC 20 Prüfsumme CRC A9 Prüfsumme CRC 18 Prüfsumme CRC ************************************************************************************************************************** BYTE ANFRAGE BYTE ANTWORT (Hex) Feldname (Hex) Feldname 11 Geräteadresse 11 Geräteadresse 03 Funktionaler Code 03 Funktionaler Code 00 Adresse des ersten Registers Hi Bytes 06 Anzahl der Antwortbytes bei 16bit pro Wert) 6B Adresse des ersten Registers Lo Bytes AE Registerwert Hi #40108 00 Anzahl der Register Hi Bytes 41 Registerwert Lo #40108 03 Anzahl der Register Lo Bytes 56 Registerwert Hi #40109 76 Prüfsumme CRC 52 Registerwert Lo #40109 87 Prüfsumme CRC 43 Registerwert Hi #40110 40 Registerwert Lo #40110 49 Prüfsumme CRC AD Prüfsumme CRC ************************************************************************************************************************** BYTE ANFRAGE BYTE ANTWORT (Hex) Feldname (Hex) Feldname 11 Geräteadresse 11 Geräteadresse 04 Funktionaler Code 04 Funktionaler Code 00 Adresse des ersten Registers Hi Bytes 02 Anzahl der Antwortbytes 08 Adresse des ersten Registers Lo Bytes 00 Registerwert Hi #30009 00 Anzahl der Register Hi Bytes 0A Registerwert Lo #30009 01 Anzahl der Register Lo Bytes F8 Prüfsumme CRC B2 Prüfsumme CRC F4 Prüfsumme CRC 98 Prüfsumme CRC ************************************************************************************************************************** BYTE ANFRAGE BYTE ANTWORT (Hex) Feldname (Hex) Feldname 11 Geräteadresse 11 Geräteadresse 05 Funktionaler Code 05 Funktionaler Code 00 Adresse des ersten Registers Hi Bytes 00 Adresse des ersten Registers Hi Bytes AC Adresse des ersten Registers Lo Bytes AC Adresse des ersten Registers Lo Bytes FF Wert der Hi Bytes FF Wert der Hi Bytes 00 Wert der Lo Bytes 00 Wert der Lo Bytes 4E Prüfsumme CRC 4E Prüfsumme CRC 8B Prüfsumme CRC 8B Prüfsumme CRC ************************************************************************************************************************** BYTE ANFRAGE BYTE ANTWORT (Hex) Feldname (Hex) Feldname 11 Geräteadresse 11 Geräteadresse 06 Funktionaler Code 06 Funktionaler Code 00 Adresse des ersten Registers Hi Bytes 00 Adresse des ersten Registers Hi Bytes 01 Adresse des ersten Registers Lo Bytes 01 Adresse des ersten Registers Lo Bytes 00 Wert der Hi Bytes 00 Wert der Hi Bytes 03 Wert der Lo Bytes 03 Wert der Lo Bytes 9A Prüfsumme CRC 9A Prüfsumme CRC 9B Prüfsumme CRC 9B Prüfsumme CRC ************************************************************************************************************************** BYTE ANFRAGE BYTE ANTWORT (Hex) Feldname (Hex) Feldname 11 Geräteadresse 11 Geräteadresse 0F Funktionaler Code 0F Funktionaler Code 00 Adresse des ersten Registers Hi Bytes 00 Adresse des ersten Registers Hi Bytes 13 Adresse des ersten Registers Lo Bytes 13 Adresse des ersten Registers Lo Bytes 00 Anzahl der zu beschr. Register Hi Bytes 00 Anzahl der gesetzten Register Hi Bytes 0A Anzahl der zu beschr. Register Lo Bytes 0A Anzahl der gesetzten Register Lo Bytes 02 Anz Bytes, die die zu setz. Werte enthalt.26 Prüfsumme CRC CD Wert des Bytes für die Register 99 Prüfsumme CRC 27-20 (1100 1101) 01 Wert des Bytes für die Register 29-28 (0000 0001) BF Prüfsumme CRC 0B Prüfsumme CRC ************************************************************************************************************************** BYTE ANFRAGE BYTE ANTWORT (Hex) Feldname (Hex) Feldname 11 Geräteadresse 11 Geräteadresse 10 Funktionaler Code 10 Funktionaler Code 00 Adresse des ersten Registers Hi Bytes 00 Adresse des ersten Registers Hi Bytes 01 Adresse des ersten Registers Lo Bytes 01 Adresse des ersten Registers Lo Bytes 00 Anzahl der Register Hi Bytes 00 Anzahl der aufgezeichneten Register Hi Bytes 02 Anzahl der Register Lo Bytes 02 Anzahl der aufgezeichneten Register Lo Bytes 04 Anz der Bytes, die gesetzt werden sollen. 12 Prüfsumme CRC Hier: 2 Werte mit je 16bit. 00 Wert Hi 40002 98 Prüfsumme CRC 0A Wert Lo 40002 01 Wert Hi 40003 02 Wert Lo 40003 C6 Prüfsumme CRC F0 Prüfsumme CRC ************************************************************************************************************************** */ if (enableSend03) { digitalWrite(rd485send,HIGH); // max485 senden // 11 04 27 7B 00 03 C8 36 Beispiel anzahl = 5; // von [0] bis 2.Byte CRC == Index letztes byte + 1 sendBuffer1[0] = modAdr; // Geräteadresse sendBuffer1[1] = 0x03; // Funktionscode sendBuffer1[2] = 0x00; // Anzahl der Antwort-Bytes sendBuffer1[3] = char((crc(&sendBuffer1[0],(anzahl-2))) & 0xff); // Prüfsumme CRC sendBuffer1[4] = char(((crc(&sendBuffer1[0],(anzahl-2))) >> 8) & 0xff); // Prüfsumme CRC anzahl = 15; // von [0] bis 2.Byte CRC == Index letztes byte + 1 sendBuffer1[0] = modAdr; // Geräteadresse sendBuffer1[1] = 0x03; // Funktionscode sendBuffer1[2] = 0x0A; // Anzahl der Antwort-Bytes sendBuffer1[3] = 0x00; // Wert des high Registerbytes 1 sendBuffer1[4] = 0x0A; // Wert des low Registerbytes 1 sendBuffer1[5] = 0x00; // Wert des high Registerbytes 2 sendBuffer1[6] = 0xAA; // Wert des low Registerbytes 2 sendBuffer1[7] = 0x00; // Wert des high Registerbytes 3 sendBuffer1[8] = 0x55; // Wert des low Registerbytes 3 sendBuffer1[9] = 0x00; // Wert des high Registerbytes 4 sendBuffer1[10] = 0x05; // Wert des low Registerbytes 4 sendBuffer1[11] = 0x00; // Wert des high Registerbytes 5 sendBuffer1[12] = 0x05; // Wert des low Registerbytes 5 sendBuffer1[13] = char((crc(&sendBuffer1[0],(anzahl-2))) & 0xff); // Prüfsumme CRC sendBuffer1[14] = char(((crc(&sendBuffer1[0],(anzahl-2))) >> 8) & 0xff); // Prüfsumme CRC anzahl = 13; // von [0] bis 2.Byte CRC == Index letztes byte + 1 sendBuffer1[0] = modAdr; // Geräteadresse sendBuffer1[1] = 0x03; // Funktionscode sendBuffer1[2] = 0x08; // Anzahl der Antwort-Bytes == 4 * Integer sendBuffer1[3] = 0x00; // Wert des high Registerbytes 1 sendBuffer1[4] = char(random(0,255));//0x0A; // Wert des low Registerbytes 1 sendBuffer1[5] = 0x00; // Wert des high Registerbytes 2 sendBuffer1[6] = char(random(0,255));//0xAA; // Wert des low Registerbytes 2 sendBuffer1[7] = 0x00; // Wert des high Registerbytes 3 sendBuffer1[8] = char(random(0,255));//0x55; // Wert des low Registerbytes 3 sendBuffer1[9] = 0x00; // Wert des high Registerbytes 4 sendBuffer1[10] = char(random(0,255));//0x05; // Wert des low Registerbytes 4 sendBuffer1[11] = 0x00; // Wert des high Registerbytes 5 sendBuffer1[12] = char(random(0,255));//0x05; // Wert des low Registerbytes 5 sendBuffer1[11] = char((crc(&sendBuffer1[0],(anzahl-2))) & 0xff); // Prüfsumme CRC sendBuffer1[12] = char(((crc(&sendBuffer1[0],(anzahl-2))) >> 8) & 0xff); // Prüfsumme CRC Serial.print(" Send: "); for (int i=0; i<anzahl; i++) { Serial1.write(sendBuffer1[i]); hexByte(sendBuffer1[i]); } //Serial.println(); //for (int i=0; i<anzahl; i++) { Serial.write(sendBuffer1[i]); } Serial.print(", ");// Serial.print(" CRC: "); Serial.print(crc(&sendBuffer1[0],(anzahl-2)),HEX); for (int i=0; i<anzahl; i++) { Serial.print(", "); Serial.print(byte(sendBuffer1[i])); } Serial.println(); if (debugRs485 && 0) {Serial.print("Send 3 "); // an Monitor Serial.println(sendBuffer1); for (int i=0; i<maxBuffer; i++) { Serial.print(highByte(unsigned(sendBuffer1[i])), HEX); Serial.print(lowByte(unsigned(sendBuffer1[i])), HEX); Serial.print(' '); // if (sendBuffer1[i] == 0) break; } Serial.println(); } enableSend03 = false; for (int i=0;i<maxBuffer;i++) sendBuffer1[i] = 0x00; // Puffer löschen Serial1.flush(); // Waits for the transmission of outgoing serial data to complete //delayMicroseconds(10); digitalWrite(rd485send,LOW); // max485 empfangen } // end send answer 3 if (enableSend04) { digitalWrite(rd485send,HIGH); // max485 senden // 11 04 27 7B 00 03 C8 36 Beispiel anzahl = 13; // von [0] bis 2.Byte CRC == Index letztes byte + 1 sendBuffer1[0] = modAdr; // Geräteadresse sendBuffer1[1] = 0x04; // Funktionscode sendBuffer1[2] = 0x08; // Anzahl der Antwort-Bytes == 4 * Integer sendBuffer1[3] = 0x00; // Wert des high Registerbytes 1 sendBuffer1[4] = char(random(0,255));//0x0A; // Wert des low Registerbytes 1 sendBuffer1[5] = 0x00; // Wert des high Registerbytes 2 sendBuffer1[6] = char(random(0,255));//0xAA; // Wert des low Registerbytes 2 sendBuffer1[7] = 0x00; // Wert des high Registerbytes 3 sendBuffer1[8] = char(random(0,255));//0x55; // Wert des low Registerbytes 3 sendBuffer1[9] = 0x00; // Wert des high Registerbytes 4 sendBuffer1[10] = char(random(0,255));//0x05; // Wert des low Registerbytes 4 sendBuffer1[11] = char((crc(&sendBuffer1[0],(anzahl-2))) & 0xff); // Prüfsumme CRC sendBuffer1[12] = char(((crc(&sendBuffer1[0],(anzahl-2))) >> 8) & 0xff); // Prüfsumme CRC Serial.print(" Send: "); for (int i=0; i<anzahl; i++) { Serial1.write(sendBuffer1[i]); hexByte(sendBuffer1[i]); } Serial.print(", ");// Serial.print(" CRC: "); Serial.print(crc(&sendBuffer1[0],(anzahl-2)),HEX); for (int i=0; i<anzahl; i++) { Serial.print(", "); Serial.print(byte(sendBuffer1[i])); } Serial.println(); if (debugRs485 && 0) {Serial.print("Send 4: "); // an Monitor Serial.println(sendBuffer1); for (int i=0; i<maxBuffer; i++) { Serial.print(highByte(unsigned(sendBuffer1[i])), HEX); Serial.print(lowByte(unsigned(sendBuffer1[i])), HEX); Serial.print(' '); // if (sendBuffer1[i] == 0) break; } Serial.println(); } enableSend04 = false; for (int i=0;i<maxBuffer;i++) sendBuffer1[i] = 0x00; // Puffer löschen Serial1.flush(); // Waits for the transmission of outgoing serial data to complete //delayMicroseconds(10); digitalWrite(rd485send,LOW); // max485 empfangen // delay(10); // enableSend06 = true; } // end send answer 4 if (enableSend06) { digitalWrite(rd485send,HIGH); // max485 senden anzahl = 8; // von [0] bis 2.Byte CRC == Index letztes byte + 1 sendBuffer1[0] = modAdr; // Geräteadresse sendBuffer1[1] = 0x06;//rcvBuffer1[1]; // Funktionscode sendBuffer1[2] = rcvBuffer1[2]; // Adresse des ersten Registers Hi Bytes sendBuffer1[3] = rcvBuffer1[3]; // Adresse des ersten Registers Lo Bytes sendBuffer1[4] = rcvBuffer1[4]; // Anzahl der aufgezeichneten Register Hi Bytes sendBuffer1[5] = rcvBuffer1[5]; // Anzahl der aufgezeichneten Register Lo Bytes sendBuffer1[6] = char((crc(&sendBuffer1[0],(anzahl-2))) & 0xff); // Prüfsumme CRC sendBuffer1[7] = char(((crc(&sendBuffer1[0],(anzahl-2))) >> 8) & 0xff); // Prüfsumme CRC Serial.print(" Send: "); for (int i=0; i<anzahl; i++) { Serial1.write(sendBuffer1[i]); hexByte(sendBuffer1[i]); } //Serial.println(); //for (int i=0; i<anzahl; i++) { Serial.write(sendBuffer1[i]); } Serial.print(", ");// Serial.print(" CRC: "); Serial.print(crc(&sendBuffer1[0],(anzahl-2)),HEX); for (int i=0; i<anzahl; i++) { Serial.print(", "); Serial.print(byte(sendBuffer1[i])); } Serial.println(); if (debugRs485 && 0) {Serial.print("Send 06: "); // an Monitor Serial.println(sendBuffer1); for (int i=0; i<maxBuffer; i++) { Serial.print(highByte(unsigned(sendBuffer1[i])), HEX); Serial.print(lowByte(unsigned(sendBuffer1[i])), HEX); Serial.print(' '); // if (sendBuffer1[i] == 0) break; } Serial.println(); } enableSend06 = false; for (int i=0;i<maxBuffer;i++) sendBuffer1[i] = 0x00; // Puffer löschen Serial1.flush(); // Waits for the transmission of outgoing serial data to complete //delayMicroseconds(10); digitalWrite(rd485send,LOW); // max485 empfangen } // end send answer 06 if (enableSend16) { digitalWrite(rd485send,HIGH); // max485 senden anzahl = 8; // von [0] bis 2.Byte CRC == Index letztes byte + 1 sendBuffer1[0] = modAdr; // Geräteadresse sendBuffer1[1] = rcvBuffer1[1]; // Funktionscode sendBuffer1[2] = rcvBuffer1[2]; // Adresse des ersten Registers Hi Bytes sendBuffer1[3] = rcvBuffer1[3]; // Adresse des ersten Registers Lo Bytes sendBuffer1[4] = rcvBuffer1[4]; // Anzahl der aufgezeichneten Register Hi Bytes sendBuffer1[5] = rcvBuffer1[5]; // Anzahl der aufgezeichneten Register Lo Bytes sendBuffer1[6] = char((crc(&sendBuffer1[0],(anzahl-2))) & 0xff); // Prüfsumme CRC sendBuffer1[7] = char(((crc(&sendBuffer1[0],(anzahl-2))) >> 8) & 0xff); // Prüfsumme CRC Serial.print(" Send: "); for (int i=0; i<anzahl; i++) { Serial1.write(sendBuffer1[i]); hexByte(sendBuffer1[i]); } //Serial.println(); //for (int i=0; i<anzahl; i++) { Serial.write(sendBuffer1[i]); } Serial.print(", ");// Serial.print(" CRC: "); Serial.print(crc(&sendBuffer1[0],(anzahl-2)),HEX); for (int i=0; i<anzahl; i++) { Serial.print(", "); Serial.print(byte(sendBuffer1[i])); } Serial.println(); if (debugRs485 && 0) {Serial.print("Send 16: "); // an Monitor Serial.println(sendBuffer1); for (int i=0; i<maxBuffer; i++) { Serial.print(highByte(unsigned(sendBuffer1[i])), HEX); Serial.print(lowByte(unsigned(sendBuffer1[i])), HEX); Serial.print(' '); // if (sendBuffer1[i] == 0) break; } Serial.println(); } enableSend16 = false; for (int i=0;i<maxBuffer;i++) sendBuffer1[i] = 0x00; // Puffer löschen Serial1.flush(); // Waits for the transmission of outgoing serial data to complete //delayMicroseconds(10); digitalWrite(rd485send,LOW); // max485 empfangen } // end send answer 16 if (debugCycle) {diffLoop=(millis()-milliAlt); Serial.print("Zykluszeit: "); Serial.print(diffLoop); Serial.println(" ms"); } milliAlt = millis(); impulsSec = false; impuls10Sec = false; impulsMin = false; impulsStunde = false; impulsTag = false; impulsWoche = false; rstrt = false; } // end loop
und noch ein Stück vom Log IOBroker:
modbus.0 2023-03-26 18:12:45.710 debug [DevID_7/holdingRegs] Poll address 0 DONE modbus.0 2023-03-26 18:12:45.684 debug [DevID_7/holdingRegs] Poll address 0 - 4 registers modbus.0 2023-03-26 18:12:45.682 debug [DevID_7/inputRegs] Poll address 0 DONE modbus.0 2023-03-26 18:12:45.669 debug [DevID_7/inputRegs] Poll address 0 - 4 registers modbus.0 2023-03-26 18:12:45.669 debug [DevID_7] Poll start --------------------- modbus.0 2023-03-26 18:12:42.224 debug [DevID_7/holdingRegs] Poll address 0 DONE modbus.0 2023-03-26 18:12:42.204 debug [DevID_7/holdingRegs] Poll address 0 - 4 registers modbus.0 2023-03-26 18:12:42.202 debug [DevID_7/inputRegs] Poll address 0 DONE modbus.0 2023-03-26 18:12:42.189 debug [DevID_7/inputRegs] Poll address 0 - 4 registers modbus.0 2023-03-26 18:12:42.189 debug [DevID_7] Poll start --------------------- modbus.0 2023-03-26 18:12:42.189 info Connected to slave modbus.0 2023-03-26 18:12:42.180 debug connect to serial /dev/ttyUSB2 with 115200 modbus.0 2023-03-26 18:12:31.071 debug Cleaning up request fifo. modbus.0 2023-03-26 18:12:31.071 debug Clearing timeout of the current request. modbus.0 2023-03-26 18:12:31.068 info Disconnected from slave modbus.0 2023-03-26 18:12:30.191 warn Poll error count: 2 code: "App Timeout" modbus.0 2023-03-26 18:12:30.068 error Cannot write single registers {"deviceId":7,"address":1,"buffer":{"type":"Buffer","data":[0,0]}}: {"err":"timeout","timeout":100} modbus.0 2023-03-26 18:12:30.068 error Request timed out. modbus.0 2023-03-26 18:12:30.066 warn Error: undefined modbus.0 2023-03-26 18:12:29.926 debug [DevID_7/holdingRegs] Poll address 0 DONE modbus.0 2023-03-26 18:12:29.904 debug [DevID_7/holdingRegs] Poll address 0 - 4 registers modbus.0 2023-03-26 18:12:29.903 debug [DevID_7/inputRegs] Poll address 0 DONE modbus.0 2023-03-26 18:12:29.891 debug [DevID_7/inputRegs] Poll address 0 - 4 registers modbus.0 2023-03-26 18:12:29.890 debug [DevID_7] Poll start --------------------- modbus.0 2023-03-26 18:12:29.890 info Connected to slave modbus.0 2023-03-26 18:12:29.885 debug connect to serial /dev/ttyUSB2 with 115200 modbus.0 2023-03-26 18:12:18.777 debug Cleaning up request fifo. modbus.0 2023-03-26 18:12:18.776 debug Clearing timeout of the current request. modbus.0 2023-03-26 18:12:18.773 info Disconnected from slave modbus.0 2023-03-26 18:12:17.772 warn Poll error count: 1 code: {"err":"timeout","timeout":100} modbus.0 2023-03-26 18:12:17.772 error Request timed out. modbus.0 2023-03-26 18:12:17.771 warn Error: undefined modbus.0 2023-03-26 18:12:17.670 debug [DevID_7/holdingRegs] Poll address 0 - 4 registers modbus.0 2023-03-26 18:12:17.669 debug [DevID_7/inputRegs] Poll address 0 DONE modbus.0 2023-03-26 18:12:17.657 debug [DevID_7/inputRegs] Poll address 0 - 4 registers modbus.0 2023-03-26 18:12:17.657 debug [DevID_7] Poll start --------------------- modbus.0 2023-03-26 18:12:14.213 debug [DevID_7/holdingRegs] Poll address 0 DONE modbus.0 2023-03-26 18:12:14.189 debug [DevID_7/holdingRegs] Poll address 0 - 4 registers modbus.0 2023-03-26 18:12:14.188 debug [DevID_7/inputRegs] Poll address 0 DONE modbus.0 2023-03-26 18:12:14.175 debug [DevID_7/inputRegs] Poll address 0 - 4 registers modbus.0 2023-03-26 18:12:14.175 debug [DevID_7] Poll start --------------------- modbus.0 2023-03-26 18:12:10.726 debug [DevID_7/holdingRegs] Poll address 0 DONE modbus.0 2023-03-26 18:12:10.712 debug [DevID_7/holdingRegs] Poll address 0 - 4 registers modbus.0 2023-03-26 18:12:10.706 debug [DevID_7/inputRegs] Poll address 0 DONE modbus.0 2023-03-26 18:12:10.693 debug [DevID_7/inputRegs] Poll address 0 - 4 registers modbus.0 2023-03-26 18:12:10.693 debug [DevID_7] Poll start --------------------- modbus.0 2023-03-26 18:12:07.249 debug [DevID_7/holdingRegs] Poll address 0 DONE modbus.0 2023-03-26 18:12:07.231 debug [DevID_7/holdingRegs] Poll address 0 - 4 registers modbus.0 2023-03-26 18:12:07.230 debug [DevID_7/inputRegs] Poll address 0 DONE modbus.0 2023-03-26 18:12:07.217 debug [DevID_7/inputRegs] Poll address 0 - 4 registers modbus.0 2023-03-26 18:12:07.217 debug [DevID_7] Poll start --------------------- modbus.0 2023-03-26 18:12:03.774 debug [DevID_7/holdingRegs] Poll address 0 DONE modbus.0 2023-03-26 18:12:03.759 debug [DevID_7/holdingRegs] Poll address 0 - 4 registers modbus.0 2023-03-26 18:12:03.756 debug [DevID_7/inputRegs] Poll address 0 DONE modbus.0 2023-03-26 18:12:03.742 debug [DevID_7/inputRegs] Poll address 0 - 4 registers modbus.0 2023-03-26 18:12:03.742 debug [DevID_7] Poll start --------------------- modbus.0 2023-03-26 18:12:03.741 info Connected to slave modbus.0 2023-03-26 18:12:03.733 debug connect to serial /dev/ttyUSB2 with 115200 modbus.0 2023-03-26 18:11:52.625 debug Cleaning up request fifo. modbus.0 2023-03-26 18:11:52.624 debug Clearing timeout of the current request. modbus.0 2023-03-26 18:11:52.620 info Disconnected from slave modbus.0 2023-03-26 18:11:51.619 warn Poll error count: 1 code: {"err":"timeout","timeout":100} modbus.0 2023-03-26 18:11:51.619 error Request timed out. modbus.0 2023-03-26 18:11:51.619 warn Error: undefined modbus.0 2023-03-26 18:11:51.519 debug [DevID_7/holdingRegs] Poll address 0 - 4 registers modbus.0 2023-03-26 18:11:51.518 debug [DevID_7/inputRegs] Poll address 0 DONE modbus.0 2023-03-26 18:11:51.506 debug [DevID_7/inputRegs] Poll address 0 - 4 registers modbus.0 2023-03-26 18:11:51.506 debug [DevID_7] Poll start --------------------- modbus.0 2023-03-26 18:11:48.061 debug [DevID_7/holdingRegs] Poll address 0 DONE modbus.0 2023-03-26 18:11:48.042 debug [DevID_7/holdingRegs] Poll address 0 - 4 registers modbus.0 2023-03-26 18:11:48.042 debug [DevID_7/inputRegs] Poll address 0 DONE modbus.0 2023-03-26 18:11:48.029 debug [DevID_7/inputRegs] Poll address 0 - 4 registers modbus.0 2023-03-26 18:11:48.029 debug [DevID_7] Poll start --------------------- modbus.0 2023-03-26 18:11:44.586 debug [DevID_7/holdingRegs] Poll address 0 DONE modbus.0 2023-03-26 18:11:44.568 debug [DevID_7/holdingRegs] Poll address 0 - 4 registers modbus.0 2023-03-26 18:11:44.566 debug [DevID_7/inputRegs] Poll address 0 DONE modbus.0 2023-03-26 18:11:44.554 debug [DevID_7/inputRegs] Poll address 0 - 4 registers modbus.0 2023-03-26 18:11:44.553 debug [DevID_7] Poll start --------------------- modbus.0 2023-03-26 18:11:44.553 info Connected to slave
-
@jg sagte in Modbus RS485 Konfiguration:
hier der komplette Arduino Code,
ich kann kein Arduinisch!
@jg sagte in Modbus RS485 Konfiguration:
die Protokolle muß ja der IOB als Master initiieren
Deswegen fragte ich nach den Registern!
gibt es da offsets?
-
@homoran
Der Arduino hat in dem Sinne des Modbus keine Register. Ich möchte mir nur Integer Werte aus dem IOB zum weiterverarbeiten zum Arduino senden. diese sollte ich aus den Protokollen mit Funktion 6 aus den Bytes 3 und 4 (Adresse 0 .. 3) und den Bytes 5 und 6 (Dateninhalt) auslesen können. -
@jg sagte in Modbus RS485 Konfiguration:
Der Arduino hat in dem Sinne des Modbus keine Register
dann befürchte ich, dass der Modbus Adapter dann nicht der richtige ist.
Wie gesagt@homoran sagte in Modbus RS485 Konfiguration:
RS485 ist nicht Modbus!
über RS485 können verschiedene Protokolle laufen.
-
@homoran
gibt es denn andere RS485 Adapter für den IO-Broker?Daten zum IOB senden geht ja einwandfrei mit dem Modbus Adapter, siehe die Antwort des Arduino auf die Anfrage des IOB, Protokolle 3 und 4.
Anfrage IOB: 007 003 000 000 000 004 0F1 0AF bedeutet 4 Eingangsregister ab Adresse 0 anfragen
Antwort MC: 001 003 008 000 07B ... bedeutet 8 Byte Werte als 4 Integerwerte zurück.Deshalb war meine ursprüngliche Frage nach der Konfiguration des Modbus Adapters um die Protokolle 6 (bzw. 16) mit Dateninhalt aus dem IOB zu senden. Auswerten kann ich die dann im Arduino nach meinen Vorstellungen, aber der IOB muß die Daten erst mal senden.
Die Definition Funktionscode 6 ist:BYTE ANFRAGE BYTE ANTWORT (Hex) Feldname (Hex) Feldname 11 Geräteadresse 11 Geräteadresse 06 Funktionaler Code 06 Funktionaler Code 00 Adresse des ersten Registers Hi Bytes 00 Adresse des ersten Registers Hi Bytes 01 Adresse des ersten Registers Lo Bytes 01 Adresse des ersten Registers Lo Bytes 00 Wert der Hi Bytes 00 Wert der Hi Bytes 03 Wert der Lo Bytes 03 Wert der Lo Bytes 9A Prüfsumme CRC 9A Prüfsumme CRC 9B Prüfsumme CRC 9B Prüfsumme CRC
leider kommen keine Werte an, nur Nullen, obwohl in den Registern Werte im IOB vorhanden sind:
-
@jg sagte in Modbus RS485 Konfiguration:
Deshalb war meine ursprüngliche Frage nach der Konfiguration des Modbus Adapters um die Protokolle 6 (bzw. 16) mit Dateninhalt aus dem IOB zu senden.
da kann ich dir nicht helfen.
-
Danke erst mal, evtl. meldet sich noch mal jemand, der Modbus seriell vielleicht schon in eigenen Projekten verwendet hat.
-
@jg Ist das Arduino Programm von Dir erstellt? Kennst Du Dich damit aus? Dann würde es sich anbieten die Kommunikation mit dem ioBroker auf TCP (Ethernet) umzustellen.
Dazu gibt es den simpleApi Adapter -
@klassisch
mit dem Arduino kann ich umgehen, das Testprogramm für den Modbusadapter habe ich selbst geschrieben, außer die Prüfsummenberechnung.
Eine Kommunikation per Ethernet mit dem IOB habe ich laufen, diese ist aber recht instabil, daher möchte ich die Kommunikation zum IOB lieber seriell aufbauen. Über den Ethernetadapter mit W5500 habe ich gleichzeitig einen Webserver, NTP per UDP, Datenkommunikation mit einem anderen Arduino per UDP und MQTT zum IOB laufen. Leider hängt sich die MQTT Übertragung bei Zugriff auf den Webserver unregelmäßig auf, was sogar zum Absturz des IOB führt. Beide fangen sich zwar wieder per watchdog, aber so ist das ganze leider nicht brauchbar. Deshalb möchte ich eine serielle Verbindung zum IOB aufbauen, den 2. Arduino habe ich auch schon seriell angebunden und NTP könnte ich auch einsparen, wenn ich mir die NTP Zeit vom IOB seriell abholen könnte. Ebenfalls habe ich schon mit Wlan mit einem ESP32 und einem Raspberry Pico getestet. Das läuft leider noch instabiler als die Version mit dem Ethernet Chip W5500.
Daher wäre mein Ausweg aus dem Dilemma eine serielle Verbindung zum IOB in beide Richtungen. Möglich wären ja theoretisch bis reichlich 120 Integerwerte in einem Telegramm (Funktionscode 16). Kennst du dich mit der Konfiguration des Modbus Adapters aus? -
@jg Ich kann gerade mal Modbus Geräte mehr oder weniger per trial & Error in den Modbus Adapter einlesen. Ich mache das dann auch nicht über USB sondern über einen RS485 <->TCP Server.
Ich kann aber kein Modbus Protokoll aufbauen, wie es hier erforderlich wäre. Bzw. ich habe das noch nie gemacht und habe auch keine Notwendigkeit dazu.
Ich habe eine kleine Herde von ESP8266, die recht stabil über simpleApi oder MQTT Daten an den ioBroker liefern. Ist hat WLAN und beim Update der Fritte oder sonstigen Wifi Störungen macht das ein oder andere schlecht mit WLAN versorgte Teil mal einen Neustart. Aber ich hatte auch schon jahrelange update Zeiten, bis ein Bagger alles stromlos machte.
Wenn aber Deine ESP32 in Deiner Umgebung kein stabiles WLAN und Deine Arduinios kein stabile LAN aufbauen können, dann ist das auch nichts.
Was Du eventuell testen könntest:- Anfrage, ob der simpleApi Adapter um eine serielle Schnittstelle erweiterbar wäre. Ich denke, die Realisierungsschancen sind eher gering, denn der Entwickler ist sehr beschäftigt und serielle Schnittstellen bei nodejs scheinen etwas aufwendiger zu sein.
- Testen, ob Du mit einem serial <-> TCP Konverter weiter kommst und so auf den simpleApi Adapter zugreifen kannst. Ich denke hierbei speziell an den USR-WIFI232-A2 (WLAN), da dieser laut Manual https://www.pusr.com/download/WIFI/USR-WIFI232-A2_User_Manual-V6.0.pdf über einen "transparent Mode" verfügt (Kap. 4.2.1, S.20). Damit könnte es nach meinem Verständnis möglich sein eine Art serial via TCP aufzubauen.
Entweder die serielle Verbindung zwischen dem Arduino und dem USRIOT direkt über "TTL"-Digitalleitungen schaffen oder eben über die kostengünstigen RS484 Konverter auf beiden Seiten.
Habe aber diesen transparenten Modus bei dem USRIOT nicht getetet. Ich verwende ihn im Modbus RTU mode, um einen modbusfähigen Stromzähler mithilfe des Modbus Adapters auszulesen.
-
@klassisch
danke für deine Vorschläge, werde mich mal mit dem Thema simpleAPI befassen -
@jg https://github.com/ioBroker/ioBroker.simple-api
setbulk um mehrere Werte an ioBroker zu übertragenKannst Du vom Browser aus testen. SimpleApi Adapter installieren und vom Office PC Browser den Befehl abschießen.