1

I have tried to set up a very simple REST API on an Arduino Industrial 101 (which is, as far as I understand, equivalent to a Yún). The Arduino is hooked up to a temperature sensor, which value is returned over the REST interface. Everything works fine at first, but over the course of a day it starts taking longer and longer for the device to respond until it completely crashes and becomes unresponsive. (At that point it also doesn't respond to ping and ssh anymore.)

On the Arduino forum there are several threads reporting similar problems (e.g. this one) but they all seem to be at least a few years old and have been solved in the mean time. (The solution reported here, for instance, has already been incorporated in my Linino version.)

If I reset the ATMega the problem persists, but if I reboot the OS it is solved for a day, so I have reason to suspect something on the Linino side is not working properly. Any help would be much appreciated, although I realize this is quite an old board.

My sketch is basically a dumbed-down version of the Bridge example:

#include <Bridge.h>
#include <BridgeServer.h>
#include <BridgeClient.h>

BridgeServer server;

void setup() {
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
  Bridge.begin();
  digitalWrite(13, HIGH);

  server.listenOnLocalhost();
  server.begin();
}

void loop() {
  // Get clients coming from server
  BridgeClient client = server.accept();

  // There is a new client?
  if (client) {
    // Process request
    process(client);

    // Close connection and free resources.
    client.stop();
  }

  delay(50); // Poll every 50ms
}

void process(BridgeClient client) {
  // no matter what the command is, return value on A1 sampled 4096 times

  int pin = 1;
  float val = 0;
  for (int i = 0; i < 4096; i++){
    val += float(analogRead(pin))/4096.0;
  }
  client.println(val*5.0/1024.0, 5); //multiply by 5/1024 to get volts

}
0
+100

I inspected the source code of the Bridge library. It is very simple.

There are no dynamic memory allocations. It uses String in client.connect(), but your sketch doesn't use it. You could print free memory in ATmega with MemoryFree library. But I am 99% percent sure it will show no memory leak.

There is no 'background' processing in the Bridge library as suggested by other answers. All commands and data are sent to the WRT on Atheros and wait for result or acknowledge. The WRT side of the Bridge library is coded in python.

The fact that the restart of the WRT is what helps to continue, confirms that the problem is on the python side of the Bridge.

Python on WRT is very far from Arduino knowledge base, so I doubt you will get a solution here.

  • It's a WiFi module so there is background processing to keep the TCP or just any connection up – Zunzulla alagaty Mar 18 at 15:30
  • @Zunzullaalagaty, the WiFi processing is done in the Atheros chip not in ATmega and input is checked only in library calls like available or read . – Juraj Mar 18 at 15:38
0

analogRead() returns a number between 0 and 1023, so the code in the process() function is where you can make some improvements.

I've added a unsigned long variable to accumulate the 4096 analog readings. After adding all the readings together, you can then divide the total by 4096. Up to this point, we are not using floating point numbers, nor do we need to. Integer math is far less "costly" to do than floating point math.

Finally, I cast the reading to a floating point number to be used in the floating point calculation client.println(val*5.0/1024.0, 5);.

I don't have an Arduino Yún or the libraries you are using to test with, so here is a simple sketch with my proposed changes to the process() function.

unsigned long previousMillis = 0;
const long refreshRate = 50;

void setup(){
  Serial.begin(9600);
  process();
}   

void process(){
  // no matter what the command is, return value on A1 sampled 4096 times
  int pin = 1;
  float val = 0;
  unsigned long temp = 0;
  for (int i = 0; i < 4096; i++){
    //val += float(analogRead(pin))/4096.0;
    temp += analogRead(pin);
  }
  temp = temp / 4096;
  val = float(temp);
  Serial.println(val*5.0/1024.0, 5);
  //client.println(val*5.0/1024.0, 5); //multiply by 5/1024 to get volts
}

void loop(){
  unsigned long currentMillis = millis();

  // Poll every 50ms
  if(currentMillis - previousMillis >= refreshRate){
    process();
    previousMillis = currentMillis;
  }
}

Zunzulla alagaty makes a good point about using delay(). My test sketch has removed the delay() and replaced it with a millis() timer, based off of the BlinkWithoutDelay sketch that comes with the IDE.

0

First of all you should try changing the delay(50);. Try using millis(); instead and see if the problem still persists.

int borderMillis = 50;
int startMillis = millis();

void loop()
{
  int nowMillis = millis();
  if(nowMillis >= borderMillis)
  {
    //ask for new client etc.

    startMillis = millis();
  }
}

If that doesn't help, try adding the yield(); method after the delay(50); / at the end of the loop. Sometimes the board just needs time to get the background duties finished, so this comes in handy.

My very last guess would be a memory leak. You could try to get the amount of heap you have left, and see if it continuously drops and won't get released. There are libraries that can help you to retrieve the amount of memory you've left.

  • I'll try this soon, but just to make sure I understand your millis() suggestion: the conditional that's used by the if, shouldn't that be (nowMillis - startMillis) >= borderMillis? – Julius Mar 15 at 19:57
  • @Julius for me it always worked without the brackets. But if that doesn't work for you, go ahead – Zunzulla alagaty Mar 15 at 23:47
  • I wasn't concerned so much about the brackets, it just seems to me that if you define nowMillis as millis() on every iteration it will almost always be larger than 50, and so the if will almost always evaluate to true. – Julius Mar 18 at 12:09
  • @Julius I assume yield() didn't help? – Zunzulla alagaty Mar 18 at 15:30
  • I tried, but the Scheduler library is not available for my board. – Julius Mar 18 at 21:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.