[(almost) Solved] Yùn STOPS working after 256 cycles ?!

Hi everyone! Again problems with Arduino Yùn platform…

This problem is quite weird since the Yùn stops responding after exactly 256 client.connected() cycles every time after reboot!!
I am using an application (client) written in C on a computer that creates a TCP socket pointing the Yùn’s IP address and sends a simple 2-characters string. The Yùn (server) receives and compares it and sends back the reply containing some temperature readings separated by commas.

PROBLEM: the communication takes place succesfully only the first 256 times!! When the C application tries to make the 257th sending loop the Yùn doesn’t seem to respond! Since the Arduino stops every time after 256 cycles and being 256 a power of 2, there are reasons to think that it might be a problem of RAM on the Atmega microcontroller…
Here is the code I am running on my Yùn:

// (C) Ing. Fabrizio Pravettoni, 2015
#include <Bridge.h>
#include <YunServer.h>
#include <YunClient.h>
#include <MAX6675.h>

#define SO 12
#define SCLK 13
#define unit 1 // 0=raw , 1=°C , 2=°F
float temp[3] = {0.0, 0.0, 0.0}; // Temperatures storage
#define tempDelay 200 // delay between Temp readings

const String SEP = ",";

#define PORT 255
YunServer server(PORT);
YunClient client;

static boolean clientActive = false;

MAX6675 Temp0(2, SO, SCLK, unit);
MAX6675 Temp1(3, SO, SCLK, unit);
MAX6675 Temp2(4, SO, SCLK, unit);

int count;

void setup(){
  Serial.begin(9600);
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);
  Bridge.begin();
  server.noListenOnLocalhost();
  server.begin();
  client = server.accept();
  delay(500);
  Serial.println("READY!\n");
  count = 0;
  digitalWrite(13, LOW);
}

void loop(){
  
  float BATT = 9.0;
  
  if (client.connected()){ // clients connection
    if (!clientActive)
      Serial.println("\nNew client.");
      
    clientActive = true;
    char msgIn[5];
    const int MSG_SIZE = sizeof(msgIn) - 1;
    int i = 0;
    if (client.available()){
      Serial.print("From client: ");
      
      while (client.available()){
        char c = client.read();
        
        if(i<MSG_SIZE){
          msgIn[i] = c;
        }
        if(c == '\n'){
          msgIn[i] = '\0';
        }
        i++;
        }
      i = 0;
      
      Serial.println(msgIn);
      
      if(strstr(msgIn,"tr")){
        Serial.println("Reading temps...");
        count++;
        getAllTherm();
        client.println(count +SEP+
                       temp[0] +SEP+
                       temp[1] +SEP+
                       temp[2] +SEP+
                       BATT);
        Serial.println(count +SEP+
                       temp[0] +SEP+
                       temp[1] +SEP+
                       temp[2] +SEP+
                       BATT);
      }
    }
  }else{ // No active connections, try to accept one
    if (clientActive)
      Serial.println("Client disconnected");
    clientActive = false;
    client = server.accept();
  }
  if(count > 99){ count = 0; }
}


void getAllTherm(){
  temp[0] = Temp0.read_temp();
  delay(tempDelay);
  temp[1] = Temp1.read_temp();
  delay(tempDelay);
  temp[2] = Temp2.read_temp();
  delay(tempDelay);
  }

I tried to understand when the problem occurs by checking the serial console: what I got was that at the 257th string sent from client Arduino doesn’t print anything, neither the “New client” line. On the PC application (client) I can see that connection to server (Yùn) succeed.

My conclusion considering all these aspects and checks is that the problem occurs on the Atmega microcontroller at the end of the 256th client connection cycle, when maybe its RAM is full. (At this point I verified and realized that even the loop() function takes 3 to 6 seconds to make a single cycle).

Am I correct? Is there something wrong with the code that fills the RAM? May be the problem in the Linux side?

Thank you all for any reply!

fab

fab03: Since the Arduino stops every time after 256 cycles and being 256 a power of 2, there are reasons to think that it might be a problem of RAM on the Atmega microcontroller...

Actually, the value 256 doesn't make me think of a memory leak, my experience is that the number of iterations would be random with a leak. It would only turn out to be a power of two if the combination of the memory used by statically allocated objects, plus the heap overhead, plus the stack size, plus the number of iterations times the leak size, all added up to the exact size of the memory. I'd say the odds of that are slim, at 1 to 256 against.

Stopping right after 256 iterations sounds suspiciously like a byte wide counter somewhere is overflowing.

I notice that once a connection is no longer active, the code goes right into another server.accept(), getting a new client object that overwrites the old one. I wonder if the client object allocates some memory (or uses a byte variable to track some resource) and it isn't freed up until the client is closed?

It might be worth adding a check in the not connected clause: if not connected, and clientActive is set, don't just print the message, but also call client.close() on the old client object before trying to connect to a new one.

@fab03, I'm agree with Shapeshifter. Experience tells me it is a counter. I suspect the variable clientActive

Jesse

jessemonroy650: I suspect the variable clientActive

While it is a byte-wide value, that's a simple on/off flag, not a counter. It's purpose is to identify when a new connection is created and an old one is closed. While anything is possible,mid be surprised if that were it.

This looks a lot like a piece of sample code I wrote and posted not too long ago, right down to the use of clientActive and the arbitrary port number of 255. I must admit that I did not test it with more than a few dozen connection attempts: it was meant as a proof of concept and not a finished solution.

In another discussion dealing with YunClient, it was noted that it was necessary to call client.close() to prevent problems on an outbound connection. I did not include a close() call on this inbound connection, because I assumed that if the client object was reporting that it was no longer connected, that it would realize that the connection was closed and clean up after itself. This may not be the case.

I will experiment with this tomorrow and see if I can duplicate the issue with the original code. In the mean time, if the OP wants to experiment, I suggest adding a call to client.close() where the client disconnected message is printed.

Solved. I added the function client.stop() after the client has disconnected. After this I realize that any YunClient/YunServer could accept up to 256 clients connected simultaneously, that is a byte of memory.

ShapeShifter: This looks a lot like a piece of sample code I wrote and posted not too long ago, right down to the use of clientActive and the arbitrary port number of 255. I must admit that I did not test it with more than a few dozen connection attempts: it was meant as a proof of concept and not a finished solution.

Yes I took this piece of code and left it unaltered for testing purposes (you answered right at my post few days ago about this topic). I thought it was useless to make my own code just to test if it works. In fact I also helped you to make your sample code more stable by testing it for a longer test time :D !

Thanks a lot for helping me! I will test this new code for few days and I'll tell you how it goes.

fab

fab03: Thanks a lot for helping me!

You're welcome! And thanks for stress-testing the code, and ultimately improving it. 8)

Follow up: as expected, I have confirmed the same findings running my original sketch: it stops accepting connections after 256 cycles. Curiously, when the server.accept() calls stop returning, the client trying to make the connections still reports successful connections - although it is not actually transferring any data.

So I added the client.stop() and I can make more than 256 connections.

But there are still some curiosities: I'm having trouble with my USB ports, in that sometimes I cannot open a serial connection to the Yun, and other times I can't upload sketches. I left the client/server pair of Yuns running, and the server output froze after 1420 connections, while the client output kept showing connection established messages (with no data) for a while after that. Now, both outputs are frozen. I don't know if that's a networking issue, or a flaky USB issue.

Even more curious: I tried adding a Bridge.put() call when incrementing my client connection counter so that I could see the current count without the USB port. When I do that, it freezes after anywhere from 23 to a couple hundred connections. Again, that's with the USB connected, so I don't know if it is due to the bridge or the USB issues.

I will keep on investigating. In the mean time, if you see any strange behavior, please report it.

Hmmm... I took out all references to Serial, and Bridge.put(). All I do now besides the actual network communications is to blink the LED while a connection is active.

I let the client and server run for a while, with both of them merrily blinking away in sync. Let that go for a while, and now that I look at it, both are dark. >:(

I tried resetting just the server side '32U4 to see if things would recover. It resets, pauses a moment while the bridge starts, and then nothing.

I then tried resetting the client side '32U4. It resets, lights the LED while the bridge starts, and the LED never goes out. Interesting, it looks like the Linux side might be hung up?

I next press the YUN RST button on the client side to restart Linux. The white light never comes on, and the LED indicating that the sketch is waiting for the Bridge to start never goes off. (The '32U4 is still trying to start the bridge, did it send something at the wrong time to interrupt the boot process?)

Cycle power on the Client side, and after booting the communications resumes. But only for a few seconds this time. :'(

fab03: Solved. I added the function client.stop() after the client has disconnected. After this I realize that any YunClient/YunServer could accept up to 256 clients connected simultaneously, that is a byte of memory.

::::SNIP:::"

@fab03, Could you upload the code and put a special note where you made the fix? I'll document that and have it ready next, if you could do that.

TIA Jesse

I made a note of the specific change I made in the original discussion. I only offer it as a data point, because I would still like to hear from fab03 about his specific change, and how well it's working for him (because I'm still having issues, which are now unfortunately random and not after a fixed number of cycles.)

Hey friends! Do not worry, I didn't forget you! I was just trying the sketch in these three days and a half! I explain again my setup during this test: a Windows PC running a C application (client) which opens a TCP socket about every 1.5 seconds and sends a raw string. An Arduino Yùn (server) that receives the string, compares it, does some processes and sends back another string containing some data. I made this long-time test connecting [u]both the PC and the Yùn via ethernet cables[/u].

The test was [u]very succesful[/u] and the data travel was very smooth during all the test. I overcame 91,000 (ninety-one thousands) send/receive cycles without problems at the end of the test.

@ShapeShifter

My long-time test just explained has been made with no USB data connection (no Arduino drivers on the test PC, USB used only to power the Yùn), thus the Serial.begin() actually did not begin.

I only made an initial shorter test with my laptop using the USB serial for debugging for about 400 (four hundred) send/receive cycles, but I encountered NO problems.

I finally found troubles using a different setup: PC via ethernet and Yùn via wi-fi. This way, after some hundreds send/receive cycles, the entire process was becoming a little slower. Don't know why. Pretty strange the fact that the situation was restored (process fast again) when I started the USB serial console (so the setup() function has run again).

Interesting data points! Thanks for sharing. 8)