基于LoRa的车辆定位跟踪系统方案

基于LoRa的车辆定位跟踪系统方案,采用超低功耗设计,待机电流可低于5μA


一、系统架构设计

1、端节点(车载设备)

GPS模块 → MCU (STM32L0/L4) → LoRa模块 → 空中
     ↓         ↓           ↓
   休眠     定时唤醒     低功耗发送

2、基站网关

LoRa模块 → MCU → 4G/NB-IoT → 云平台
    ↓         ↓         ↓
  接收     解析      转发

3、云平台

MQTT服务器 → 数据库 → Web应用/APP
    ↓           ↓         ↓
实时监控    轨迹存储    位置显示

二、超低功耗关键技术

技术 实现方式 功耗节省
RTC唤醒 深度睡眠+定时唤醒 99.9%
GPS智能开关 冷启动+热启动切换 80%
LoRa ADR 自适应数据速率 50%
数据压缩 只发变化量 70%
电压监测 动态调整发射功率 40%

三、硬件选型(超低功耗版)

1、主控

2、LoRa模块

3、GPS模块

4、电源管理


四、终端代码(STM32L0 + FreeRTOS)

1、主程序框架

// main.h
#ifndef __MAIN_H
#define __MAIN_H

#include "stm32l0xx_hal.h"
#include "cmsis_os.h"

// 系统工作模式
typedef enum {
    MODE_DEEP_SLEEP = 0,    // 深度睡眠
    MODE_GPS_FIX,          // GPS定位
    MODE_LORA_TX,          // LoRa发送
    MODE_LORA_RX,          // LoRa接收
    MODE_CHARGING,         // 充电
    MODE_FAULT             // 故障
} System_Mode_t;

// 定位数据结构
typedef struct {
    double latitude;       // 纬度
    double longitude;      // 经度
    float altitude;        // 海拔
    float speed;           // 速度 km/h
    float course;          // 航向
    uint8_t satellites;    // 卫星数
    uint8_t fix_status;    // 定位状态
    uint32_t timestamp;    // 时间戳
} GPS_Data_t;

// LoRa消息结构
typedef struct {
    uint32_t device_id;    // 设备ID
    GPS_Data_t gps;        // GPS数据
    uint16_t battery;      // 电池电压 mV
    int8_t rssi;          // 接收信号强度
    int8_t snr;           // 信噪比
    uint8_t sequence;     // 序列号
} LoRa_Message_t;

#endif

2、电源管理

// power_manager.c
#include "power_manager.h"
#include "stm32l0xx_hal.h"

// 电源状态
static Power_State_t power_state = {0};

// 进入停止模式(最低功耗)
void Enter_Stop_Mode(uint32_t wakeup_sec)
{
    // 1. 关闭所有外设时钟
    __HAL_RCC_GPIOA_CLK_DISABLE();
    __HAL_RCC_GPIOB_CLK_DISABLE();
    __HAL_RCC_GPIOC_CLK_DISABLE();
    __HAL_RCC_GPIOD_CLK_DISABLE();
    __HAL_RCC_GPIOH_CLK_DISABLE();
    
    // 2. 配置唤醒引脚
    HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN2);  // PA0
    
    // 3. 配置RTC唤醒
    HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, wakeup_sec, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);
    
    // 4. 进入停止模式
    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
    
    // 5. 唤醒后重新初始化时钟
    SystemClock_Config();
}

// 测量电池电压
uint16_t Measure_Battery_Voltage(void)
{
    uint16_t adc_value;
    float voltage;
    
    // 使能ADC
    HAL_ADC_Start(&hadc);
    HAL_ADC_PollForConversion(&hadc, 10);
    adc_value = HAL_ADC_GetValue(&hadc);
    HAL_ADC_Stop(&hadc);
    
    // 计算电压 (VBAT分压1/3)
    voltage = adc_value * 3.0f * 3.3f / 4095.0f;
    
    return (uint16_t)(voltage * 1000);  // 返回mV
}

// 电池保护
uint8_t Check_Battery_Status(void)
{
    uint16_t voltage = Measure_Battery_Voltage();
    
    if (voltage > 4200) {      // 4.2V
        return BATTERY_FULL;
    } else if (voltage > 3400) { // 3.4V
        return BATTERY_NORMAL;
    } else if (voltage > 3200) { // 3.2V
        return BATTERY_LOW;
    } else {                    // < 3.2V
        return BATTERY_CRITICAL;
    }
}

3、GPS智能管理

// gps_manager.c
#include "gps_manager.h"

// GPS工作模式
typedef enum {
    GPS_MODE_OFF = 0,
    GPS_MODE_COLD_START,   // 冷启动
    GPS_MODE_HOT_START,    // 热启动
    GPS_MODE_TRACKING,     // 跟踪
    GPS_MODE_BACKUP        // 备份模式
} GPS_Mode_t;

// GPS智能管理器
void GPS_Smart_Manager(GPS_Data_t *gps)
{
    static uint8_t gps_mode = GPS_MODE_OFF;
    static uint32_t last_fix_time = 0;
    static uint8_t fix_count = 0;
    
    uint32_t current_time = HAL_GetTick();
    
    // 根据时间决定启动模式
    if (current_time - last_fix_time > 300000) {  // 超过5分钟
        gps_mode = GPS_MODE_COLD_START;  // 冷启动
    } else if (current_time - last_fix_time > 60000) {  // 1-5分钟
        gps_mode = GPS_MODE_HOT_START;   // 热启动
    } else {
        gps_mode = GPS_MODE_TRACKING;    // 跟踪模式
    }
    
    // 根据模式设置GPS
    switch (gps_mode) {
        case GPS_MODE_COLD_START:
            GPS_Cold_Start();
            break;
        case GPS_MODE_HOT_START:
            GPS_Hot_Start();
            break;
        case GPS_MODE_TRACKING:
            GPS_Set_Tracking_Mode();
            break;
    }
    
    // 尝试获取定位
    if (GPS_Get_Fix(gps, 30000)) {  // 30秒超时
        last_fix_time = current_time;
        fix_count++;
        
        // 如果连续3次定位成功,进入备份模式
        if (fix_count >= 3) {
            GPS_Enter_Backup_Mode();
        }
    } else {
        fix_count = 0;
    }
}

// GPS冷启动
void GPS_Cold_Start(void)
{
    // 发送冷启动命令
    GPS_Send_Command("$PMTK103*30\r\n");
    
    // 配置参数
    GPS_Send_Command("$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28\r\n");  // 只输出GGA,RMC
    GPS_Send_Command("$PMTK220,1000*1F\r\n");  // 1Hz更新率
}

// GPS热启动
void GPS_Hot_Start(void)
{
    GPS_Send_Command("$PMTK101*32\r\n");
}

// GPS进入备份模式
void GPS_Enter_Backup_Mode(void)
{
    GPS_Send_Command("$PMTK161,0*28\r\n");  // 进入备份模式
}

4、LoRa通信协议

// lora_protocol.h
#ifndef __LORA_PROTOCOL_H
#define __LORA_PROTOCOL_H

// 消息类型
typedef enum {
    MSG_POSITION = 0x01,     // 位置信息
    MSG_HEARTBEAT = 0x02,    // 心跳
    MSG_ALARM = 0x03,        // 报警
    MSG_CONFIG = 0x04,       // 配置
    MSG_ACK = 0x05,          // 确认
} Message_Type_t;

// 位置消息结构(压缩)
typedef struct __attribute__((packed)) {
    uint8_t type;           // 0x01
    uint32_t device_id;     // 设备ID
    int32_t latitude;       // 纬度*1e7
    int32_t longitude;      // 经度*1e7
    uint16_t altitude;      // 海拔 m
    uint8_t speed;         // 速度 km/h
    uint8_t course;        // 航向/2
    uint8_t satellites;    // 卫星数
    uint16_t battery;      // 电池电压 mV
    uint8_t rssi;          // 信号强度
    uint8_t snr;           // 信噪比
    uint16_t sequence;     // 序列号
    uint8_t checksum;      // 校验和
} Position_Message_t;

// 心跳消息(更小)
typedef struct __attribute__((packed)) {
    uint8_t type;           // 0x02
    uint32_t device_id;     // 设备ID
    uint16_t battery;      // 电池电压
    uint8_t status;        // 状态
    uint16_t sequence;     // 序列号
    uint8_t checksum;      // 校验和
} Heartbeat_Message_t;

#endif

5、主程序

// main.c
#include "main.h"
#include "power_manager.h"
#include "gps_manager.h"
#include "lora_protocol.h"

// FreeRTOS任务
TaskHandle_t gps_task_handle;
TaskHandle_t lora_task_handle;
TaskHandle_t sleep_task_handle;

// 系统状态
System_State_t system_state = {0};
GPS_Data_t gps_data = {0};
LoRa_Message_t lora_msg = {0};

int main(void)
{
    // 1. 低功耗初始化
    HAL_Init();
    SystemClock_Config_LowPower();
    
    // 2. 外设初始化
    MX_GPIO_Init();
    MX_DMA_Init();
    MX_USART1_UART_Init();  // GPS
    MX_USART2_UART_Init();  // LoRa
    MX_RTC_Init();
    MX_ADC_Init();
    
    // 3. FreeRTOS初始化
    osKernelInitialize();
    
    // 4. 创建任务
    xTaskCreate(GPS_Task, "GPS", 256, NULL, 3, &gps_task_handle);
    xTaskCreate(LoRa_Task, "LoRa", 256, NULL, 2, &lora_task_handle);
    xTaskCreate(Sleep_Task, "Sleep", 128, NULL, 1, &sleep_task_handle);
    
    // 5. 启动调度器
    osKernelStart();
    
    while (1) { }
}

// GPS任务
void GPS_Task(void *arg)
{
    while (1) {
        // 等待唤醒信号
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
        
        // 智能GPS管理
        GPS_Smart_Manager(&gps_data);
        
        // 通知LoRa任务有新数据
        xTaskNotifyGive(lora_task_handle);
        
        // 挂起任务直到下次唤醒
        vTaskSuspend(NULL);
    }
}

// LoRa任务
void LoRa_Task(void *arg)
{
    Position_Message_t pos_msg = {0};
    
    while (1) {
        // 等待GPS数据
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
        
        // 构建消息
        pos_msg.type = MSG_POSITION;
        pos_msg.device_id = DEVICE_ID;
        pos_msg.latitude = (int32_t)(gps_data.latitude * 1e7);
        pos_msg.longitude = (int32_t)(gps_data.longitude * 1e7);
        pos_msg.altitude = (uint16_t)gps_data.altitude;
        pos_msg.speed = (uint8_t)gps_data.speed;
        pos_msg.course = (uint8_t)(gps_data.course / 2);
        pos_msg.satellites = gps_data.satellites;
        pos_msg.battery = Measure_Battery_Voltage();
        pos_msg.sequence = system_state.sequence++;
        pos_msg.checksum = Calculate_Checksum(&pos_msg, sizeof(pos_msg)-1);
        
        // 发送消息
        LoRa_Send_Message(&pos_msg, sizeof(pos_msg));
        
        // 挂起任务
        vTaskSuspend(NULL);
    }
}

// 睡眠任务
void Sleep_Task(void *arg)
{
    TickType_t last_wake_time = xTaskGetTickCount();
    
    while (1) {
        // 唤醒GPS和LoRa任务
        vTaskResume(gps_task_handle);
        vTaskResume(lora_task_handle);
        
        // 等待任务完成
        vTaskDelay(1000 / portTICK_PERIOD_MS);
        
        // 计算下次唤醒时间
        uint32_t sleep_seconds = Calculate_Sleep_Interval();
        
        // 挂起所有任务
        vTaskSuspend(gps_task_handle);
        vTaskSuspend(lora_task_handle);
        
        // 进入停止模式
        Enter_Stop_Mode(sleep_seconds);
        
        // 唤醒后继续
        last_wake_time = xTaskGetTickCount();
    }
}

6、智能休眠策略

// sleep_manager.c
#include "sleep_manager.h"

// 根据场景计算休眠时间
uint32_t Calculate_Sleep_Interval(void)
{
    static uint8_t motion_state = 0;
    static uint32_t last_speed = 0;
    uint32_t interval;
    
    // 根据速度动态调整上报频率
    if (gps_data.speed > 80) {  // 高速行驶
        interval = 10;  // 10秒
    } else if (gps_data.speed > 30) {  // 城市行驶
        interval = 30;  // 30秒
    } else if (gps_data.speed > 5) {  // 慢速移动
        interval = 60;  // 1分钟
    } else {  // 静止
        // 检测是否在移动
        if (fabs(gps_data.speed - last_speed) < 0.5) {
            motion_state++;
            if (motion_state > 5) {  // 连续5次静止
                interval = 300;  // 5分钟
            } else {
                interval = 120;  // 2分钟
            }
        } else {
            motion_state = 0;
            interval = 60;  // 1分钟
        }
    }
    
    last_speed = gps_data.speed;
    return interval;
}

// 运动检测算法
uint8_t Detect_Motion(void)
{
    static float last_lat = 0, last_lon = 0;
    static uint32_t last_time = 0;
    float distance;
    
    // 计算移动距离
    distance = Calculate_Distance(last_lat, last_lon, 
                                 gps_data.latitude, gps_data.longitude);
    
    // 计算时间差
    uint32_t time_diff = HAL_GetTick() - last_time;
    
    // 更新上一次位置
    last_lat = gps_data.latitude;
    last_lon = gps_data.longitude;
    last_time = HAL_GetTick();
    
    // 判断是否移动
    if (distance > 10.0 && time_diff < 10000) {  // 10米/10秒
        return 1;  // 移动
    }
    
    return 0;  // 静止
}

五、网关程序(STM32 + 4G)

// gateway.c
#include "main.h"
#include "lora_protocol.h"

// MQTT主题定义
#define TOPIC_POSITION "vehicle/%08X/position"
#define TOPIC_HEARTBEAT "vehicle/%08X/heartbeat"

// 网关主循环
void Gateway_Main_Loop(void)
{
    uint8_t rx_buffer[64];
    uint8_t rx_len;
    
    while (1) {
        // 1. 接收LoRa消息
        if (LoRa_Receive(rx_buffer, &rx_len, 1000)) {
            // 2. 解析消息
            Message_Type_t msg_type = rx_buffer[0];
            
            switch (msg_type) {
                case MSG_POSITION: {
                    Position_Message_t *pos = (Position_Message_t*)rx_buffer;
                    
                    // 验证校验和
                    if (Verify_Checksum(pos, sizeof(*pos))) {
                        // 转换为JSON
                        char json[256];
                        Format_Position_JSON(pos, json, sizeof(json));
                        
                        // 发布到MQTT
                        char topic[64];
                        sprintf(topic, TOPIC_POSITION, pos->device_id);
                        MQTT_Publish(topic, json);
                        
                        // 存储到本地
                        Store_Position_To_SD(pos);
                    }
                    break;
                }
                    
                case MSG_HEARTBEAT: {
                    Heartbeat_Message_t *hb = (Heartbeat_Message_t*)rx_buffer;
                    
                    char json[128];
                    Format_Heartbeat_JSON(hb, json, sizeof(json));
                    
                    char topic[64];
                    sprintf(topic, TOPIC_HEARTBEAT, hb->device_id);
                    MQTT_Publish(topic, json);
                    break;
                }
            }
        }
        
        // 3. 检查下行命令
        Check_Downlink_Commands();
    }
}

六、云平台接口

1、MQTT JSON格式

{
  "device_id": "12345678",
  "timestamp": 1633046400,
  "latitude": 31.230416,
  "longitude": 121.473701,
  "altitude": 12.5,
  "speed": 45.2,
  "course": 120.5,
  "satellites": 8,
  "battery": 3765,
  "rssi": -65,
  "snr": 10,
  "sequence": 1024
}

2、HTTP API接口

// 上报位置
POST /api/v1/position
Content-Type: application/json

// 查询轨迹
GET /api/v1/track?device_id=12345678&start=1633046400&end=1633132800

参考代码 基于lora车辆定位跟踪,超低功耗 www.youwenfan.com/contentcnu/70045.html

七、功耗测试数据

工作状态 电流 持续时间 能耗
深度睡眠 2μA 3550秒 7.1μAh
GPS冷启动 25mA 30秒 208μAh
GPS跟踪 18mA 10秒 50μAh
LoRa发送 120mA 0.5秒 16.7μAh
单次循环 平均 3600秒 281.8μAh
年总耗电 616mAh

使用3000mAh电池可工作约5年


八、PCB布局注意事项

1、电源部分

电池 → 保护电路 → DCDC → LDO → MCU
         ↓          ↓       ↓
      电量检测    GPS     LoRa

2、天线设计


九、功耗优化技巧

1. 使用TCXO替换晶体

2. 动态电压调节

// 根据负载调整电压
void Adjust_Core_Voltage(uint8_t level)
{
    PWR->CR &= ~PWR_CR_VOS;
    PWR->CR |= (level << PWR_CR_VOS_Pos);
    while ((PWR->CSR & PWR_CSR_VOSF) != 0);
}

3. 内存保持模式

// 只保留必要内存
void Enable_BKPSRAM_Retention(void)
{
    __HAL_RCC_PWR_CLK_ENABLE();
    HAL_PWR_EnableBkUpAccess();
    __HAL_RCC_BKPSRAM_CLK_ENABLE();
    HAL_PWREx_EnableBkUpReg();
}

十、部署建议

1、安装位置

2、天线安装

 

专注于matlab/simulink,电子电路,编程