FastBond3挑战部分+ 基于GPS模块实现的自行车码表
当前项目是使用ESP32-C6 dev kit + 安信可 GP02 GPS模块实现的GPS码表, 具体实现的功能有: 可以通过屏幕查看当前的经纬度信息,RTC时间, 海拔, 和运动速度等。 PCB使用立创EDA设计。
标签
FastBond3
自行车码表
Wang Chong
更新2024-10-24
31

简介

由于前一段时间参加DIY活动获得了几个GP02的模块, 于是这次FastBond3活动便用了起来。当前项目是使用ESP32-C6 dev kit + 安信可 GP02 GPS模块实现的GPS码表, 具体实现的功能有: 可以通过屏幕查看当前的经纬度信息,RTC时间, 海拔, 和运动速度等。 PCB使用立创EDA设计。 GPS模块是采用的串口通讯, 因此只需要保证当前模块的最小电路工作正常即可完成单片机(ESP32-C6)和 GP02模块的通信(TX 和 RX 反接)。并且驱动ST7735 128*160 屏幕。



实物验证 (三版PCB)

紫色的为第一版, 绿色的为第二版, 黑色的为第三版(可用),但是天线连接超级差.

eab810241e99ca083652007fb974b2d.jpg


踩坑记录 一


我第一次打板的时候, 是紫色的PCB,但是由于屏幕的接口我错误的使用了2.0MM间距的排母,因此导致了排针没办法焊接上去,所以我便进行了再次打板, 也就是绿色的。


踩坑记录 二


但是绿色的PCB我发现了一个问题就是ESP32-C6 官方说明板子的右上角也就是下图红色框处。3V3 可以作为VI-IN, 但是实际上在我验证的时候,发现右边GPS供电处明显电压不稳定。 板子并不能正常工作, 如果使用5V5供电则为正常。


image.png


image.png


下图为5V5 供电的VIN


image.png


因此,我使用了多种的办法来排除电压不稳定带来的错误,最初使用的AMS1117。 报废了一个GPS和 AHT10。


调试


下图为,使用刀片划断PCB供电来排查是否由供电异常导致的。因为并不清楚到底时哪里供电导致的电压不稳定,因此我只能使用刀片切割每一个供电的输入电路并且使用USB进行供电进行调试。可惜的是,我在这次调试的时候并没有发现是因为GPS的输出导致了使用串口下载程序时的噪音。并且在拆卸模组的时候直接把它拆散架了。


5c34b96e7983c99057a769ac99ce74b.jpg


在确定电压是因为3.3 VI-IN 导致的后, 就有了现在的最终版本(但是还存在问题, 太难搜到卫星了. 已经解决是因为卫星接线天线连接的问题)



正面


08b0d36de6b91e31c3f2c1b99fee0c7.jpg


背面


da1db55373c89bbe50f806215e8a6ef.jpg


连接好天线和屏幕的码表,由于天线连接不牢固导致开路或者短路状态,导致的无法搜到卫星.


883477f9ff60a65a1962eb8cc02c350.jpg



原理图


image.png


这边的电源电路采用了SE8850它可以接受最大40V的电压输入, 输出5V 250ma的电流。 但是实际上,不建议使用太高的电压输入, 以免造成电路损坏。GPS 和 湿温度传感器的电路均为官方推荐的设计电路。


PCB


image.png


image.png


代码


#include <Adafruit_GFX.h>       // 图形库
#include <Adafruit_ST7735.h>    // ST7735 驱动库
#include <SPI.h>                // SPI 库


// 定义屏幕引脚
#define TFT_CS     5    // 片选引脚
#define TFT_RST    4    // 复位引脚
#define TFT_DC     2    // 数据/命令选择引脚
#define TFT_SCLK   18   // SPI 时钟引脚
#define TFT_MOSI   23   // SPI 数据引脚


// 创建 TFT 对象,指定屏幕引脚
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);


// 函数: 解析NMEA格式的$GPRMC语句并获取经纬度
void parseGPSData(String nmea) {
  if (nmea.startsWith("$GPRMC")) { // 判断是否是GPRMC语句
    int index = 0;
    String values[12]; // 存储解析出的各个字段


    // 解析语句的各个字段
    for (int i = 0; i < nmea.length(); i++) {
      if (nmea[i] == ',' || nmea[i] == '*') { // 字段分隔符为','或'*'
        values[index] = nmea.substring(i + 1);
        index++;
      }
    }


    // 提取各个字段的数据
    String utcTime = values[0];            // UTC时间
    String status = values[1];             // 状态(A=有效, V=无效)
    String latitude = values[2];           // 纬度
    String latDirection = values[3];       // 纬度方向(N/S)
    String longitude = values[4];          // 经度
    String lonDirection = values[5];       // 经度方向(E/W)
    String speed = values[6];              // 速度
    String date = values[8];               // 日期


    // 只有在数据有效时才进行显示
    if (status == "A") {
      float lat = convertToDecimal(latitude, latDirection);
      float lon = convertToDecimal(longitude, lonDirection);


      // 显示到屏幕
      tft.fillScreen(ST77XX_BLACK);
      tft.setCursor(0, 0);
      tft.setTextColor(ST77XX_WHITE);
      tft.setTextSize(1);
     
      tft.print("Lat: ");
      tft.println(lat, 6);
      tft.print("Lon: ");
      tft.println(lon, 6);
      tft.print("Speed: ");
      tft.println(speed);


      Serial.print("Lat: ");
      Serial.println(lat, 6);
      Serial.print("Lon: ");
      Serial.println(lon, 6);
      Serial.print("Speed: ");
      Serial.println(speed);
    } else {
      // 如果状态为无效,显示“没有找到卫星”
     
      Serial.println("GPS data invalid");
    }
  }
}


// 将ddmm.mmmm格式转换为十进制格式
float convertToDecimal(String coord, String direction) {
  float decimalValue;
  float degrees = coord.substring(0, 2).toFloat(); // 前两位为度
  float minutes = coord.substring(2).toFloat();    // 后面的为分


  // 转换为十进制格式
  decimalValue = degrees + (minutes / 60.0);


  // 如果方向是南纬或西经,则取负
  if (direction == "S" || direction == "W") {
    decimalValue = -decimalValue;
  }


  return decimalValue;
}


void setup() {
  Serial.begin(9600);    // 初始化串口,用于调试
  Serial.println("TFT screen test");


  // 初始化 SPI 并设置屏幕
  SPI.begin(TFT_SCLK, -1, TFT_MOSI, TFT_CS);    // 初始化 SPI 引脚


  // 初始化屏幕
  tft.initR(INITR_BLACKTAB);    // 初始化为黑色标签模式
  tft.fillScreen(ST77XX_RED);   // 将屏幕清空为红色背景


  // 设置屏幕字体颜色和大小
  tft.setTextColor(ST77XX_WHITE);
  tft.setTextSize(1);



     tft.fillScreen(ST77XX_BLACK); // 清空屏幕为黑色背景
      tft.setCursor(0, 0);
      tft.setTextColor(ST77XX_WHITE);
      tft.setTextSize(2); // 可以调整文本大小
      tft.println("No satellites found");
 
  Serial.println("Screen initialized");
}


void loop() {
  // 检查串口上是否有可用数据
  if (Serial.available()) {
    // 读取直到换行符 ('\n') 的 ASCII 字符串
    String receivedString = Serial.readStringUntil('\n');
    Serial.println(receivedString);


    // 解析GPS数据
    parseGPSData(receivedString);
  }
}


在上述代码的主要逻辑即为解析GPS卫星的串口数据并且显示在屏幕上,但是目前的搜星很难搜索到卫星。(我暂时也不知道原因, 我猜测可能是因为天线的问题, 下次如果再进行迭代的话应该换一个连接更紧的端子来连接天线。)


下图为搜索不到卫星的界面


image.png


总结


目前程序方面都是正常的, 不建议复刻 (已经修复了, 可以复刻, 原理图可以通用, PCB可以自己设计成你想要的 10-22-2024更新),因为不知道是因为设计问题还是什么问题, 在我测试的这么多次仅仅搜索到了一次卫星数据。 而且信号较弱没有没选中,且仅仅返回了RTC时间。 可以再下一次迭代的时候直接买GPS的开发板然后接上去,这样的话可以保证GPS可用,而且可以降低(我焊接水平的)调试成本。


在这次DIY的项目中,我体会到了实际硬件工程师设计开发板时迭代的辛苦,下次再设计电路的时候一定要多多验证然后再转为PCB的打板(之前测试的时候可以搜到星, 打成PCB就搜不到了)。


还有一点需要注意的是, 当前的程序烧录的话不可以将开发板接到底座上,否则GPS模块的串口输出会影响程序烧录时的写入。


更新日志

2024 -10 - 21 23:25

问题解决了! 折腾了一天, 搜不到星的原因是因为这个天线的连接问题(要么开路, 要么短路, 就是不OK), 这个IPEX的天线接口是真的不行,强烈建议大家不要用这个接口,超级容易松动。谁用谁知道这个能有多坑!(这个垃圾天线完成了它的使命, 帮助我找出为什么搜不到GPS的错误)


1565580a650f1bb5bb2112e26db8a75.jpg


更新后的原理图

image.png


更新后的PCB


image.png


image.png



总结

通过参加这次的Fastbond第三季活动,我学会了多个元器件的使用和设计, 尤其是GPS模块的设计更使我印象深刻. 在实际设计中也应该考虑是否能够在日常环境中使用,尤其是在运动场景中,上下颠簸很容易造成天线的连接松动, 所以物料的选型一定要做好.

附件下载
BOM_Board1_Schematic1_2024-10-23.xlsx
TFT_screen.ino
ProPrj_自行车码表_2024-10-23.zip
团队介绍
个人
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号