/*
Java HTML Battery Level Gauge
For Teensy 3.x and ESP8266
Using a Teensy 3.1 to Connect an ESP8266 to PC USB Serial *******
Compiled with Arduino 1.60 and Teensyduino 1.21b6
ESP8266 Firmware: AT21SDK95-2015-01-24.bin
Based on ESP8266 Demo code by Ray Wang
Original sketch by Ray Wang @ Rayshobby LLC - http://raysfiles.com/arduino/ESP8266a_arduino.ino
Teensy ACD library by Pedvide http://forum.pjrc.com/threads/25532-ADC-library-update-now-with-support-for-Teensy-3-1
Java Speedometer Code by Metormote http://bl.ocks.org/metormote/6392996
*/
#include <ADC.h>
#define BUFFER_SIZE 4096
#define SSID "NetworkG" // change this to match your WiFi SSID
#define PASS "springsummerautumnwinter" // change this to match your WiFi password
#define PORT "15164" // Port 8080 is default webserver port
char buffer[BUFFER_SIZE];
const int readPin = A9; // ADC0
ADC *adc = new ADC(); // adc object
int n = 0;
int value;
float BatteryLevel;
// 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() {
pinMode(readPin, INPUT); //pin 23 single ended
Serial.begin(9600);
adc->setAveraging(50); // set number of averages
adc->setResolution(12); // set bits of resolution
adc->setConversionSpeed(ADC_LOW_SPEED); // change the conversion speed
// setConversionSpeed() can be ADC_VERY_LOW_SPEED, ADC_LOW_SPEED, ADC_MED_SPEED, ADC_HIGH_SPEED_16BITS, ADC_HIGH_SPEED or ADC_VERY_HIGH_SPEED
adc->setSamplingSpeed(ADC_LOW_SPEED); // change the sampling speed
// setSamplingSpeed() can be ADC_VERY_LOW_SPEED, ADC_LOW_SPEED, ADC_MED_SPEED, ADC_HIGH_SPEED or ADC_VERY_HIGH_SPEED
// assume esp8266 operates at 115200 baud rate
// change if necessary to match your modules' baud rate
Serial1.begin(115200); // Teensy Hardware Serial port 1 (pins 0 and 1)
Serial.begin(115200); // Teensy USB Serial Port
delay(5000);
Serial.println("begin.");
setupWiFi();
// print device IP address
//Serial.print("device ip addr: ");
//Serial1.println("AT+CIFSR");
//wait_for_esp_response(1000);
}
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() {
// 16.8V to 14.8V 4S Li-Ion Battery Pack to Voltage Divider gives 3.3v to 2.91v
// Convert to 0 to 100%
value = adc->analogRead(readPin, ADC_0);
BatteryLevel = (((value*3.3/adc->getMaxValue(ADC_0))*254.5455) - 740.00000);
// Serial.print(value);
// Serial.print(" ");
// Serial.println(BatteryLevel);
delay(20);
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(1000);
Serial.println("-> serveing homepage");
serve_homepage(ch_id);
}
}
}
}
}
void serve_homepage(int ch_id) {
n=n+1;
String header = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\nRefresh: 300\r\n";
String content="";
content += "<!DOCTYPE html>";
content += "<html>";
content += "<head>";
content += "<title>Teensy3-ESP8266 Wi-Fi Battery Level</title>";
content += " <h1> <font color=#dddddd> TEENSY 3 </font> </h1>";
content += " <p> <font color=#ff66ff> ESP8266 Wireless Webserver Battery Level </font> </p>";
content += " <p> <font color=#ffffff> Teensy server uptime ";
content += String(millis());
content += " milliseconds </p>";
content += "<p> This page has been served ";
content += String(n);
content += " times since last reboot </font> </p>";
content += "<link rel='stylesheet' href='http://fonts.googleapis.com/css?family=Play:700,400' type='text/css'>";
content += "<script type=\"text/javascript\" src=\"http://iop.io/js/vendor/d3.v3.min.js\"></script>";
content += "<script type=\"text/javascript\" src=\"http://iop.io/js/vendor/polymer/PointerEvents/pointerevents.js\"></script>";
content += " <script type=\"text/javascript\" src=\"http://iop.io/js/vendor/polymer/PointerGestures/pointergestures.js\"></script>";
content += "<script type=\"text/javascript\" src=\"http://iop.io/js/iopctrl.js\"></script>";
content += "<style>";
content += "body {";
content += "font: 24px arialbold;";
content += " background-color: #222222;";
content += "}";
content += ".unselectable {";
content += "-moz-user-select: -moz-none;";
content += "-khtml-user-select: none;";
content += "-webkit-user-select: none;";
content += "-ms-user-select: none;";
content += "user-select: none;";
content += "}";
// content += "/* css formats for the gauge */";
content += ".gauge .domain {";
content += "stroke-width: 2px;";
content += "stroke: #fff;";
content += "}";
content += ".gauge .tick line {";
content += "stroke: #fff;";
content += "stroke-width: 2px;";
content += "}";
content += ".gauge line {";
content += "stroke: #fff;";
content += "}";
content += ".gauge .arc, .gauge .cursor {";
content += "opacity: 0;";
content += "}";
content += ".gauge .major {";
content += "fill: #fff;";
content += "font-size: 20px;";
content += "font-family: 'Play', verdana, sans-serif;";
content += "font-weight: normal;";
content += "}";
content += ".gauge .indicator {";
content += "stroke: #EE3311;";
content += "fill: #000;";
content += "stroke-width: 4px;";
content += "}";
// content += "/* css formats for the segment display */";
// content += ".segdisplay .on {";
// content += "fill: #00FFFF;";
// content += "}";
// content += ".segdisplay .on {";
// content += "fill: #00FFFF;";
// content += "opacity: 0.10;";
// content += "}";
content += "</style>";
content += "</head>";
content += "<body>";
content += "<div>";
content += "<span id=\"speedometer\"></span>";
content += "</div>";
content += "<script>";
content += "var svg = d3.select(\"#speedometer\")";
content += ".append(\"svg:svg\")";
content += ".attr(\"width\", 400)";
content += ".attr(\"height\", 400);";
content += "var gauge = iopctrl.arcslider()";
content += ".radius(150)";
content += ".events(false)";
content += ".indicator(iopctrl.defaultGaugeIndicator);";
content += "gauge.axis().orient(\"in\")";
content += ".normalize(true)";
content += ".ticks(10)";
content += ".tickSubdivide(9)";
content += ".tickSize(10, 8, 10)";
content += ".tickPadding(5)";
content += ".scale(d3.scale.linear()";
content += ".domain([0, 100])";
content += ".range([-3*Math.PI/4, 3*Math.PI/4]));";
// content += "var segDisplay = iopctrl.segdisplay()";
// content += ".width(80)";
// content += ".digitCount(6)";
// content += ".negative(false)";
// content += ".decimals(1);";
//content += "svg.append(\"g\")";
// content += ".attr(\"class\", \"segdisplay\")";
// content += ".attr(\"transform\", \"translate(130, 200)\")";
// content += ".call(segDisplay);";
content += "svg.append(\"g\")";
content += ".attr(\"class\", \"gauge\")";
content += ".call(gauge);";
//content += "segDisplay.value(";
//content += String(n*94);
//content += ");";
content += "gauge.value(";
content += String((int)BatteryLevel);
content += ");";
content += "</script>";
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(2000)) {
//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);
Serial1.println("AT+CWJAP?");
wait_for_esp_response(1000);
Serial1.println("AT+CIPSTA?");
wait_for_esp_response(1000);
Serial1.println("AT+CWMODE?");
wait_for_esp_response(1000);
Serial1.println("AT+CIFSR");
wait_for_esp_response(5000);
Serial1.println("AT+CWLAP");
wait_for_esp_response(5000);
Serial.println("---------------*****##### READY TO SERVE #####*****---------------");
}