lorawan 工业温控器量产版源代码 stm32l073+sx1278 支持iap固件升级 温度采集,湿度采集 两路继电器控制 1路外部5v模拟输入 1路加热板工况状态监测 lorawan网关后台远程控制,周期上报

最近在折腾一款基于STM32L073和SX1278的LoRaWAN工业温控器,支持IAP固件升级、温湿度采集、继电器控制,还能远程操控。今天简单聊聊量产版代码设计里几个有意思的点,顺带贴点关键代码。


硬件架构与基础配置

主控是STM32L073,低功耗+LoRa模组SX1278的经典组合。底层驱动直接用HAL库,但针对低功耗做了优化。比如SX1278的SPI初始化,需要关中断防止时序被打断:

void SX1278_SPI_Init() {
    __HAL_SPI_DISABLE(&hspi1);  // 先停掉SPI
    hspi1.Instance->CR1 = SPI_BAUDRATEPRESCALER_8 | SPI_DIRECTION_2LINES 
                        | SPI_POLARITY_LOW | SPI_PHASE_1EDGE;
    __HAL_SPI_ENABLE(&hspi1);   // 重新使能
}

这里手动配置SPI的寄存器而不是全用HAL,主要是为了减少函数调用层级,降低功耗。


IAP升级实战:空中更新固件

工业场景下,远程升级是刚需。我们的IAP方案把Flash分为Bootloader区(0x08000000-0x08003FFF)和APP区。升级流程:

  1. 网关下发加密固件包;
  2. 设备接收后写入外部Flash缓存;
  3. 校验通过后跳转Bootloader搬运代码。

关键代码是跳转函数:

void JumpToBootloader() {
    void (*SysMemBootJump)(void) = (void (*)(void))(*((uint32_t*)0x1FF00004));
    __disable_irq();  // 关中断
    HAL_RCC_DeInit();
    HAL_DeInit();
    SysTick->CTRL = 0;
    SysTick->LOAD = 0;
    SysTick->VAL = 0;
    __set_MSP(*(__IO uint32_t*)0x08000000);  // 重置栈指针
    SysMemBootJump();
}

坑点:跳转前必须彻底复位外设,否则可能因残留状态导致Bootloader异常。


温湿度采集与滤波

传感器用的是SHT30,I2C通信。但工业环境干扰大,采集数据要做滑动平均滤波:

#define FILTER_LEN 5
static float temp_history[FILTER_LEN] = {0};

float GetFilteredTemp() {
    // 采集新数据并插入数组
    for(int i=FILTER_LEN-1; i>0; i--){
        temp_history[i] = temp_history[i-1];
    }
    temp_history[0] = SHT30_ReadTemp();
    
    // 计算平均值
    float sum = 0;
    for(int i=0; i<FILTER_LEN; i++){
        sum += temp_history[i];
    }
    return sum / FILTER_LEN;
}

注意:滤波长度不宜过长,否则响应延迟会影响控温精度,实测5次平均效果最佳。


控制与监测:继电器与工况检测

两路继电器控制加热/制冷设备,代码简单但硬件有讲究:

void Relay_SetState(int ch, bool state) {
    if(ch == 1) HAL_GPIO_WritePin(RELAY1_GPIO_Port, RELAY1_Pin, state?GPIO_PIN_SET:GPIO_PIN_RESET);
    else if(ch == 2) HAL_GPIO_WritePin(RELAY2_GPIO_Port, RELAY2_Pin, state?GPIO_PIN_SET:GPIO_PIN_RESET);
    // 添加状态回读校验
    if(Relay_GetState(ch) != state) {
        Error_Handler();  // 硬件异常处理
    }
}

硬件坑:继电器线圈必须加反向二极管吸收反电动势,否则MCU的GPIO容易烧!


LoRaWAN通信:周期上报与远程控制

使用Class A模式,每10分钟上报一次数据。重点在Payload编码优化:

uint8_t EncodePayload(float temp, float humidity) {
    uint8_t buf[6];
    int16_t temp_int = (int16_t)(temp * 10);  // 精度0.1℃
    uint16_t humidity_int = (uint16_t)(humidity * 10);
    memcpy(buf, &temp_int, 2);
    memcpy(buf+2, &humidity_int, 2);
    // 附加模拟输入和工况状态
    buf[4] = ReadAnalogInput();
    buf[5] = GetHeaterStatus();
    return buf;
}

网关下发指令时,通过FPort区分控制类型(如FPort=1控制继电器,FPort=2设置上报间隔)。


结语

这套系统已经在几个工厂跑了大半年,稳定性达标。代码层面最大的教训是:低功耗和实时性需要精细平衡。比如温控逻辑中,如果为了省电频繁进入Stop模式,可能导致继电器动作延迟。最终方案是动态调整采集频率——温度越接近设定阈值,采集越频繁。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐