基于 Arduino 的户外 LoRa-GPS 跟踪器(原理图+PCB+代码)


原标题:基于 Arduino 的户外 LoRa-GPS 跟踪器(原理图+PCB+代码)
基于Arduino的户外LoRa-GPS跟踪器:从原理到实践的深度解析
在当今物联网(IoT)蓬勃发展的时代,远程数据传输和位置跟踪技术变得越来越重要。无论是资产追踪、野外探险、环境监测还是宠物定位,一个可靠、低功耗、长距离的跟踪解决方案都具有巨大的应用潜力。本文将深入探讨如何设计和构建一个基于 Arduino 的户外 LoRa-GPS 跟踪器,详细阐述其核心元器件的选择、功能、原理图设计考量、PCB 布局优化以及固件编程细节,旨在为您提供一个从理论到实践的全面指南。
项目概述与核心技术
户外 LoRa-GPS 跟踪器旨在实现设备在广阔区域内的位置信息采集与远距离传输。其核心在于结合了全球定位系统(GPS)模块用于精确获取地理坐标,以及 LoRa(Long Range)无线技术用于低功耗、长距离的数据通信。Arduino 平台作为其主控制器,以其易用性、丰富的库支持和活跃的社区,成为快速原型开发和实际部署的理想选择。该跟踪器将能够周期性地获取当前位置,并通过 LoRa 网络发送至接收端(如 LoRaWAN 网关或另一个 LoRa 节点),从而实现远程监控。
核心元器件选择与深度解析
构建一个稳定可靠的 LoRa-GPS 跟踪器,关键在于选择合适的元器件。以下将详细介绍各项核心元器件的选择理由、功能及其在系统中的作用。
1. 微控制器单元 (MCU) - Arduino 兼容开发板
推荐型号: ESP32-WROOM-32 开发板(集成ESP32芯片)
选择理由: 虽然用户提及基于 Arduino,但考虑到户外跟踪器对低功耗、无线连接(LoRa和可能的Wi-Fi/蓝牙用于配置)、处理能力和内存的需求,ESP32 芯片集成的开发板是比传统 Arduino Uno 或 Mega 更优的选择。ESP32 是一款功能强大的双核 32 位微控制器,内置 Wi-Fi 和蓝牙,拥有丰富的 GPIO 端口、ADC、DAC、SPI、I2C、UART 等接口,并且支持 FreeRTOS 实时操作系统,能够轻松处理 GPS 数据解析和 LoRa 模块通信等并发任务。其低功耗模式(如深度睡眠)对于延长电池寿命至关重要。虽然它不是传统的 Arduino 板,但其开发环境与 Arduino IDE 完全兼容,可以使用 Arduino 框架进行编程,满足了“基于 Arduino”的精神。
功能与作用:
数据处理核心: 作为整个跟踪器的大脑,负责协调所有外设的工作。
GPS 数据解析: 通过 UART 接口与 GPS 模块通信,解析 NMEA 协议数据,提取经纬度、海拔、时间等信息。
LoRa 数据封装与传输: 将解析后的 GPS 数据或其他传感器数据封装成 LoRa 协议包,并通过 SPI 接口控制 LoRa 模块进行无线传输。
电源管理: 控制各个模块的供电,并在不需要时将其置于低功耗模式或完全关闭,以最大限度地延长电池寿命。
用户交互与调试: 可能通过串口或板载 LED 提供状态指示,方便调试。
固件存储与执行: 存储并运行跟踪器的控制逻辑代码。
2. LoRa 无线通信模块
推荐型号: Semtech SX1276/SX1278 模块(如基于此芯片的 Ra-02 或 RFM95W 模块)
选择理由: LoRa 技术以其超长距离、低功耗和高抗干扰性成为户外物联网应用的理想选择。Semtech 的 SX127x 系列芯片是 LoRa 技术的基石,广泛应用于各种 LoRa 模块中。选择成熟的模块(如 Ra-02 或 RFM95W)可以简化硬件设计,因为它们通常已经集成了射频前端、晶振和匹配电路。这些模块支持多种频率(如 433MHz、868MHz、915MHz,根据地区法规选择),并提供 SPI 接口与微控制器通信,易于集成。
功能与作用:
远距离无线通信: 实现跟踪器与远端接收设备(如 LoRaWAN 网关或另一个 LoRa 节点)之间的数据传输,传输距离可达数公里甚至数十公里。
低功耗传输: LoRa 调制方式本身具有低功耗特性,配合模块的低功耗模式,有助于延长电池寿命。
数据包发送: 接收来自 ESP32 的数据(如 GPS 坐标),将其调制成 LoRa 信号并通过天线发送出去。
频率选择与配置: 根据地区法规和应用需求,配置工作频率、扩频因子(SF)、带宽(BW)和编码率(CR)等参数,以优化传输性能。
3. GPS 定位模块
推荐型号: U-blox NEO-6M 或 NEO-M8N 模块
选择理由: U-blox 是全球领先的定位技术供应商,其 NEO 系列 GPS 模块以高精度、快速定位、低功耗和良好的性价比而闻名。NEO-6M 是一款经典的入门级 GPS 模块,性能稳定,价格亲民。如果对定位精度和多星座支持有更高要求,NEO-M8N 则是一个更好的选择,它支持 GPS、GLONASS、BeiDou 等多种卫星系统,定位速度更快,精度更高。这些模块通常通过 UART(串口)与微控制器通信,输出标准的 NMEA 0183 协议数据,易于解析。
功能与作用:
卫星信号接收: 接收来自全球定位系统卫星的信号。
位置信息解算: 基于接收到的卫星信号,解算出当前的经度、纬度、海拔、速度、时间等地理信息。
NMEA 数据输出: 将解算出的位置信息以 NMEA 0183 协议格式通过 UART 接口输出给 ESP32。
热启动/冷启动: 支持快速热启动(有历史位置信息时),缩短定位时间。
低功耗模式: 部分模块支持周期性唤醒定位,以降低整体功耗。
4. 电源管理单元
户外跟踪器通常由电池供电,因此高效的电源管理至关重要。
4.1 锂电池
推荐型号: 3.7V 18650 锂离子电池(2000mAh - 3400mAh)
选择理由: 18650 锂离子电池具有能量密度高、循环寿命长、自放电率低等优点,是便携式电子设备的常用电源。其标准电压为 3.7V,与大多数低功耗电子元件兼容。选择合适的容量(mAh)取决于期望的续航时间。
功能与作用:
供电: 为整个跟踪器系统提供电能。
能量存储: 储存电能,确保设备在没有外部电源的情况下长时间运行。
4.2 升压/降压模块 (DC-DC Converter)
推荐型号:
升压模块: MT3608 模块(输入 2V-24V,输出 5V-28V,电流可达 2A)
降压模块: AMS1117-3.3V 线性稳压器(用于 3.3V 供电)或 MP1584EN 降压模块(输入 4.5V-28V,输出 0.8V-20V,电流可达 3A)
选择理由:
MT3608: 如果使用 3.7V 锂电池直接供电,而某些模块(如 ESP32 或 GPS 模块)需要 5V 才能稳定工作或充电管理芯片需要 5V 输入,则需要升压模块。MT3608 是一款高效的升压转换器,体积小巧,输出电流能力强。
AMS1117-3.3V / MP1584EN: ESP32 和 LoRa 模块通常工作在 3.3V。如果主电源(如升压后的 5V 或直接的 3.7V 电池)电压高于 3.3V,则需要降压模块。AMS1117 线性稳压器简单易用,但效率较低,适用于电流需求不大的情况。MP1584EN 是一款高效的开关降压转换器,适用于对效率有更高要求的场景,能够提供更稳定的 3.3V 供电。
功能与作用:
电压转换: 将电池提供的电压转换为各模块所需的稳定工作电压(如 3.3V 或 5V)。
稳压: 确保在电池电压波动时,为敏感的电子元件提供稳定的电源,防止因电压不稳导致的功能异常。
效率优化: 开关型 DC-DC 转换器(如 MT3608 和 MP1584EN)具有高转换效率,能最大限度地减少能量损耗,从而延长电池续航时间。
4.3 锂电池充电管理模块
推荐型号: TP4056 模块
选择理由: TP4056 是一款成熟、廉价且功能完善的单节锂电池充电管理芯片。它集成了充电管理、过放保护、过流保护和短路保护等功能,能够安全有效地为 3.7V 锂电池充电。模块通常带有 Micro USB 接口,方便使用手机充电器进行充电。
功能与作用:
锂电池充电: 提供恒流/恒压充电模式,确保锂电池安全高效充电。
充电状态指示: 通常通过 LED 指示充电状态(充电中/充电完成)。
电池保护: 集成过充、过放、过流和短路保护,防止电池损坏或发生危险。
5. 天线
5.1 LoRa 天线
推荐型号: 433MHz/868MHz/915MHz 螺旋弹簧天线或外置 SMA 接口棒状天线
选择理由: LoRa 通信的性能很大程度上取决于天线。螺旋弹簧天线体积小巧,可以直接焊接到 PCB 上,适合紧凑型设计。外置 SMA 接口棒状天线通常增益更高,性能更好,但需要额外的 SMA 连接器和更大的空间。选择哪种取决于对尺寸和性能的权衡。天线的工作频率必须与 LoRa 模块的频率相匹配。
功能与作用:
信号辐射与接收: 将 LoRa 模块发出的射频信号转换为电磁波辐射出去,并将接收到的电磁波转换为射频信号送回模块。
阻抗匹配: 确保天线与 LoRa 模块的射频输出阻抗(通常为 50 欧姆)匹配,以最大限度地传输功率,减少信号反射损耗。
5.2 GPS 天线
推荐型号: 有源陶瓷 GPS 天线(带 IPEX 或 SMA 接口)
选择理由: 有源 GPS 天线内置低噪声放大器(LNA),能够放大微弱的卫星信号,提高 GPS 模块的定位性能和灵敏度,尤其是在信号较弱的环境下。陶瓷天线体积小巧,适合集成。IPEX 接口适合内部连接,SMA 接口适合外置天线。
功能与作用:
卫星信号接收: 接收来自 GPS 卫星的 L1 频段信号。
信号放大(有源天线): 放大接收到的微弱卫星信号,提高信噪比,改善定位精度和速度。
6. 其他辅助元器件
6.1 杜邦线/连接器
推荐型号: 2.54mm 间距杜邦线、排针、排母、JST 连接器
选择理由: 用于模块与模块之间、模块与 PCB 之间的连接,方便调试和组装。JST 连接器常用于电池连接,具有防反插和更可靠的连接。
功能与作用:
电气连接: 建立各元器件之间的电气通路。
模块化: 方便各模块的插拔和更换,便于维护和升级。
6.2 按钮
推荐型号: 6x6mm 轻触开关
选择理由: 可用于唤醒设备、模式切换或复位等功能。
功能与作用:
用户输入: 提供简单的用户交互界面。
功能控制: 触发特定的程序功能,如进入深度睡眠、发送测试数据等。
6.3 LED 指示灯
推荐型号: 3mm 或 5mm LED(红、绿、蓝)
选择理由: 用于指示设备状态,如电源开启、GPS 定位成功、LoRa 数据发送等。
功能与作用:
状态指示: 提供直观的设备运行状态反馈。
调试辅助: 在开发和测试阶段,通过 LED 闪烁模式帮助判断程序执行流程。
6.4 电阻、电容
推荐型号: 各类贴片或直插电阻、陶瓷电容、电解电容
选择理由: 电阻用于限流、分压、上拉/下拉等;电容用于电源滤波、信号耦合/去耦、储能等。这些是电路设计中最基本的无源元件,根据具体电路需求选择合适的阻值、容值和封装。
功能与作用:
电阻: 控制电流、分压、提供偏置。
电容: 滤除电源噪声、稳定电源、存储电荷、信号耦合。
6.5 结构件与外壳
推荐型号: ABS 或聚碳酸酯防水外壳(IP67 或更高等级)
选择理由: 户外跟踪器必须具备良好的防水、防尘、防震能力,以应对恶劣的户外环境。选择合适的防护等级(如 IP67 表示防尘且可浸入 1 米深的水中 30 分钟而不受影响)的外壳至关重要。
功能与作用:
物理保护: 保护内部电子元件免受水、灰尘、冲击、紫外线和极端温度的影响。
环境适应性: 确保设备在户外环境中长期稳定运行。
美观与集成: 提供一个专业的、集成的外观,并方便安装天线和电池。
原理图设计考量
原理图是硬件设计的蓝图,它定义了所有元器件之间的电气连接。以下是设计 LoRa-GPS 跟踪器原理图时需要重点考虑的几个方面:
1. 微控制器与外设连接
ESP32 与 LoRa 模块 (SX127x): 通常通过 SPI 接口连接。确保正确连接 SPI 的 MOSI、MISO、SCK、CS(片选)引脚。此外,还需要连接 LoRa 模块的 RST(复位)引脚和 DIOx(中断)引脚,用于接收模块状态变化(如数据发送完成、接收到数据)的中断信号,这对于低功耗操作至关重要。
ESP32 与 GPS 模块 (NEO-6M/M8N): 通常通过 UART 接口连接。连接 ESP32 的 RXD 到 GPS 模块的 TXD,ESP32 的 TXD 到 GPS 模块的 RXD。注意电压电平匹配,如果 ESP32 是 3.3V,GPS 模块是 5V,可能需要电平转换器(但大多数 GPS 模块兼容 3.3V 逻辑)。
电源引脚: 所有模块都需要正确的 VCC 和 GND 连接。确保电源线足够粗,以承载所需电流。
2. 电源管理电路
电池输入: 锂电池通过 TP4056 充电模块连接。TP4056 的输出(BAT+ 和 BAT-)连接到整个电路的电源输入端。
DC-DC 转换器: 根据需要,将 TP4056 的输出(或直接电池)连接到升压或降压模块的输入端。升压模块的输出通常为 5V,用于给 ESP32 供电(如果 ESP32 板需要 5V 输入)或作为其他 5V 模块的电源。降压模块(如 AMS1117-3.3V 或 MP1584EN)的输入可以是 5V 或电池电压,输出稳定在 3.3V,用于给 ESP32 芯片本身、LoRa 模块和 GPS 模块供电。
电源滤波: 在每个电源输入端(特别是微控制器和射频模块的电源引脚)放置足够的去耦电容(如 0.1uF 陶瓷电容和 10uF/100uF 电解电容),以滤除电源噪声,确保供电稳定。
3. 天线连接
LoRa 天线: LoRa 模块的 RF 输出引脚应通过 50 欧姆阻抗匹配网络(通常由电感和电容组成,模块内部已集成)连接到天线接口(如 IPEX 或 SMA)。确保 RF 走线尽可能短且直,避免锐角弯折。
GPS 天线: 有源 GPS 天线需要 3.3V 或 5V 供电。通常 GPS 模块会提供一个 VCC_ANT 引脚用于此目的。天线信号通过同轴电缆连接到 GPS 模块的 RF 输入引脚。
4. 低功耗设计
模块控制: 在原理图中预留控制引脚,允许 ESP32 独立控制 LoRa 模块和 GPS 模块的电源(通过 MOSFET 或专门的电源管理 IC),在不需要时完全切断其供电,而不是仅仅进入低功耗模式。这能最大限度地降低整体功耗。
上拉/下拉电阻: 确保所有未使用的 GPIO 引脚或需要特定状态的引脚(如 LoRa 模块的 RST 引脚)都有正确的上拉或下拉电阻,防止浮空导致的高功耗。
LED 指示灯: LED 应串联限流电阻,并确保在低功耗模式下关闭,避免不必要的电流消耗。
5. 保护电路
ESD 保护: 在外部接口(如 USB 端口、天线接口)附近放置 ESD 保护器件(如 TVS 二极管),以防止静电放电损坏内部芯片。
反接保护: 在电池输入端添加二极管或 MOSFET 反接保护电路,防止电池反接损坏电路。
PCB 设计与布局优化
PCB(Printed Circuit Board)设计是将原理图转化为实际电路板的关键步骤,其质量直接影响设备的性能和可靠性。
1. 尺寸与外形
外壳适配: PCB 的尺寸和形状必须与所选的防水外壳内部空间完美匹配,并预留固定孔位。
元件高度: 考虑外壳内部高度限制,选择合适的元件封装(如贴片元件优先于直插元件),并合理布局,避免元件过高导致无法合盖。
2. 元件布局
功能分区: 将功能相近的元件(如电源管理、微控制器、LoRa 模块、GPS 模块)集中放置,形成独立的区域,有助于减少相互干扰。
电源路径: 核心电源路径(如电池输入、DC-DC 转换器、3.3V 稳压输出)应尽可能短而粗,以降低阻抗,减少电压降。
射频区域: LoRa 模块和天线应放置在 PCB 的边缘,远离数字电路和高频噪声源。射频走线应尽可能短、直,并保持 50 欧姆阻抗匹配,通常需要下方有完整的地平面作为参考。
GPS 天线: GPS 天线应放置在 PCB 上方,远离其他高频元件,避免信号遮挡和干扰。如果使用陶瓷天线,其下方不应有地平面,或者需要开窗处理,以确保天线性能。
连接器与接口: USB 接口、电池连接器、天线连接器等应放置在 PCB 边缘,方便外部连接。
散热: 对于大电流或发热元件(如 DC-DC 转换器、线性稳压器),应在 PCB 上预留足够的铜皮面积作为散热区域,或考虑添加散热片。
3. 走线策略
电源线与地线: 电源线和地线应尽可能宽,形成低阻抗通路。建议使用大面积铜皮作为地平面,以提供良好的接地参考和屏蔽效果。
信号线: 数字信号线应避免长距离平行走线,以减少串扰。高速信号线(如 SPI 的 SCK、MOSI、MISO)应尽量短。
差分信号: 如果有差分信号(如 USB 数据线),应进行差分对走线,并保持等长。
射频走线: LoRa 模块到天线的射频走线是关键。应使用 50 欧姆阻抗控制走线(通过调整走线宽度和与地平面的距离),并确保走线下方有完整的地平面。避免锐角弯折,尽量使用圆弧或 45 度角。
过孔: 尽量减少信号线上的过孔数量,特别是在高速和射频走线上。电源和地线可以使用多个过孔,以降低阻抗。
4. 层数选择
双层板: 对于简单的 LoRa-GPS 跟踪器,双层板通常足够。一层用于信号走线,另一层主要作为地平面,同时承载少量信号线。
四层板: 如果空间非常紧张,或者对射频性能和 EMC(电磁兼容性)有更高要求,可以考虑四层板。通常布局为:顶层(信号/元件)、内层 1(地平面)、内层 2(电源平面)、底层(信号/元件)。四层板能提供更好的信号完整性和抗干扰能力。
5. 丝印与阻焊
元件标识: 在丝印层上清晰地标注元件位号(如 R1、C1、U1)和元件方向(如二极管、电解电容的极性),方便焊接和调试。
接口标识: 标注连接器的功能(如 VCC、GND、RX、TX)。
阻焊: 阻焊层覆盖除焊盘和过孔外的所有铜皮,防止短路和氧化。
固件编程(Arduino 代码)
固件是跟踪器的灵魂,它控制着硬件的运行逻辑。以下是基于 Arduino IDE 的 ESP32 平台固件代码结构和关键功能实现。
```cpp
// 引入必要的库文件
#include <SPI.h> // 用于LoRa模块的SPI通信
#include <LoRa.h> // LoRa库,通常是RadioHead或ESP32 LoRa库
#include <TinyGPS++.h> // 用于解析GPS NMEA数据
#include <HardwareSerial.h> // ESP32的硬件串口,用于GPS模块通信
#include <esp_sleep.h> // ESP32的深度睡眠功能
// ====================================================================
// 硬件引脚定义
// ====================================================================
// LoRa模块引脚定义 (根据实际连接调整)
#define LORA_CS_PIN 18 // LoRa模块的片选引脚 (CS/NSS)
#define LORA_RST_PIN 14 // LoRa模块的复位引脚 (RST)
#define LORA_DIO0_PIN 26 // LoRa模块的DIO0引脚 (中断引脚)
// GPS模块串口定义 (ESP32有多个硬件串口,选择一个未被USB占用的)
// 这里使用UART2,对应GPIO16 (RX) 和 GPIO17 (TX)
#define GPS_RX_PIN 16 // GPS模块的TX连接到ESP32的RX
#define GPS_TX_PIN 17 // GPS模块的RX连接到ESP32的TX
HardwareSerial SerialGPS(2); // 创建一个HardwareSerial对象用于GPS
// LED指示灯引脚 (可选)
#define STATUS_LED_PIN 2 // 板载LED或自定义LED引脚
// ====================================================================
// LoRa配置参数
// ====================================================================
// LoRa工作频率 (根据地区法规选择,例如:中国433MHz,欧洲868MHz,北美915MHz)
#define LORA_FREQUENCY 433E6 // 433MHz
// LoRa扩频因子 (SF) - 影响距离和数据速率,SF7最快,SF12最慢但距离最远
#define LORA_SF 7
// LoRa带宽 (BW) - 影响数据速率和灵敏度,125kHz是常用值
#define LORA_BW 125E3 // 125kHz
// LoRa编码率 (CR) - 影响抗干扰能力,4/5是常用值
#define LORA_CR 5 // 4/5
// 发射功率 (dBm) - 越大距离越远,但功耗也越大,注意法规限制
#define LORA_TX_POWER 20 // 20dBm (最大值,约100mW)
// ====================================================================
// GPS配置
// ====================================================================
// GPS串口波特率 (通常为9600)
#define GPS_BAUD_RATE 9600
// TinyGPS++ 对象
TinyGPSPlus gps;
// ====================================================================
// 功耗管理与定时器
// ====================================================================
// 每次发送数据之间的睡眠时间 (秒)
// 这是一个关键参数,直接影响电池续航
#define SLEEP_DURATION_SECONDS 300 // 每5分钟发送一次数据
// ====================================================================
// 全局变量
// ====================================================================
unsigned long lastGPSTime = 0; // 记录上次成功获取GPS数据的时间
const unsigned long GPS_TIMEOUT_MS = 60000; // GPS定位超时时间 (1分钟)
// ====================================================================
// 函数声明
// ====================================================================
void setupLoRa();
void setupGPS();
void getGPSData();
void sendLoRaData(String data);
void enterDeepSleep();
void blinkLED(int times, int delayMs);
// ====================================================================
// SETUP 函数
// ====================================================================
void setup() {
Serial.begin(115200); // 初始化USB串口用于调试输出
Serial.println("LoRa-GPS Tracker Starting...");
// 初始化LED引脚
pinMode(STATUS_LED_PIN, OUTPUT);
blinkLED(3, 100); // 启动时LED闪烁3次
setupLoRa(); // 初始化LoRa模块
setupGPS(); // 初始化GPS模块
Serial.println("Setup Complete. Entering loop...");
}
// ====================================================================
// LOOP 函数
// ====================================================================
void loop() {
// 尝试获取GPS数据
getGPSData();
// 检查是否成功获取到有效的GPS数据
if (gps.location.isValid() && gps.location.age() < GPS_TIMEOUT_MS) {
// 构造要发送的数据字符串
String latitude = String(gps.location.lat(), 6); // 纬度,保留6位小数
String longitude = String(gps.location.lng(), 6); // 经度,保留6位小数
String altitude = String(gps.altitude.meters(), 2); // 海拔,保留2位小数
String satellites = String(gps.satellites.value()); // 卫星数量
String payload = "Lat:" + latitude + ",Lon:" + longitude + ",Alt:" + altitude + ",Sat:" + satellites;
Serial.print("GPS Data: ");
Serial.println(payload);
// 发送LoRa数据
sendLoRaData(payload);
// 成功发送后进入深度睡眠
enterDeepSleep();
} else {
Serial.println("Waiting for valid GPS data...");
// 如果长时间未获取到有效GPS数据,可以考虑进入短暂睡眠或重试
// 为了节省功耗,即使没有GPS数据也进入睡眠,等待下次唤醒重试
delay(5000); // 短暂等待,避免无限循环占用CPU
enterDeepSleep(); // 强制进入睡眠,即使GPS未定位成功,避免耗尽电池
}
}
// ====================================================================
// 辅助函数实现
// ====================================================================
/**
* @brief 初始化LoRa模块
*/
void setupLoRa() {
Serial.println("Initializing LoRa...");
// 设置LoRa模块的SPI引脚
LoRa.setPins(LORA_CS_PIN, LORA_RST_PIN, LORA_DIO0_PIN);
// 初始化LoRa模块
if (!LoRa.begin(LORA_FREQUENCY)) {
Serial.println("LoRa initialization failed! Check wiring and frequency.");
while (1); // LoRa初始化失败,程序停止
}
// 设置LoRa参数
LoRa.setSpreadingFactor(LORA_SF);
LoRa.setSignalBandwidth(LORA_BW);
LoRa.setCodingRate4(LORA_CR);
LoRa.setTxPower(LORA_TX_POWER); // 设置发射功率
Serial.println("LoRa initialized successfully.");
Serial.print("Frequency: "); Serial.print(LORA_FREQUENCY / 1E6); Serial.println(" MHz");
Serial.print("Spreading Factor: "); Serial.println(LORA_SF);
Serial.print("Bandwidth: "); Serial.print(LORA_BW / 1E3); Serial.println(" kHz");
Serial.print("Coding Rate: 4/"); Serial.println(LORA_CR + 4); // CR_4_5, CR_4_6, etc.
Serial.print("Tx Power: "); Serial.print(LORA_TX_POWER); Serial.println(" dBm");
}
/**
* @brief 初始化GPS模块串口
*/
void setupGPS() {
Serial.println("Initializing GPS Serial...");
SerialGPS.begin(GPS_BAUD_RATE, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
Serial.println("GPS Serial initialized.");
}
/**
* @brief 获取GPS数据
* 此函数会阻塞,直到获取到有效数据或超时
*/
void getGPSData() {
Serial.println("Attempting to get GPS data...");
lastGPSTime = millis(); // 记录开始时间
// 循环读取GPS串口数据并解析,直到获取到有效定位或超时
while (millis() - lastGPSTime < GPS_TIMEOUT_MS) {
while (SerialGPS.available()) {
gps.encode(SerialGPS.read()); // 将串口数据喂给TinyGPS++解析器
}
if (gps.location.isValid() && gps.location.age() < GPS_TIMEOUT_MS) {
Serial.println("GPS Fix acquired!");
blinkLED(1, 500); // GPS定位成功,LED闪烁一次
return; // 成功获取数据,退出函数
}
delay(100); // 短暂延时,避免CPU空转
}
Serial.println("GPS timeout or no valid data received.");
blinkLED(5, 50); // GPS超时,LED快速闪烁5次
}
/**
* @brief 通过LoRa发送数据
* @param data 要发送的字符串数据
*/
void sendLoRaData(String data) {
Serial.print("Sending LoRa packet: ");
Serial.println(data);
// LoRa.beginPacket() 准备发送数据包
LoRa.beginPacket();
LoRa.print(data); // 将数据写入数据包
LoRa.endPacket(); // 结束数据包并发送
Serial.println("LoRa packet sent.");
blinkLED(2, 100); // LoRa发送成功,LED闪烁两次
}
/**
* @brief 使ESP32进入深度睡眠模式以节省功耗
*/
void enterDeepSleep() {
Serial.print("Entering deep sleep for ");
Serial.print(SLEEP_DURATION_SECONDS);
Serial.println(" seconds...");
// 设置唤醒源为定时器
esp_sleep_enable_timer_wakeup(SLEEP_DURATION_SECONDS * 1000000ULL); // 参数为微秒
// 关闭所有不必要的GPIO,以进一步降低功耗
// 注意:某些引脚可能需要保持状态,根据实际电路决定
for (int i = 0; i < 40; i++) { // 遍历所有GPIO (ESP32有近40个GPIO)
if (i != LORA_CS_PIN && i != LORA_RST_PIN && i != LORA_DIO0_PIN &&
i != GPS_RX_PIN && i != GPS_TX_PIN && i != STATUS_LED_PIN) {
// 确保不影响正在使用的引脚
pinMode(i, INPUT_PULLDOWN); // 将未使用的引脚设置为下拉输入,防止浮空
}
}
digitalWrite(STATUS_LED_PIN, LOW); // 确保LED在睡眠前关闭
Serial.flush(); // 等待所有串口数据发送完毕
esp_deep_sleep_start(); // 进入深度睡眠
// 程序执行到这里将不会返回,ESP32会重启
}
/**
* @brief LED闪烁函数
* @param times 闪烁次数
* @param delayMs 每次闪烁的延时 (毫秒)
*/
void blinkLED(int times, int delayMs) {
for (int i = 0; i < times; i++) {
digitalWrite(STATUS_LED_PIN, HIGH);
delay(delayMs);
digitalWrite(STATUS_LED_PIN, LOW);
delay(delayMs);
}
}
责任编辑:David
【免责声明】
1、本文内容、数据、图表等来源于网络引用或其他公开资料,版权归属原作者、原发表出处。若版权所有方对本文的引用持有异议,请联系拍明芯城(marketing@iczoom.com),本方将及时处理。
2、本文的引用仅供读者交流学习使用,不涉及商业目的。
3、本文内容仅代表作者观点,拍明芯城不对内容的准确性、可靠性或完整性提供明示或暗示的保证。读者阅读本文后做出的决定或行为,是基于自主意愿和独立判断做出的,请读者明确相关结果。
4、如需转载本方拥有版权的文章,请联系拍明芯城(marketing@iczoom.com)注明“转载原因”。未经允许私自转载拍明芯城将保留追究其法律责任的权利。
拍明芯城拥有对此声明的最终解释权。