注:视频在附件压缩包中。
目录
一、背景技术 2
二、整理框架 2
三、亮点分析 3
四、硬件分析 3
4.1 主要模块介绍 3
4.2 主要原理图分析 4
4.3 实物分析 6
五、软件分析 7
5.1 微信小程序 7
5.2 主机软件分析 8
5.3 从机软件分析 12
六、工作过程分析 13
北京霜林网络科技有限公司
一、背景技术
目前,常见的液化气充装系统是充装人员根据开票人员提供的充值小票来给液化气罐定量的充值,这种充装方式受充装人员的操作影响较大,容易受到充装人员误操作导致的多充或少充,且加大了管理员对充气罐剩余气体总量控制的难度。
现有充装系统,通常是一台控制器控制一台充装设备,多台设备之间独立管理,造成了整体管理松散,充装数据统计不方便,不利于接入物联网以及实现远程监控管理的问题。
鉴于现有的液化气充装系统存在的问题,基于LoRa无线通信技术和Tiny OS操作系统设计一新型的液化气智能充装系统
二、整理框架
液化气智能充装系统整体框架如图1所示。主要包括手机小程序、主机控制单元和多个从机控制单元。主机控制单元包括主机控制器、小票打印模块、蓝牙模块、存储单元和LoRa无线通信模块。每个从机控制单元包括LoRa无线通信模块、从机控制器、语音模块、扫码模块、继电器、电磁阀和充装秤模块。
三、亮点分析
新型的液化气智能充装系统,利用LoRa无线通信技术,省去了在液化气充装站布线的不便(布线不易满足防爆要求),具有诸多优点,如下所示:
亮点1:微信小程序实现订单管理和数据同步,自动生成可视化订单报表和充装数据。传统的液化气充装站采用手写或者电脑打票的方式,不利于充装数据和开票信息的可视化存储,采用微信小程序下订单,省去了原有的硬件成本,操作方便,且开发了每周和每月的报表自动生成功能,有利于对充装数据和订单数据的统一管理。
亮点2:采用TencentOS-tiny操作系统,简化开发流程,优化系统性能,移植性强。主机需要处理的任务较多,逻辑较为复杂,如果采用轮询 中断的处理方式,将会带来很高的延时,影响整理的流畅性。TencentOS-tiny操作系统是面向物联网领域开发的实时操作系统,具有低功耗,低资源占用,模块化,安全可靠等特点,可有效提升物联网终端产品开发效率,且适配于多款MCU,本次开发使用的主机控制器是基于Cortex M4内核的STM32F407单片机,TencentOS-tiny操作系统可快速移植至该单板,使用简便,可大大的优化系统的性能,增强主机的实时性。
亮点3:采用LoRa无线通信技术,传输距离远,功耗低,成本低。本系统中主机控制单元和从机控制单元间采用LoRa无线通信技术,省去了现实中布线的麻烦,且LoRa无线技术具有灵敏度高,传输距离远等优点,完美的适合在液化气充装站的场景(液化气充装站因为特殊的防爆要求不能方便的布线)。
亮点4:采用动态预测算法,实时估计下一时刻充装质量,单片机控制电磁阀充装,最大化的避免了气候和温度对充装过程的影响。在实际的液化气充装过程中,由于受到天气、温度等的影响,充值的压力是一个变化值,充装过程中的充装速度是一个不断变化的过程,怎样准确的对下一时刻充装质量的预测完成整个的充装过程就成了一个关键的因素。本系统采用一种动态预测算法,估计下一时刻的充装值,适配不同气候对充装过程造成的影响。
四、硬件分析
4.1 主要模块介绍
整个充装系统用到的重要模块如图2所示。主机控制单元用到的有主控模块、蓝牙模块、热敏打印机和LoRa模块。其中主控模块负责和小程序以及各从机间的交互工作;蓝牙模块负责主机和小程序间的通信;热敏打印机负责将小程序下的订单按照一定格式打印;LoRa模块负责主机和各从机间的通信。
从机控制单元主要使用的有主控模块、LoRa模块、扫码模块、充装秤、继电器和防爆电磁阀模块。其中主控模块负责协调充装过程、解析二维码数据及和主机间的通信;LoRa模块负责从机和主机间号的无线通信数据传输;扫码模块负责解析二维码的数据,并传递给从机;充装秤、继电器和防爆电磁阀模块协同工作负责整个充装过程的起始和停止。
4.2 主要原理图分析
从机控制单元的主控MCU采用的是STM32F407,原理图如图3所示。从机所连接的主要外设有FLSAH、TF Card、LoRa等模块,关系如图4所示。主机主要外设如图5所示。
LoRa模块原理图如图6所示。LoRa模块与MCU间通过SPI接口通信,除此之外LoRa模块有一个重要的DIO0管脚,标志着LoRa模块是否完成通信数据的收发过程。
继电器模块原理图如图7所示。为了减小继电器对MCU及其他部件的影响,将输入和输出信号隔离开,采用光电隔离的方式驱动继电器模块,除此外,在继电器的输出端增加了自恢复保险丝,防止电流过大损坏器件。
4.3 实物分析
主机实物如图8所示,PCB板正面包含了MCU模块、LoRa模块和打印机接口及指示灯;PCB板背面包括了电源模块和蓝牙模块。
从机实物如图9所示,PCB板正面包括了MCU、继电器、电磁阀接口、扫码模块、蜂鸣器和充装秤接口,PCB板背面包括了LoRa模块的电源模块。
五、软件分析
5.1 微信小程序
微信小程序界面如图10所示。图10(a)、(b)、(c)分别展示了小程序主页面、下订单页面和状态设置页面。在下订单页面可以按照金额、总量和单瓶三种不同的方式按照客户的要求进行下单,状态设置界面可以对从机的的工作模式进行设定。
5.2 主机软件分析
主机的main函数主要包括了板级外设的初始化,主要初始化了系统嘀嗒计时器(ms级中断)、调试串口、LoRa模块、蓝牙模块、打印机模块和SD卡模块等外设,除此之外基于Tiny OS操作系统新建了两个任务,分别是蓝牙数据处理任务和LoRa数据处理任务。
代码语言:javascript复制int main(void)
{
SysTick_Init(); // 嘀嗒计时器
debug_usart_init(); // log调试串口
lora_dio_init(); // LoRaDIO初始化
lora_spi_init(); // LoRa SPI初始化
get_version_and_print(); // 获取LoRa版本号
bluetooth_init(); // 蓝牙初始化
printer_init(); // 打印机初始化
f_mount(&fs,"0:",1); // 挂载SD卡
radio_p = RadioDriverInit(); // SX1278初始化
radio_p->Init(); // SX1278初始化
// 开始创建任务
osKernelInitialize(); // 初始化tiny_OS
osThreadCreate(osThread(task1), NULL); // 创建任务1,与从机LoRa通信
osThreadCreate(osThread(task2), NULL); // 创建任务2,与小程序蓝牙通信
osKernelStart(); // Start TOS Tiny
}
任务1的处理代码如下所示,主要负责LoRa数据的处理,在处理之前首先打开LoRa的接收模式,等LoRa模块接收数据完成之后对不同的数据帧进行相应的分析,sx127x_data_get()函数为LoRa数据的处理函数。
代码语言:javascript复制// 任务1函数
void task1(void *pdata)
{
uint32_t task1_num = 0;
radio_p->StartRx(); // 打开LoRa接收
while(1)
{
task1_num ;
printa("任务1执行第 %d 次rn", task1_num); // release版本 printa不打印
sx127x_data_get(); // 获取从机LoRa发送的信息
osDelay(2000);
}
}
任务2的处理代码如下所示,主要负责蓝牙数据的处理,在蓝牙模块接收数据完成之后对小程序发送的数据进行解析,Bluetooth_Printer_Sd()为蓝牙数据的解析函数。
代码语言:javascript复制// 任务2函数
void task2(void *pdata)
{
uint32_t task2_num = 0;
while(1)
{
task2_num ;
printa("任务2执行第 %d 次rn", task2_num); // release版本 printa不打印
Bluetooth_Printer_Sd(); // 获取蓝牙模块的数据
osDelay(1000);
}
}
LoRa数据获取函数如下所示,包含了LoRa工作过程中发送超时、发送完成、接收超时和接收完成等工作状态的判定,同时包含了接受完成后数据的解析接口的调用(函数master_protocol_analysis)。
代码语言:javascript复制// LoRa数据获取
uint8_t sx127x_data_get(void)
{
uint8_t status = 0;
switch( radio_p->Process() )
{
case RF_RX_TIMEOUT:
break;
case RF_RX_DONE:
radio_p->GetRxPacket(Buffer, ( uint16_t* )&BufferSize);
if( BufferSize > 0 )
{
cal_master_receive_packetnum(); //计算接收数据的个数
status = master_protocol_analysis(Buffer, BufferSize);
memset(Buffer, 0, BufferSize); //清空sx127x接收缓冲区
}
break;
case RF_TX_DONE:
cal_master_send_packetnum(); // 计算发送数据的个数
radio_p->StartRx();
SendDataOkFlag = 1;
break;
case RF_TX_TIMEOUT:
break;
default:
break;
}
return status;
}
蓝牙数据获取的函数如下所示,包含了蓝牙获取数据是否完成的判定以及下一步数据解析接口的调用(函数bluetooth_command和函数bluetooth_data)。
代码语言:javascript复制// 蓝牙数据解析
void Bluetooth_Printer_Sd(void)
{
uint8_t *ble_rxdata = NULL;
uint8_t ble_uart_recv_data_len = strlen(bluetooth_recv_data);
printk("%s .. bluetooth_recv_data = %srn", __FUNCTION__, bluetooth_recv_data);
// 蓝牙命令
if (bluetooth_recv_done_flag == 1)
{
bluetooth_recv_done_flag = 0; // 清标志位
ble_rxdata = malloc(ble_uart_recv_data_len);
if (ble_rxdata == NULL)
{
printf("%s .. ", __FUNCTION__);
perror("malloc");
}
memcpy(ble_rxdata, bluetooth_recv_data, ble_uart_recv_data_len 1); // 拷贝数据
memset(bluetooth_recv_data, '