CC3000 and Teensy 3.1

Status
Not open for further replies.

jpatrick62

Well-known member
I recently upgraded to Arduino 1.61 and TeensyDuino 1.22, and it seems my CC3000 web server has become slow and hangs on requests. On Arduino 1.5 and Teensy 1.8
the web server worked (after setting SPI_CLOCK_DIV2)except that it would need a reboot after about 15 mins as it would stop responding. I was hoping the new
libs would solve the need to reboot after 15 mins. I have a rotary bcd switch that listens for SmartConfig when set to 0, and then boots with the config on a switch setting other
than 0. This seems to work well, and I always connect/reconnect to my AP as expected. I have flashed the CC3000 to the latest firmware (1.14) successfully, and I can get the
hardware to run the buildtest and other examples successfully.


Code:
/***************************************************
 * HTTPServer5
 * 
 * This code will be auto-configurable for the SSID and 
 * password (in deference to the AP). We use TI SmartConfig as
 * a template for this. This code also serves as a web server.
 ****************************************************/
#include <Adafruit_CC3000.h>
#include <SPI.h>+
#include "utility/debug.h"
#include "utility/socket.h"

#define ADAFRUIT_CC3000_IRQ   3  // MUST be an interrupt pin!
#define ADAFRUIT_CC3000_VBAT  5
#define ADAFRUIT_CC3000_CS    10
// SCK = 13, MISO = 12, and MOSI = 11

#define WIFI_CONNECTED 6
#define WIFI_TX 7
#define DEVICE_NAME "TEST1"

//for the bcd rotary
#define BIT_1 14
#define BIT_2 15
#define BIT_4 16
int iRotaryPosition = 0;


// SPI_CLOCK_DIVIDER caused the server to crash as the SPI bus speed could keep up with fast requests
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT, SPI_CLOCK_DIV2);

// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2
#define WLAN_SECURITY   WLAN_SEC_WPA2

#define LISTEN_PORT           80      
#define MAX_ACTION            10               // Maximum length of the HTTP action that can be parsed.
#define MAX_PATH              256              // Maximum length of the HTTP request szQuery that can be parsed.
#define BUFFER_SIZE           MAX_ACTION + MAX_PATH + 20  // Size of buffer for incoming request data.
#define TIMEOUT_MS            500              // Amount of time in milliseconds to wait for an incoming request to finish.  

#define AP_CONNECTION_CHECK_PERIOD   15*60*1000 //every 15 minutes...

Adafruit_CC3000_Server httpServer(LISTEN_PORT);
uint8_t   buffer[BUFFER_SIZE+1];                // Incoming request buffer...
int       bufindex = 0;
char     action[MAX_ACTION+1];
char     szQuery[MAX_PATH+1];                     // Actual query string from the client...
char     szRotary[10] = {0};                      // The rotary char buffer...
char     szCC3000FirmwareVersion[MAX_PATH+1] = {0};
unsigned long ulLastCheckPeriod = 0;
char      szIpAddress[50] = {0};


void setup(void)
{
  pinMode(WIFI_CONNECTED, OUTPUT);
  pinMode(WIFI_TX, OUTPUT);
  digitalWrite(WIFI_CONNECTED, LOW);
  digitalWrite(WIFI_TX, LOW);
  Serial.begin(115200);
  delay(1000);

  Serial.print("Free RAM: "); 
  Serial.println(getFreeRam(), DEC);
  
   RotaryInit();

  //Read the rotary position, if Listen mode (rotary position 0) has been selected, 
  //then listen, otherwise reconnect using exising credentials stored in NVRAM on the CC3000
  if(readRotary()==0)
  {
    Serial.println("Listening...");
    listen4Config();
  }
  else
  {
    connect2AP();
  }

  Serial.println("Request DHCP");
  while (!cc3000.checkDHCP())
  {
    delay(100); // Do: Insert a DHCP timeout!
  }  

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

  // Start the http server and listen for connections
  httpServer.begin();
  Serial.println("Listening for connections...");
}
/*============================================================================
 loop()
 main processing loop
 ===========================================================================*/
void loop(void)
{
  //get the current rotary value
  getRotaryStringVal(szRotary);

  // Try to get a client which is connected.
  Adafruit_CC3000_ClientRef client = httpServer.available();
  if (client) 
  {
     Serial.println("Client connected.");
    // Process this request until it completes or times out.
    // Note that this is explicitly limited to handling one request at a time!

    // Clear the incoming data buffer and point to the beginning of it.
    bufindex = 0;
    memset(&buffer, 0, sizeof(buffer));

    // Clear action and szQuery strings.
    memset(&action, 0, sizeof(action));
    memset(&szQuery,   0, sizeof(szQuery));

    // Set a timeout for reading all the incoming data.
    unsigned long endtime = millis() + TIMEOUT_MS;

    // Read all the incoming data until it can be parsed or the timeout expires.
    bool parsed = false;
    while (!parsed && (millis() < endtime) && (bufindex < BUFFER_SIZE)) 
    {
      if (client.available()) 
      {
        buffer[bufindex++] = client.read();
      }
      parsed = parseRequest(buffer, bufindex, action, szQuery);
    }

     Serial.println("---PARSED---");
    // Handle the request if it was parsed.
    if (parsed) 
    {
      Serial.print("Action: "); 
      Serial.println(action);
      Serial.print("Query: "); 
      Serial.println(szQuery);
      // Check the action to see if it was a GET request.

      digitalWrite(WIFI_TX, HIGH);
      if (strcmp(action, "GET") == 0) 
      {
        // Respond with the szQuery that was accessed.
        // First send the success response code.
        client.fastrprintln("HTTP/1.1 200 OK");
        // Then send a few headers to identify the type of data returned and that
        // the connection will not be held open.
        client.fastrprintln("Content-Type: text/plain");
        client.fastrprintln("Connection: close");
        client.fastrprintln("Server: Adafruit CC3000");
        // Send an empty line to signal start of body.
        client.fastrprintln("");
        // Now send the response data.
        client.fastrprint("Your query: "); 
        client.fastrprintln(szQuery);
        client.fastrprint("The rotary value: ");
        client.fastrprintln(szRotary);
        if(!strcmp(szQuery, "/version"))
        {
          checkFirmwareVersion();
          client.fastrprint("CC3000 firmware version is: ");
          client.fastrprintln(szCC3000FirmwareVersion);
        }
      }
      else 
      {
        // Unsupported action, respond with an HTTP 405 method not allowed error.
        client.fastrprintln("HTTP/1.1 405 Method Not Allowed");
        client.fastrprintln("");
      }
      digitalWrite(WIFI_TX, LOW);
    }

    // Wait a short period to make sure the response had time to send before
    // the connection is closed (the CC3000 sends data asyncronously).
    delay(200);

    // Close the connection when done.
    Serial.println("Client disconnected");
    client.close();
  }

}


/**************************************************************************/
/*!
    @brief  Tries to read the 6-byte MAC address of the CC3000 module
*/
/**************************************************************************/
void displayMACAddress(void)
{
  uint8_t macAddress[6];
  
  if(!cc3000.getMacAddress(macAddress))
  {
    Serial.println("Unable to retrieve MAC Address!\r\n");
  }
  else
  {
    Serial.print("MAC Address : ");
    cc3000.printHex((byte*)&macAddress, 6);
  }
}
/*-------------------------------------------------------------------------------
 parseRequest()
 // Return true if the buffer contains an HTTP request.  Also returns the request
 // szQuery and action strings if the request was parsed.  This does not attempt to
 // parse any HTTP headers because there really isn't enough memory to process
 // them all.
 // HTTP request looks like:
 //  [method] [szQuery] [version] \r\n
 //  Header_key_1: Header_value_1 \r\n
 //  ...
 //  Header_key_n: Header_value_n \r\n
 //  \r\n
 -------------------------------------------------------------------------------*/
bool parseRequest(uint8_t* buf, int bufSize, char* action, char* szQuery) 
{
  // Check if the request ends with \r\n to signal end of first line.
  if (bufSize < 2)
    return false;
  if (buf[bufSize-2] == '\r' && buf[bufSize-1] == '\n') 
  {
    parseFirstLine((char*)buf, action, szQuery);
    return true;
  }
  return false;
}
/*-------------------------------------------------------------------------------
 parseFirstLine()
 -------------------------------------------------------------------------------*/
// Parse the action and szQuery from the first line of an HTTP request.
void parseFirstLine(char* line, char* action, char* szQuery) 
{
  // Parse first word up to whitespace as action.
  char* lineaction = strtok(line, " ");
  if (lineaction != NULL)
    strncpy(action, lineaction, MAX_ACTION);
  // Parse second word up to whitespace as szQuery.
  char* linepath = strtok(NULL, " ");
  if (linepath != NULL)
    strncpy(szQuery, linepath, MAX_PATH);
}
/*-------------------------------------------------------------------------------
 displayConnectionDetails()
 ------------------------------------------------------------------------------*/
// 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("Unable to retrieve the IP Address!\r\n");
    return false;
  }
  else
  {
    Serial.print("\nIP Addr: "); 
    cc3000.printIPdotsRev(ipAddress);
    Serial.print("\nNetmask: "); 
    cc3000.printIPdotsRev(netmask);
    Serial.print("\nGateway: "); 
    cc3000.printIPdotsRev(gateway);
    Serial.print("\nDHCPsrv: "); 
    cc3000.printIPdotsRev(dhcpserv);
    Serial.print("\nDNSserv: "); 
    cc3000.printIPdotsRev(dnsserv);
    Serial.println();

    return true;
  }
}

/*---------------------------------------------------------------------------
 listen4Config
 ---------------------------------------------------------------------------*/
void listen4Config()
{
  /* is the default behaviour)  */
  Serial.println("\nInitialising the CC3000 ...");
  
   if (!cc3000.begin(false))
  {
    Serial.println("Unable to initialise the CC3000");
    while(1);
  }

  uint16_t firmware = checkFirmwareVersion();
  if (firmware < 0x113) 
  {
    Serial.println("Wrong firmware version!");
    for(;;);
  }
  displayMACAddress();

  /* Try to use the smart config app (no AES encryption), saving */
  /* the connection details if we succeed */
  Serial.println("Waiting for a SmartConfig connection (~60s) ...");
  if (!cc3000.startSmartConfig(DEVICE_NAME))
  {
    Serial.println("SmartConfig failed");
    while(1);
  }

  digitalWrite(WIFI_CONNECTED, HIGH);
  Serial.println("Saved connection details and connected to AP!");
}
/*---------------------------------------------------------------------------
 connect2AP
 
 This method initializes the CC3000 with existing connection info stored in NVRAM
 on board the CC3000.
 ---------------------------------------------------------------------------*/
void connect2AP()
{
  // Initialise the module
  Serial.println("\nInitializing...");

  // get the existing connection details from NVRAM
  if (!cc3000.begin(false, true, DEVICE_NAME))
  {
    Serial.println("Unable to re-connect - try Listening mode for connection information");
    while(1);
  }

  digitalWrite(WIFI_CONNECTED, HIGH);
  Serial.println("Connected!");
}
/*--------------------------------------------------------------------------
 checkFirmwareVersion()   
 
 Tries to read the CC3000's internal firmware patch ID
 --------------------------------------------------------------------------*/
uint16_t checkFirmwareVersion(void)
{
  uint8_t major, minor;
  uint16_t version;

#ifndef CC3000_TINY_DRIVER  
  if(!cc3000.getFirmwareVersion(&major, &minor))
  {
    Serial.println("Unable to retrieve the firmware version!\r\n");
    version = 0;
  }
  else
  {

    Serial.print("Firmware V. : ");
    Serial.print(major); 
    Serial.print("."); 
    Serial.println(minor);
    sprintf(szCC3000FirmwareVersion, "%d.%d", major, minor);
    version = major; 
    version <<= 8; 
    version |= minor;
  }
#endif
  return version;
}
/////////////////////////////////////////////////////////////////////////////
void RotaryInit()
{
  pinMode(BIT_1, INPUT_PULLUP); // 1
  pinMode(BIT_2, INPUT_PULLUP); // 2
  pinMode(BIT_4, INPUT_PULLUP); // 4
}
//////////////////////////////////////////////////////////////////////////////
int readRotary()
{
  int iValue = 0;
  if(digitalRead(BIT_1)==LOW)
    iValue += 1;
  if(digitalRead(BIT_2)==LOW)
    iValue += 2;
  if(digitalRead(BIT_4)==LOW)
    iValue += 4;
    
  return iValue;
}
/////////////////////////////////////////////////////////////////////////////////
void getRotaryStringVal(char* szBuffer)
{
  iRotaryPosition = readRotary();
  itoa(iRotaryPosition, szBuffer, 10);
}
 
I was informed you must run the teensy 3.1 at 72mhz or lower for this to work.
I have not verified this since I gave up on this combo a while back.
 
Hmm - seemed to work much better before the Arduino and TeensyDuino upgrades. Maybe I'll revert back and see what happens. Does anyone know of a solid
Wifi/Teensy 3.1 combo? I have been running Teensy 3.1 projects on Ethernet and that has worked well, but now the customers want the freedom of Wifi, which I
cannot blame them for. I need a solid combo that will stay connected and is reliable as a sensor update and small web server combo for intermitten database
requests. Would appreciate anyone with good experience on this! I see the teensy LC, which should lower the cost, but I really need a Wifi module to use...
 
I just ordered a sample of these ESP8266 chips and will design a small add-on shield for the Teensy and/or a breadboardable version. Most available modules only breakout two GPIO pins but there are at least three more that can be made available. The data sheet is surprisingly complete making such design possible. Even more interesting is the ESP6203 which is a smaller version of the ESP8266 better suited to a small add-on but I haven't found a source for these yet. The design of a wifi soft-AP using this chip as Teensy add-on should be no more difficult than the design for the nRF24L01+.
When I have something working I'll report...

Oh, and I HATE the double row of headers on most of these modules; I will make my board breadboard friendly with 0.1" machine pin headers at the edges like God intended.
 
Last edited:
Don't know yet, but certainly under $20. It depends on the cost of the crystal and how big a pain it is to assemble and test. But the chips are pretty cheap from China and the circuit is relatively simple!

Here's a nice example of what I intend to do as far as functionality but not as gigantically huge as this breakout board; mine will be appallingly small, as usual!

Instead of breaking out an existing module I will just design the ESP8266 circuit from scratch to be more breadboard friendly and maximally useful. I expect to be able to do this in a 0.7" x 0.8" board size including the pcb antenna.
 
Last edited:
As deployment to customers was mentioned. If this is for commercial commercial deployment, would this RF stuff not have to be FCC certified ?
 
So I got my sketch listed above to work as a web server. Interestingly, I added delay time of 1000 ms after Adafruit_CC3000_ClientRef's httpServer.available call

i.e

Code:
Adafruit_CC3000_ClientRef client = httpServer.available();
  if (client) 
  {
    //do something
  }
  delay(1000)

Now the server is up and stable for longer than ever and it seems to respond quicker as well. So I can only think that repeated calls to the httpServer.available() method are the root of my
issues, but I cannot prove it as yet. BTW I am on Arduino 1.6. and the latest TeensyDuino (1.22?).
 
So, I'm the one that ran into issues with the Teensy 3.1 running at 96Mhz with the CC3000. I could get the device to upload my sketches, and it would begin to connect to my Access Point, but after that would hang. With no changes to my code, and changing it to 72Mhz, it would run flawlessly. I now have one running my Quarantine Fish tanks lights only right now flawless at 72Mhz, and reading two DS18B20 Temp Sensors. It has been up and running for two weeks now. I have not had a need to do a delay after the "if (client)".
 
sorscode, you said

With no changes to my code, and changing it to 72Mhz, it would run flawlessly

Where specifically did you make that change? That looks like a better alternative.
 
in arduino ide, tools menu, select cpu speed 72mhz.
let us know if your original program works after lowering the cpu speed.
 
Ok, so I set the CPU speed from 96 to 72 and took out the delay and the web server became unresponsive. Put the speed back to 96 overclock and put the delay back in and it's been up and
solid for several hours. Then again, I set the Adafruit_CC3000 int for SPI_CLOCK_DIV2, if you are setting the speed to 72 MHZ, what are you setting the Adafruit_CC3000 init's SPI speed at? It looks like
the SPI bus speed may be the key component here.

BTW, I am seeing:

CC3000 firmware returns 1.32, which should be the latest.
TeensyDuino at 1.22
Arduino at 1.63
 
Here is mine. I'm going to grab my spare Teensy 3.1 and CC3000, and load your code. I believe you posted the whole thing.

Code:
///// CC3000 Module Global Settings
#define ADAFRUIT_CC3000_IRQ   3  // MUST be an interrupt pin!
#define ADAFRUIT_CC3000_VBAT  5
#define ADAFRUIT_CC3000_CS    10
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT, SPI_CLOCK_DIVIDER); 
#define WLAN_SSID       "..............."
#define WLAN_PASS       "..............."
#define WLAN_SECURITY   WLAN_SEC_WPA2
Adafruit_CC3000_Server server(80); // Webserver Code
 
Here is mine. I'm going to grab my spare Teensy 3.1 and CC3000, and load your code. I believe you posted the whole thing.

Sorscode, the funny thing is that in Adafruit_CC3000.h, we have

Code:
#if defined(__arm__) && defined(__SAM3X8E__) // Arduino Due
  #define SPI_CLOCK_DIVIDER 6 // used to set the speed for the SPI bus; 6 == 14 Mhz on the Arduino Due
#else
  #define SPI_CLOCK_DIVIDER SPI_CLOCK_DIV2

so it can't be the SPI bus speed that is the issue, so I'm a bit perplexed at this moment. I'm going to hook this
up to the OScope and see what the SPI bus looks like when it is working well and then when it freezes. What is your
Arduino/Teensduino versions and the firmware on your CC3000?
 
Hello, I didn't get a chance to run your code yet. However here is my specs..

Arduino IDE - 1.6.3
Teensyduino - 1.22
CC3000 - 1.24
 
jpatrick62 - I haven't forgotten about this. I'm reading up on how the SmartConfig works, as I have never used it before. I should be able to test tomorrow. Sorry for the delay.
 
If I recall correctly, there is an arduino sketch that will upgrade the firmware of cc3000. And in case you confirmed the newer firmware has problems, you can revert back to the older firmware. Or maybe patrick can try the 1.24 firmware to see if it works.
 
Quick update, wasn't able to get SmartConfig to work at the office (maybe way to many SSIDs advertised). So I modified only one line, and added two lines to get my CC3000 to connect to my MiFi. Currently it's working. Only be running for about 5 minutes. I will keep you posted.

Do you have something pulling the device at a set interval?
 
Ok, so I tried it a couple different ways, It seems like even if you don't browse to the device after about 17 minutes it locks up. I've also tested doing pulling every minute, and it also locked up. I tried DIV2 and DIV, and both show the same behavior. Going thru the code now, and going to turn on more debugging.
 
Alright, so played with this some more, and on mine it's not actually locking up. What is happening is the device is dissociating with the wireless. If you add a basic function in your loop to check periodically if your still connected to the WiFi, and re-associate if disconnected, it seems to run fine. This is one reason why I try to stay away from wireless, and use Ethernet for everything.
 
OK, to upgrade the firmware, run the driverpatch_1_14 sketch that comes from Adafruit CC_3000 library in the examples directory to bring the frimware up to the latest rev. Make sure you provide an external power source, otherwise the sketch may hang and the firmware update will fail. In the event that the update does fail for some reason, you can run the sketch over again until it successfully updates. I am in the middle of updating my development tools to include visual micro with debug in the hopes that
I can walk into the .cpp files and find where this thing is hanging or disconnecting. Unfortunately, I'll have to wait till tomorrow to get VS2013 and use that with the new Visual Micro.
 
Status
Not open for further replies.
Back
Top