Arduino on Lilygo OLED Lora ESP32 (board TTGO-Lora32-OLED V1″)
#define USE_OLED
#ifdef USE_OLED
//Libraries for OLED Display
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#endif
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiAP.h>
const char *ssid = "GPSWIFI";
const char *password = "12345678";
WiFiServer server(80);
const unsigned char ubxRate1Hz[] =
{ 0x06,0x08,0x06,0x00,0xE8,0x03,0x01,0x00,0x01,0x00 };
const unsigned char ubxRate5Hz[] =
{ 0x06,0x08,0x06,0x00,200,0x00,0x01,0x00,0x01,0x00 };
const unsigned char ubxRate10Hz[] =
{ 0x06,0x08,0x06,0x00,100,0x00,0x01,0x00,0x01,0x00 };
const unsigned char ubxRate16Hz[] =
{ 0x06,0x08,0x06,0x00,50,0x00,0x01,0x00,0x01,0x00 };
// Disable specific NMEA sentences
const unsigned char ubxDisableGGA[] =
{ 0x06,0x01,0x08,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x01 };
const unsigned char ubxDisableGLL[] =
{ 0x06,0x01,0x08,0x00,0xF0,0x01,0x00,0x00,0x00,0x00,0x00,0x01 };
const unsigned char ubxDisableGSA[] =
{ 0x06,0x01,0x08,0x00,0xF0,0x02,0x00,0x00,0x00,0x00,0x00,0x01 };
const unsigned char ubxDisableGSV[] =
{ 0x06,0x01,0x08,0x00,0xF0,0x03,0x00,0x00,0x00,0x00,0x00,0x01 };
const unsigned char ubxDisableRMC[] =
{ 0x06,0x01,0x08,0x00,0xF0,0x04,0x00,0x00,0x00,0x00,0x00,0x01 };
const unsigned char ubxDisableVTG[] =
{ 0x06,0x01,0x08,0x00,0xF0,0x05,0x00,0x00,0x00,0x00,0x00,0x01 };
const unsigned char ubxDisableZDA[] =
{ 0x06,0x01,0x08,0x00,0xF0,0x08,0x00,0x00,0x00,0x00,0x00,0x01 };
#define Battadc 36
#define ADC_FACTOR (0.000635*2.0*1.362)
#define BATT_LOW 3.5
#define SDA 21
#define SCL 22
#ifdef USE_OLED
//OLED pins
#define OLED_SDA 4
#define OLED_SCL 15
#define OLED_RST 16
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RST);
#endif
bool enable_dbg;
bool sig_valid, sig_rxok;
float sig_speed, saved_spd;
int sig_sats;
#define NUM_V_ENTRIES 5
float maxspeed[NUM_V_ENTRIES];
int vbatt;
// Cut out the wanted substring from a comma-separated string
static String extract_val(char *buf, int len, int cpos)
{
String str="";
int i,cc=0,cs=0,ce=255;
for (i=0;i<len;i++) {
if (buf[i]==',') {
cc++; // count commas
if(cc==cpos) cs=i+1;
if(cc==cpos+1) {ce=i; break;}
}
else if (buf[i]=='*' || buf[i]=='\r')
ce=i;
}
if (cs == 0) // no comma seen - no result
return str;
int s = min(ce-cs, 255);
for (i=0; i<s; i++) // build string, could be nicer...
str+=(char)buf[cs+i];
// memcpy(tgt, &buf[cs], s);
return str;
}
void parse_gps(char c) {
static char buf[127];
static int pos=0;
if (c=='\n') {
buf[pos]=0;
if (buf[2]=='V' && buf[3]=='T' && buf[4]=='G') {
sig_rxok = true;
String s = extract_val(buf, pos, 7);
if (s.length() > 0)
sig_valid = true;
Serial.println(s);
sig_speed = s.toFloat();
saved_spd = sig_speed;
}
else if (buf[2]=='G' && buf[3]=='G' && buf[4]=='A') {
#ifdef USE_OLED
display.print(buf);
#endif
String s = extract_val(buf
, pos, 7);
Serial.println(s);
sig_sats = s.toInt();
}
}
else if (c=='$') pos=0;
else if (pos < sizeof(buf))
buf[pos++] = c;
}
//Warteschleife, die ankommende Daten vom GPS Modul verarbeitet und den Status des Tasters prüft
static void smartdelay(unsigned long ms)
{
unsigned long start = millis();
do
{
while (Serial2.available()) {
char c=Serial2.read();
parse_gps(c);
if (enable_dbg) Serial.print(c);
//display.print(c);
}
//display.display();
} while (millis() - start < ms);
}
static void sendUBX( const unsigned char *progmemBytes, size_t len )
{
Serial2.write( 0xB5 ); // SYNC1
Serial2.write( 0x62 ); // SYNC2
uint8_t a = 0, b = 0;
while (len-- > 0) {
uint8_t c = ( *progmemBytes++ );
a += c;
b += a;
Serial2.write( c );
}
Serial2.write( a ); // CHECKSUM A
Serial2.write( b ); // CHECKSUM B
delay(100);
}
static void updateRate()
{
sendUBX(ubxRate5Hz, 10);
}
void setup() {
pinMode(0, INPUT_PULLUP); // button
pinMode(SCL, INPUT_PULLUP); // I2C of GPS compass
pinMode(SDA, INPUT_PULLUP);
// analogSetAttenuation(ADC_0db); // control sensitivity; ADC_11db, ADC_6db, ADC_2_5db, ADC_0db
// pinMode(Battadc, INPUT);
// adcAttachPin(Battadc);
Serial.begin(115200); // debug
Serial2.begin(9600,SERIAL_8N1,12,13); // GPS
#ifdef USE_OLED
//reset OLED display via software
pinMode(OLED_RST, OUTPUT);
digitalWrite(OLED_RST, LOW);
delay(20);
digitalWrite(OLED_RST, HIGH);
//initialize OLED
Wire.begin(OLED_SDA, OLED_SCL);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3c, false, false)) { // Address 0x3C for 128x32
//Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
#endif
// setup WIFI server
WiFi.softAP(ssid, password);
IPAddress myIP = WiFi.softAPIP(); // usually 192.168.4.1
server.begin();
#ifdef USE_OLED
display.setTextColor(WHITE);
display.setTextSize(1);
display.clearDisplay();
display.setCursor(0, 0);
display.println("Simon's WIFI GPS");
display.println("IP address:");
display.println(myIP);
display.display();
#endif
delay(2000);
sendUBX(ubxDisableGLL, 12);
sendUBX(ubxDisableGSA, 12);
sendUBX(ubxDisableGSV, 12);
sendUBX(ubxDisableRMC, 12);
sendUBX(ubxDisableZDA, 12);
Serial2.print("$PUBX,41,1,0007,0003,19200,0*25\r\n");
Serial2.flush();
delay(100);
Serial2.end();
Serial2.begin(19200,SERIAL_8N1,12,13);
delay(1000);
updateRate();
}
void wifi() {
WiFiClient client = server.available(); // listen for incoming clients
if (client) { // if you get a client,
char i;
Serial.println("New Client."); // print a message out the serial port
String currentLine = ""; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client's connected
if (client.available()) { // if there's bytes to read from the client,
char c = client.read(); // read a byte, then
// Serial.write(c); // print it out the serial monitor
if (c == '\n') { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that's the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what's coming, then a blank line:
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println();
// the content of the HTTP response follows the header:
char tmp[32];
client.print("<html><head><meta http-equiv=\"refresh\" content=\"10; URL=/\" /></head>");
client.print("<body style=\"background-color:black;\"><h1 style=\"color:white;font-size:80px\">Simon's WIFI GPS</h1>");
client.println("<p style=\"color:white;font-size:60px\"><b>");
sprintf(tmp, "Max = %4.1f km/h", maxspeed[0]);
client.print(tmp);
client.println("</p><p style=\"color:white;font-size:30px\">");
for (i=1;i<NUM_V_ENTRIES;i++) {
sprintf(tmp, "%4.1f km/h", maxspeed[i]);
client.print(tmp);
client.println("<br>");
}
sprintf(tmp, "<br>Batt = %2.3f V", (float)vbatt*ADC_FACTOR);
client.print(tmp);
client.println("<br>");
sprintf(tmp, "<br>Signal rx ok = %d", sig_rxok);
client.print(tmp);
client.println("<br>");
sprintf(tmp, "<br># of satellites = %d", sig_sats);
client.print(tmp);
client.println("<br>");
client.print("<br><br><a href=\"/R\">RESET</a> Vmax.<br></p></body></html>");
// The HTTP response ends with another blank line:
client.println();
// break out of the while loop:
break;
} else { // if you got a newline, then clear currentLine:
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
// Check to see if the client request was "GET /H" or "GET /L":
if (currentLine.endsWith("GET /R")) {
for (i=0; i<NUM_V_ENTRIES; i++)
maxspeed[i] = 0.0;
}
}
}
// close the connection:
client.stop();
// Serial.println("Client Disconnected.");
}
}
void loop() {
int i;
bool spdwritten = false;
char tmp[32];
float spd;
smartdelay(0);
#ifdef USE_OLED
display.clearDisplay(); // drawString(x,y,text);? or ACROBOTIC_SSD1306 with setTextXY/putString
display.setCursor(0, 0);
#endif
if (sig_valid) {
spd = sig_speed;
sig_speed = 0.0;
// show maximum speed, with 5 places to see glitches
#ifdef USE_OLED
display.println("Geschwindigkeit (max)");
#endif
for (i=0; i<NUM_V_ENTRIES; i++) {
if (spd > maxspeed[i] && !spdwritten) {
maxspeed[i] = spd;
spdwritten = true;
break;
}
}
#ifdef USE_OLED
for (i=0; i<NUM_V_ENTRIES; i++) {
if (i==0)
display.setTextSize(2);
sprintf(tmp, "%4.1f km/h", maxspeed[i]);
display.println(tmp);
if (i==0)
display.setTextSize(1);
}
// show current speed
sprintf(tmp,"S%4.1f Sats %3d", saved_spd, sig_sats);
display.print(tmp);
} else {
display.println("No GPS fix.");
if (sig_rxok)
display.println("GPS RX ok");
sprintf(tmp," Sats %3d", sig_sats);
display.print(tmp);
#endif
}
vbatt = analogRead(Battadc);
#ifdef USE_OLED
if ((float)vbatt*ADC_FACTOR < BATT_LOW) {
display.setCursor(108, 32);
display.print("LOW");
}
display.display();
#endif
if (digitalRead(0)==0) { // clear
for (i=0;i<NUM_V_ENTRIES; i++)
maxspeed[i] = 0.0;
#ifdef USE_OLED
display.clearDisplay();
#endif
}
wifi();
}