Jump to content
43oh

CC3200 Wifi delay issue


Recommended Posts

First day with Energia, loaded it onto my 3200 in minutes, so sofar its a lot more user friendly than the TI offer :)

 

I have been trying out the webserver demo, and noticed that if I dont include a small delay in every println the connection gets dropped, I am guessing this is some buffer being filled faster than it can offload to the webclient.

 

The interesting part of the code is below, in the dummy printouts, if I lower delay to 1 or just remove it, the connection is closed pretty early, 5 seems steady, and 2 was not enough, so somewhere in between.

 

The CC3200 is connected to a local wifi, not sure which speed though.

        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          delay(25);
          client.println("Content-Type: text/html");
          delay(25);
          client.println("Connection: close");  // the connection will be closed after completion of the response
          delay(25);
          client.println("Refresh: 5");  // refresh the page automatically every 5 sec
          delay(25);
          client.println();
          delay(25);
          client.println("<!DOCTYPE HTML>");
          delay(25);
          client.println("<html>");

          for (uint16_t i=0; i<2000; i++)
          {
            client.println("Dummy");
            delay(5);
          }

Any ideas ?

Link to post
Share on other sites
/*
  WiFi Web Server

 A simple web server that shows the value of the analog input pins.
 using a WiFi shield.

 This example is written for a network using WPA encryption. For
 WEP or WPA, change the Wifi.begin() call accordingly.

 Circuit:
 * WiFi shield attached
 * Analog inputs attached to pins A0 through A5 (optional)

 created 13 July 2010
 by dlf (Metodo2 srl)
 modified 31 May 2012
 by Tom Igoe

 */

#include <SPI.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiServer.h>


// your network name also called SSID
char ssid[] = "xxx";
// your network password
char password[] = "xxx";
// your network key Index number (needed only for WEP)
int keyIndex = 0;
int clientid = 0;
  
WiFiServer server(80);

void setup() {

  Serial.begin(115200);      // initialize serial communication
  pinMode(RED_LED, OUTPUT);      // set the LED pin mode

  // attempt to connect to Wifi network:
  Serial.print("Attempting to connect to Network named: ");
  // print the network name (SSID);
  Serial.println(ssid); 
  // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
  WiFi.begin(ssid, password);
  while ( WiFi.status() != WL_CONNECTED) {
    // print dots while we wait to connect
    Serial.print(".");
    delay(300);
  }
  
  Serial.println("\nYou're connected to the network");
  Serial.println("Waiting for an ip address");
  
  while (WiFi.localIP() == INADDR_NONE) {
    // print dots while we wait for an ip addresss
    Serial.print(".");
    delay(300);
  }

  // you're connected now, so print out the status  
  printWifiStatus();
  
  Serial.println("Starting webserver on port 80");
  server.begin();                           // start the web server on port 80
  Serial.println("Webserver started!");

}


void loop() {
  // listen for incoming clients
  WiFiClient client = server.available();
  if (client) {
    clientid++;
    Serial.print("new client ");
    Serial.println(clientid);
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          delay(25);
          client.println("Content-Type: text/html");
          delay(25);
          client.println("Connection: close");  // the connection will be closed after completion of the response
          delay(25);
          client.println("Refresh: 5");  // refresh the page automatically every 5 sec
          delay(25);
          client.println();
          delay(25);
          client.println("<!DOCTYPE HTML>");
          delay(25);
          client.println("<html>");

          for (uint16_t i=0; i<2000; i++)
          {
            client.println("Dummy");
            delay(5);
          }
          /*
          // output the value of each analog input pin
          for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
            int sensorReading = analogChannel; //analogRead(analogChannel);
            client.print("analog input ");
            client.print(analogChannel);
            client.print(" is ");
            client.print(sensorReading);
            client.println("<br />");
          }
          */
          client.println("</html>");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }

    // close the connection:
    client.stop();
    Serial.print("client ");
    Serial.print(clientid);
    Serial.println(" disonnected");
  }
}


void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("Network Name: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

Thats the complete Sketch, its just the webserver example with some added loop to make output.

 

If I change the delay to 1 ms, connection gets dropped, I am testing with telnet to eliminate any browser issues, but chrome is getting the same result.

I first noticed it when running the unmodified sketch, every 1 in 5 times I would get all 5 lines, but the rest of the time it would cut out after a set number of lines (not characters, ie. I could send one very long line but not 2 short), so maybe its something todo with repeated calling of println in short succession.

$ telnet 192.168.1.146 80
Trying 192.168.1.146...
Connected to 192.168.1.146.
Escape character is '^]'.

HTTP/1.1 200 OK
Content-Type: text/html
Connection: close
Refresh: 5

<!DOCTYPE HTML>
<html>
Dummy
Dummy
Dummy
Dummy
Dummy
Dummy
Dummy
Connection closed by foreign host.

Link to post
Share on other sites

Yes, I formatted the device and loaded the service pack.

 

It may be something locally, its connected to a unifi standard ap, which should be connected to the same switch as my PC, although there is a off chance that it picked another AP than the nearest.

Since its local traffic the router shouldnt have an effect, theres a HP network printer on the same LAN that broadcasts alot of crap, it has caused issues with lesser ethernet devices before.

Link to post
Share on other sites
  • 2 weeks later...

A can also confirm the same phenomena (6 bad / 1 good). I've duplicated client.print to a serial.print. It displays properly on serial each call.

            Serial.print("analog input");
            client.print("analog");
            Serial.print(analogChannel);
            client.print(analogChannel);
            Serial.print(" = ");
            client.print(" = ");
            Serial.println(sensorReading);
            client.print(sensorReading);
            client.println("<br />");
Link to post
Share on other sites

Hi folks- Thanks for bringing this one up again.  As it turns out there is a bug, someone reported it as a Github issue and I made a pull-request to fix it.

 

I am going to put together a zipfile with the current WiFi library for CC3200, and CC3100 (MSP430 & Tiva) which incorporates the bugfixes.  It also adds AP mode support, and fixes Tiva support for the CC3100 (there was a bug there as well).  Stand by...

Link to post
Share on other sites

Download this and unzip it from the Energia main install directory, e.g. C:\energia-0101E0013 or wherever (Linux/MacOSX should work with this too).

 

Energia13_wifi_servicepack_09302014.zip

 

The fix for this bug, BTW, is that the Network Processor (I call it the "CC3100" within the "CC3200" personally) does provide flow-control messaging if its internal buffers have been used up, which can happen especially with certain .print* functions that do numbers -- typically numeric print/println's result in several discrete executions of the .write() function with only a single byte, which produce an sl_Send() WiFi Network Processor call all by themselves, and if I'm not mistaken (inferring from documentation) the CC3100 is programmed to allocate a separate 1500 byte buffer for each call.  Obviously that's inefficient, but there's no clear way around it just yet, however the updated WiFiClient.cpp now checks for the SL_EAGAIN (-11) return value and sets up a paced-retry loop instead of just assuming it's a critical error and closing the connection.

 

See the WiFiClient::write(const uint8_t *buffer, size_t size) implementation in WiFiClient.cpp for details.

Link to post
Share on other sites

almost forgot to add, too, the new .sslConnect() option for WiFiClient.

It does not perform certificate validation (that is a whole 'nother can of worms.... still not sure what we're going to do for that), but it'll get you connected to an SSL link.  One big caveat is the TCP connection needs to be SSL from the get-go; I don't see any way the CC3100 stack will let you open an unencrypted connection and then convert it into an SSL link (STARTTLS style).

Link to post
Share on other sites

Wonderful the new files works, so it would be better to make a buffer locally before transmitting it to the CC3200 ?

I guess most small packages is due to not being able to just string the output together on the fly, like "str"+val, but sprintf can do that.

 

Also tested ssl connect against a rapidssl cert, it connects and sends/recieves data and it fails if I try to ssl connect to a non ssl server, so I think its encrypted, hard to prove though :)

Link to post
Share on other sites

I'm on a roll today folks -- if anyone wants to test-drive "AP mode client tracking", this next "servicepack" includes changes to WiFi.cpp/.h and utility/SimpleLinkCallbacks.cpp to enable the WiFiClass library to track clients who connect & disconnect from the AP, notifying the # of clients attached and when one does connect, making its IP address available via .getLastDevice():

 

Energia13_wifi_servicepack_09302014_2.zip

 

Example code in loop() to use this:

  static int knowndevs = 0;
  int nowdevs = 0;

  nowdevs = WiFi.getTotalDevices();
  if (nowdevs > knowndevs) {
    Serial.print("Client connected!  IP = ");
    WiFi.getLatestDevice().printTo(Serial);
    Serial.println();
  }
  if (nowdevs < knowndevs) {
    Serial.println("Client disconnected.");
  }
  knowndevs = nowdevs;

This could be used with autonomous WiFi devices to, say, enable a power-hungry gadget only when someone is connected to the AP, and shut it down when nobody is connected.

 

As always, CC3100+MSP430/Tiva support was not left behind, and I personally tested the changes with CC3100+MSP430F5529LP and CC3100+TM4C123GXL LaunchPads.

 

Note: WiFi.h limits the size of the registry database (basically an array of structs containing a boolean, uint8_t[4] and uint8_t[6] for IP & MAC) to 4 connected clients; above that, the "total connected" figure should still work but the getLastDevice() will keep showing the last one connected before the database became full.

 

Could trim the memory usage a bit by just storing the last octet (192.168.1 is the subnet used by default anyhow), and use its state in place of the "boolean in_use" too.

Link to post
Share on other sites

@@spirilis, great job and thank you for the contributions!

 

I think it would make sense to also be able to "walk" the list of the connected clients and get the details for each connected client. Looking at the patch this information is already retained (for 4 clients right now) and probably easy to expose through an API.

 

Probably something like:

nowdevs = WiFi.getTotalDevices();

for (int thisDev = 0; thisDev < nowdevs; thisDev++) {
    Serial.print("Dev: ");
    Serial.print(thisDev);
    Serial.print("\tipAddress: ");
    Serial.print(WiFi.ipAddress(thisDev));
    Serial.print("\tmacAddress: ");
    Serial.println(WiFi.macAddress(thisDev));
}
Link to post
Share on other sites

 

@@spirilis, great job and thank you for the contributions!

 

I think it would make sense to also be able to "walk" the list of the connected clients and get the details for each connected client. Looking at the patch this information is already retained (for 4 clients right now) and probably easy to expose through an API.

 

Probably something like:

nowdevs = WiFi.getTotalDevices();

for (int thisDev = 0; thisDev < nowdevs; thisDev++) {
    Serial.print("Dev: ");
    Serial.print(thisDev);
    Serial.print("\tipAddress: ");
    Serial.print(WiFi.ipAddress(thisDev));
    Serial.print("\tmacAddress: ");
    Serial.println(WiFi.macAddress(thisDev));
}

I'll add something like that... was having trouble coming up with function names for how to name it :)

edit: eh, another goofy detail is there's no MACAddress class for storing & dumping MACs.  might have to make one...

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...