问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

使用ESP8266+GPS模块+OLED屏幕DIY一块GPS定位器

创作时间:
作者:
@小白创作中心

使用ESP8266+GPS模块+OLED屏幕DIY一块GPS定位器

引用
CSDN
1.
https://blog.csdn.net/a654540233/article/details/142500249

本文将介绍如何使用ESP8266开发板、GPS模块和OLED屏幕制作一个GPS定位器。通过本教程,读者可以学习到硬件连接、程序编写以及数据处理等实用技能。

1. 材料准备

  1. ESP8266开发板(建议购买带有CH340或CP2102驱动的NodeMCU)

  2. GPS模块(支持NMEA协议)

  3. 0.96寸OLED屏幕(支持I²C协议)

  4. 若干杜邦线(母对母)

2. 接线说明

OLED屏幕接线

NODEMCU开发板
OLED屏幕
备注
G
GND
NodeMCU中有多个地线引脚,选择一个即可
3V
VCC
NodeMCU中有多个3V供电引脚,选择一个即可
D1 (GPIO 5)
SCL
SCL代表"Serial Clock Line",即串行时钟线
D2 (GPIO 4)
SDA
SDA代表"Serial Data Line",即串行数据线

GPS模块接线

NODEMCU开发板
GPS模块
备注
D5 (GPIO 14)
RXD
GPS的RX接模拟串口的TX引脚定义
D6 (GPIO 12)
TXD
GPS的TX接模拟串口的RX引脚定义
G
GND
NodeMCU中有多个地线引脚,选择一个即可
3V
VDD
NodeMCU中有多个3V供电引脚,选择一个即可

3. 烧录程序

打开Arduino IDE,选择开发板为NodeMCU 1.0 (ESP-12E Module)。使用以下代码,直接上传即可。如果本地没有相关库,需要手动安装TinyGPSPlus、Adafruit_GFX和Adafruit_SSD1306这三个库。

4. 上电效果

由于是在室内环境,GPS可能无法搜到卫星信号,因此可能没有数据输出。当GPS成功搜星后,会自动获取时间和经纬度信息。需要注意的是,这里的经纬度是WGS84坐标系,无法直接使用。如需转换为其他坐标系(如火星坐标系或百度坐标系),可以参考相关转换方法。

5. 完整代码

#include <TinyGPSPlus.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <SoftwareSerial.h>
#include "ESP8266WiFi.h"

// I2C款接线说明
// NodeMCU开发板	 0.96寸OLED 引脚连接对应关系
// GND	          GND
// 3V3	          VCC
// SCL	          D1 (GPIO 5)
// SDA	          D2 (GPIO 4)

#define SCREEN_WIDTH 128                                                   // OLED display width, in pixels
#define SCREEN_HEIGHT 64                                                   // OLED display height, in pixels
#define OLED_RESET 13                                                      // 重置引脚
#define SCREEN_ADDRESS 0x3C                                                // OLED 显示屏的地址,固化在芯片上
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);  // 创建实例

// gps模块引脚定义
#define RXPin 12  // GPIO 12 对应nodemcu D6
#define TXPin 14  // GPIO 14 对应nodemcu D5

// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);

// The TinyGPSPlus object
TinyGPSPlus gps;

// 一些需要使用的变量
int Year, Month, Date, Hour, Minute, Second, Yea, Mon, Dat, Hou;
double Lat, Lng;
String sMonth, sDate, sHour, sMinute, sSecond;

void setup() {
  Serial.begin(9600);
  WiFi.mode(WIFI_OFF);  //关闭WIFI模块省电
  WiFi.forceSleepBegin();
  ss.begin(9600);  //GPS模块虚拟串口

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ;  // Don't proceed, loop forever
  }
  display.clearDisplay();       // 清屏
  display.setTextColor(WHITE);  // 设置字体颜色为白色
  display.display();            // 显示
  //OLED屏初始化代码
}

void loop() {
  boolean newData = false;
  for (unsigned long start = millis(); millis() - start < 300;) {
    while (ss.available()) {
      if (gps.encode(ss.read())) {
        newData = true;
      }
    }
  }  //上面是GPS数据接收的固定代码,不能删除

  Yea = gps.date.year();       //年
  Mon = gps.date.month();      //月
  Dat = gps.date.day();        //日
  Hou = gps.time.hour();       //时
  Minute = gps.time.minute();  //分
  Second = gps.time.second();  //秒
  Lng = gps.location.lng();    //经度
  Lat = gps.location.lat();    //纬度

  // 创建一个字符串来存储所有变量
  // String origin = String(Yea) + "-" + String(Mon) + "-" + String(Dat) + " " + String(Hou) + ":" + String(Minute) + ":" + String(Second)  + " (" + String(Lng, 8) + "," + String(Lat, 8) + ")";
  // 输出整个字符串
  // Serial.println(origin);

  //年月日时转换部分,将UTC时间转换为北京时间,并消除错误
  Hour = Hou + 8;  //修正时区
  if (Hour >= 24) {
    Hour = Hour - 24;  //修正小时超程
  }
  if (Hou + 8 >= 24) {
    Date = Dat + 1;
    if ((Mon == 1 || Mon == 3 || Mon == 5 || Mon == 7 || Mon == 8 || Mon == 10 || Mon == 12) && (Date > 31)) {
      Date = Date - 30;
      Month = Mon + 1;  //大月进位
    } else {
      Month = Mon;
      Year = Yea;
    }
    if ((Mon == 4 || Mon == 6 || Mon == 9 || Mon == 11) && (Date > 30)) {
      Date = Date - 29;
      Month = Mon + 1;  //小月进位
    } else {
      Month = Mon;
      Year = Yea;
    }
    if ((Yea % 4 == 0) && (Date > 29)) {
      Date = Date - 28;
      Month = Mon + 1;  //闰月判定并进位
    } else {
      Month = Mon;
      Year = Yea;
    }
    if ((Yea % 4 != 0) && (Date > 28)) {
      Date = Date - 27;
      Month = Mon + 1;  //非闰月判定并进位
    } else {
      Month = Mon;
      Year = Yea;
    }
    if (Month > 12) {
      Month = Month - 12;
      Year = Yea + 1;  //年超程进位
    }
  } else {
    Date = Dat;
    Month = Mon;
    Year = Yea;
  }

  //结果显示部分
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(38, 0);
  display.setTextSize(1);
  display.print(Year);
  display.setCursor(63, 0);
  display.setTextSize(1);
  display.print("-");
  display.setTextSize(1);
  display.setCursor(71, 0);
  sMonth = formatNumber(Month, 2);
  display.print(sMonth);
  display.setCursor(83, 0);
  display.setTextSize(1);
  display.print("-");
  display.setTextSize(1);
  display.setCursor(91, 0);
  sDate = formatNumber(Date, 2);
  display.print(sDate);
  display.setTextSize(2);
  display.setCursor(26, 13);
  sHour = formatNumber(Hour, 2);
  display.print(sHour);
  display.setCursor(46, 13);
  display.setTextSize(2);
  display.print(":");
  display.setTextSize(2);
  display.setCursor(56, 13);
  sMinute = formatNumber(Minute, 2);
  display.print(sMinute);
  display.setCursor(76, 13);
  display.setTextSize(2);
  display.print(":");
  display.setTextSize(2);
  display.setCursor(86, 13);
  sSecond = formatNumber(Second, 2);
  display.print(sSecond);
  display.setTextSize(1);
  display.setCursor(35, 33);
  display.print(gps.location.lng(), 8);
  display.setTextSize(1);
  display.setCursor(35, 43);
  display.print(gps.location.lat(), 8);
  // 创建一个字符串来存储所有变量
  // String message = String(Year) + "-" + String(sMonth) + "-" + String(sDate) + " "+ String(sHour) + ":" + String(sMinute) + ":" + String(sSecond) + " (" + String(Lng, 8) + "," + String(Lat, 8) + ")";
  // 输出整个字符串
  // Serial.println(message);
  display.setCursor(105, 53);
  display.setTextSize(1);
  display.print("m");
  display.setCursor(50, 53);
  display.setTextSize(1);
  display.print("km/h");
  display.setTextSize(1);
  display.setCursor(80, 53);
  display.print(gps.speed.mps());
  display.setTextSize(1);
  display.setCursor(25, 53);
  display.print(gps.speed.kmph());
  display.display();
  delay(500);
  display.clearDisplay();
}

// 格式化数字的函数
String formatNumber(int number, int digits) {
  String formatted = "";
  if (number < pow(10, digits - 1)) {
    formatted = String(number, DEC);
    while (formatted.length() < digits) {
      formatted = "0" + formatted;
    }
  } else {
    formatted = String(number, DEC);
  }
  return formatted;
}
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号