Modbus TCP Slave nach TCP Master - Arduino Nano + ENC28J60

Moin

ich versuche seit Tagen erfolglos mit dem Arduino Nano und einem ENC28J60 Ethernet Shield als Client/Master, Register vom Server/Slave abzufragen.

Als Grundlage dient die UIPEthernet.h Bibliothek.
Das Beispiel Simple_Ethernet_Test.ino funktioniert, die Hardware läuft also.

Ich hab mir aus diesem Beispiel ein minimal Test zusammen geschustert.

Laut Wireshark geht die Anfrage raus und eine Antwort vom Slave wird auch gesendet.

Nur der Nano bekommt's nicht mit und ich weiss nich warum.
Ich würde micht über einen Schubser in die richtige Richung sehr freuen.

Gruß
Robert

Ach ja ...
hier der Sketch:

// minimal Test Arduino Nano + Nano Ethernet Shield V1.0 mit ENC28J60
// Modbus TCP/IP Master lese HReg 520 von Modbus TCP/IP Slave

#include <UIPEthernet.h>
byte mac[] = { 0x54, 0x34, 0x41, 0x30, 0x30, 0x31 };
IPAddress mbMaster(192, 168, 0, 89); 	//Arduino Nano + ENC28J60 Master
IPAddress mbSlave(192,168,0, 10);		//Modbus Slave

EthernetClient client;

void setup() {
    Serial.begin(115200);
    delay(500);
    Serial.print("Sketch=");
    Serial.println(__FILE__);
    Serial.println("Los geht's...");

    Ethernet.begin(mac, mbMaster);
    Serial.print("mbMaster Address: ");
    Serial.println(Ethernet.localIP()); 
}
void loop() {
	size_t size;
	int nTransactionID,nProtocolID,nLengthOfNext,nL;
	if (client.connect(mbSlave,502)) {
        Serial.println("client.connect");
        String szStr = "000000000006010302080001"; // ByteLenght=06; uID=01; FC=03 (Read HReg); Address=520 (0x0208); n Address=01 (0x0001)
        nL = szStr.length() / 2;
        uint8_t* msg = (uint8_t*)malloc(nL*sizeof(uint8_t));
        msg = uiHex(msg,szStr);
        client.write(msg,nL);
        free(msg);

        while((size = client.available()) > 0) {
            Serial.println("client.available");
            uint8_t* msg = (uint8_t*)malloc(size);
            size = client.read(msg,size);
            for(uint8_t i=0 ; i < size ; i++) {
                Serial.print("msg");
                Serial.println(msg[i],HEX);
                vHex2n(msg[i]);
            }
            free(msg);
        }
		//client.stop();
        Serial.println("client not available");
	}
	delay(1000);
}

void vHex2n(char X) {
   if (X < 16) {Serial.print("0");}
   Serial.print(X, HEX);
}

unsigned int uiHexToInt(String hex) {
  int intValue = (int)strtol(&(hex[0]), NULL, 16);
  return intValue;
}

uint8_t* uiHex(uint8_t* m,String str) {
  int nStr = str.length();
  String strAux;
  char sz[3];
  
  for(int i = 0; i < nStr; i += 2 ) {
    sz[0] = str.charAt(i);
    sz[1] = str.charAt(i+1);
    sz[2] = 0;
    m[i/2] = uiHexToInt(sz);
	//Serial.println(m[i/2],HEX);
  }
  return m;
}

Du hast Dir das "dümmste" Ethernetmodul ausgesucht, das es gibt. Bei dem Ding muss der Arduino fast alles selbst machen und das kostet auch Speicher.
Was sagt die Speicherauslastung nach dem Kompilieren?

Gruß Tommy

Moin

Ist mein erstes Ethernet Modul. Wollte nicht so viel Kabelage haben. Wäre der original Ethernet Shield "klüger"?

Speicher lag bei ca. 54/50.
War auch etwas verwunder.
Der Nano ist auch ein Clone.

Gruß
Robert

das Beispiel
https://www.binefa.cat/php/doc/modbus/
zeigt aber genau den anderen Weg, nämlich den Arduino als Slave laufen zu lassen. Du hast dann ein paar Zeilen weggelassen aber daraus wird noch kein Master.

Ich denke du hast einfach mit dem falschen Beispiel begonnen. Suche mal nach einem Modbus TCP Master.

Moin

Das das Beispiel ein Slave ist, hatte ich erkannt. Parallel hatte ich mich am WebClient Beispiel orientiert. Jedoch scheint bei mir noch etwas zu fehlen.
Auch hatte ich schon einige Client Beispiele getestet. Aber leider wurde entweder der Nano oder der ENC28J60 nicht unterstützt.
Ich schau mal ob ich noch ne Lösung finde.

Gruß
Robert

Moin

nach ewigen rumprobieren, hab ich es endlich geschafft mein Register zu lesen!
Hier der Sketch:

#include <UIPEthernet.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress server(192,168,0,72);
IPAddress ip(192, 168, 0, 89);
IPAddress myDns(192, 168, 0, 1);

EthernetClient client;

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

  Serial.println("Initialize Ethernet without DHCP:");
  Ethernet.begin(mac, ip, myDns);

  delay(1000);
  Serial.print("connecting to ");
  Serial.print(server);
  Serial.println("...");
}

void loop() {
    bool timeOutFlag = false;
	if (!client.connected()) {
		client.connect(server, 502);
		unsigned long start_time = millis();
		while(!client.connected()) {
			if ((millis() - start_time) > 3000) {
				timeOutFlag = true;
				Serial.println("connection failed");
				break;
			}
			delay(1);
		}
	}
	if (client.connected())  {
        if (!timeOutFlag) {
            int nL;
            debugPrint("client.connect",0,false);
            String szStr = "000000000006010302080001"; // ByteLenght=06; uID=01; FC=03 (Read HReg); Address=520 (0x0208); n Address=01 (0x0001)
            //String szStr = "000000000009011002080001020001";
            nL = szStr.length() / 2;
            uint8_t* msg = (uint8_t*)malloc(nL*sizeof(uint8_t));
            msg = uiHex(msg,szStr);
            client.write(msg,nL);
            free(msg);
        }
        if (!timeOutFlag) {
            while(!client.available()) {
                delay(1);
            }
    		size_t size;
    		while((size = client.available()) > 0) {
                debugPrint("size",size,true);
                debugPrint("client.available",0,false);
    			uint8_t* msg = (uint8_t*)malloc(size);
    			size = client.read(msg,size);
    		/*	for(uint8_t i=0 ; i < size ; i++) {
    				//Serial.print("msg=");
    				Serial.println(msg[i],HEX);
    				vHex2n(msg[i]);
    			}
            */
               Serial.print(msg[9],HEX);
               Serial.println(msg[10],HEX);
    			free(msg);
    		}
           client.stop();
        }
	}
   delay(500);
}

void debugPrint(String strvar, uint32_t var, bool opt) {
    if (opt) {
        Serial.print(strvar + " = ");
        Serial.println(var);
    }
    else {
        Serial.println(strvar);
    }
}

void vHex2n(char X) {
   if (X < 16) {Serial.print("0");}
   //Serial.print(X, HEX);
}

unsigned int uiHexToInt(String hex) {
  int intValue = (int)strtol(&(hex[0]), NULL, 16);
  return intValue;
}

uint8_t* uiHex(uint8_t* m,String str) {
  int nStr = str.length();
  String strAux;
  char sz[3];
  
  for(int i = 0; i < nStr; i += 2 ) {
    sz[0] = str.charAt(i);
    sz[1] = str.charAt(i+1);
    sz[2] = 0;
    m[i/2] = uiHexToInt(sz);
    //Serial.println(m[i/2],HEX);
  }
  return m;
}

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.