Arduino Byte Übertragung [Modbus Kamoer KCM-ODM Pumpe]

Hallo,

ich habe ein Problem,
denn ich möchte ein Protokoll über die serielle Schnittstelle senden und weis überhaupt nicht wie.

Bitte um Hilfe.

Die Kommunikation sieht folgendermaßen aus:

Einmal
1 Byte | 1Byte | 2Byte | 2Byte | und 2Byte CRC check.
Beispiel
C0 | 05 |1004| FF00| D9EA
und

1Byte, 1Byte, 2Byte, 2Byte,1Byte, daten, CRC

Beispiel
C0, 10, 3001, 0002, 04, 42 C8 00 00, 0B18
Kann mir hier jemand behilflich sein?

Gruß

dann würde ich mal ganz einfach anfangen.

void send(){
  Serial.write(0xC0);    // 1 byte
  Serial.write(0x05);    // 1 byte
  Serial.write(0x10); Serial.write(0x04);// 2 byte
  Serial.write(0xff); Serial.write(0x00);  // 2 byte
  Serial.write(0xD9); Serial.write(0xEA);// crc hartkodiert
}

void setup() {
  Serial.begin(115200);

  send();
}

void loop() {
}

besser wäre es du würdest exakt beschreiben, an welches Gerät du etwas senden möchtest (Link auf das Produkt setzen) und das Datenblatt / Beschreibung der Schnittstelle verlinken, damit man genau sieht wie das sein soll.

Es ist eine Pumpe die per RS485 Befehle entgegen nimmt.
Ein Wandler habe ich erst dazwischen geschaltet.

Aber bevor ich weiter etwas aufbaue wollte ich erst einmal die Kommunikation testen.

Ich habe da etwas gefunden, aber es funktioniert nicht, es fehlen einfach daten bei der Übertragung, die 00 wird nicht angezeigt und Checksumme wird auch nicht übertragen. Zu Monitor.

char s[2]={0,0};
char buf[8]={0}; //make this larger than any anticipated string.
char init_str[]={0xC0,0x05,0x10,0x04,0xFF,0x00,0xD9,0};  //CRC = D9EA

unsigned char WB_Parity_Calc( char *str )
{
    unsigned char Par;
    Par = 0x00;
    while( *str )
      Par ^= *str++;
      Par = Par & 0x7F;                                                 
    return ~Par;         
}

void Taster(){
  while(digitalRead(pinT) == 0) {delay(50); digitalWrite(HeartbeatLed,!digitalRead(HeartbeatLed));}
   memset(buf, '\0', sizeof(buf));               //clear output string
  strncat(buf,init_str,sizeof(buf));            
   s[0]=WB_Parity_Calc(buf);                   
  strncat(buf,s,sizeof(buf));                   
  Serial.println(buf);                      

for(int i=0;i <8; i++){         // Ausgabe testen
  Serial.print(buf[i],HEX);  
  Serial.print(",");
    }

Einmal raten reicht.

Bitte einen Link auf das Produkt und auf deren Datenblatt / Protokoll-Beschreibung, weil wenn das Modbus ist nimm was fertiges und funktionierendes.

Da es kein sichtbares Zeichen ist, must Du es sichtbar machen.

Da gibt es nichts vertiges,
China ware Kamoer Pumpe.
Und es sind nur 2-3 Beispiele angegeben.
Wie angegeben erster Post.

Und wie kann ich den kompletten Datensatz mit Checksumme(D9EA) sichtbar machen?

Mensch gib doch mal einen link zu dem wo was da dokumentiert ist!
Wer soll sich denn da was aus den Fingern saugen udn seine Zeit unnütz mit der Glaskugel verbringen?

Meine ist im Übregen grad zur Reinigung.

z.B. eine Variante wäre:
Das Printable Interface implementieren

C0 kann die Device Adresse sein
05 kann der Function Code für Coil Write sein
0x1004 ist die Kennung für einen Ausgang
0xFF00 ist einer der zwei gültigen Werte für diesen Function Code ( A Value of 0xFF00 requests the coil to be ON - aus dem Modbus Application Protocol Specification V1.1.b3):

ergibt einen Modbus CRC von 0xEAD9 der dann HiNibble/LowNibble rausgeschickt wird.

ich würde einfach

result = node.writeSingleCoil(0x1004, 1);

mit der Modbus Master von DocWalker probieren.

Vieleicht ist es aber auch gar nicht eilig und du findest auch selber eine Lösung.

Sorry,
das ist alles was an Protokoll vorhanden ist.


Ich möchte doch nur wissen, wie ich die komplette Sequenz(Adresse,Funktion Code, Coil adresse, Qoutput und CRC check) (C0 05 1004 FF00 D9EA)übertragen kann und das im Monitor sichtbar zur überprüfung darstellen kann.

Das verstehe ich nicht!

Das bild ist schon mal gut, da steht fast alles drinne was man bräuchte.
Jetzt fehlt noch der link auf die eigentliche Pumpe damit auch jene die mal danach suchen, wissen wofür das ganze dienen soll.

ich verstehe dich auch nicht.
Warum willst du dir Binärdaten auf der seriellen Schnittstelle ansehen wenn du eh weist was du losgesendet hast.

Wenn ich was schreibe, will ich auch überprüfen können, ob das was gesendet wurde auch stimmt.

(https://de.aliexpress.com/item/1005005016148383.html?spm=a2g0o.productlist.main.3.a661e799yXPgkQ&algo_pvid=1288bc76-7f87-4ffe-87c1-924a157e3282&algo_exp_id=1288bc76-7f87-4ffe-87c1-924a157e3282-1&pdp_npi=4%40dis!EUR!132.07!132.07!!!140.42!140.42!%402103867617057583922735651e84bc!12000031351088635!sea!DE!917198501!&curPageLogUid=ZaONWUYibUCb&utparam-url=scene%3Asearch|query_from%3A)

mit
Serial.print(buf[i],HEX);
kannst du etwas ausdrucken.

Wenn dir das nicht reicht und du immer noch darauf bestehst ein Standard-Protokoll selber zu implementieren anstatt eine fertige Library zu verwenden, dann poste wenigestens einen vollständigen Sketch und beschreibe was anders funktionieren soll.

Es braucht da schonen einen Sketch von dir, weil wir nicht sehen was du da sonst noch gemacht hast und die paar Zeilen von dir oben in #3 sind nicht lauffähig.

Ich würde ja gerne z.B. die Library verwenden.
Doch verstehe ich die Funktionsaufrufe nicht.
Wo stelle ich die Adresse C0 ein und wo wird der CRC hinzugefügt?
Gerade in dem Post 03 soll die Initialisierung der Pumpe den Inhalt von
init_str[]={0xC0,0x05,0x10,0x04,0xFF,0x00,0xD9,0};
Übertragen.
Ja er Funktioniert nicht richtig, aber warum?
Und ich muss ja für eine Fehleranalyse das sehen, was ich ausgebe.
Wie soll ich denn sonnst dahinterkommen was falsch läuft.

Nicht Lauffähig?
Ja deswegen, was ist denn da faul?
Da ich es nicht weiß, habe ich ja die Fragen gestellt.

Und in dem Aufruf:
for(int i=0;i <8; i++){
Serial.print(buf[i],HEX);
Serial.print(",");
}
Soll der Inhalt von (buf) als, HEX dargestellt werden.
C0,5,10,4,FF,D1,0,0, wird angezeigt.
Aber es fehlt '0x00 und 0xD9 der CRC' und wo kommt D1 und die zwei Nullen am Ende her?

Also wie soll ich es überprüfen was gesendet wird?

aus dem Beispiel

  // communicate with Modbus slave ID 2 over Serial (port 0)
  node.begin(2, Serial);

wenn deine Node 0xC0 hat dann musst du eben statt 2 die 0xC0 nehmen.

funktioniert gar nicht, weil da ein setup, ein loop, alles was es zum kompilieren braucht - fehlt.

wirklich sehen würdest du es nur, wenn du dir die Ausgabe in ein Terminalprogram überträgst, das auch die reinen Werte in HEX darstellen kann. CoolTerm, SSCOM32, Hyperterminal ... was auch immer.

Wenn du dir die Daten lesbar ausgibst machst wieder irgendwas was evtl. falsch ist.

Also poste einen vollständigen Sketch. Ich bau keinen aus dem Stückwerkt da oben zusammen wenns das eh schon bei dir am PC gibt. (Abgesehen davon hab ich btw schon mal einen VOLLSTÄNDIGEN Sketch gemacht...)

Hallo,
wie Dir ja bereits gezeigt wurde solltest Du das mit Serial.write() ausgeben. Wenn Du jetzt erst mal sehen willlst was Du sendest , solltest Du einen Terminal Programm nutzen das dir HEX Daten anzeigen kann. Ich nutze da HTerm zu.

hier mal was wie man sowas machen könnte, ob das allerdings mit Deiner Pumpe klappt weiß ich nicht. Wie bereits geschrieben dazu gibt es fertige libs. Ich selbst hab von Mod Bus keine Ahnung , kann da also nix zu sagen.
Eventuell musst Du auch erst mal sicher sein das die Modbus Adresse überhaupt stimmt. Die kann man sicher auslesen.


byte start[] = {0xC0, 0xC5, 0x10, 0x04, 0xFF, 0x00, 0xD9, 0xEA};
byte ein[] = {0xC0, 0xC5, 0x10, 0x01, 0xFF, 0x00, 0xC9, 0xEB};
byte aus[] = {0xC0, 0xC5, 0x10, 0x00, 0xFF, 0x00, 0x88, 0x18};

int l; // länge 
void setup() {
  Serial.begin(115200);

  l = sizeof(start) / sizeof(start[0]);
  // Serial.println(l);
  send(start, l);
  
}

void loop() {

 delay(5000);
 l = sizeof(ein) / sizeof(ein[0]);
 send (ein,l);
 delay(5000);
 l = sizeof(aus) / sizeof(aus[0]);
 send(aus,l);
}

void send ( const byte *s, const int l) {
  for (int i = 0; i < l; i++ ) {
    //Serial.write(s[i]); // für die Ausgabe an die Pumpe
    Serial.print(s[i],HEX);  // für den Monitor in der IDE  
  }
  Serial.println(); // neue Zeile an der Pumpe entfernen
}

1 Like

So, erst schon einmal Danke, bin ein Stückchen weiter.
Habe jetzt mal beides ausprobiert.
Ich habe bisher nur das was ich gepostet habe und nun dank euch die beiden Varianten Library und manuell.

Zu der manuellen Variante.
Hier fehlen bei der Ausgabe 2 Nullen: Soll > C050104FF00D9EA Ist C05104FF0D9EA.
Wenn es nur in der Anzeige Unterdrückt wird, dann müsste der CRC check ohne die Letzten 2Byte ebenfalls D9EA ergeben.
Nun zur nächsten Frage, wie berechne ich den CRC check für die byte Arrays?

Und dann bei der Library Variante? Wie sieht es dort mit dem CRC check aus.
Wird dieser automatisch bei der Ausführung result eingesetzt?

da fehlen keine nullen, sondern es werden keine vornullen ausgegeben, wenn du zwischen den bytes einen leerschritt machst siehst du es.

Die Library setzt nicht nur den crc sondern kontrolliert auch den crc vom Slave.
im Result steht nicht der CRC sondern das Ergebnis der Übertragung.
Auch das gibst dir als HEX aus - Fehlernummern die mit 0xE beginnen sind Verbindungsfehler, Fehler kleiner 0xE sind schon Rückmeldungen vom Slave.
Die Bedeutungen der Fehler findest am begin der ModbusMaster.h Datei.