Project

General

Profile

EtherCard: Enc28J60 not sending packets for time to time

Added by RaphYot over 4 years ago

Hello everyone,

First post sot le me start by thanking you for the awesome work you’re doing on jeelabs. I’m using the EtherCard library on my arduino for a while, I love it as it has a light memory footprint, and the last enhancements are awesome.

I’m looking for advice on how I can make the below working flawlessly. I’m doing an HTTP POST to a web API that has a timeout of 30 seconds, if there is a command waiting on the API it will answer faster and close the connection. I then need to reopen the connection straight away to listen for new commands. I’m using the stash and session numbers to keep track of the current call. My problem is that for time to time the en28j60 is not sending out the new TCP packets, although my arduino serial debugs shows the code ran. I know it’s not sending the packets because I’m sniffing the traffic right out of the arduino and I don’t see the POST request going out. I have about one packet out of 5 to 10 randomly failing.

Here are some relevant parts of my code, I’m not using the EtherCard library anywhere else:

#define MAX_TIME_WAIT_GET 31 // Timeout of commands API in case I didn't see the closed connection from server
byte Ethernet::buffer[900];
Stash stash;
[...]
void setup() {
#if SERIAL
  Serial.begin(9600);
  Serial.println("Starting..");
#endif
  delay(1000);   // This delay is to wait for the Ethernet Controller to get ready
  for (;;) { // keep trying until you succeed
    delay(500);
    if (ether.begin(sizeof Ethernet::buffer, mymac, 10) == 0) {
      Serial.println( "Failed to access Ethernet controller");
      continue;
    }

    if (!ether.dhcpSetup()) {
      Serial.println("DHCP failed");
      continue;
    }

    ether.printIp("IP:  ", ether.myip);
    ether.printIp("GW:  ", ether.gwip);
    ether.printIp("DNS: ", ether.dnsip);

    if (!ether.dnsLookup(website))
      Serial.println("DNS failed");

    ether.printIp("SRV: ", ether.hisip);
    break;
  }
}
[...]
void loop() {
[...]
  // Each second, manage some counters
  if (second == 1) {
    last_command_api++;
  }
[...]
  ether.packetLoop(ether.packetReceive());

  if (last_command_api>=MAX_TIME_WAIT_GET) {
    delay(50); // Give the eth shield a bit of time?
    last_command_api=0;
    Stash::prepare(
      PSTR("GET http://$F/rest/v0/block/$F/commands HTTP/1.0" "\r\n"
           "Host: $F" "\r\n"
           "X-Ninja-Token: $F" "\r\n"
           "Content-Type: application/json" "\r\n"
           "\r\n")
      , website
      ,  PSTR(NODEID)
      , website
      , PSTR(TOKEN)
    );

    session_rcv = ether.tcpSend();
    Serial.print(F(">>> Listening session "));
    Serial.println(session_rcv);
    return; // Starting over to give the chip some time
  }

  const char* reply_rcv = ether.tcpReply(session_rcv);

  if (reply_rcv != 0) {
      // We got a reply, we can send a new GET request
      Serial.print(F("Reply COMMAND (GET) in "));
      Serial.print(last_command_api);
      Serial.print(F(" : "));
      Serial.println(reply_rcv);
      last_command_api = MAX_TIME_WAIT_GET; // So we'll send the new request in the next loop() call
      delay(50); // Give the chip a bit of time?
      return;
   }

[...]
}

So, looking at the code above I do see on the serial “>>> Listening session X” but I don’t see the TCP packets going out, the next run after the timeout of 31 seconds usually works fine and a new TCP session is established.

Thanks!
Raph


Replies (4)

RE: EtherCard: Enc28J60 not sending packets for time to time - Added by RaphYot over 4 years ago

I didn’t progress on that one, I added delays left and right (just in case) but it didn’t help.
Anyone could make a suggestion on how to ensure every packet are sent when I call ether.tcpSend() ?

Thanks!

RE: EtherCard: Enc28J60 not sending packets for time to time - Added by foxener over 4 years ago

I had a lot of problems to get a more or less stable working http connection with the EtherCard library.

The main issue for me was memory leakage in the Stash. So what I did was follow the number of free bytes in the stash (Stash::freeCount()) after every request. From time to time when the response was not handled ‘correctly’ (and this was with some Internet connections no problem, but on other locations it was but irregular) I lost memory.

My solution was to trigger a reset if the memory of the Stash became to low. (See https://github.com/dovadi/ReadP1/blob/master/ReadP1.ino)

Maybe you have a similar problem …….

RE: EtherCard: Enc28J60 not sending packets for time to time - Added by RaphYot over 4 years ago

Thanks, that gave me a bit new ideas to move forward. Unfortunately the stash memory is stable, I’m printing it at every places.

Furthermore, I realised that ether.tcpReply(session_rcv) sometimes doesn’t track the right TCP session, but it’s not linked with my issue (I suppose). I’m also wondering if the TCP connection is being closed correctly, I’d need to investigate further but but time is missing so I’ll probably not use the stash for now.

    (1-4/4)