[Solved] CC3000 Hang

For other supported Arduino products from Adafruit: Shields, accessories, etc.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
nmck
 
Posts: 3
Joined: Mon Dec 09, 2013 10:44 am

[Solved] CC3000 Hang

Post by nmck »

Hi,

I had a look over the forum to see if there was a similar issue, didn't see one the same as mine so here goes..

I am using the cc3000 breakout board to connect to my server to retrieve some information i.e. commands, Its running the webclient example. It runs perfectly and does everything I need it to, but every so often it will hang on "Connect to xx.x.xx.xxx".

I originally thought it may be a arduino memory issue but I have since found out that it is a connection issue.

I disabled my server and ran the code and was able to replicate the issue, Everything works (connecting, dhcp, get server ip address etc.) great up until it tries to connect to the server, which obviously wont work when the server is disabled.

So what I think I need is a way to timeout this part of the code. Im pretty sure its the connectTCP() function in the library, Is there a way to insert a timeout type function in there? So if its trying to connect for say 2 seconds it will stop and move onto the next part of the code.

Any info would be greatly appreicated,

Thanks
Last edited by nmck on Tue Dec 10, 2013 6:47 pm, edited 1 time in total.

User avatar
adafruit_support_rick
 
Posts: 35092
Joined: Tue Mar 15, 2011 11:42 am

Re: CC3000 Hang

Post by adafruit_support_rick »

I forwarded this to engineering

User avatar
PlastiBots
 
Posts: 120
Joined: Fri Mar 25, 2011 7:12 pm

Re: CC3000 Hang

Post by PlastiBots »

I'll also add that I have a similar issue. I have a project that retrieves info from the server (based on the AF WiFi Robot). I added some timer code to print the duration to the serial window and let it run a number of times. Although the timing of the crash varies, it always does at some point. I've seen ranges from 25 minutes to 3 hours of run time. For these cases, I am doing nothing with the robot and the webserver json file contents are not changing - it's retrieving the same data with each call. However, when I use WiFi Bot Control to send commands (which causes the json file to be updated very quickly), the sketch seems to crash sooner (i.e within 1-2 minutes of driving the robot).

I can only speculate, but it seems that there is some disruption possibly between the sketch making the call to the server and reading the json file contents and WiFi Bot Control making calls to the server to update the (same) json file. However, I would expect, if this was the issue, that the crash would be immediate. I suppose it could be the WiFi connection.

It would be nice if there was a catch routine we could add that could be used to detect an issue, and allow for a re-connect. Of sorts.

User avatar
tdicola
 
Posts: 1074
Joined: Thu Oct 17, 2013 9:11 pm

Re: CC3000 Hang

Post by tdicola »

Do you mind posting the code for the webclient example that is hanging? There was an issue with servers that closed the connection too quickly causing the example to get stuck in a loop. This was fixed recently in the library by adding a timeout to receive data, but you might be using the older example code.

nmck
 
Posts: 3
Joined: Mon Dec 09, 2013 10:44 am

Re: CC3000 Hang

Post by nmck »

Here is is the webclient example code I am working from:

Code: Select all

/*************************************************** 
  This is an example for the Adafruit CC3000 Wifi Breakout & Shield

  Designed specifically to work with the Adafruit WiFi products:
  ----> https://www.adafruit.com/products/1469

  Adafruit invests time and resources providing this open source code, 
  please support Adafruit and open-source hardware by purchasing 
  products from Adafruit!

  Written by Limor Fried & Kevin Townsend for Adafruit Industries.  
  BSD license, all text above must be included in any redistribution
 ****************************************************/
 
 /*
This example does a test of the TCP client capability:
  * Initialization
  * Optional: SSID scan
  * AP connection
  * DHCP printout
  * DNS lookup
  * Optional: Ping
  * Connect to website and print out webpage contents
  * Disconnect
SmartConfig is still beta and kind of works but is not fully vetted!
It might not work on all networks!
*/
#include <Adafruit_CC3000.h>
#include <ccspi.h>
#include <SPI.h>
#include <string.h>
#include "utility/debug.h"

// These are the interrupt and control pins
#define ADAFRUIT_CC3000_IRQ   3  // MUST be an interrupt pin!
// These can be any two pins
#define ADAFRUIT_CC3000_VBAT  5
#define ADAFRUIT_CC3000_CS    10
// Use hardware SPI for the remaining pins
// On an UNO, SCK = 13, MISO = 12, and MOSI = 11
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,
                                         SPI_CLOCK_DIV2); // you can change this clock speed

#define WLAN_SSID       "myNetwork"           // cannot be longer than 32 characters!
#define WLAN_PASS       "myPassword"
// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2
#define WLAN_SECURITY   WLAN_SEC_WPA2

#define IDLE_TIMEOUT_MS  3000      // Amount of time to wait (in milliseconds) with no data 
                                   // received before closing the connection.  If you know the server
                                   // you're accessing is quick to respond, you can reduce this value.

// What page to grab!
#define WEBSITE      "www.adafruit.com"
#define WEBPAGE      "/testwifi/index.html"


/**************************************************************************/
/*!
    @brief  Sets up the HW and the CC3000 module (called automatically
            on startup)
*/
/**************************************************************************/

uint32_t ip;

void setup(void)
{
  Serial.begin(115200);
  Serial.println(F("Hello, CC3000!\n")); 

  Serial.print("Free RAM: "); Serial.println(getFreeRam(), DEC);
  
  /* Initialise the module */
  Serial.println(F("\nInitializing..."));
  if (!cc3000.begin())
  {
    Serial.println(F("Couldn't begin()! Check your wiring?"));
    while(1);
  }
  
  // Optional SSID scan
  // listSSIDResults();
  
  if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {
    Serial.println(F("Failed!"));
    while(1);
  }
   
  Serial.println(F("Connected!"));
  
  /* Wait for DHCP to complete */
  Serial.println(F("Request DHCP"));
  while (!cc3000.checkDHCP())
  {
    delay(100); // ToDo: Insert a DHCP timeout!
  }  

  /* Display the IP address DNS, Gateway, etc. */  
  while (! displayConnectionDetails()) {
    delay(1000);
  }

  ip = 0;
  // Try looking up the website's IP address
  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);
  
  // Optional: Do a ping test on the website
  /*
  Serial.print(F("\n\rPinging ")); cc3000.printIPdotsRev(ip); Serial.print("...");  
  replies = cc3000.ping(ip, 5);
  Serial.print(replies); Serial.println(F(" replies"));
  */  

  /* Try connecting to the website.
     Note: HTTP/1.1 protocol is used to keep the server from closing the connection before all data is read.
  */
  Adafruit_CC3000_Client www = cc3000.connectTCP(ip, 80);
  if (www.connected()) {
    www.fastrprint(F("GET "));
    www.fastrprint(WEBPAGE);
    www.fastrprint(F(" HTTP/1.1\r\n"));
    www.fastrprint(F("Host: ")); www.fastrprint(WEBSITE); www.fastrprint(F("\r\n"));
    www.fastrprint(F("\r\n"));
    www.println();
  } else {
    Serial.println(F("Connection failed"));    
    return;
  }

  Serial.println(F("-------------------------------------"));
  
  /* Read data until either the connection is closed, or the idle timeout is reached. */ 
  unsigned long lastRead = millis();
  while (www.connected() && (millis() - lastRead < IDLE_TIMEOUT_MS)) {
    while (www.available()) {
      char c = www.read();
      Serial.print(c);
      lastRead = millis();
    }
  }
  www.close();
  Serial.println(F("-------------------------------------"));
  
  /* You need to make sure to clean up after yourself or the CC3000 can freak out */
  /* the next time your try to connect ... */
  Serial.println(F("\n\nDisconnecting"));
  cc3000.disconnect();
  
}

void loop(void)
{
 delay(1000);
}

/**************************************************************************/
/*!
    @brief  Begins an SSID scan and prints out all the visible networks
*/
/**************************************************************************/

void listSSIDResults(void)
{
  uint8_t valid, rssi, sec, index;
  char ssidname[33]; 

  index = cc3000.startSSIDscan();

  Serial.print(F("Networks found: ")); Serial.println(index);
  Serial.println(F("================================================"));

  while (index) {
    index--;

    valid = cc3000.getNextSSID(&rssi, &sec, ssidname);
    
    Serial.print(F("SSID Name    : ")); Serial.print(ssidname);
    Serial.println();
    Serial.print(F("RSSI         : "));
    Serial.println(rssi);
    Serial.print(F("Security Mode: "));
    Serial.println(sec);
    Serial.println();
  }
  Serial.println(F("================================================"));

  cc3000.stopSSIDscan();
}

/**************************************************************************/
/*!
    @brief  Tries to read the IP address and other connection details
*/
/**************************************************************************/
bool displayConnectionDetails(void)
{
  uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv;
  
  if(!cc3000.getIPAddress(&ipAddress, &netmask, &gateway, &dhcpserv, &dnsserv))
  {
    Serial.println(F("Unable to retrieve the IP Address!\r\n"));
    return false;
  }
  else
  {
    Serial.print(F("\nIP Addr: ")); cc3000.printIPdotsRev(ipAddress);
    Serial.print(F("\nNetmask: ")); cc3000.printIPdotsRev(netmask);
    Serial.print(F("\nGateway: ")); cc3000.printIPdotsRev(gateway);
    Serial.print(F("\nDHCPsrv: ")); cc3000.printIPdotsRev(dhcpserv);
    Serial.print(F("\nDNSserv: ")); cc3000.printIPdotsRev(dnsserv);
    Serial.println();
    return true;
  }
}
There is a timeout function in there for adjusting the response time but from what I can tell it doesn't reach that part of the code. This is why I suspect it is something to do with the connectTCP() function.

It may be because the port is open on the server so it does get through but there is nothing there, if I visit the address on my web browser (chrome) then it tries to load the page for about 10 seconds before saying "Oops! Google Chrome could not connect to xx.xx.xx.xx". So what would be useful is some similar functionality in the connectTCP() function where after some time it will move on.

User avatar
tdicola
 
Posts: 1074
Joined: Thu Oct 17, 2013 9:11 pm

Re: CC3000 Hang

Post by tdicola »

Ah thanks for confirming, yep that looks like the fixed example code. I was poking around a bit at the library source and it doesn't look like it's really possible to add a timeout without better support from TI. Here's a thread from TI support where they confirm the connect API (used internally by connectTCP) is blocking with a 1 minute timeout. It might be interesting to check if you see your sketch waiting a minute and then failing just to check that the 1 minute delay at least applies.

It does sound like there might be a way to reduce the timeout to 20 seconds though by calling their netapp_timeout_values API. You can get access to call this in your sketch by including "utility/netapp.h". I think you would want to do something like (untested):

Code: Select all

unsigned long aucDHCP = 14400;
unsigned long aucARP = 3600;
unsigned long aucKeepalive = 10;
unsigned long aucInactivity = 20;
if (netapp_timeout_values(&aucDHCP, &aucARP, &aucKeepalive, &aucInactivity) != 0) {
  Serial.println("Error setting inactivity timeout!");
}

nmck
 
Posts: 3
Joined: Mon Dec 09, 2013 10:44 am

Re: CC3000 Hang

Post by nmck »

Thanks tdicola! That seemed to do the trick, just what I was after.

As you mentioned the default timeout is 1 minute, however that doesn't seem to apply in the Arduino library. It needs to be explicitly called using netapp_timeout_values. The minimum timeout value is 20 seconds which works in the sketch.

Just for anyone wondering when the timeout occurs after 20 seconds the CC3000 returns "Connection error", the sketch then reacts as if there has been a failed connection (i.e. www.connected() returned false)

netapp_timeout_values may be a useful thing to add to the Adafruit library as it doesn't seem that the default values are initialized.

User avatar
knack2
 
Posts: 6
Joined: Sat Dec 28, 2013 4:37 pm

Re: [Solved] CC3000 Hang

Post by knack2 »

I believe I also have this same issue and see the posted code as a way to initialize the CC3000 timeouts but my questions is about where this would go in my sketch.

I initialize the CC3000 in the setup portion of the code and I have this code in my loop prior to the CC3000 routines to post to the website I am using but it hasn't seemed to help... my code still randomly hangs after some period of time. Everything compiles properly and seems to run but not sure if these timeouts are really being initialized.

I am just checking some basic sensors and printing to an LCD so not sure what else could be an issue.

Any help is appreciated.

User avatar
tdicola
 
Posts: 1074
Joined: Thu Oct 17, 2013 9:11 pm

Re: [Solved] CC3000 Hang

Post by tdicola »

Put the code in your setup function, after all the CC3000 setup code. I don't think it would hurt to have it in the loop, but try moving it out just to be sure.

Do you mind posting the code for the sketch? There might be something else that's causing the device to hang and it would help with troubleshooting.

User avatar
knack2
 
Posts: 6
Joined: Sat Dec 28, 2013 4:37 pm

Re: [Solved] CC3000 Hang

Post by knack2 »

Code is below. Not sure my code is totally correct and I am definitely a novice but think I have the latest libraries at least.

Thanks so much for any insight.

Code: Select all

// Libraries
#include <Adafruit_CC3000.h>
#include <ccspi.h>
#include <SPI.h>
#include <string.h>
#include "utility/debug.h"
#include "DHT.h"
#include <stdlib.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP085.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <avr/WDT.h>
#include <RTClib.h>
#include <utility/netapp.h>


// Define CC3000 chip pins
#define ADAFRUIT_CC3000_IRQ   3
#define ADAFRUIT_CC3000_VBAT  47
#define ADAFRUIT_CC3000_CS    53

#if defined(__SAM3X8E__)
    #undef __FlashStringHelper::F(string_literal)
    #define F(string_literal) string_literal
#endif

#define cs   46
#define dc   49
#define rst  48  // you can also connect this to the Arduino reset

Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst);
float p = 3.1415926;

// DHT sensor
DHT dht;

// 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
// BH1750 instance
int BH1750address = 0x23;
byte buff[2];

// BMP085 instance
Adafruit_BMP085 bmp = Adafruit_BMP085(10085);

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

#define IDLE_TIMEOUT_MS  3000

// Xively parameters
#define WEBSITE  "api.xively.com"
#define API_key  "MY_XIVELY_API"
#define feedID  "MY_FEED_KEY"

uint32_t ip;

void setup(void)
{
  
  byte buff[2];

  if (!cc3000.begin())
  {
    while(1);
  }
 
 dht.setup(2);
  
 if(!bmp.begin())
  {
   while(1);
   }
   
 tft.initR(INITR_BLACKTAB);   // initialize a ST7735S chip, black tab
  tft.setRotation(0);
  
 // Connect to WiFi network
  cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY);

  /* Wait for DHCP to complete */
  while (!cc3000.checkDHCP())
  {
    delay(200);
  }    
  
}

void loop(void)
{
  
  tft.invertDisplay(false); 
  
  sensors_event_t event;
  bmp.getEvent(&event);
  
  int i;
  uint16_t val=0;
  BH1750_Init(BH1750address);
  if(2==BH1750_Read(BH1750address))
  {
    val=((buff[0]<<8)|buff[1])/1.2;
  }

  
  // Get data & transform to integers
  float h = dht.getHumidity();
  float t = dht.getTemperature();
  float tempf = dht.toFahrenheit(t);
  float lux = val;
  float baro = event.pressure;
  float soil = analogRead(15);
  
  float tempc;
    bmp.getTemperature(&tempc);
 
  int temperature = (int) tempf;
  int humidity = (int) h;
  int light = (int) lux;
  int barometer = (int) baro;
  int temperaturec = (int) tempc;
  int soilmoisture = (int) soil;
   
  
  // Prepare JSON for Xively & get length
  int length = 0;

  String data = "";
  data = data + "\n" + "{\"version\":\"1.0.0\",\"datastreams\" : [ {\"id\" : \"Temperature_F\",\"current_value\" : \"" + String(temperature) + "\"}," 
  + "{\"id\" : \"Humidity\",\"current_value\" : \"" + String(humidity) + "\"},"
  + "{\"id\" : \"Barometer\",\"current_value\" : \"" + String(barometer) + "\"},"
  + "{\"id\" : \"TemperatureC\",\"current_value\" : \"" + String(temperaturec) + "\"}," 
  + "{\"id\" : \"SoilMoisture\",\"current_value\" : \"" + String(soilmoisture) + "\"},"
  + "{\"id\" : \"Luminosity\",\"current_value\" : \"" + String(light) + "\"}]}";
  
  length = data.length();
  
  tft.fillScreen(ST7735_BLACK);
  tft.setTextColor(ST7735_WHITE);
  tft.setTextSize(2);
  tft.setCursor(0, 0);
  tft.print("TempF Humi");
  tft.setCursor(0, 20);
  tft.setTextSize(2);
  tft.setTextColor(ST7735_GREEN);
  tft.print(tempf, 1);//tft.print(char(247));
  tft.setTextColor(ST7735_WHITE);
  tft.setTextSize(1);
  tft.setTextColor(ST7735_GREEN);
  tft.setTextSize(2);
  tft.print("  ");tft.print(h, 1);//tft.println("%");
  tft.setTextColor(ST7735_WHITE);
  tft.setCursor(0, 40);
  tft.println("TempC Soil");
  tft.setTextColor(ST7735_GREEN);
  tft.setTextSize(2);
  tft.setCursor(0, 60);
  tft.print(tempc, 1);tft.print("  ");
  if(analogRead(3)>800)
  {
    tft.setTextColor(ST7735_RED);
  }
  else
  {
    tft.setTextColor(ST7735_GREEN);
  }
  tft.println(analogRead(3));
    
  tft.setTextSize(1);
  tft.setCursor(0, 80);
  tft.setTextColor(ST7735_WHITE);
  tft.print("Luminosity: ");
  tft.setTextColor(ST7735_YELLOW);tft.print(val, DEC);
  tft.setTextColor(ST7735_WHITE);
  tft.println(" LUX");
  tft.setCursor(0, 92);
  tft.setTextColor(ST7735_WHITE);
  tft.print("Barometer: ");
  tft.setTextColor(ST7735_BLUE);
  tft.print(event.pressure);
  tft.setTextColor(ST7735_WHITE);
  tft.println("hPa");
  tft.setCursor(0, 100);

 
unsigned long aucDHCP = 14400;
unsigned long aucARP = 3600;
unsigned long aucKeepalive = 10;
unsigned long aucInactivity = 20;
if (netapp_timeout_values(&aucDHCP, &aucARP, &aucKeepalive, &aucInactivity) != 0) {
  tft.fillScreen(ST7735_BLACK);
  tft.setCursor(0, 100);
  tft.setTextSize(2);
  tft.println("Error setting inactivity timeout!");
}

  // Get the website IP & print it
  ip = 0;
  while (ip == 0) {
    if (! cc3000.getHostByName(WEBSITE, &ip)) {
    }
    delay(500);
  }
  cc3000.printIPdotsRev(ip);
  
  // Send request
  {
  Adafruit_CC3000_Client client = cc3000.connectTCP(ip, 80);
  if (client.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 {
    tft.setCursor(140, 0);
    tft.print(F("Connection Failed"));    
    return;
  }
  
  
  
 unsigned long lastRead = millis();
 while (client.connected() && (millis() - lastRead < IDLE_TIMEOUT_MS)) {
    while (client.available()) {
      char c = client.read();
      lastRead = millis();
    }
  }
  
  client.close();
  delay(5000);
}

  
  tft.fillScreen(ST7735_BLACK);
  tft.setTextColor(ST7735_WHITE);
  tft.setTextSize(2);
  tft.setCursor(0, 0);
  tft.print("TempF Humi");
  tft.setCursor(0, 20);
  tft.setTextSize(2);
  tft.setTextColor(ST7735_GREEN);
  tft.print(tempf, 1);//tft.print(char(247));
  tft.setTextColor(ST7735_WHITE);
  tft.setTextSize(1);
  tft.setTextColor(ST7735_GREEN);
  tft.setTextSize(2);
  tft.print("  ");tft.print(h, 1);//tft.println("%");
  tft.setTextColor(ST7735_WHITE);
  tft.setCursor(0, 40);
  tft.println("TempC Soil");
  tft.setTextColor(ST7735_GREEN);
  tft.setTextSize(2);
  tft.setCursor(0, 60);
  tft.print(tempc, 1);tft.print("  ");
  if(analogRead(3)>800)
  {
    tft.setTextColor(ST7735_RED);
  }
  else
  {
    tft.setTextColor(ST7735_GREEN);
  }
  tft.println(analogRead(3));
    
  tft.setTextSize(1);
  tft.setCursor(0, 80);
  tft.setTextColor(ST7735_WHITE);
  tft.print("Luminosity: ");
  tft.setTextColor(ST7735_YELLOW);tft.print(val, DEC);
  tft.setTextColor(ST7735_WHITE);
  tft.println(" LUX");
  tft.setCursor(0, 92);
  tft.setTextColor(ST7735_WHITE);
  tft.print("Barometer: ");
  tft.setTextColor(ST7735_BLUE);
  tft.print(event.pressure);
  tft.setTextColor(ST7735_WHITE);
  tft.println("hPa");
  tft.setCursor(0, 100);

  // Wait 10 seconds until next update

  delay(5000);
  digitalWrite(44, LOW);
  
}


int BH1750_Read(int address) //
{
  int i=0;
  Wire.beginTransmission(address);
  Wire.requestFrom(address, 2);
  while(Wire.available()) //
  {
    buff[i] = Wire.read();  // receive one byte
    i++;
  }
  Wire.endTransmission();  
  return i;
}

void BH1750_Init(int address) 
{
  Wire.beginTransmission(address);
  Wire.write(0x10);//1lx resolution 120ms
  Wire.endTransmission();
}

User avatar
tdicola
 
Posts: 1074
Joined: Thu Oct 17, 2013 9:11 pm

Re: [Solved] CC3000 Hang

Post by tdicola »

Thanks for posting the full code. Hrm, nothing immediately jumps out as an issue. If you add some Serial.println calls to output debug info like "Read sensor data", "Sent message to Xively", "Updated display", etc. at the appropriate spots, can you pinpoint where it might be getting hung up?

Locked
Please be positive and constructive with your questions and comments.

Return to “Other Arduino products from Adafruit”