I’ve been working with the W5500 for a couple of weeks now and everything was going quite well until yesterday. I ported the Wiznet W5500 Arduino library over to Particle for use with Particle Photon and Electron modules. I tested DHCP which worked well and I tested UDP which worked well for sending out broadcast data on the network.
Yesterday I decided to try out TCP clients and connect the W5500 to a server running via Netcat on my Mac. It’s not working yet.
The EthernetClient.connect(IP, port) function always returns 0. It goes into a while loop to check that status() returns SnSR::Established but it never does. status() always returns 0x13 which is SnSR::INIT Here is a block of my code which basically adds print debugs to the connect function:
int EthernetClient::connect(IPAddress ip, uint16_t port, network_interface_t) {
Serial.println("in connect function");
if (_sock != MAX_SOCK_NUM){
Serial.println("_sock != MAX_SOCK_NUM");
return 0;
}
Serial.println("Here");
for (int i = 0; i < MAX_SOCK_NUM; i++) {
Serial.println("Inside For Loop");
uint8_t s = w5500.readSnSR(i);
if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT || s == SnSR::CLOSE_WAIT) {
_sock = i;
break;
}
}
Serial.println("After for loop in connect");
if (_sock == MAX_SOCK_NUM){
Serial.println("_sock != MAX_SOCK_NUM, after loop");
return 0;
}
_srcport++;
if (_srcport == 0){
_srcport = 1024;
}
socket(_sock, SnMR::TCP, _srcport, 0);
delay(1000);
byte* lA = (byte*)&ip.raw().ipv4;
Serial.printf("Attempting to connect to: %i.%i.%i.%i on port %i", lA[3], lA[2], lA[1], lA[0], port);
if (!::connect(_sock, lA, port)) {
_sock = MAX_SOCK_NUM;
return 0;
}
while (status() != SnSR::ESTABLISHED) {
delay(10);
uint8_t state = status();
if (state == SnSR::CLOSED) {
_sock = MAX_SOCK_NUM;
Serial.println("Got here");
return 0;
}else{
Serial.printf("status() = %02X \n", state);
}
}
return 1;
}
My serial console shows status() = 13 repeatedly until got here prints and the connection fails. Any ideas on this? I can tell you the Particle module runs faster than the Arduino processor from previous experience. Could this be an issue?
I do not immediately see anything wrong with the code. 0x13 is the status after socket is open, and as connect returns with 0x13, I guess it can not/does not proceed to connect. The only educated guess I have is that you pass variable port as 0. I am not sure, I had the case before that connect does not work if destination port is 0.
I have the destination port set to 4000. I also added debug code to the connect function which reads back the destination IP and port from the W5500 class. It prints out the correct IP and port number. See revised connect function here where I check the destination IP and port:
int EthernetClient::connect(IPAddress ip, uint16_t port, network_interface_t) {
Serial.println(“in connect function”);
if (_sock != MAX_SOCK_NUM){
Serial.println(“_sock != MAX_SOCK_NUM”);
return 0;
}
Serial.println(“Here”);
for (int i = 0; i < MAX_SOCK_NUM; i++) {
Serial.println("Inside For Loop");
uint8_t s = w5500.readSnSR(i);
if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT || s == SnSR::CLOSE_WAIT) {
_sock = i;
break;
}
}
Serial.println("After for loop in connect");
if (_sock == MAX_SOCK_NUM){
Serial.println("_sock != MAX_SOCK_NUM, after loop");
return 0;
}
_srcport++;
if (_srcport == 0){
_srcport = 1024;
}
socket(_sock, SnMR::TCP, _srcport, 0);
delay(1000);
byte* lA = (byte*)&ip.raw().ipv4;
Serial.printf("Attempting to connect to: %i.%i.%i.%i on port %i", lA[3], lA[2], lA[1], lA[0], port);
if (!::connect(_sock, lA, port)) {
_sock = MAX_SOCK_NUM;
return 0;
}
uint8_t ipArray[4];
w5500.readSnDIPR(_sock, ipArray);
uint16_t setPort = w5500.readSnDPORT(_sock);
Serial.printf("_sock IP and port: %i.%i.%i.%i on port %i", ipArray[3], ipArray[2], ipArray[1], ipArray[0], setPort);
while (status() != SnSR::ESTABLISHED) {
delay(10);
uint8_t state = status();
if (state == SnSR::CLOSED) {
_sock = MAX_SOCK_NUM;
Serial.println("Got here");
return 0;
}else{
Serial.printf("status() = %02X \n", state);
}
}
return 1;
}
It prints out correctly as 192.168.1.53 which is my computer’s local IP on the network and port 4000 which is the port I’m listening on. So it seems the IP and port of the server is set correctly but it’s just never succeeding. I also cannot get the TCP server to work on the W5500 either.
Do you check for interrupt flags - do they change at least?
It seems connect function needs to be troubleshot. It would help if you can point to its code.
My full port of the Arduino Library thus far is available on this github repo:
Not sure where to check interrupt flags or which ones you are refering to. Can you elaborate? Thank you very much for your help/interest to this point.
I am afraid to be not so familiar with libraries you use; please look into “sockets” header files, or “w5500” header file, you should be able to locate W5500 register read call (I am sure there will be comment/verbose description saying so). Then read register one by one and dump to the log.
Now you can decode info yourself, following information in datasheet:
MR = 0
Gateway = 1.1.168.192, looks very strange, I think it should be 192.168.1.1?
Network mask = 0.255.255.255 - also looks reversed?
MAC address = DE:AD:BE:EF:FE:ED (dead beef feed )
W5500 IP address = 70.1.168.192 - for sure reversed
Well, I see something strange for sure. Either you get dump in wrong order, or you program registers incorrectly.
Looking to socket registers I see TCP with delayed ACK, open state, and local port 1025. Also note that first octet of local MAC address has bit 1 set.
I’m seeing the same thing with all IPs being reversed. I honestly thought that was normal. This is Wiznet’s Arduino library, I really didn’t touch anything I can think of that would have reversed that. Also I can atest that DHCP is working properly which would have to make use of these reversed IPs right? Heck I don’t know.
Lol that dead beef feed was also straight out of the Arduino library samples. I can’t take comedic credit for that.
Here’s my block of code that prints out the registers. No way it’s wrong, pretty straight forward.
//dump registers for Socket 0.
Serial.println("Registers for Socket 0");
for(int i = 0x00; i < 0x3A; i++){
Serial.printf("Register %02X : %02X\n", i, read(i, 0x09));
}
Serial.println();
Serial.println("Common Registers");
//dump common registers.
for(int i = 0x00; i < 0x3A; i++){
Serial.printf("Register %02X : %02X\n", i, read(i, 0x01));
}
I could try passing the server IP in to the client connect function backwards and see if that works I suppose.
With DHCP which works using UDP broadcast you actually do not need IP addresses and mask fields I guess. May it be that you read this information from DHCP response packet in wrong way?
OK. I might have fibbed just a little bit earlier when I said I didn’t touch anything. The Ethernet object had calls that required raw IP addresses. The platform I’m working on “Particle” does not have that function like Arduino does so I had to get the raw address in another way. It has a ipv4 function that returns the IP in raw form but as luck would have it it reverses the order of the array for some really stupid reason. Anyway I went through and reversed the array everywhere in the Wiznet library and viola Connected to Server. Pretty stocked at this point.
@Eugeny can’t thank you enough for all the help. Hopefully it’s smooth sailing from here on out(it never is so I’ll talk to you soon
Yes, I did complete the port to Particle and developed a library for Particle here which works with the Photon. The forum actually will not let me post a link to the repo for some reason but just search GitHub for Wiznet-W5500-Particle
If you are using build.particle.io then just search libraries for NCD_Ethernet_Overlay. We developed the library to work with this Wiznet based Ethernet overlay module we manufacture.