WIFI DTU产品设计与实现(基于STM32F103+QT配置上位机案例设计分享)

简介: WIFI DTU产品设计与实现(基于STM32F103+QT配置上位机案例设计分享)

1 、什么是 WIFI DTU?

1.1 、什么是 DTU ?

DTU (Data Transfer unit),是专门用于将串口数据转换为 IP 数据或将 IP 数据转换为串 口数据通过无线通信网络进行传送的无线终端设备。DTU 广泛应用于气象、水文水利、地质等行业。

1.2 、什么是 WIFI DTU?

使用 WIFI 模组,完成 DTU 的功能,就叫做 WIFI DTU,WIFI DTU 的实现难点在于配网以及后期多端口及多种协议和端口的适配。


前面我们也介绍过,其实通过文件系统ini文件改个参数也可以实现配网:


基于小熊派SD卡+Fatfs+移植开源iniparse解析库并使用

2 、WIFI DTU 市场调研

淘宝和京东上可以看到有类似的 WIFI DTU 产品:

640.png

640.png

640.png

640.png

3 、WIFI DTU 实现方法

3.1 通过一个 MCU+ 一个 WIFI 模组的方式来实现

优点:


1、开发者只需熟悉使用 WIFI 模组的 AT 指令,使用一个 MCU 结合串口 AT 指令与 WIFI 模组 通信,编写软件即可完成 WIFI DTU 的功能,


2、MCU IO 扩展接口丰富,可以拓展实现多种接口的通信,完成更加复杂的 DTU 功能。


3、产品开发出来以后,如有多个拓展 IO,客户可自行根据需求进行二次开发,实现产品。


4、定好 MCU 端的协议,无论后期模组怎么变,一套好的通信协议即可兼容所有模组。


缺点:


1、成本高昂,对于单一只需要与服务器建立连接,发送数据到服务器的需求不太友好,这 样等于把事情复杂化了,硬件成本也相对增加了。


2、需要自行开发配网的上位机或者手机 APP,时间成本增加。


3.2 通过支持二次开发的 WIFI 模组的方式来实现。

优点:


1、成本低廉,因为只有一个模组,极限的利用模组本身的 SDK 即可完成功能需求的开发。


2、通常模组厂已经支持相应的配网协议,可通过手机 app,微信小程序,网页实现配网,模组厂支持力度大,技术也非常成熟。


缺点:


1、对于初学或者无模组 SDK 经验的开发者来说不太友好,正所谓专业的人做专业的事,想 要随时上手任何一款通信模组的 SDK 短时间内很难上手,模组的SDK 多种多样,有用C语言开发的,有用 C++开发的,Lua 语言开发的等等,复杂多化。


2、对于模组 IO 管脚本身就少的来说,拓展其它功能就不太适合了,更别说二次开发。


3、产品更新迭代快,可能你现在用的是这个模组,过一段时间,另一个模组又出来了,如果客户有需求换产品,这时候要做功能迁移,由于模组 SDK 千变万化,开发者也得适应这种规律。

4 市场上常见WIFI DTU的功能

4.1 斐悦极限无线wifi串口服务器

640.png

4.2 常见上位机软件配置功能

640.png

640.png

5、简单小型WIFI DTU设计与实现

5.1 小型WIFI DTU外观及硬件设计

很早之前就做了一些超级简单的小型WIFI DTU,现在就把它开源出来分享给大家,如下图所示,这就是我们设计的DTU。

640.png

此处附上其中一个Demo板子ESP32版本的原理图:

640.png

5.2 小型WIFI DTU与上位机通信协议制定

5.2.1 WIFI模式设置

640.png

5.2.2 WIFI 连接AP指令设置与查询

640.png

5.2.3 WIFI 一键配置SoftAP参数指令设置与查询

640.png

5.2.4 WIFI 建立TCP链接,UDP传输或SSL连接指令设置与查询

640.png

5.2.5 WIFI 模组一键配置参数设置及查询

640.png

5.3 小型WIFI DTU软件设计

5.3.1 STM32CubeMX工程配置

640.png

由于配置参数过多,限于篇幅限制,这里就不贴出来了,见文章最后回复关键字自行下载,谢谢谅解!

5.3.2   软件设计思路

系统初始化以后会读取FLASH,获取配置前透传的设置并打印

struct  Upper_Variable     Upper_Val;
struct  Upper_WFVariable   Upper_ESP32Val;
/******************************************************************************************************************************************************************************
** 函数名:void   DTU_ReadFlash_SetData(struct Upper_WFVariable *Upper_WFVal)
** 功能描述:获取配置前透传的设置并打印
** 输入参数:  Upper_WFVal   存储结构体
** 输出参数:无
** 返回:无
*******************************************************************************************************************************************************************************/
void   DTU_ReadFlash_SetData(void)
{
    memset(ESP32_FlashReadTest, 0, sizeof(ESP32_FlashReadTest));
    Flash_ReadData(SetDebug_Add, ESP32_FlashReadTest);
    strcpy(Upper_Val.Upper_Debug, ESP32_FlashReadTest);
    if(strcmp("0", Upper_Val.Upper_Debug) == 0)
    {
        Debug_f = 0;
    }
    else if(strcmp("1", Upper_Val.Upper_Debug) == 0)
    {
        Debug_f = 1;
    }
    DTU_Flash_GetData(SetDebug_Add, Upper_Val.Upper_Debug, "Debug状态:");
    DTU_Flash_GetData(SetWFMode_Add, Upper_ESP32Val.Upper_SetWFMode, "WIFI模式:");
    DTU_Flash_GetData(SetWFJAP_SSID_Add, Upper_ESP32Val.Upper_SetWFJAP_SSID, "AP模式SSID:");
    DTU_Flash_GetData(SetWFJAP_PWD_Add, Upper_ESP32Val.Upper_SetWFJAP_PWD, "AP模式PWD:");
    DTU_Flash_GetData(SetWFSAP_SSID_Add, Upper_ESP32Val.Upper_SetWFSAP_SSID, "SoftAP模式SSID:");
    DTU_Flash_GetData(SetWFSAP_PWD_Add, Upper_ESP32Val.Upper_SetWFSAP_PWD, "SoftAPAP模式PWD:");
    DTU_Flash_GetData(SetWFCIPSTART_Type_Add, Upper_ESP32Val.Upper_SetWFCIPSTART_Type, "连接的模式:");
    DTU_Flash_GetData(SetWFCIPSTART_RemoteIP_Add, Upper_ESP32Val.Upper_SetWFCIPSTART_RemoteIP, "服务器端的IP:");
    DTU_Flash_GetData(SetWFCIPSTART_RemotePort_Add, Upper_ESP32Val.Upper_SetWFCIPSTART_RemotePort, "服务器端的端口号:");
}

这里的参数存储用结构体Upper_VariableUpper_WFVariable进行维护:

#define  Mode_L         2
#define  SSID_L         20
#define  PWD_L          20
#define  Type_L               5
#define  RemoteIP_L             100
#define  RemotePort_L                   10
struct Upper_Variable
{
    //模组设置模式
    uint8_t Upper_State;
    char  Upper_SetMode[Mode_L];  
    //模组品牌
    char  Upper_ModuleBrand[Mode_L];
    //Debug信息开关
    char  Upper_Debug[Mode_L];        
};
struct Upper_WFVariable
{
    //WIFI的模式设置
    char Upper_SetWFMode[Mode_L];       
    //WIFI的AP模式的SSID
    char Upper_SetWFJAP_SSID[SSID_L];
    //WIFI的AP模式的PWD
    char Upper_SetWFJAP_PWD[PWD_L];                   
    //WIFI的SoftAP的SSID
    char Upper_SetWFSAP_SSID[SSID_L];
    //WIFI的SoftAP的PWD
    char Upper_SetWFSAP_PWD[PWD_L];                   
    //字符串串参数,连接类型,"TCP","UDP" 或 "SSL"
    char Upper_SetWFCIPSTART_Type[Type_L];
    //字符串串参数,远端 IP 地址
    char Upper_SetWFCIPSTART_RemoteIP[RemoteIP_L];
    //IP地址的端口号
    char Upper_SetWFCIPSTART_RemotePort[RemotePort_L];  
};
//建立ESP32结构体和ESP8266结构体;
extern  struct  Upper_WFVariable   Upper_ESP32Val;

WIFI DTU主要有以下模式

/**********************
DTU状态列表
**********************/
enum   DTU_State_List
{
        //系统空闲模式
  DTU_FreeMode = 0,
        //系统存储配置检测模式
  DTU_ConfigurationDetMode, 
        //系统配置设置模式
  DTU_ConfigurationSetMode,
        //系统透传模式
  DTU_PassthroughMode,
        //系统透传数据解析模式
  DTU_DataAnalysisMode, 
        //系统配置模式
  DTU_ConfigurationMode,  
        //系统错误模式
  DTU_ERRORMode,            
};

当用户长按按键时候,进入系统配置模式:

void key_L_CallBack(void)
{
    if(ESP32_STATE_D.ESP32_State != DTU_ConfigurationMode)  
    {
        ESP32_STATE_D.ESP32_State = DTU_ConfigurationMode;
    }
    DEBUG("按键长按\r\n");
}

系统配置模式:

/******************************************************************************************************************************************************************************
** 函数名:void   Upper_State_Dis(void)
** 功能描述:上位机配置状态机
** 输入参数:无
** 输出参数:无
** 返回:无
*******************************************************************************************************************************************************************************/
void   Upper_State_Dis(void)
{
    Upper_RX_Dis();
    Upper_Find_Dis(&Upper_Val);
    Upper_Set_Dis(&Upper_Val);
    switch(Upper_Val.Upper_State)
    {
        case  Upper_FreeMode:
            if(strcmp(Upper_Val.Upper_SetMode, "2") == 0)
            {
                Upper_Val.Upper_State = Upper_ESP32Mode;
                DEBUG("进入ESP32模式\r\n");
            }
            break;
        case    Upper_ESP32Mode:
            Upper_ESP32_ValDis(&Upper_ESP32Val);
            Upper_WFFind_ValDis(&Upper_ESP32Val);
            break;
    }
    Upper_S_bit.Upper_Byte = 0;
    memset(Upper_Rx_Buffer, 0, sizeof(Upper_Rx_Buffer));
}

系统配置模式对应的状态灯做如下处理:

系统状态对应LED灯
*********************************************************************/
if(ESP32_STATE_D.ESP32_State != DTU_ConfigurationMode)//系统空闲模式灯显示
{
    LED_SetColor(0, 1, 0);    //设置颜色为绿色
}
else if(ESP32_STATE_D.ESP32_State == DTU_ConfigurationMode)//系统配置模式灯显示
{
    LED_SetColor(0, 0, 1);    //设置颜色为蓝色
}
else if(ESP32_STATE_D.ESP32_State == DTU_PassthroughMode)//系统配置模式灯显示
{
    LED_SetColor(0, 1, 1);    //设置颜色为紫色
}

当用户短按按键时,进入系统存储配置检测模式,此时判断在系统初始化时读取FLASH的参数的参数,如果没有相应的参数,则用户需要长按按键切换到配置模式进行参数设置。

//系统存储配置检测模式
case DTU_ConfigurationDetMode:    
            DTU_STATE_D.DTU_ConfDep = ESP32_PassthroughDet(&Upper_ESP32Val);
            if(DTU_STATE_D.DTU_ConfDep == ESP32_OK)
            {
                DEBUG("检测到存储的配置信息齐全\r\n");
                ESP32_STATE_D.ESP32_SetModeState = TCP_Step0;
                ESP32_STATE_D.ESP32_State = DTU_ConfigurationSetMode;
            }
            else if(DTU_STATE_D.DTU_ConfDep == ESP32_ERR)
            {
                DEBUG("检测到存储的配置信息有空的\r\n");
                DEBUG("可以长按进入配置模式\r\n");
                DEBUG("配置成功后短按退出配置模式\r\n");
                DEBUG("退出配置模式后自动进入数据透传模式\r\n");
                ESP32_STATE_D.ESP32_State = DTU_ERRORMode;
            }
            break;

系统透传模式:

//系统透传模式
case DTU_PassthroughMode:         
            if(Uart1_Recv_End_Flag)
            {
                DEBUG("tx_len = %d\r\n", Uart1_Rx_Len);     
                DEBUG("发送的数据:%s\r\n", Uart1_Rx_Buffer); 
                Print(&huart2, "%s", Uart1_Rx_Buffer);
                Uart1_Rx_Len = 0;         //清除计数
                Uart1_Recv_End_Flag = 0;  //清除接收结束标志位
                memset(Uart1_Rx_Buffer, 0, sizeof(Uart1_Rx_Buffer));
            }
            if(Uart2_Recv_End_Flag)
            {
                //复位连接超时
                DTU_STATE_D.DTU_TCPLinkTimeOut = Set_TCPLinkTimeOut;    
                DEBUG("rx_len = %d\r\n", Uart2_Rx_Len);         
                DEBUG("接收的数据:%s\r\n", Uart2_Rx_Buffer);     
                Uart2_Rx_Len = 0;         
                Uart2_Recv_End_Flag = 0;  
                memset(Uart2_Rx_Buffer, 0, sizeof(Uart2_Rx_Buffer));
            }
            if(!DTU_STATE_D.DTU_TCPLinkTimeOut)   
            {
                DTU_STATE_D.DTU_TCPLinkCnt ++;
                memset(&ESP32_S_bit, 0, sizeof(ESP32_S_bit));           
                memset(ESP32_Rx_Buffer, 0, sizeof(ESP32_Rx_Buffer));    
                memset(Uart2_Rx_Buffer, 0, sizeof(Uart2_Rx_Buffer));    
                if(DTU_STATE_D.DTU_TCPLinkCnt != Set_TCPLinkCnt)
                {
                    ESP32_STATE_D.ESP32_State = DTU_ConfigurationDetMode;
                }
                else
                {
                    Print(&huart2, "+++");
                    HAL_Delay(200);
                    Print(&huart2, "AT+CIPCLOSE\r\n");
                    HAL_Delay(200);
                    memset(&DTU_STATE_D, 0, sizeof(DTU_STATE_D));           
                    ESP32_STATE_D.ESP32_State = DTU_ERRORMode;
                }
            }
            break;

由于当初特殊原因导致项目没有继续完成下去,所以有几个模式没有实现,但该DTU已经可以实现简单的透传功能了,有兴趣的小伙伴可以自行添加完善这个项目。

上位机配置(基于QT5实现)

由于WIFI DTU的项目是我们之前工作之余在朱友鹏老师指导下实现的,故名为鹏力云,鹏力是指的深圳鹏力电子,云指的是深圳云之手科技,后续我将会在小熊派上将这个STM32版本和QT上位机重新进行整合后发布。

640.png

感兴趣的小伙伴可自行下载代码编译,与DTU硬件进行联调。

640.png

640.png

640.png

640.png

开源项目资料下载

公众号后台回复:DTU 即可获取下载链接。

往期精彩

分享一个近期开源火爆全网的额温枪方案(硬件+源码)


火爆全网开源额温枪同平台之华大HC32L136 SDK开发入门


深圳云之手科技开源炫酷RGB灯板DIY项目


云之手红外式测温计产品设计分享(基于合泰BH67F2752方案)


STM32F103产品级开源项目:iLook.Time设计解读

目录
相关文章
|
2月前
|
IDE 开发工具 C++
QT案例IDE编写 -- 创建项目
QT案例IDE编写 -- 创建项目
26 0
|
2月前
|
数据挖掘 C++
QT基础入门——项目案例(七)
QT基础入门——项目案例(七)
97 0
QT基础入门——项目案例(七)
|
4月前
|
中间件 编译器 调度
STM32cubemx对FreeRTOS的适配(工程模板配置)
STM32cubemx对FreeRTOS的适配(工程模板配置)
83 0
|
5月前
|
设计模式 容器
34 QT - 聊天案例
34 QT - 聊天案例
59 0
|
2月前
|
编解码 IDE 开发工具
QT案例IDE编写 -- 另存为操作及编辑操作
QT案例IDE编写 -- 另存为操作及编辑操作
18 0
|
2月前
|
存储 自然语言处理
QT案例词典 -- 存储内容及遍历
QT案例词典 -- 存储内容及遍历
12 1
|
2月前
|
自然语言处理
QT案例词典 -- 释放堆区空间及查询单词
QT案例词典 -- 释放堆区空间及查询单词
17 1
|
2月前
|
编解码 IDE 开发工具
QT案例IDE编写 -- 通过枚举实现编码切换
QT案例IDE编写 -- 通过枚举实现编码切换
13 0
|
2月前
|
IDE 开发工具 C语言
QT案例IDE编写 -- 代码编写
QT案例IDE编写 -- 代码编写
22 0
|
2月前
|
IDE 开发工具 C语言
QT案例IDE编写 -- 编译操作
QT案例IDE编写 -- 编译操作
15 0

推荐镜像

更多