前言
做拓展項(xiàng)目需要要用GPS定位數(shù)據(jù)以及超聲設(shè)計(jì),之前沒(méi)有用過(guò)ESP-12F這個(gè)開(kāi)發(fā)板去做過(guò),都是用到STM32板子,今天嘗試用Arduino環(huán)境進(jìn)行開(kāi)發(fā),并實(shí)現(xiàn)GPS經(jīng)緯度數(shù)據(jù)獲取以及超聲測(cè)距
一、芯片介紹
這款芯片的可用io口還是比較少的,只適合做小型的設(shè)備控制,不用看圖上有很多io口,其實(shí)他很多都不能用,否則就會(huì)導(dǎo)致啟動(dòng)錯(cuò)誤,我已經(jīng)踩過(guò)坑了
ESP-12F可用輸出引腳列表
GPIO編號(hào) | 物理引腳 | 特殊限制 | 最大輸出電流 | PWM支持 | 推薦用途 |
---|---|---|---|---|---|
GPIO4 | Pin 10 | 無(wú) | 12mA | ?? | LED控制、傳感器驅(qū)動(dòng) |
GPIO5 | Pin 11 | 啟動(dòng)時(shí)需高電平 | 12mA | ?? | 繼電器、數(shù)字輸出 |
GPIO12 | Pin 14 | 啟動(dòng)時(shí)需低電平 | 12mA | ?? | 按鍵輸入、低功耗設(shè)備 |
GPIO13 | Pin 15 | 無(wú) | 12mA | ?? | SPI MOSI、數(shù)據(jù)總線 |
GPIO14 | Pin 16 | 啟動(dòng)時(shí)需高電平 | 12mA | ?? | SPI CLK、高速信號(hào) |
GPIO15 | Pin 17 | 必須啟動(dòng)時(shí)低電平 | 12mA | ?? | 接地設(shè)備控制 |
禁止使用的輸出引腳
GPIO編號(hào) | 限制原因 |
---|---|
GPIO0 | 啟動(dòng)模式選擇(需外部上拉) |
GPIO2 | 內(nèi)部上拉,啟動(dòng)時(shí)需高電平 |
GPIO16 | 僅支持開(kāi)漏輸出 |
二、材料準(zhǔn)備
準(zhǔn)備這是四個(gè)材料就行了
ESP8266開(kāi)發(fā)板 | ESP8266-Node |
顯示屏-0.96寸 | 顯示屏-0.96寸 |
GPS模塊 | ATGM336H |
GPS是每一秒自動(dòng)進(jìn)行發(fā)送數(shù)據(jù),當(dāng)GPS狀態(tài)的閃爍,就說(shuō)明獲取到了衛(wèi)星定位了
超聲波模塊 | HC-SR04 |
三、代碼編寫(xiě)
這個(gè)的話,我主要調(diào)一個(gè)重要部分,最后會(huì)附上源碼,因?yàn)槲掖a里面帶了聯(lián)網(wǎng)部分,我這邊就先暫時(shí)把聯(lián)網(wǎng)部分屏蔽掉的
1 超聲測(cè)距部分
一個(gè)io設(shè)置為輸入,一個(gè)設(shè)置為輸出
// 檢測(cè)距離
void Distance_text(void) {
// 發(fā)送觸發(fā)信號(hào)
digitalWrite(trigPin, LOW); // 確保先拉低Trig引腳
delayMicroseconds(2); // 維持2微秒
digitalWrite(trigPin, HIGH); // 觸發(fā)脈沖
delayMicroseconds(10); // 維持10微秒
digitalWrite(trigPin, LOW); // 結(jié)束觸發(fā)
// 測(cè)量回波脈沖持續(xù)時(shí)間
distance = float(pulseIn(echoPin, HIGH) * 17) / 1000;
if ((int)distance < 50) {
} else {
}
// 顯示結(jié)果
// Serial.print("disc:");
// if (distance > 0) {
// Serial.print(distance);
// Serial.println(" cm");
// } else {
// Serial.println("out");
// }
}
2 GPS部分
使用模擬串口,進(jìn)行數(shù)據(jù)接收和解析。并且這里利用了顯示了時(shí)區(qū),我們的時(shí)區(qū)需要+8H,就是當(dāng)前時(shí)間,程序已經(jīng)完成這部分
void gpsParser() {
while (gpsSerial.available()) {
char Res = gpsSerial.read();
if (Res == '$') {
point1 = 0;
memset(USART_RX2_BUF, 0, sizeof(USART_RX2_BUF));
}
USART_RX2_BUF[point1++] = Res;
// 檢測(cè)GPRMC/GNRMC語(yǔ)句
if (point1 >= 6 && USART_RX2_BUF[3] == 'R' && USART_RX2_BUF[4] == 'M' && USART_RX2_BUF[5] == 'C') {
if (Res == 'n') {
memset(Save_Data.GPS_Buffer, 0, sizeof(Save_Data.GPS_Buffer));
memcpy(Save_Data.GPS_Buffer, USART_RX2_BUF, point1);
Save_Data.isGetData = true;
point1 = 0;
}
}
if (point1 >= sizeof(USART_RX2_BUF) - 1) {
point1 = 0;
}
}
}
void parseGpsBuffer() {
char* subString;
char* subStringNext;
char usefullBuffer[2] = { 0 };
int commaCount = 0;
subString = strtok(Save_Data.GPS_Buffer, ",");
while (subString != NULL) {
switch (commaCount) {
case 1: // UTC時(shí)間
strncpy(Save_Data.UTCTime, subString, sizeof(Save_Data.UTCTime));
break;
case 2: // 數(shù)據(jù)有效性
strncpy(usefullBuffer, subString, sizeof(usefullBuffer));
break;
case 3: // 緯度
strncpy(Save_Data.latitude, subString, sizeof(Save_Data.latitude));
break;
case 4: // N/S
strncpy(Save_Data.N_S, subString, sizeof(Save_Data.N_S));
break;
case 5: // 經(jīng)度
strncpy(Save_Data.longitude, subString, sizeof(Save_Data.longitude));
break;
case 6: // E/W
strncpy(Save_Data.E_W, subString, sizeof(Save_Data.E_W));
break;
}
subString = strtok(NULL, ",");
commaCount++;
}
Save_Data.isUsefull = (usefullBuffer[0] == 'A');
Save_Data.isParseData = true;
}
void printGpsBuffer() {
if (Save_Data.isUsefull) {
// 轉(zhuǎn)換經(jīng)度
longitude_sum = atof(Save_Data.longitude);
int longitude_int = (int)(longitude_sum / 100);
float longitude = longitude_int + (longitude_sum - longitude_int * 100) / 60;
// 轉(zhuǎn)換緯度
latitude_sum = atof(Save_Data.latitude);
int latitude_int = (int)(latitude_sum / 100);
float latitude = latitude_int + (latitude_sum - latitude_int * 100) / 60;
// 轉(zhuǎn)化為經(jīng)緯度
longitude_sum = longitude_int + ((longitude_sum / 100 - longitude_int) * 100) / 60;
latitude_sum = latitude_int + ((latitude_sum / 100 - latitude_int) * 100) / 60;
// 時(shí)間解析修正
String utcTime = Save_Data.UTCTime;
if (utcTime.length() >= 6) {
// 安全解析
hour = utcTime.substring(0, 2).toInt(); // 小時(shí)
minute = utcTime.substring(2, 4).toInt(); // 分鐘
second = utcTime.substring(4, 6).toInt(); // 秒
// 時(shí)區(qū)調(diào)整(UTC+8)
hour += 8;
// 處理溢出
if (hour >= 24) {
hour -= 24;
// 日期+1(需補(bǔ)充日期處理邏輯)
} else if (hour < 0) {
hour += 24;
// 日期-1
}
// 時(shí)間有效性驗(yàn)證
if (hour < 0 || hour >= 24 || minute < 0 || minute >= 60 || second < 0 || second >= 60) {
Serial.println("Invalid Time Data");
return;
}
格式化輸出
Serial.printf("Local Time: %02d:%02d:%02dn", hour, minute, second);
} else {
Serial.println("UTC Time Format Error");
}
Serial.print("Latitude: ");
Serial.print(latitude, 6);
Serial.print(" ");
Serial.println(Save_Data.N_S);
Serial.print("Longitude: ");
Serial.print(longitude, 6);
Serial.print(" ");
Serial.println(Save_Data.E_W);
Serial.println("---------------------");
} else {
Serial.println("GPS Data Invalid");
}
}
3 完整代碼
編譯芯片的選擇:ESPino(ESP-12)Module
#include <SoftwareSerial.h>
#include <PubSubClient.h>
#include <Ticker.h>
#include <ESP8266WiFi.h>
//OLED
#include <U8g2lib.h>
#include <Wire.h>
//JSON
#include <ArduinoJson.h>
// 設(shè)置wifi接入信息(請(qǐng)根據(jù)您的WiFi信息進(jìn)行修改)
const char* ssid = "NET";
const char* password = "12345678";
const char* mqttServer = "iot-06z00axdhgfk24n.mqtt.iothub.aliyuncs.com";
// 如以上MQTT服務(wù)器無(wú)法正常連接,請(qǐng)前往以下頁(yè)面尋找解決方案
// http://www.taichi-maker.com/public-mqtt-broker/
Ticker ticker;
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);
int count; // Ticker計(jì)數(shù)用變量
int count_2;
// ****************************************************
// 注意!以下需要用戶根據(jù)然也物聯(lián)平臺(tái)信息進(jìn)行修改!否則無(wú)法工作!
// ****************************************************
const char* mqttUserName = "smartdevice&h9sjy2rtcTI"; // 服務(wù)端連接用戶名(需要修改)
const char* mqttPassword = "5ba9463de09043190a8a743647518c46b1db6e1bfc2e0021198efe3384580772"; // 服務(wù)端連接密碼(需要修改)
const char* clientId = "h9sjy2rtcTI.smartdevice|securemode=2,signmethod=hmacsha256,timestamp=1739158837609|"; // 客戶端id (需要修改)
const char* subTopic = "/broadcast/h9sjy2rtcTI/test1"; // 訂閱主題(需要修改)
const char* pubTopic = "/broadcast/h9sjy2rtcTI/test2"; // 訂閱主題(需要修改)
const char* willTopic = "/broadcast/h9sjy2rtcTI/test2"; // 遺囑主題名稱(需要修改)
// ****************************************************
//遺囑相關(guān)信息
const char* willMsg = "esp8266 offline"; // 遺囑主題信息
const int willQos = 0; // 遺囑QoS
const int willRetain = false; // 遺囑保留
const int subQoS = 1; // 客戶端訂閱主題時(shí)使用的QoS級(jí)別(截止2020-10-07,僅支持QoS = 1,不支持QoS = 2)
const bool cleanSession = true; // 清除會(huì)話(如QoS>0必須要設(shè)為false)
// LED 配置
#define LED_BUILTIN 15
#define LED 2
bool ledStatus = HIGH;
int Waning = 0;
int Ledstate = 0;
// OLED
#define SCL 14
#define SDA 12
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, SCL, SDA, /*reset=*/U8X8_PIN_NONE);
char str[50]; //拼接字符使用
// 定義超聲波傳感器引腳
#define trigPin 5
#define echoPin 4
float distance;
// 配置軟串口(根據(jù)實(shí)際接線修改引腳)
SoftwareSerial gpsSerial(15, 13); // RX: D8, TX: D7
// GPS數(shù)據(jù)結(jié)構(gòu)
struct {
char GPS_Buffer[128];
char UTCTime[12];
char latitude[16];
char N_S[2];
char longitude[16];
char E_W[2];
bool isGetData = false;
bool isParseData = false;
bool isUsefull = false;
} Save_Data;
// 全局變量
char USART_RX2_BUF[256];
unsigned char point1 = 0;
float longitude_sum, latitude_sum;
int hour, minute, second;
void setup() {
Serial.begin(9600); // 啟動(dòng)串口通訊
gpsSerial.begin(9600); // GPS模塊常用波特率
gpsSerial.println("GPS Parser Started");
//OELD
u8g2.begin();
u8g2.setFont(u8g2_font_t0_16_tf); //設(shè)定字體 u8g2_font_ncenB08_tr
// //設(shè)置ESP8266工作模式為無(wú)線終端模式
// WiFi.mode(WIFI_STA);
// // 連接WiFi
// connectWifi();
// // 設(shè)置MQTT服務(wù)器和端口號(hào)
// mqttClient.setServer(mqttServer, 1883);
// mqttClient.setCallback(receiveCallback);
// // 連接MQTT服務(wù)器
// connectMQTTserver();
// Ticker定時(shí)對(duì)象
ticker.attach(1, tickerCount);
// LED和蜂鳴器
pinMode(LED_BUILTIN, OUTPUT); // 設(shè)置板上LED引腳為輸出模式
pinMode(LED, OUTPUT); // 設(shè)置板上LED引腳為輸出模式
digitalWrite(LED, ledStatus); // 啟動(dòng)后關(guān)閉板上LED
digitalWrite(LED_BUILTIN, ledStatus); // 啟動(dòng)后關(guān)閉板上LED
pinMode(trigPin, OUTPUT); // 設(shè)置Trig引腳為輸出模式
pinMode(echoPin, INPUT); // 設(shè)置Echo引腳為輸入模式
}
void loop() {
// // 如果開(kāi)發(fā)板未能成功連接服務(wù)器,則嘗試連接服務(wù)器
// if (!mqttClient.connected()) {
// connectMQTTserver();
// } else {
//1秒更新一次
if (count_2 >= 1) {
Distance_text(); // 測(cè)量距離
u8g2.clearBuffer();
// 解析 GPS
if (Save_Data.isGetData) {
parseGpsBuffer();
Save_Data.isGetData = false;
}
if (Save_Data.isParseData) {
printGpsBuffer();
Save_Data.isParseData = false;
}
// LED
if (Ledstate) {
digitalWrite(LED_BUILTIN, HIGH); // 啟動(dòng)
} else {
digitalWrite(LED_BUILTIN, LOW);
gpsSerial.println("歡迎使用");
Serial.print("歡迎使用");
}
if (ledStatus == LOW) {
ledStatus = HIGH;
digitalWrite(LED, ledStatus);
} else {
ledStatus = LOW;
digitalWrite(LED, ledStatus);
}
if ((int)longitude_sum > 1) {
sprintf(str, "Log: %.6f", longitude_sum);
u8g2.drawStr(0, 16, str);
sprintf(str, "Lat: %.6f", latitude_sum);
u8g2.drawStr(0, 32, str);
sprintf(str, "Time: %02d:%02d:%02d", hour, minute, second);
u8g2.drawStr(0, 48, str);
} else {
sprintf(str, "Log: error", longitude_sum);
u8g2.drawStr(0, 16, str);
sprintf(str, "Lat: error", latitude_sum);
u8g2.drawStr(0, 32, str);
sprintf(str, "Time:error", hour, minute, second);
u8g2.drawStr(0, 48, str);
}
sprintf(str, "Disc: %.2f CM", distance);
u8g2.drawStr(0, 64, str);
u8g2.sendBuffer(); //顯示
count_2 = 0;
}
//4秒發(fā)送一次
if (count >= 4) {
// 每隔4秒鐘發(fā)布一次信息
// pubMQTTmsg();
count = 0;
}
}
gpsParser();
// 處理信息以及心跳
mqttClient.loop();
}
// 連接WiFi
void connectWiFi() {
WiFi.begin(ssid, password);
//Serial.print("Connecting");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
// Serial.println("nConnected! IP: " + WiFi.localIP().toString());
}
//計(jì)時(shí)器
void tickerCount() {
count++;
count_2++;
}
// 連接MQTT服務(wù)器并訂閱信息
void connectMQTTserver() {
// 根據(jù)ESP8266的MAC地址生成客戶端ID(避免與其它ESP8266的客戶端ID重名)
/* 連接MQTT服務(wù)器
boolean connect(const char* id, const char* user,
const char* pass, const char* willTopic,
uint8_t willQos, boolean willRetain,
const char* willMessage, boolean cleanSession);
若讓設(shè)備在離線時(shí)仍然能夠讓qos1工作,則connect時(shí)的cleanSession需要設(shè)置為false
*/
if (mqttClient.connect(clientId, mqttUserName,
mqttPassword, willTopic,
willQos, willRetain, willMsg, cleanSession)) {
// Serial.print("MQTT Server Connected. ClientId: ");
// Serial.println(clientId);
// Serial.print("MQTT Server: ");
// Serial.println(mqttServer);
subscribeTopic(); // 訂閱指定主題
} else {
// Serial.print("MQTT Server Connect Failed. Client State:");
// Serial.println(mqttClient.state());
delay(5000);
}
}
// 收到信息后的回調(diào)函數(shù)
void receiveCallback(char* topic, byte* payload, unsigned int length) {
// Serial.print("Message Received [");
// Serial.print(topic);
// Serial.print("] ");
// for (int i = 0; i < length; i++) {
// Serial.print((char)payload[i]);
// }
//解析數(shù)據(jù)
massage_parse_json((char*)payload);
//回傳數(shù)據(jù)
// pubMQTTmsg();
}
// 訂閱指定主題
void subscribeTopic() {
// 通過(guò)串口監(jiān)視器輸出是否成功訂閱主題以及訂閱的主題名稱
// 請(qǐng)注意subscribe函數(shù)第二個(gè)參數(shù)數(shù)字為QoS級(jí)別。這里為QoS = 1
if (mqttClient.subscribe(subTopic, subQoS)) {
//Serial.println(subTopic);
} else {
//Serial.print("Subscribe Fail...");
connectMQTTserver(); // 則嘗試連接服務(wù)器
}
}
// 發(fā)布信息
void pubMQTTmsg() {
char pubMessage[254];
// 數(shù)據(jù)流
MQTT_FillBuf(pubMessage);
// 實(shí)現(xiàn)ESP8266向主題發(fā)布信息
if (mqttClient.publish(pubTopic, pubMessage)) {
//Serial.println("Publish Topic:");Serial.println(pubTopic);
//Serial.println("Publish message:");
//Serial.println(pubMessage);
} else {
subscribeTopic(); // 則嘗試連接服務(wù)器
//Serial.println("Message Publish Failed.");
}
}
// ESP8266連接wifi
void connectWifi() {
u8g2.clearDisplay(); // 清屏
sprintf(str, "Wait ... ");
u8g2.drawStr(0, 32, str);
u8g2.sendBuffer(); //顯示
WiFi.begin(ssid, password);
//等待WiFi連接,成功連接后輸出成功信息
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
// Serial.print(".");
}
//Serial.println("WiFi Connected!");
}
// 數(shù)據(jù)封裝
unsigned char MQTT_FillBuf(char* buf) {
char text[256];
memset(text, 0, sizeof(text));
strcpy(buf, "{");
if ((int)latitude_sum > 1) {
memset(text, 0, sizeof(text));
sprintf(text, ""lat":"%.6f",", latitude_sum); // Temp是數(shù)據(jù)流的一個(gè)名稱,temper是溫度值
strcat(buf, text);
memset(text, 0, sizeof(text));
sprintf(text, ""log":"%.6f",", longitude_sum); // Temp是數(shù)據(jù)流的一個(gè)名稱,temper是溫度值
strcat(buf, text);
}
memset(text, 0, sizeof(text));
sprintf(text, ""disc":"%d",", (int)distance); // Temp是數(shù)據(jù)流的一個(gè)名稱,temper是溫度值
strcat(buf, text);
memset(text, 0, sizeof(text));
sprintf(text, ""waring":"%d",", Waning); // Temp是數(shù)據(jù)流的一個(gè)名稱,temper是溫度值
strcat(buf, text);
memset(text, 0, sizeof(text));
sprintf(text, ""led":"%d"", digitalRead(LED_BUILTIN)); // Temp是數(shù)據(jù)流的一個(gè)名稱,temper是溫度值
strcat(buf, text);
memset(text, 0, sizeof(text));
sprintf(text, "}");
strcat(buf, text);
return strlen(buf);
}
// 解析json數(shù)據(jù)
void massage_parse_json(char* message) {
// 聲明一個(gè) JSON 文檔對(duì)象
StaticJsonDocument<200> doc;
// 解析 JSON 數(shù)據(jù)
DeserializationError error = deserializeJson(doc, (const char*)message);
// 檢查解析是否成功
if (error) {
// Serial.print("Failed to parse JSON: ");
// Serial.println(error.c_str());
return;
}
// 從解析后的 JSON 文檔中獲取鍵值對(duì)
int cmd = doc["cmd"];
JsonObject data = doc["data"];
switch (cmd) {
case 1:
Ledstate = data["led"];
count = 1;
break;
case 2:
if((int)latitude_sum > 1){
sprintf(str, "當(dāng)前時(shí)間:%02d:%02d:%02d", hour, minute, second);
gpsSerial.println(str);
}else{
sprintf(str, "請(qǐng)先到開(kāi)闊地帶進(jìn)行定位定位", hour, minute, second);
gpsSerial.println(str);
}
count = 1;
break;
case 3:
count = 1;
break;
}
}
// 檢測(cè)距離
void Distance_text(void) {
// 發(fā)送觸發(fā)信號(hào)
digitalWrite(trigPin, LOW); // 確保先拉低Trig引腳
delayMicroseconds(2); // 維持2微秒
digitalWrite(trigPin, HIGH); // 觸發(fā)脈沖
delayMicroseconds(10); // 維持10微秒
digitalWrite(trigPin, LOW); // 結(jié)束觸發(fā)
// 測(cè)量回波脈沖持續(xù)時(shí)間
distance = float(pulseIn(echoPin, HIGH) * 17) / 1000;
if ((int)distance < 50) {
} else {
}
// 顯示結(jié)果
// Serial.print("disc:");
// if (distance > 0) {
// Serial.print(distance);
// Serial.println(" cm");
// } else {
// Serial.println("out");
// }
}
void gpsParser() {
while (gpsSerial.available()) {
char Res = gpsSerial.read();
if (Res == '$') {
point1 = 0;
memset(USART_RX2_BUF, 0, sizeof(USART_RX2_BUF));
}
USART_RX2_BUF[point1++] = Res;
// 檢測(cè)GPRMC/GNRMC語(yǔ)句
if (point1 >= 6 && USART_RX2_BUF[3] == 'R' && USART_RX2_BUF[4] == 'M' && USART_RX2_BUF[5] == 'C') {
if (Res == 'n') {
memset(Save_Data.GPS_Buffer, 0, sizeof(Save_Data.GPS_Buffer));
memcpy(Save_Data.GPS_Buffer, USART_RX2_BUF, point1);
Save_Data.isGetData = true;
point1 = 0;
}
}
if (point1 >= sizeof(USART_RX2_BUF) - 1) {
point1 = 0;
}
}
}
void parseGpsBuffer() {
char* subString;
char* subStringNext;
char usefullBuffer[2] = { 0 };
int commaCount = 0;
subString = strtok(Save_Data.GPS_Buffer, ",");
while (subString != NULL) {
switch (commaCount) {
case 1: // UTC時(shí)間
strncpy(Save_Data.UTCTime, subString, sizeof(Save_Data.UTCTime));
break;
case 2: // 數(shù)據(jù)有效性
strncpy(usefullBuffer, subString, sizeof(usefullBuffer));
break;
case 3: // 緯度
strncpy(Save_Data.latitude, subString, sizeof(Save_Data.latitude));
break;
case 4: // N/S
strncpy(Save_Data.N_S, subString, sizeof(Save_Data.N_S));
break;
case 5: // 經(jīng)度
strncpy(Save_Data.longitude, subString, sizeof(Save_Data.longitude));
break;
case 6: // E/W
strncpy(Save_Data.E_W, subString, sizeof(Save_Data.E_W));
break;
}
subString = strtok(NULL, ",");
commaCount++;
}
Save_Data.isUsefull = (usefullBuffer[0] == 'A');
Save_Data.isParseData = true;
}
void printGpsBuffer() {
if (Save_Data.isUsefull) {
// 轉(zhuǎn)換經(jīng)度
longitude_sum = atof(Save_Data.longitude);
int longitude_int = (int)(longitude_sum / 100);
float longitude = longitude_int + (longitude_sum - longitude_int * 100) / 60;
// 轉(zhuǎn)換緯度
latitude_sum = atof(Save_Data.latitude);
int latitude_int = (int)(latitude_sum / 100);
float latitude = latitude_int + (latitude_sum - latitude_int * 100) / 60;
// 轉(zhuǎn)化為經(jīng)緯度
longitude_sum = longitude_int + ((longitude_sum / 100 - longitude_int) * 100) / 60;
latitude_sum = latitude_int + ((latitude_sum / 100 - latitude_int) * 100) / 60;
// 時(shí)間解析修正
String utcTime = Save_Data.UTCTime;
if (utcTime.length() >= 6) {
// 安全解析
hour = utcTime.substring(0, 2).toInt(); // 小時(shí)
minute = utcTime.substring(2, 4).toInt(); // 分鐘
second = utcTime.substring(4, 6).toInt(); // 秒
// 時(shí)區(qū)調(diào)整(UTC+8)
hour += 8;
// 處理溢出
if (hour >= 24) {
hour -= 24;
// 日期+1(需補(bǔ)充日期處理邏輯)
} else if (hour < 0) {
hour += 24;
// 日期-1
}
// 時(shí)間有效性驗(yàn)證
if (hour < 0 || hour >= 24 || minute < 0 || minute >= 60 || second < 0 || second >= 60) {
Serial.println("Invalid Time Data");
return;
}
格式化輸出
Serial.printf("Local Time: %02d:%02d:%02dn", hour, minute, second);
} else {
Serial.println("UTC Time Format Error");
}
Serial.print("Latitude: ");
Serial.print(latitude, 6);
Serial.print(" ");
Serial.println(Save_Data.N_S);
Serial.print("Longitude: ");
Serial.print(longitude, 6);
Serial.print(" ");
Serial.println(Save_Data.E_W);
Serial.println("---------------------");
} else {
Serial.println("GPS Data Invalid");
}
}
編譯完成后圖片
四、實(shí)現(xiàn)效果
開(kāi)啟串口會(huì)輸出
五、 參考
Arduino IDE 使用安裝以及ESP32庫(kù)的導(dǎo)入(離線)https://blog.csdn.net/herui_2/article/details/135296814?spm=1001.2014.3001.5501
ESP32/ESP8622 -- 使用MQTT協(xié)議連接云平臺(tái)(帶圖文說(shuō)明)https://herui.blog.csdn.net/article/details/135317019?spm=1001.2014.3001.5502
聯(lián)系方式 微信號(hào):13648103287