0

I am running into an issue with a loop call on an Arduino MKR1000. I have tried the solutions suggested in this question and it usually works for 5 minutes and then collapses. I am trying to make two calls to different APIs every 10 seconds and update something on the Arduino accordingly, but the loops seem to be getting out of sync after a few minutes. Here is the code - I tried to shorten it...

#include <Time.h>
#include <SPI.h>
#include <WiFi101.h>
#include "arduino_secrets.h"

// put your local wifi info here
const char* ssid     = SECRET_SSID;
const char* password = SECRET_PASS;

const char* host = "bustime.mta.info";

void setup() {
  Serial.begin(9600);
  delay(10);
 // connecting to a WiFi network
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(300);
    Serial.print(". ");
  }    
}

void loop() {
  Serial.println("START THE LOOP");
  // Use WiFiclient class to create TCP connections
  WiFiClient client;
  WiFiClient client2;
  char * serviceDeliveryString = new char[40]();
  strcpy(serviceDeliveryString, "/ServiceDelivery");
  char * responseTimestampString = new char[40]();
  strcpy(responseTimestampString, "<ResponseTimestamp>");  
  char * TString = new char[40]();
  strcpy(TString, "T");

  if (!client.connect(host, 80)) {
    lcd.clear();
    lcd.gotoXY(0, 0);
    lcd.string(connectionFailed);
    delay(2000);
    return;
  }

  //connect to schedule data
  if (!client2.connect(host, 80)) {
    lcd.clear();
    lcd.gotoXY(0, 0);
    lcd.string(connectionFailed);
    delay(2000);
    return;
  }

  char * req1full = new char [100]();
  strcat(req1full, "GET /api/siri/stop-monitoring.xml?key=KEY&OperatorRef=MTA");
  strcat(req1full, " HTTP/1.1");
  client.println(req1full);
  client.println("Host: bustime.mta.info");
  client.println("Connection: close\r\n");

  char * req2full = new char [100]();
  strcat(req2full, "GET /api/where/schedule-for-stop/MTA_");
  strcat(req2full, stopNum);
  strcat(req2full, ".xml?");
  strcat(req2full, "key=KEY HTTP/1.1");
  Serial.println(req2full);
  client2.println(req2full);
  client2.println("Host: bustime.mta.info");
  client2.println("Connection: close\r\n");

  //Pause long enough for the connection to happen. Make this longer if you have issues.
  delay(1000);

  while(client.available()){
    if (client.findUntil(responseTimestampString, serviceDeliveryString)){
      Serial.println("inside client...");
      client.findUntil(TString, serviceDeliveryString);
      String mtaTime = client.readStringUntil('.');
      Serial.println(mtaTime);   
    }
    delay(10);
  }


  while(client2.available()){
    if (client2.findUntil("<currentTime>", "/data")){
      Serial.println("inside client2...");
      String mtaTime2 = client2.readStringUntil('<');
      Serial.println(mtaTime2);   
    }
    delay(10);
  }

  client.stop();
  client2.stop();
  delay(9000);

}

The output starts out looking good:

START THE LOOP
GET /api/where/schedule-for-stop/MTA_306762.xml?key=KEY HTTP/1.1
inside client...
22:13:38
inside client...
22:13:38
inside client2...
1541211218146
START THE LOOP
GET /api/where/schedule-for-stop/MTA_306762.xml?key=KEY HTTP/1.1
inside client...
22:13:51
inside client...
22:13:51
inside client2...
1541211231815
START THE LOOP
GET /api/where/schedule-for-stop/MTA_306762.xml?key=KEY HTTP/1.1
inside client...
22:14:04
inside client...
22:14:04
inside client2...
1541211244465

But eventually something seems to happen with the loops and this is the final output, when it should keep running:

inside client...
22:19:02
inside client...
22:19:02
START THE LOOP
GET /api/where/schedule-for-stop/MTA_306762.xml?key=KEY HTTP/1.1
START THE LOOP
GET /api/where/schedule-for-stop/MTA_306762.xml?key=KEY HTTP/1.1
START THE LOOP

Any suggestions for how to fix this?

  • is there a restriction on the frequency or the number of API calls to bustime.mta.info? – jsotola Nov 3 '18 at 2:53
  • No, I don't believe so. – garson Nov 3 '18 at 3:01
  • Hint: Possible memory leak. A lot of "new" but few "delete" (malloc/free). – Mikael Patel Nov 3 '18 at 13:34
  • thanks @MikaelPatel, I have cut out the 'new' and it seems to be working okay. – garson Nov 3 '18 at 14:29
3

You keep calling new to allocate memory but you never free it. This is a memory leak and eventually you run out. Instead of constantly creating new arrays, why don't you make those global or static. Or even just local arrays if you don't need them to be persistent. On a microcontroller you really don't want to be using new unless absolutely necessary.

  • I used "new" so that all the entries would be initialized as missing. I could move all the array declarations to before loop() though. Or maybe in setup()? THANK YOU for responding! – garson Nov 3 '18 at 2:49
  • What do you mean by "initialized as missing". That phrase doesn't make any sense to me. – Delta_G Nov 3 '18 at 3:15
  • If you put the array definitions in setup then they'll be local to setup and you can't use them in loop. – Delta_G Nov 3 '18 at 3:16
  • If you want to use "dynamic" allocation like that, consider using alloca(), since it allocates the space on the stack and it's automatically freed when the function finishes. – Majenko Nov 3 '18 at 11:20

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.