Bootstrap

使用esp8266+gps模块+oled屏幕diy一块gps定位器

1.材料准备

1.ESP8266开发板,某宝可以直接购买nodemcu.(ch340和cp2102都可.我这里用的是ch340驱动的)
nodemcu正面
nodemcu背面

2.GPS模块(NMEA协议的)
大夏龙雀GPS模块
在这里插入图片描述

3.0.96寸的OLED屏幕(4针 I²C协议的)
在这里插入图片描述
在这里插入图片描述
4.杜邦线母对母若干

2.接线说明

OLED屏幕需要连接 GND VCC SCL SDA四个引脚 具体对应关系 如下

NODEMCU开发板OLED屏幕备注
GGNDnodemcu中有多个地线引脚.选择一个即可
3VVCCnodemcu中有多个3v供电引脚.选择一个即可
D1(GPIO 5)SCLSCL代表"Serial Clock Line",即串行时钟线
D2(GPIO 4)SDASDA代表"Serial Data Line",即串行数据线

GPS模块需要连接 RXD TXD GND VDD 四个引脚 具体对应关系 如下

NODEMCU开发板GPS模块备注
D5(GPIO 14)RXDgps的RX接模拟串口的TX引脚定义
D6(GPIO 12)TXDgps的TX接模拟串口的RX引脚定义
GGNDnodemcu中有多个地线引脚.选择一个即可
3VVDDnodemcu中有多个3v供电引脚.选择一个即可

3.接线图

在这里插入图片描述

4.烧录程序

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

5.上电效果

在这里插入图片描述
因为是在室内,gps搜不到星.所以没数据.搜星成功会自动获取到时间和经纬度信息.需要注意的是这里的经纬度是WGS84坐标系.无法直接使用.如需使用则需要做相应的转换.具体可以看我的另一篇文章 java实现GPS(WGS-84)坐标系-火星(GCJ-02)坐标系-百度(BD-09)坐标系转换

6.完整代码

贴上完整代码

#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;
}

;