一、准备工作
在开发之前,我们需要
1.创建自己的开发者账号:创建账号-领取语音接入优惠券
**现在注册还能再五个工作日内领取语音接入优惠券
2.准备MCU开发板及软件开发环境
说明:本文中使用以下设备进行开发实践。
- 开发环境为KEIL5。
- 开发板TYDE3.0。TYDE3.0 涂鸦智能 IoT开发板使用说明
MCU为ST公司生产的STM32F103C8T6。
通信模组为杭州涂鸦科技有限公司开发的高性能Wi-Fi模块TYWE1S。(WiFi 模组介绍–TYWE1S)
二、创建产品
这里我们以照明为例。
操作步骤
1.登录涂鸦智能平台(创建账号-领取语音接入优惠券),点击创建产品
2.创建产品
a. 选择您的产品开发模式。目前涂鸦可提供自定义产品开发和Soc产品在线开发两种产品智能化模式,您可以按需选择。我们这里选择照明-自定义-照明。
b. 填写产品信息。选择产品类别,点击图标,填写您的产品名称并选择通信方式。
c. 选择产品功能。您可以根据实际情况选择产品功能,可以全选,也可以单独添加或取消,完成后点击“添加选中功能”即可。如果一时还不是非常明确功能,没有关系,创建完成后可以再次编辑,也可以自定义添加功能和开启所需的云功能。
d. 选择APP界面样式。App控制界面是智能产品的皮肤。我们已经提供了不同样式的模板供选择,你可根据样式喜好及产品功能综合进行选择。(企业账号会有更多面板选择,账号升级可联系商务同学)
e. 创建成功,立即体验。使用选中的模板,产品即创建成功,并且可以立即用手机扫码体验你的产品。值得注意的是,需要用“涂鸦智能App”中的“扫一扫”功能才可以哦。
此时,手机上已经可以预览你的产品,体验产品功能及界面样式。
三、 开发设备端
本示例中使用TYDE3.0开发板。
3.1开发板示意图
3.2连接硬件
将MCU和Wi-Fi模块TYWE1S的接收和发送串口连接,如下图所示:
3.3配网验证
本示例长按按键1即可重置WiFi,使其进入配网模式。
配网模式分两种:
a. smart(EZ)模式。广播模式,一对多,操作简单。但在网络环境复杂或者不支持smart配置的路由器时,有可能配网不成功。
b. AP(兼容)模式。一对一,操作稍复杂,配网稳定可靠。
触发机制可以自定义,以指示灯快闪、慢闪做区分。
smart模式配网:
进入app,点击右上角“+”符号添加设备
选择相应设备照明-照明(Wi-Fi)
确认指示灯快闪
输入Wi-Fi密码
等待一段时间即可配网成功
AP模式配网:
进入app,点击右上角“+”符号添加设备
选择相应设备照明-照明(Wi-Fi)
点击右上角“兼容模式”
确认指示灯慢闪
输入Wi-Fi密码
将手机Wi-Fi连接到设备热点“smart_xxxx”
返回app等待一段时间即可配网成功
需要注意:
指示灯状态与APP配网状态一致。如不一致,请先切换设备配网状态或app配网状态,使其一致。
路由器2.4G信号。目前搭载涂鸦模块的Wi-Fi设备只支持2.4G的信号,如果是非2.4G信号的路由器设备则无法扫描到该路由器,从而无法正常连接上路由器进行工作。
确保密码输入正确。路由器、手机、设备距离尽可能缩短。
四. 移植SDK实战
您可以在产品开发的第三步“硬件调试”这里下载MCU SDK。
mcu_sdk包是根据涂鸦开发平台上定义的产品功能,自动生成的MCU代码。通讯及协议解析架构已写好,可直接添加到原有MCU工程中,快速完成MCU程序开发。
详细步骤请参考:
涂鸦SDK软件移植步骤
五. SDK 函数架构解析
六. 关键函数说明
6.1配网函数
重置WiFi
函数名称 : reset_wifi
功能描述 : MCU主动重置wifi工作模式
输入参数 : 无
返回参数 : 无
使用说明 : 1:MCU主动调用,通过mcu_get_reset_wifi_flag()函数获取重置wifi是否成功
2:如果为模块自处理模式,MCU无须调用该函数
*****************************************************************************/
void mcu_reset_wifi(void)
{
reset_wifi_flag = RESET_WIFI_ERROR;
wifi_uart_write_frame(WIFI_RESET_CMD, 0);
}
选择smartconfig/AP模式
/*****************************************************************************
函数名称 : mcu_set_wifi_mode
功能描述 : MCU设置wifi工作模式
输入参数 : mode:
SMART_CONFIG:进入smartconfig模式
AP_CONFIG:进入AP模式
返回参数 : 无
使用说明 : 1:MCU主动调用
2:成功后,可判断set_wifi_config_state是否为TRUE;TRUE表示为设置wifi工作模式成功
3:如果为模块自处理模式,MCU无须调用该函数
*****************************************************************************/
void mcu_set_wifi_mode(unsigned char mode)
{
unsigned char length = 0;
set_wifimode_flag = SET_WIFICONFIG_ERROR;
length = set_wifi_uart_byte(length, mode);
wifi_uart_write_frame(WIFI_MODE_CMD, length);
}
6.2功能函数
所有DP****数据上报
在模块重启或者重新配网后,WiFi模块主动下发状态查询指令,此时需要MCU上报设备所有DP状态给WiFi模块进行同步
把所有需要上报的DP点初值填入相应上报函数,为面板提供开机显示初值。
注意:用户请勿随意调用all_data_update()函数,该函数会在特定时间主动调用。
单个DP****数据上报
在某DP点状态发生变化时,mcu需要主动上报,APP会更新显示。
上报格式为 mcu_dp_xxxx_updata(DPID_X,n),DPID_X为状态改变的DP点。
all_data_update()内的函数,均可单独调用。
以开关DP数据为例:
mcu_dp_bool_update(DPID_LED_SWITCH,FlashBuffer.led_switch); //BOOL型数据上报;
DP****数据下发处理函数
在protocol.c文件中,每个可下发的DP点,都有一个单独下发数据处理函数。格式为dp_download_xxx_handle(),xxx为可下发DP点。函数解析功能点之后,MCU需在相应位置完成逻辑控制。
以接收到开关DP数据为例:
/*****************************************************************************
函数名称 : dp_download_led_switch_handle
功能描述 : 针对DPID_LED_SWITCH的处理函数
输入参数 : value:数据源数据
: length:数据长度
返回参数 : 成功返回:SUCCESS/失败返回:ERROR
使用说明 : 可下发可上报类型,需要在处理完数据后上报处理结果至app
*****************************************************************************/
static unsigned char dp_download_led_switch_handle(const unsigned char value[], unsigned short length)
{
//示例:当前DP类型为BOOL
unsigned char ret;
//0:关/1:开
unsigned char led_switch;
uint8_t colour_r,colour_g,colour_b;
led_switch = mcu_get_dp_download_bool(value,length);
if(led_switch == 0)
{
//开关关
LED_RGB_Control(0,0,0);
}
else
{
//开关开
switch(FlashBuffer.work_mode)
{
case 0:
LED_RGB_Control(FlashBuffer.bright_value,FlashBuffer.bright_value,FlashBuffer.bright_value);
break;
case 1:
colour_r = hex_to_bcd(FlashBuffer.colour[0],FlashBuffer.colour[1]);
colour_g = hex_to_bcd(FlashBuffer.colour[2],FlashBuffer.colour[3]);
colour_b = hex_to_bcd(FlashBuffer.colour[4],FlashBuffer.colour[5]);
LED_RGB_Control(colour_r,colour_g,colour_b);
break;
case 2:
colour_r = hex_to_bcd(FlashBuffer.scene[0],FlashBuffer.scene[1]);
colour_g = hex_to_bcd(FlashBuffer.scene[2],FlashBuffer.scene[3]);
colour_b = hex_to_bcd(FlashBuffer.scene[4],FlashBuffer.scene[5]);
LED_RGB_Control(colour_r,colour_g,colour_b);
break;
}
}
Earse_Flash(PARA_ADDR);
FlashBuffer.led_switch = led_switch;
if(Write_Flash(PARA_ADDR,(unsigned char *)&FlashBuffer,sizeof(FlashBuffer)) == ERROR)
{
return ERROR;
}
//处理完DP数据后应有反馈
ret = mcu_dp_bool_update(DPID_LED_SWITCH,led_switch);
if(ret == SUCCESS)
return SUCCESS;
else
return ERROR;
}
MCU_ON_switch1()和MCU_OFF_switch1()为MCU控制开关函数,完成具体动作。当设备状态在非APP控制下发生变化,MCU中需要调用
mcu_dp_bool_update(DPID_SWITCH_1,switch_1);
上传功能点(开关)状态实时状态,形成反馈,一般接收处理函数已经自动调用该函数。
6.3 WiFi功能测试
说明:
(1)模块内部目前扫描指定的 SSID: tuya_mdev_test,返回扫描结果和信号强度百分比。
(2)这里为了最大程度防止不良品这里建议客户将路由于设备距离控制在 5 米左右,信号强度大于等于 60%为合格,这里可以根据自己产线和工厂环境的情况自行调整。
宏定义:
6:MCU是否需要支持wifi功能测试
如需要请开启该宏,并且mcu在需要wifi功能测试处调用mcu_api.c文件内mcu_start_wifitest
并在protocol.c文件wifi_test_result函数内查看测试结果,
wifi_test_result内部有#err提示,完成函数后请删除该#err
******************************************************************************/
#define WIFI_TEST_ENABLE //开启WIFI产测功能
MCU发起WiFi功能测试:
#ifdef WIFI_TEST_ENABLE
/*****************************************************************************
函数名称 : mcu_start_wifitest
功能描述 : mcu发起wifi功能测试
输入参数 : 无
返回参数 : 无
使用说明 : MCU需要自行调用该功能
*****************************************************************************/
void mcu_start_wifitest(void)
{
wifi_uart_write_frame(WIFI_TEST_CMD,0);
}
#endif
6.4 OTA设置
打开SDK中protocol.h打开宏定义2.选择关键字PACKGE_SIZE的大小为256
/******************************************************************************
2:MCU是否需要支固件升级
如需要支持MCU固件升级,请开启该宏
MCU可调用mcu_api.c文件内的mcu_firm_update_query()函数获取当前MCU固件更新情况
********WARNING!!!**********
当前接收缓冲区为关闭固件更新功能的大小,固件升级包为256字节
如需要开启该功能,串口接收缓冲区会变大
******************************************************************************/
#define SUPPORT_MCU_FIRM_UPDATE //开启MCU固件升级功能(默认关闭)
/******************************************************************************
3:定义收发缓存:
如当前使用MCU的RAM不够,可修改为24
******************************************************************************/
#ifndef SUPPORT_MCU_FIRM_UPDATE
#define WIFI_UART_QUEUE_LMT 16 //数据接收队列大小,如MCU的RAM不够,可缩小
#define WIFI_UART_RECV_BUF_LMT 24 //根据用户DP数据大小量定,必须大于24
#else
#define WIFI_UART_QUEUE_LMT 128 //数据接收队列大小,如MCU的RAM不够,可缩小
#define WIFI_UART_RECV_BUF_LMT 300 //固件升级缓冲区,需大缓存,必须大于260
#endif
#define WIFIR_UART_SEND_BUF_LMT 24 //根据用户DP数据大小量定,必须大于24
/******************************************************************************
MUC进入固件升级代码在protocol.c中,并且修改升级完成后的版本号。
*****************************************************************************/
unsigned char mcu_firm_update_handle(const unsigned char value[],unsigned long position,unsigned short length)
{
// #error "请自行完成MCU固件升级代码,完成后请删除该行"
unsigned long addr;
if(length == 0)
{
#ifdef ENABLE_BOOT
//固件数据发送完成
FlashBuffer.magic_code = FIREWARE_UPDATE_FLAG;
if(Earse_Flash(PARA_ADDR) == ERROR)
return ERROR;
//写入升级标志
if(Write_Flash(PARA_ADDR,(unsigned char *)&FlashBuffer,sizeof(FlashBuffer)) == ERROR)
return ERROR;
Reset();
#endif
}
else
{
//固件数据处理
addr = FIREWARE_ADDR_H;
if(position % 1024 == 0)
{
if(Earse_Flash(addr + position) == ERROR)
return ERROR;
}
if(Write_Flash(addr + position,(unsigned char *)value,length) == ERROR)
return ERROR;
}
return SUCCESS;
}
#endif
五、. OTA功能相关说明
5.1协议介绍
(1)说明:模块仅作为支持,MCU 升级的数据传输通道,也不对数据内容做任何解析
(2)4种升级方式:app 提醒升级、app 静默升级、app 强制升级、app 检测升级。
(3)MCU 升级相关流程图:
WIFI 模块发送完所有的升级包,重新发送 01 命令字(3.2 查询产品信息)MCU 需要一分钟回复产品信息中的软件版本号带上升级后的 MCU 版本号,版本号需要和在涂鸦后台配置升级的版本号保持一致。
1. 升级启动(升级包大小通知)
模块发送:
字段 长度(byte) 说明
帧头 2 0x55aa
版本 1 0x03
命令字 1 0x0a
数据长度 2 0x0004
数据 4 固件包字节数,unsigned int, 大端
校验和 1 从帧头开始按字节求和得出的结果对256求余
例:0x55aa 00 0a 0004 00006800 75(固件包长度 26624,即 26KB)
MUC返回:
字段 长度(byte) 说明
帧头 2 0x55aa
版本 1 0x03
命令字 1 0x0a
数据长度 2 0x0001
数据 1 升级包分包传输大小: 0x00:默认 256byte(兼容旧 固件) 0x01:512byte 0x02:1024byte
校验和 1 从帧头开始按字节求和得出的结果对256求余
例:0x55aa 03 0a 0001 00 0d
MUC返回:
字段 长度(byte) 说明
帧头 2 0x55aa
版本 1 0x03
命令字 1 0x0a
数据长度 2 0x0001
数据 1 升级包分包传输大小: 0x00:默认 256byte(兼容旧 固件) 0x01:512byte 0x02:1024byte
校验和 1 从帧头开始按字节求和得出的结果对256求余
例:0x55aa 03 0a 0001 00 0d
2. 升级包传输
升级包传输数据格式:包偏移(unsigned short) + 包数据
MCU 若收到该帧数据长度为 4 且包偏移>=固件大小,则包传输结束
模块发送返回:
字段 长度(byte) 说明
帧头 2 0x55aa
版本 1 0x03
命令字 1 0x0b
数据长度 2 0x0004+数据包长度
数据 N 前四字节,固定为包偏移, 后面为数据包内容
校验和 1 从帧头开始按字节求和得出的结果对256求余
若要升级的文件大小 530Byte,(最后一包数据可不回复)
(1) 第一包数据,包偏移为 0x00000000,数据包长度为 256
0x55aa 00 0b 0104 00000000 xx…xx XX
(2) 第二包数据,包偏移为 0x00000100,数据包长度为 256
0x55aa 00 0b 0104 00000100 xx…xx XX
(3) 第三包数据,包偏移为 0x00000200,数据包长度为 18
0x55aa 00 0b 0016 00000200 xx…xx XX
(4) 最后一包,包偏移为 0x00000212,数据包长度为 0
0x55aa 00 0b 0004 00000212 xx…xx XX
MCU返回:
字段 长度(byte) 说明
帧头 2 0x55aa
版本 1 0x03
命令字 1 0x0b
数据长度 2 0x0000
数据 N 无
校验和 1 从帧头开始按字节求和得出的结果对256求余
例:0x55aa 03 0b 0000 0d |
|