Teensy 3.2 + ESP8266-12Q+ High Speed ADC + Websocket

Status
Not open for further replies.

abecross

New member
Hi all,
Been working for couple of nights on ESP8266-12Q and Teensy 3.2 and have got it to serve the basic webpage refreshed every 5 seconds. Apart from occasional freezing up, it is working ok but its slow. Has anyone worked on how to integrate websocket to this for high speed data streaming?
 
I have implemented websocket. I use my own esp8266 library and customized webduino webserver library. The websocket part is basically an extension to the webduino library.
Note that since esp8266 only allows one server, the http server and websocket port will be the same. This actually works out better, since you do not have to hardcode any port number on the client javascript. You can create the client websocket like

ws = new WebSocket("ws://"+window.location.host);

what webserver library are you using?
All you need to do is read the websocket RFC6455 and implement it as an incoming http handler. It is fairly straightforward.

Also, speaking of speed, what baud rate are you running esp8266? If you run it at max speed of 4608000 baud, that speed might already be sufficient for your needs. If not, then you can take the max baud rate + websocket route. Websocket alone may not solve your speed issue.
 
@doughboy, sounds promising. I'm currently running a Digital Readout for my Lathe using a WebSocket Server with a WIZ820 LAN Module. It transmits the encoder data to a Web Browser running on a standard tablet (see the video below for a demonstration).

https://www.youtube.com/watch?v=WNYi6aPL8Rg
https://www.youtube.com/watch?v=ZLVXQfjfS6Q

Im now thinking of replacing the LAN connection with an ESP8622 based WIFI connection. Obviously this only makes sense if the WebSocket Server is running very stable and with small latency (< 250ms). Do you have any experience with the stability of the connection you want to share? Any pitfalls to watch out for?

Thanks
Lutz
 
I've been running my test for over a month non stop, and for my application, I think it is quite stable.
I also implemented websocket ping/pong, and I think the firefox implementation is not quite stable. (the server ping, the client pong), so I don't use it anymore.

Since you will be dealing with wifi, you are subject to interference that you don't have using a wired connection. The wifi throughput will be lower during busy time, usually early evening at my house. If you run the esp8266 wifi at 4.6 megabaud, you can get a minimum of 1 megabit per second throughput on wifi, a lot faster if your location does not have a ton of wifi signals, 2 mbit/s is typical. That is decent speed for my application.
 
Thanks for the information. Did it run all that time without loosing connection? That would be perfect!
Overall transmission rate is not very important for me. The data volume from the counters is rather limited (four 32bit counter values every 100ms plus 2 bytes WebSocket overhead should be doable). I'm more afraid of delayed or pausing transmission which would lead to a lagging display of the position data which would be very disturbing in my application. But as they say: the proof of the pudding is in the eating, so I'll give it a try.
 
I was losing connection when I had ping/pong enabled. You can always reconnect because you can get notified with OnDisconnect callback. With Wifi, there is no guarantee.
my implementation only supports text data (0x81 op). So I send data in json format. I send fan RPM data to client that displays in gauge graphics. Since I use browser as client, it has built in support for json data parsing. So it is sort of similar to your application. If your data is for human to read, isn't 10x per second overkill?
 
I found this Arduino ESP8266 Webserver to be robust - full featured - reliable : github.com/nailbuster/myWebServer

GitHub uses/links to JSON Arduino code library - and also uses the TIME library Paul is maintaining that results in NTP time:
Library requires the use of the following 3rd party libraries to be installed:
TimeLib for ntp here: https://github.com/PaulStoffregen/Time
Arduino Json here: https://github.com/bblanchon/ArduinoJson

It doesn't have MQTT or WebSocket - but supports FTP and Web Uploading and for dev/debug use even OTA upload. The NailBuster guy is responsive to issues I've found - and has MQTT in another repository and it should plug in - ideally the same for WebSocket? Runs SPIFFS for 3MB 'FileSystem' data with 1MB for code on 4MB ESP8266 - FTP can read write files and the server runs HTML from there.

I need to get back to it. His library adds a great deal - including WiFi config setup/storage and incorporates all the sketch based kraap seen in the 'Example WebServer HelloServer' into the library under the covers. Skipping includes - this runs:
Code:
void setup() {  // put your setup code here, to run once:
	Serial.begin(115200);
	MyWebServer.begin();	
}
void loop() {  // put your main code here, to run repeatedly:
	MyWebServer.handle();
}
 
If your data is for human to read, isn't 10x per second overkill?
If you just look at the displayed position data it is definitely overkill, but if you need to set the lathe to a precise target position a lag in the displayed position is quite annoying. It starts to feel sluggish at about 200ms update time so I set it to 100ms.

I found this Arduino ESP8266 Webserver to be robust - full featured - reliable : github.com/nailbuster/myWebServer
I had a quick look at the code, looks like its based on the ESP8266WebServer which is included in the ESP Arduino libraries. I'll dig in deeper tomorrow. Anyway, its absolutely amazing what one can do with those little modules. I really like the idea of tossing a $5 integrated Webserver + WebSocket server onto a board and use your smartphone, an old tablet or whatever device a web server runs on as high end display for a teensy frontend. Add a little HTML/CSS/js and you have a state of the art GUI for your projects.

BTW: Just stumbled over this https://leanpub.com/ESP8266_ESP32 ebook. I think this is a very useful collection of the somehow spread ESP documentation.
 
Can you help ?

I have implemented websocket. I use my own esp8266 library and customized webduino webserver library. The websocket part is basically an extension to the webduino library.
Note that since esp8266 only allows one server, the http server and websocket port will be the same. This actually works out better, since you do not have to hardcode any port number on the client javascript. You can create the client websocket like

ws = new WebSocket("ws://"+window.location.host);

what webserver library are you using?
All you need to do is read the websocket RFC6455 and implement it as an incoming http handler. It is fairly straightforward.

Also, speaking of speed, what baud rate are you running esp8266? If you run it at max speed of 4608000 baud, that speed might already be sufficient for your needs. If not, then you can take the max baud rate + websocket route. Websocket alone may not solve your speed issue.

Hi doughboy, Will it be possible to share the library or suggest ? I am not using any library but a simple rx/tx connection. I have no idea whatsoever also about how to implement that ws code in my code.

Here is my code.
Code:
#define BUFFER_SIZE 2048

#define SSID  "*******"      // change this to match your WiFi SSID
#define PASS  "********1"  // change this to match your WiFi password
#define PORT  "80"           // using port 8080 by default

char buffer[BUFFER_SIZE];

// By default we are looking for OK\r\n
char OKrn[] = "OK\r\n";
byte wait_for_esp_response(int timeout, char* term = OKrn) {
  unsigned long t = millis();
  bool found = false;
  int i = 0;
  int len = strlen(term);
  // wait for at most timeout milliseconds
  // or if OK\r\n is found
  while (millis() < t + timeout) {
    if (Serial1.available()) {
      buffer[i++] = Serial1.read();
      if (i >= len) {
        if (strncmp(buffer + i - len, term, len) == 0) {
          found = true;
          break;
        }
      }
    }
  }
  buffer[i] = 0;
  Serial.print(buffer);
  return found;
}

void setup() {

  
  Serial1.begin(115200);  // TEENSY Hardware Serial port 1   (pins 0 and 1)
  Serial.begin(115200);   // TEENSY USB Serial Port

  delay(2000);
  Serial.println("begin.");
  setupWiFi();

  // print device IP address
  Serial.print("device ip addr: ");
  Serial1.println("AT+CIFSR");
  wait_for_esp_response(1000);
  analogReadResolution(13);
}

bool read_till_eol() {
  static int i = 0;
  if (Serial1.available()) {
    buffer[i++] = Serial1.read();
    if (i == BUFFER_SIZE)  i = 0;
    if (i > 1 && buffer[i - 2] == 13 && buffer[i - 1] == 10) {
      buffer[i] = 0;
      i = 0;
      Serial.print(buffer);
      return true;
    }
  }
  return false;
}

void loop() {
  int ch_id, packet_len;
  char *pb;
  if (read_till_eol()) {
    if (strncmp(buffer, "+IPD,", 5) == 0) {
      // request: +IPD,ch,len:data
      sscanf(buffer + 5, "%d,%d", &ch_id, &packet_len);
      if (packet_len > 0) {
        // read serial until packet_len character received
        // start from :
        pb = buffer + 5;
        while (*pb != ':') pb++;
        pb++;
        if (strncmp(pb, "GET /", 5) == 0) {
          wait_for_esp_response(5);
          Serial.println("-> serve homepage");
          serve_homepage(ch_id);
        }
      }
    }
  }
}

void serve_homepage(int ch_id) {

  String header = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\nRefresh: 1\r\n";

  String content = "";
  content += "<!DOCTYPE html>";
  content += "<html>";
  content += "<body>";

  content += " <h1> Checking for T32 & ESP8266</h1> <br/>  ";


  content += "<font color=#0000FF> ";
  float val = analogRead(A0) * 0.40283203125 / 1000;
  content += String(val, 3);
 content += "</body>";
  content += "</html>";
  content += "<br />\n";
  content += "\r\n";

  header += "Content-Length:";
  header += (int)(content.length());
  header += "\r\n\r\n";
  Serial1.print("AT+CIPSEND=");
  Serial1.print(ch_id);
  Serial1.print(",");
  Serial1.println(header.length() + content.length());
  if (wait_for_esp_response(1000)) {
    //delay(100);
    Serial1.print(header);
    Serial1.print(content);
  }
  else {
    Serial1.print("AT+CIPCLOSE=");
    Serial1.println(ch_id);
  }
}

void setupWiFi() {

  // turn on echo
  Serial1.println("ATE1");
  wait_for_esp_response(1000);

  // try empty AT command
  //Serial1.println("AT");
  //wait_for_esp_response(1000);

  // set mode 1 (client)
  Serial1.println("AT+CWMODE=3");
  wait_for_esp_response(1000);

  // reset WiFi module
  Serial1.print("AT+RST\r\n");
  wait_for_esp_response(1500);

  //join AP
  Serial1.print("AT+CWJAP=\"");
  Serial1.print(SSID);
  Serial1.print("\",\"");
  Serial1.print(PASS);
  Serial1.println("\"");
  wait_for_esp_response(5000);

  // start server
  Serial1.println("AT+CIPMUX=1");
  wait_for_esp_response(1000);

  //Create TCP Server in
  Serial1.print("AT+CIPSERVER=1,"); // turn on TCP service
  Serial1.println(PORT);
  wait_for_esp_response(1000);

  Serial1.println("AT+CIPSTO=30");
  wait_for_esp_response(1000);

  Serial1.println("AT+GMR");
  wait_for_esp_response(1000);

  Serial.println("---------------*****##### READY TO SERVE #####*****---------------");

}
 
Status
Not open for further replies.
Back
Top