preface
Use esp32 one + GPS module + OLED small screen to make a portable low-power velocimeter
1, What is Esp32 One?
Esp32 One is a development board compatible with raspberry pie pin developed by Weixue electronics based on the custom pin of Xtensa LX6 dual core processor.
2, Using hardware
Esp32 One x1
L76X GPS Module x1
0.96 "Oled screen x1
Button x1
1k resistance x1
Some problems of DuPont line
3, Hardware construction steps
1. Connect Oled to Esp32 One.
The 4-pin 0.96-inch Oled screen is adopted, the SPI communication is connected to Esp32, and the corresponding Oled SCL SDA pin is connected to the SPI pin of Esp32 chip
Access GPOS.26 GPIO.33 through circuit diagram
Test the oled screen, develop it with arduino ide, and open the routine to test hello world
2. Connect L76X GPS Module to Esp32
The L76X GPS Module has five interfaces. The color of the cable is different from the usual pin line.
The green flat cable corresponds to the positive interface of VCC and is connected to positive 3.3~5v
The Yellow cable corresponds to GND grounding interface grounding
The blue cable corresponds to the TX port, which is connected through the hard serial port. Definition io33, corresponding pin 38
The black flat cable corresponds to the RX port, which is connected through the hard serial port. Define io32 and the corresponding pin is 35
The red cable corresponds to PPS (not connected here)
3. Key pull-down 1k Ω resistance
The opposite side of the key is welded with DuPont wire. At one end, 1k Ω resistance is used to pull down the resistance. One end is connected with positive 3.3v, one end is connected with io13, corresponding to GPIO pin 12, and one end is grounded.
4, Development code side
The program is developed using arduino ide. U8G2 library needs to be installed. Open arduino ide and select project → load library → manage library.
Search u8g2 download library.
1. Analyzing GPS database
void GPSRES() { while (MySerial_stm32.available()) { // comdata = "";// Cache reset int i = 0; memset(comdata, 0, sizeof(comdata)); memset(rc, 0, sizeof(rc)); // Serial.print(MySerial_stm32.available()); while (MySerial_stm32.available() > 0)//Whether there is data on the circular serial port { // Serial.print(char(MySerial_stm32.read())); char res = char(MySerial_stm32.read()); if (res == '$') { // Serial.print("comdataLine:"); // Serial.println(comdata); // Serial.println("over"); if (strstr(comdata, "GNRMC")) { Serial.println("enter"); Analyze(strstr(comdata, "GNRMC")); } Display(); ButtonEvent(); Serial.println("LoopRun"); //char *rc2 = strstr(comdata, "GNRMC"); // Find_String(comdata, "GNRM", "\n", rc); i = 0; memset(comdata, 0, sizeof(comdata)); // delayMicroseconds (500) ; } else { comdata[i] += res;//Overlay data to comdata i++; // delay(1);// Delay waiting for response } delayMicroseconds (1400) ; } // Find_String(comdata, "$GNRM", "\n", rc); // Serial.print("comdata:"); // Serial.println(comdata); // Serial.println("over"); // Serial.println(rc); } }
2. Screen display
void Display() { Serial.println(UTC); Serial.println(State); Serial.println(Speed); Serial.println(Direction); Serial.println(UTCDate); Serial.println(FinalSpeed); if (LastSpeed < FinalSpeed) { for (int i = 0; i < (millis() - lastSpeedTime) / SpeedUpdateTime; i++) { LastSpeed++; if (LastSpeed >= FinalSpeed) { break; } } } if (LastSpeed > FinalSpeed) { for (int i = 0; i < (millis() - lastSpeedTime) / SpeedUpdateTime; i++) { LastSpeed--; if (LastSpeed <= FinalSpeed) { break; } } } lastSpeedTime = millis(); u8g2.firstPage(); do { if (State == "A") { if ((millis() - lastUpdateTime) > 10000) { weeprom(); lastUpdateTime = millis(); } u8g2.setFont(u8g2_font_t0_12_tf); // use chinese2 for all the glyphs of "Hello world" u8g2.setFontDirection(0); u8g2.setCursor(0, 12); u8g2.print(year); u8g2.print("/"); u8g2.print(month); u8g2.print("/"); u8g2.print(day); u8g2.print(" "); //Time display u8g2.print(hour); u8g2.print(":"); u8g2.print(UTC.charAt(2)); u8g2.print(UTC.charAt(3)); u8g2.print(":"); u8g2.print(UTC.charAt(4)); u8g2.println(UTC.charAt(5)); // lastUpdateTime = millis(); // } u8g2.setFont(u8g2_font_luBS24_tn); u8g2.setFontDirection(0); u8g2.setCursor(0, 42); u8g2.print(LastSpeed); u8g2.setFont(u8g2_font_logisoso16_tr); // use chinese2 for all the glyphs of "Hello world" u8g2.setFontDirection(0); u8g2.setCursor(68, 42); u8g2.print(F(" Km/h")); u8g2.setFont(u8g2_font_logisoso16_tr); u8g2.setCursor(0, 64); if (kmFlag == 0) { u8g2.setFont(u8g2_font_t0_12_tf); u8g2.setCursor(4, 60); u8g2.print("T"); u8g2.setFont(u8g2_font_logisoso16_tr); u8g2.setCursor(16, 64); u8g2.print((int)(Tkm + 0.5)); } else if (kmFlag == 1) { u8g2.setFont(u8g2_font_t0_12_tf); // use chinese2 for all the glyphs of "Hello world" u8g2.setCursor(4, 56); u8g2.print("1"); u8g2.setFont(u8g2_font_logisoso16_tr); u8g2.setCursor(16, 64); u8g2.print(km); } else if (kmFlag == 2) { u8g2.setFont(u8g2_font_t0_12_tf); // use chinese2 for all the glyphs of "Hello world" u8g2.setCursor(4, 64); u8g2.print("2"); u8g2.setFont(u8g2_font_logisoso16_tr); u8g2.setCursor(16, 64); u8g2.print(km2); } u8g2.setFont(u8g2_font_t0_12_tf); u8g2.print("Km"); if (FinalDirection != -1) { u8g2.setFont(u8g2_font_logisoso16_tr); u8g2.setCursor(78, 64); if (FinalDirection >= 0 && FinalDirection < 22.5 || FinalDirection > 337.5 && FinalDirection <= 360) u8g2.print("N"); else if (FinalDirection > 22.5 && FinalDirection < 67.5) u8g2.print("Ne"); else if (FinalDirection > 67.5 && FinalDirection < 112.5) u8g2.print("E"); else if (FinalDirection > 112.5 && FinalDirection < 157.5) u8g2.print("Se"); else if (FinalDirection > 157.5 && FinalDirection < 202.5) u8g2.print("S"); else if (FinalDirection > 202.5 && FinalDirection < 247.5) u8g2.print("Sw"); else if (FinalDirection > 247.5 && FinalDirection < 292.5) u8g2.print("W"); else if (FinalDirection > 292.5 && FinalDirection < 337.5) u8g2.print("Nw"); u8g2.setFont(u8g2_font_t0_12_tf); u8g2.setCursor(101, 64); u8g2.print("^"); u8g2.print(FinalDirection); } else { u8g2.setFont(u8g2_font_t0_12_tf); u8g2.setCursor(78, 60); u8g2.print("calculat"); } } else { if (year != 0) { u8g2.setFont(u8g2_font_t0_12_tf); // use chinese2 for all the glyphs of "Hello world" u8g2.setFontDirection(0); u8g2.setCursor(0, 12); u8g2.print(year); u8g2.print("/"); u8g2.print(month); u8g2.print("/"); u8g2.print(day); u8g2.print(" "); //Time display u8g2.print(hour); u8g2.print(":"); u8g2.print(UTC.charAt(2)); u8g2.print(UTC.charAt(3)); u8g2.print(":"); u8g2.print(UTC.charAt(4)); u8g2.println(UTC.charAt(5)); } if (kmFlag == 0) { u8g2.setFont(u8g2_font_t0_12_tf); u8g2.setCursor(4, 60); u8g2.print("T"); u8g2.setFont(u8g2_font_logisoso16_tr); u8g2.setCursor(16, 64); u8g2.print((int)(Tkm + 0.5)); } else if (kmFlag == 1) { u8g2.setFont(u8g2_font_t0_12_tf); // use chinese2 for all the glyphs of "Hello world" u8g2.setCursor(4, 56); u8g2.print("1"); u8g2.setFont(u8g2_font_logisoso16_tr); u8g2.setCursor(16, 64); u8g2.print(km); } else if (kmFlag == 2) { u8g2.setFont(u8g2_font_t0_12_tf); // use chinese2 for all the glyphs of "Hello world" u8g2.setCursor(4, 64); u8g2.print("2"); u8g2.setFont(u8g2_font_logisoso16_tr); u8g2.setCursor(16, 64); u8g2.print(km2); } u8g2.setFont(u8g2_font_t0_12_tf); u8g2.print("Km"); u8g2.setFont(u8g2_font_logisoso16_tr); // use chinese2 for all the glyphs of "Hello world" u8g2.setFontDirection(0); u8g2.setCursor(16, 40); if (flag == 0) u8g2.print(F("Find GPS")); // write something to the internal memory else if (flag == 1) u8g2.print(F("Find GPS.")); // write something to the internal memory else if (flag == 2) u8g2.print(F("Find GPS..")); // write something to the internal memory else if (flag == 3) u8g2.print(F("Find GPS...")); // write something to the internal memory if ((millis() - lastUpdateTime) > 500) { flag++; digitalWrite(pin, state); state = !state; lastUpdateTime = millis(); } if (flag >= 4) { flag = 0; } } } while ( u8g2.nextPage() ); }
3. GPS velocity analysis
void Analyze(char *res) { // char *Res = (char*)malloc(512); // strcpy(Res,res); char arr[512] = {0}; char* tmp = NULL; memcpy(arr, res, sizeof(arr)); Serial.print("rcData:"); Serial.println(arr); Serial.println("over"); if (arr)//If comdata has data { int j = 0; for (int i = 1; i < 128; i++) { if (arr[i] == ',') { pos[j] = i; j++; } } UTC = ""; State = ""; Speed = ""; Direction = ""; UTCDate = ""; int i; Serial.println(j); if (j == 12) { Serial.println(rc); for (i = pos[0] + 1; i < pos[1]; i++) { UTC += arr[i]; } for (int i = pos[1] + 1; i < pos[2]; i++) { State += arr[i]; } for (int i = pos[6] + 1; i < pos[7]; i++) { Speed += arr[i]; } for (int i = pos[7] + 1; i < pos[8]; i++) { Direction += arr[i]; } for (int i = pos[8] + 1; i < pos[9]; i++) { UTCDate += arr[i]; } Serial.print("UTC:"); Serial.println(UTC); Serial.print("State:"); Serial.println(State); Serial.print("Speed:"); Serial.println(Speed); Serial.print("Direction:"); Serial.println(Direction); Serial.print("UTCDate:"); Serial.println(UTCDate); if (UTC.length() > 0) { utc_to_local_time(8); } else { Serial.println("noUTC"); year = 0; //particular year month = 0; //month day = 0; //date hour = 0; //hour mins = 0; //minute sec = 0; //second } } } if (State == "V") { speedflag = 1; Serial.println("NoSite"); } else { if (speedflag == 1) { lastTime = millis(); speedflag = 0; } int str_len = Speed.length() + 1; Speed.toCharArray(Speeds, str_len); FinalSpeed = (int)(atof(Speeds) * 1.852 + 0.5); Serial.println(FinalSpeed); int str_len2 = Direction.length() + 1; if (Direction.length() == 0) { FinalDirection = -1; } else { Direction.toCharArray(Directions, str_len2); FinalDirection = (int)(atof(Directions) + 0.5); } km += (((millis() - lastTime) * (atof(Speeds) * 1.852)) / 3600000); km2 += (((millis() - lastTime) * (atof(Speeds) * 1.852)) / 3600000); Tkm += (((millis() - lastTime) * (atof(Speeds) * 1.852)) / 3600000); lastTime = millis(); SpeedUpdateTime = 100 - abs(FinalSpeed - LastSpeed); if (SpeedUpdateTime >= 100 || SpeedUpdateTime <= 0) { SpeedUpdateTime = 1; } } }
4. GPS international time analysis
//UTC time is converted to time in any time zone. If it is converted to Beijing time, timezone can be transmitted to 8 void utc_to_local_time(int timezone) { year = 2000 + (int)(UTCDate.charAt(4) - '0') * 10 + (int)(UTCDate.charAt(5) - '0'); month = (int)(UTCDate.charAt(2) - '0') * 10 + (int)(UTCDate.charAt(3) - '0'); day = (int)(UTCDate.charAt(0) - '0') * 10 + (int)(UTCDate.charAt(1) - '0'); hour = (int)(UTC.charAt(0) - '0') * 10 + (int)(UTC.charAt(1) - '0'); int lastday = 0; //last day of this month int lastlastday = 0; //last day of last month hour = hour + timezone; //January, February, March, April, may, June, July, August, September, October, November and December if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) { lastday = 31;//Days of this month lastlastday = 30;//The number of days of last month should be added here if (month == 3) { if ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)) //if this is lunar year lastlastday = 29; else lastlastday = 28; } if (month == 8 || month == 1) //It should be August and January, because the number of days in the previous month (July and December) of August and January is 31 days lastlastday = 31; } else if (month == 4 || month == 6 || month == 9 || month == 11) { lastday = 30; lastlastday = 31; } else { lastlastday = 31; if ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)) lastday = 29; else lastday = 28; } if (hour >= 24) // if >24, day+1 { hour -= 24; day += 1; if (day > lastday) // next month, day-lastday of this month { day -= lastday; month += 1; if (month > 12) // next year, month-12 { month -= 12; year += 1; } } } if (hour < 0) // if <0, day-1 { hour += 24; day -= 1; if (day < 1) // month-1, day=last day of last month { day = lastlastday; month -= 1; if (month < 1) // last year, month=12 { month = 12; year -= 1; } } } }
5. Button switching function
void ButtonEvent(){ if (digitalRead(26)) { delay(10); btn_flag = 1; unsigned long i = millis(); Serial.println(i); Serial.println(millis()); while (digitalRead(26) && btn_flag == 1) { // wdt_reset(); if (millis() - i > 2500) { if (kmFlag == 1) km = 0; else if (kmFlag == 2) km2 = 0; Serial.print("ResKm:"); Serial.println(kmFlag); Serial.println(km); Serial.println(km2); weeprom(); btn_flag = 0; //Display(); delay(100); } } if (millis() - i < 500) { kmFlag++; if (kmFlag >= 3) { kmFlag = 0; } Serial.println(kmFlag); } } }
Overall code
#include <Arduino.h> #include <U8g2lib.h> #include "EEPROM.h" #ifdef U8X8_HAVE_HW_SPI #include <SPI.h> #endif #ifdef U8X8_HAVE_HW_I2C #include <Wire.h> #endif #include <stdio.h> #Include < hardwareserial. H > / / import the ESP32 serial port operation library. Using this library, we can map the serial port to other pins for use // #include <avr/wdt.h> #define SDA_PIN A4 #define SCL_PIN A5 int FirstDownload = 0; U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); HardwareSerial MySerial_stm32(1); unsigned long lastUpdateTime = 0; //Record the last time the screen was refreshed unsigned long lastSpeedTime = 0; //Record the last time the screen was refreshed unsigned long SpeedUpdateTime = 10; const unsigned long updateInterval = 200; // Screen refresh interval 200ms int x;//Cache function //char *rc = NULL;// String function char comdata[256] = ""; char rc[128] = ""; int pos[12]; String UTC = ""; String State = ""; String Speed = ""; char Speeds[20] = ""; int FinalSpeed = 0; int LastSpeed = 0; String Direction = ""; char Directions[20] = ""; int FinalDirection = 0; String UTCDate = ""; int flag = 0; double Tkm = 0; double km = 0; double km2 = 0; char kms[10] = ""; unsigned long lastTime = 0; int speedflag = 1; unsigned short kmFlag = 0; int eeAddress = 0; unsigned long year; //particular year unsigned int month; //month unsigned int day; //date unsigned int hour; //hour unsigned int mins; //minute unsigned long sec; //second int pin = 13; volatile int state = LOW; unsigned int duration; int btn_flag = 1; void setup() { //Define baud rate // wdt_enable(WDTO_4S); // Serial2.begin Serial.begin(115200); MySerial_stm32.begin(9600, SERIAL_8N1, 33, 32); MySerial_stm32.setRxBufferSize(1024); u8g2.begin(); u8g2.enableUTF8Print(); pinMode(26, INPUT); pinMode(pin, OUTPUT); if (FirstDownload == 1) { EEPROM.writeDouble(eeAddress, Tkm); eeAddress += sizeof(double); EEPROM.writeDouble(eeAddress, km); eeAddress += sizeof(double); EEPROM.writeDouble(eeAddress, km2); eeAddress += sizeof(double); EEPROM.writeInt(eeAddress, kmFlag); } Tkm = EEPROM.readDouble(eeAddress); eeAddress = sizeof(double); km = EEPROM.readDouble(eeAddress); eeAddress += sizeof(double); km2 = EEPROM.readDouble(eeAddress); eeAddress += sizeof(double); kmFlag = EEPROM.readInt(eeAddress); Serial.println(Tkm); Serial.println(km); Serial.println(km2); Serial.println(kmFlag); } void loop() { GPSRES(); // wdt_reset(); } void GPSRES() { while (MySerial_stm32.available()) { // comdata = "";// Cache reset int i = 0; memset(comdata, 0, sizeof(comdata)); memset(rc, 0, sizeof(rc)); // Serial.print(MySerial_stm32.available()); while (MySerial_stm32.available() > 0)//Whether there is data on the circular serial port { // Serial.print(char(MySerial_stm32.read())); char res = char(MySerial_stm32.read()); if (res == '$') { // Serial.print("comdataLine:"); // Serial.println(comdata); // Serial.println("over"); if (strstr(comdata, "GNRMC")) { Serial.println("enter"); Analyze(strstr(comdata, "GNRMC")); } Display(); ButtonEvent(); Serial.println("LoopRun"); //char *rc2 = strstr(comdata, "GNRMC"); // Find_String(comdata, "GNRM", "\n", rc); i = 0; memset(comdata, 0, sizeof(comdata)); // delayMicroseconds (500) ; } else { comdata[i] += res;//Overlay data to comdata i++; // delay(1);// Delay waiting for response } delayMicroseconds (1400) ; } // Find_String(comdata, "$GNRM", "\n", rc); // Serial.print("comdata:"); // Serial.println(comdata); // Serial.println("over"); // Serial.println(rc); } } void Analyze(char *res) { // char *Res = (char*)malloc(512); // strcpy(Res,res); char arr[512] = {0}; char* tmp = NULL; memcpy(arr, res, sizeof(arr)); Serial.print("rcData:"); Serial.println(arr); Serial.println("over"); if (arr)//If comdata has data { int j = 0; for (int i = 1; i < 128; i++) { if (arr[i] == ',') { pos[j] = i; j++; } } UTC = ""; State = ""; Speed = ""; Direction = ""; UTCDate = ""; int i; Serial.println(j); if (j == 12) { Serial.println(rc); for (i = pos[0] + 1; i < pos[1]; i++) { UTC += arr[i]; } for (int i = pos[1] + 1; i < pos[2]; i++) { State += arr[i]; } for (int i = pos[6] + 1; i < pos[7]; i++) { Speed += arr[i]; } for (int i = pos[7] + 1; i < pos[8]; i++) { Direction += arr[i]; } for (int i = pos[8] + 1; i < pos[9]; i++) { UTCDate += arr[i]; } Serial.print("UTC:"); Serial.println(UTC); Serial.print("State:"); Serial.println(State); Serial.print("Speed:"); Serial.println(Speed); Serial.print("Direction:"); Serial.println(Direction); Serial.print("UTCDate:"); Serial.println(UTCDate); if (UTC.length() > 0) { utc_to_local_time(8); } else { Serial.println("noUTC"); year = 0; //particular year month = 0; //month day = 0; //date hour = 0; //hour mins = 0; //minute sec = 0; //second } } } if (State == "V") { speedflag = 1; Serial.println("NoSite"); } else { if (speedflag == 1) { lastTime = millis(); speedflag = 0; } int str_len = Speed.length() + 1; Speed.toCharArray(Speeds, str_len); FinalSpeed = (int)(atof(Speeds) * 1.852 + 0.5); Serial.println(FinalSpeed); int str_len2 = Direction.length() + 1; if (Direction.length() == 0) { FinalDirection = -1; } else { Direction.toCharArray(Directions, str_len2); FinalDirection = (int)(atof(Directions) + 0.5); } km += (((millis() - lastTime) * (atof(Speeds) * 1.852)) / 3600000); km2 += (((millis() - lastTime) * (atof(Speeds) * 1.852)) / 3600000); Tkm += (((millis() - lastTime) * (atof(Speeds) * 1.852)) / 3600000); lastTime = millis(); SpeedUpdateTime = 100 - abs(FinalSpeed - LastSpeed); if (SpeedUpdateTime >= 100 || SpeedUpdateTime <= 0) { SpeedUpdateTime = 1; } } } void Display() { Serial.println(UTC); Serial.println(State); Serial.println(Speed); Serial.println(Direction); Serial.println(UTCDate); Serial.println(FinalSpeed); if (LastSpeed < FinalSpeed) { for (int i = 0; i < (millis() - lastSpeedTime) / SpeedUpdateTime; i++) { LastSpeed++; if (LastSpeed >= FinalSpeed) { break; } } } if (LastSpeed > FinalSpeed) { for (int i = 0; i < (millis() - lastSpeedTime) / SpeedUpdateTime; i++) { LastSpeed--; if (LastSpeed <= FinalSpeed) { break; } } } lastSpeedTime = millis(); u8g2.firstPage(); do { if (State == "A") { if ((millis() - lastUpdateTime) > 10000) { weeprom(); lastUpdateTime = millis(); } u8g2.setFont(u8g2_font_t0_12_tf); // use chinese2 for all the glyphs of "Hello world" u8g2.setFontDirection(0); u8g2.setCursor(0, 12); u8g2.print(year); u8g2.print("/"); u8g2.print(month); u8g2.print("/"); u8g2.print(day); u8g2.print(" "); //Time display u8g2.print(hour); u8g2.print(":"); u8g2.print(UTC.charAt(2)); u8g2.print(UTC.charAt(3)); u8g2.print(":"); u8g2.print(UTC.charAt(4)); u8g2.println(UTC.charAt(5)); // lastUpdateTime = millis(); // } u8g2.setFont(u8g2_font_luBS24_tn); u8g2.setFontDirection(0); u8g2.setCursor(0, 42); u8g2.print(LastSpeed); u8g2.setFont(u8g2_font_logisoso16_tr); // use chinese2 for all the glyphs of "Hello world" u8g2.setFontDirection(0); u8g2.setCursor(68, 42); u8g2.print(F(" Km/h")); u8g2.setFont(u8g2_font_logisoso16_tr); u8g2.setCursor(0, 64); if (kmFlag == 0) { u8g2.setFont(u8g2_font_t0_12_tf); u8g2.setCursor(4, 60); u8g2.print("T"); u8g2.setFont(u8g2_font_logisoso16_tr); u8g2.setCursor(16, 64); u8g2.print((int)(Tkm + 0.5)); } else if (kmFlag == 1) { u8g2.setFont(u8g2_font_t0_12_tf); // use chinese2 for all the glyphs of "Hello world" u8g2.setCursor(4, 56); u8g2.print("1"); u8g2.setFont(u8g2_font_logisoso16_tr); u8g2.setCursor(16, 64); u8g2.print(km); } else if (kmFlag == 2) { u8g2.setFont(u8g2_font_t0_12_tf); // use chinese2 for all the glyphs of "Hello world" u8g2.setCursor(4, 64); u8g2.print("2"); u8g2.setFont(u8g2_font_logisoso16_tr); u8g2.setCursor(16, 64); u8g2.print(km2); } u8g2.setFont(u8g2_font_t0_12_tf); u8g2.print("Km"); if (FinalDirection != -1) { u8g2.setFont(u8g2_font_logisoso16_tr); u8g2.setCursor(78, 64); if (FinalDirection >= 0 && FinalDirection < 22.5 || FinalDirection > 337.5 && FinalDirection <= 360) u8g2.print("N"); else if (FinalDirection > 22.5 && FinalDirection < 67.5) u8g2.print("Ne"); else if (FinalDirection > 67.5 && FinalDirection < 112.5) u8g2.print("E"); else if (FinalDirection > 112.5 && FinalDirection < 157.5) u8g2.print("Se"); else if (FinalDirection > 157.5 && FinalDirection < 202.5) u8g2.print("S"); else if (FinalDirection > 202.5 && FinalDirection < 247.5) u8g2.print("Sw"); else if (FinalDirection > 247.5 && FinalDirection < 292.5) u8g2.print("W"); else if (FinalDirection > 292.5 && FinalDirection < 337.5) u8g2.print("Nw"); u8g2.setFont(u8g2_font_t0_12_tf); u8g2.setCursor(101, 64); u8g2.print("^"); u8g2.print(FinalDirection); } else { u8g2.setFont(u8g2_font_t0_12_tf); u8g2.setCursor(78, 60); u8g2.print("calculat"); } } else { if (year != 0) { u8g2.setFont(u8g2_font_t0_12_tf); // use chinese2 for all the glyphs of "Hello world" u8g2.setFontDirection(0); u8g2.setCursor(0, 12); u8g2.print(year); u8g2.print("/"); u8g2.print(month); u8g2.print("/"); u8g2.print(day); u8g2.print(" "); //Time display u8g2.print(hour); u8g2.print(":"); u8g2.print(UTC.charAt(2)); u8g2.print(UTC.charAt(3)); u8g2.print(":"); u8g2.print(UTC.charAt(4)); u8g2.println(UTC.charAt(5)); } if (kmFlag == 0) { u8g2.setFont(u8g2_font_t0_12_tf); u8g2.setCursor(4, 60); u8g2.print("T"); u8g2.setFont(u8g2_font_logisoso16_tr); u8g2.setCursor(16, 64); u8g2.print((int)(Tkm + 0.5)); } else if (kmFlag == 1) { u8g2.setFont(u8g2_font_t0_12_tf); // use chinese2 for all the glyphs of "Hello world" u8g2.setCursor(4, 56); u8g2.print("1"); u8g2.setFont(u8g2_font_logisoso16_tr); u8g2.setCursor(16, 64); u8g2.print(km); } else if (kmFlag == 2) { u8g2.setFont(u8g2_font_t0_12_tf); // use chinese2 for all the glyphs of "Hello world" u8g2.setCursor(4, 64); u8g2.print("2"); u8g2.setFont(u8g2_font_logisoso16_tr); u8g2.setCursor(16, 64); u8g2.print(km2); } u8g2.setFont(u8g2_font_t0_12_tf); u8g2.print("Km"); u8g2.setFont(u8g2_font_logisoso16_tr); // use chinese2 for all the glyphs of "Hello world" u8g2.setFontDirection(0); u8g2.setCursor(16, 40); if (flag == 0) u8g2.print(F("Find GPS")); // write something to the internal memory else if (flag == 1) u8g2.print(F("Find GPS.")); // write something to the internal memory else if (flag == 2) u8g2.print(F("Find GPS..")); // write something to the internal memory else if (flag == 3) u8g2.print(F("Find GPS...")); // write something to the internal memory if ((millis() - lastUpdateTime) > 500) { flag++; digitalWrite(pin, state); state = !state; lastUpdateTime = millis(); } if (flag >= 4) { flag = 0; } } } while ( u8g2.nextPage() ); } void weeprom() { Serial.println("w to eeprom"); digitalWrite(pin, state); state = !state; EEPROM.writeInt(eeAddress, kmFlag); eeAddress -= sizeof(double); EEPROM.writeDouble(eeAddress, km2); eeAddress -= sizeof(double); EEPROM.writeDouble(eeAddress, km); EEPROM.writeDouble(0, Tkm); } void ButtonEvent(){ if (digitalRead(26)) { delay(10); btn_flag = 1; unsigned long i = millis(); Serial.println(i); Serial.println(millis()); while (digitalRead(26) && btn_flag == 1) { // wdt_reset(); if (millis() - i > 2500) { if (kmFlag == 1) km = 0; else if (kmFlag == 2) km2 = 0; Serial.print("ResKm:"); Serial.println(kmFlag); Serial.println(km); Serial.println(km2); weeprom(); btn_flag = 0; //Display(); delay(100); } } if (millis() - i < 500) { kmFlag++; if (kmFlag >= 3) { kmFlag = 0; } Serial.println(kmFlag); } } } //UTC time is converted to time in any time zone. If it is converted to Beijing time, timezone can be transmitted to 8 void utc_to_local_time(int timezone) { year = 2000 + (int)(UTCDate.charAt(4) - '0') * 10 + (int)(UTCDate.charAt(5) - '0'); month = (int)(UTCDate.charAt(2) - '0') * 10 + (int)(UTCDate.charAt(3) - '0'); day = (int)(UTCDate.charAt(0) - '0') * 10 + (int)(UTCDate.charAt(1) - '0'); hour = (int)(UTC.charAt(0) - '0') * 10 + (int)(UTC.charAt(1) - '0'); int lastday = 0; //last day of this month int lastlastday = 0; //last day of last month hour = hour + timezone; //January, February, March, April, may, June, July, August, September, October, November and December if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) { lastday = 31;//Days of this month lastlastday = 30;//The number of days of last month should be added here if (month == 3) { if ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)) //if this is lunar year lastlastday = 29; else lastlastday = 28; } if (month == 8 || month == 1) //It should be August and January, because the number of days in the previous month (July and December) of August and January is 31 days lastlastday = 31; } else if (month == 4 || month == 6 || month == 9 || month == 11) { lastday = 30; lastlastday = 31; } else { lastlastday = 31; if ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)) lastday = 29; else lastday = 28; } if (hour >= 24) // if >24, day+1 { hour -= 24; day += 1; if (day > lastday) // next month, day-lastday of this month { day -= lastday; month += 1; if (month > 12) // next year, month-12 { month -= 12; year += 1; } } } if (hour < 0) // if <0, day-1 { hour += 24; day -= 1; if (day < 1) // month-1, day=last day of last month { day = lastlastday; month -= 1; if (month < 1) // last year, month=12 { month = 12; year -= 1; } } } }
5, Overall operation effect
There is some deviation between the measured speed and the mobile phone speed measurement. The reason is that the signal frequency received by GPS is slow. Using more advanced GPS can solve the problem.
summary
The key to the development of Esp32 One is to find the corresponding pin. The programming pin can choose ESP IDF development.
On the basis of this project, the longitude and latitude can be analyzed. In addition, Nb IOT transmits the longitude and latitude information to the cloud, which can be forwarded to the mobile APP
For specific applications, you can view the GPS mobile phone positioning written before.
On the basis of this project, it can be further extended. Considering that there is no satellite positioning signal indoors, esp32 One can be used to connect WiFi judgment equipment. When there is no WiFi indoors and outdoors, Nb IOT equipment can be used to connect to the cloud to transmit longitude and latitude information, speed information and time information to the cloud for processing. Later development history track, real-time speed display, etc.