How can i add a "reset" in my loop to secure that processes continues?

Hi,
I have made a simple project that reads två sensors and via Wifi connects to Xively to upload the sensors values. However for some reason the loop stops and a forced reset is needed to get the loop started again. (not optimal)

my skills are bit limited but my idea would be to add an interup reset based on timer? e.g. if loop is not completed in 30sec then reset loop. However i would need help to understand where in my code i should put the interupt and possible also example code.

any good ideas is apriciated.

// Libraries
#include <Adafruit_CC3000.h>
#include <ccspi.h>
#include <SPI.h>
#include <string.h>
#include "utility/debug.h"
#include "DHT.h"
#include<stdlib.h>

// Define CC3000 chip pins
#define ADAFRUIT_CC3000_IRQ   3
#define ADAFRUIT_CC3000_VBAT  5
#define ADAFRUIT_CC3000_CS    10

// DHT sensor
#define DHTPIN 53
#define DHTTYPE DHT22

// Create CC3000 instances
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,
                                         SPI_CLOCK_DIV2); // you can change this clock speed
                                         
// DHT instance
DHT dht(DHTPIN, DHTTYPE);

// WLAN parameters
#define WLAN_SSID       "xxxxx"
#define WLAN_PASS       "xxxxx*"
// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2
#define WLAN_SECURITY   WLAN_SEC_WPA2

// Xively parameters
#define WEBSITE  "api.xively.com"
#define API_key  "zzzzzzzz"
#define feedID  "zzzzzzzzz"

uint32_t ip;

void setup(void)
{
  // Initialize
  Serial.begin(115200);
  
  Serial.println(F("\nInitializing..."));
  if (!cc3000.begin())
  {
    Serial.println(F("Couldn't begin()! Check your wiring?"));
    while(1);
  }
 
}

void loop(void)
{
  // Connect to WiFi network
  cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY);
  Serial.println(F("Connected!"));
  
  /* Wait for DHCP to complete */
  Serial.println(F("Request DHCP"));
  while (!cc3000.checkDHCP())
  {
    delay(100);
  }  

  // Get the website IP & print it
  ip = 0;
  Serial.print(WEBSITE); Serial.print(F(" -> "));
  while (ip == 0) {
    if (! cc3000.getHostByName(WEBSITE, &ip)) {
      Serial.println(F("Couldn't resolve!"));
    }
    delay(500);
  }
  cc3000.printIPdotsRev(ip);
  
  // Get data & transform to integers
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  
  int temperature = (int) t;
  int humidity = (int) h;
  
  // Prepare JSON for Xively & get length
  int length = 0;

  String data = "";
  data = data + "\n" + "{\"version\":\"1.0.0\",\"datastreams\" : [ {\"id\" : \"Temperature\",\"current_value\" : \"" + String(temperature) + "\"}," 
  + "{\"id\" : \"Humidity\",\"current_value\" : \"" + String(humidity) + "\"}]}";
  
  length = data.length();
  Serial.print("Data length");
  Serial.println(length);
  Serial.println();
  
  // Print request for debug purposes
  Serial.print("PUT /v2/feeds/");
  Serial.print(feedID);
  Serial.println(".json HTTP/1.0");
  Serial.println("Host: api.xively.com");
  Serial.print("X-ApiKey: ");
  Serial.println(API_key);
  Serial.print("Content-Length: ");
  Serial.println(length, DEC);
  Serial.print("Connection: close");
  Serial.println();
  Serial.print(data);
  Serial.println();
  
  // Send request
  Adafruit_CC3000_Client client = cc3000.connectTCP(ip, 80);
  if (client.connected()) {
    Serial.println("Connected!");
    client.println("PUT /v2/feeds/" + String(feedID) + ".json HTTP/1.0");
    client.println("Host: api.xively.com");
    client.println("X-ApiKey: " + String(API_key));
    client.println("Content-Length: " + String(length));
    client.print("Connection: close");
    client.println();
    client.print(data);
    client.println();
  } else {
    Serial.println(F("Connection failed"));    
    return;
  }
  
  Serial.println(F("-------------------------------------"));
  while (client.connected()) {
    while (client.available()) {
      char c = client.read();
      Serial.print(c);
    }
  }
  client.close();
  Serial.println(F("-------------------------------------"));
  
  Serial.println(F("\n\nDisconnecting"));
  cc3000.disconnect();
  
  // Wait 10 seconds until next update
  delay(10000);
  
}

Serial output as it should look when loop is succesfull

Started AP/SSID scan




Connecting to slow...Waiting to connect...Connected!
Request DHCP
api.xively.com -> 216.52.233.120Data length128

PUT /v2/feeds/zzzzzzzzz.json HTTP/1.0
Host: api.xively.com
X-ApiKey: zzzzzzzzzz
Content-Length: 128
Connection: close

{"version":"1.0.0","datastreams" : [ {"id" : "Temperature","current_value" : "23"},{"id" : "Humidity","current_value" : "24"}]}


Connect to 216.52.233.120:80
Connected!
-------------------------------------
HTTP/1.1 200 OK
Date: Sat, 29 Mar 2014 07:08:49 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 0
Connection: close
X-Request-Id: 80d4b2d4d0ec76967005b023247276b33e9ef5eb
Cache-Control: max-age=0
Vary: Accept-Encoding

-------------------------------------
Disconnecting

Serial output when failed

Started AP/SSID scan




Connecting to slow...Waiting to connect...Connected!
Request DHCP
api.xively.com -> 216.52.233.120Data length128

PUT /v2/feeds/zzzzzzzz.json HTTP/1.0
Host: api.xively.com
X-ApiKey: zzzzzzzzzzzz
Content-Length: 128
Connection: close

{"version":"1.0.0","datastreams" : [ {"id" : "Temperature","current_value" : "23"},{"id" : "Humidity","current_value" : "24"}]}

Connect to 216.52.233.120:80
Connected!

if loop is not completed in 30sec then reset loop.

In other words the watchdog timer. It will do that for you if correctly set up. You don't need an interrupt routine or anything, but this should be the exception, not the way the code is designed to work as the norm.

So you say the code appears to crash after

Serial.println("Connected!");

There are a heap of client.println()s after that, have you tried adding other serial debugging prints to see exactly what line fails?


Rob

any good ideas is apriciated.

OK> Stop doing this. The String class wastes resources like no other class.

  String data = "";
  data = data + "\n" + "{\"version\":\"1.0.0\",\"datastreams\" : [ {\"id\" : \"Temperature\",\"current_value\" : \"" + String(temperature) + "\"}," 
  + "{\"id\" : \"Humidity\",\"current_value\" : \"" + String(humidity) + "\"}]}";

A fixed size character buffer and sprintf() are what you need.

You have some infinite loops using WHILE. If they don't get the expected result they will never end. Only code like this if you are certain there will be a successful result in a reasonable time.

You can rewrite the code so that it just tries one of those calls at one go and you can then check (using millis()) if too much time has elapsed and abort if necessary. You should replace all the delays with millis() using the techniques in the Blink Without Delay example sketch.

...R

Robin2:
You have some infinite loops using WHILE. If they don't get the expected result they will never end. Only code like this if you are certain there will be a successful result in a reasonable time.

You can rewrite the code so that it just tries one of those calls at one go and you can then check (using millis()) if too much time has elapsed and abort if necessary. You should replace all the delays with millis() using the techniques in the Blink Without Delay example sketch.

...R

This this sounds interesting, the problem is most likely due to some wierd response/lack of response from Xivly.. its pretty hard to debug since it happens randomly sometimes after 1h other times after 12hours. The other suggestions seems bit to tricky for me to code my self by your suggestion i think ill manage to implement. Thanks alot

other suggestions & hits are wellcome

newbee112:

Robin2:
You have some infinite loops using WHILE. If they don't get the expected result they will never end. Only code like this if you are certain there will be a successful result in a reasonable time.

You can rewrite the code so that it just tries one of those calls at one go and you can then check (using millis()) if too much time has elapsed and abort if necessary. You should replace all the delays with millis() using the techniques in the Blink Without Delay example sketch.

...R

This this sounds interesting, the problem is most likely due to some wierd response/lack of response from Xivly.. its pretty hard to debug since it happens randomly sometimes after 1h other times after 12hours. The other suggestions seems bit to tricky for me to code my self by your suggestion i think ill manage to implement. Thanks alot

other suggestions & hits are wellcome

I been at it for few hours but i cant get it to work. i am simply to novis att this :frowning: do you have any example code that you can refer me to?

With my limited debugging skills it seems that its within this IF statement the program fails depending on lack of respons from Xivly.com.

Can i add some timer to this code that makes the program try for e.g. 10 secounds and if not sucesfull then disconnect and continue the loop?

 if (client.connected()) {
    Serial.println("Connected!"); 
    client.println("PUT /v2/feeds/" + String(feedID) + ".json HTTP/1.0"); /this is where the loop stops 
    client.println("Host: api.xively.com");
    client.println("X-ApiKey: " + String(API_key));
    client.println("Content-Length: " + String(length));
    client.print("Connection: close");
    client.println();
    client.print(data);
    client.println();
  } else {
    Serial.println(F("Connection failed"));    
    return;
  }

You have this piece of code (just as an example)

  /* Wait for DHCP to complete */
  Serial.println(F("Request DHCP"));
  while (!cc3000.checkDHCP())
  {
    delay(100);
  }

It could be rewritten something like this

unsigned long startMillis = millis();
unsigned long maxWait = 3000; // 3 seconds
boolean DHCPresult = 'W'; // W = waiting
boolean DHCPconnect = false;
while(DHCPresult == 'W') {
   if (cc3000.checkDHCP()) {
       DHCPresult = 'C'; // C = connected
   }
   else {
     delay(100); // is a delay actually necessary
   }
   if (millis() - startMillis >= maxWait) {
      DHCPresult = 'T';  // T = timeout
   }
}

...R

Thanks!
I Just noticed another flaw in the orginal code, if it doesnt resolve the IP for Xively site then it hangs there aswell.
I think ill just ignore the whole part of the code that interacts with Xively and store the data on my own linux server at home.. It seems to be to many issues with going online using Xively service.

thanks for all your great support, ill start a new sketch :slight_smile:

    client.println("PUT /v2/feeds/" + String(feedID) + ".json HTTP/1.0"); /this is where the loop stops

I think that there is a big clue right there.

A static sized array, sprintf(), and banishing the String class will help.