如下图所示,这就是腾讯定制开发板EVB_G0开发板啦:
关于这款开发板的介绍,详细资料可以参考以下TencentOS官方公众号的两篇DIY作品的文章:
基于TencentOS Tiny&腾讯连连的炫酷物联网智能灯,你值得拥有!
1、DIY项目展示
为了DIY这个简单的小项目,我把它改造成下面这个样子,也加了不少模块,有些功能并没有实现:
先来看下目前的基本功能演示:
2、项目整体框架
3、项目软件主要逻辑
3.1、STM32CubeMX配置
这个模板直接拷贝TencentOS tiny
官方内核BSP包里的,然后我自己再加了一些别的配置进去做了下简单的修改。
3.2、云端与设备交互逻辑
在没有云端指令下发时,设备会定时上传当前环境的光强数值到腾讯云平台,当有云端指令下发时,主要分为以下几种情况:
控制E53_SC1模组上的电灯亮灭
控制外接RGB浪漫彩灯定时闪烁
控制热敏打印机打一周(周一~周日)情书
控制热敏打印机打印云端下发的字符串
根据云平台规定,编写如下Json数据模板脚本:
{ "version": "1.0", "profile": { "ProductId": "WONYDFWVJO", "CategoryId": "539" }, "properties": [ { "id": "power_switch", "name": "电灯开关", "desc": "控制灯光", "required": true, "mode": "rw", "define": { "type": "bool", "mapping": { "0": "关灯", "1": "开灯" } } }, { "id": "power_switch1", "name": "浪漫彩灯", "desc": "控制彩灯", "required": true, "mode": "rw", "define": { "type": "bool", "mapping": { "0": "关彩灯", "1": "开彩灯" } } }, { "id": "lx", "name": "光照强度", "desc": "光照强度", "mode": "r", "define": { "type": "int", "min": "0", "max": "20000", "start": "0", "step": "1", "unit": "lx" }, "required": false }, { "id": "week", "name": "一周情书", "desc": "一周的情书", "mode": "rw", "define": { "type": "enum", "mapping": { "0": "Monday", "1": "Tuesday", "2": "Wednesday", "3": "Thursday", "4": "Friday", "5": "Saturday", "6": "Sunday" } }, "required": false }, { "id": "cloud_print", "name": "云打印机", "desc": "通过云端下发字符串控制打印机打印数据", "mode": "rw", "define": { "type": "string", "min": "0", "max": "2048" }, "required": false } ], "events": [], "actions": []}
在腾讯云平台以及腾讯连连小程序上数据模板展示效果如下:
光强属于上行指令:
memset(report_topic_name, 0, sizeof(report_topic_name));size = snprintf(report_topic_name, TOPIC_NAME_MAX_SIZE, "$thing/up/property/%s/%s", product_id, device_name);if (size < 0 || size > sizeof(report_topic_name) - 1){ printf("pub topic content length not enough! content size:%d buf size:%d", size, (int)sizeof(report_topic_name));}
当设备上线时,平台会收到上行数据,定时显示当前环境下的光强数值:
while (1){ // 读取光照强度,数据存放在 e53_value e53_value = e53_scl_read_data(); printf("e53 value %.0f lx\r\n", e53_value); memset(e53_str, 0, sizeof(e53_str)); sprintf(e53_str, "%.0f lx(lm/m2)", e53_value); OLED_Clear(); OLED_ShowString(0, 0, (uint8_t*)"TencentOS-tiny", 16); OLED_ShowString(0, 2, (uint8_t*)e53_str, 16); // 1. 构造上报的JSON memset(payload, 0, sizeof(payload)); snprintf(payload, sizeof(payload), REPORT_LX_DATA_TEMPLATE, e53_value); // 2. 向数据模板 topic 发布光照强度信息 if (tos_tf_module_mqtt_pub(report_topic_name, QOS0, payload) != 0) { printf("module mqtt pub fail\n"); break; } else { printf("module mqtt pub success\n"); } tos_sleep_ms(7000);}
除了光强以外,其余的参数属性属于下行指令,当平台下发指令时,会触发MQTT做数据订阅功能时的回调函数:default_message_handler
,这部分在初始化的时候就设计好了,代码如下:
// 5. 订阅数据模板 topicsize = snprintf(report_reply_topic_name, TOPIC_NAME_MAX_SIZE, "$thing/down/property/%s/%s", product_id, device_name);if (size < 0 || size > sizeof(report_reply_topic_name) - 1){ printf("sub topic content length not enough! content size:%d buf size:%d", size, (int)sizeof(report_reply_topic_name));}if (tos_tf_module_mqtt_sub(report_reply_topic_name, QOS0, default_message_handler) != 0){ printf("module mqtt sub fail\n");}else{ printf("module mqtt sub success\n");}
该函数会依次对下发的指令进行匹配处理,下发的指令格式是Json,这里我们采用CJson来对数据进行解析:
/**************************************************************** 函数名称: default_message_handler* 说 明: IoT Explorer下行数据处理***************************************************************/static void default_message_handler(mqtt_message_t* msg){ cJSON *root; cJSON *params; cJSON *method; cJSON *week_love; cJSON *power_switch; cJSON *power_switch1; cJSON *cloud_print ; root = cJSON_Parse(msg->payload + 1); if (!root) { printf("Invalid json root\r\n"); return; } method = cJSON_GetObjectItem(root, "method"); if (!method) { printf("Invalid json method\r\n"); cJSON_Delete(root); return; } if (0 != strncmp(method->valuestring, "control", sizeof("control") - 1)) { cJSON_Delete(root); return; } //获取参数 params = cJSON_GetObjectItem(root, "params"); if (!params) { printf("Invalid json params\r\n"); cJSON_Delete(root); return; } //获取power_switch参数 power_switch = cJSON_GetObjectItem(params, "power_switch"); if (power_switch) iot_explorer_handle_power_switch(power_switch->valueint); //获取power_switch1参数 power_switch1 = cJSON_GetObjectItem(params, "power_switch1"); if (power_switch1) iot_explorer_handle_power_switch1(power_switch1->valueint); //获取week参数 week_love = cJSON_GetObjectItem(params, "week"); if(week_love) iot_explorer_handle_week(week_love->valueint); //获取cloud_print参数 cloud_print = cJSON_GetObjectItem(params, "cloud_print"); if(cloud_print) iot_explorer_handle_string(cloud_print->valuestring); cJSON_Delete(root);}
参数功能如下:
- power_switch 参数
控制E53模块上的电灯
调用iot_explorer_handle_power_switch
函数处理。
/**************************************************************** 函数名称: iot_explorer_handle_power_switch* 说 明: 根据power switch控制开关***************************************************************/static void iot_explorer_handle_power_switch(int power_switch){ if (0 == power_switch) { printf("iot-explorer close the light\r\n"); LED_CLOSE; HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET); OLED_Clear(); OLED_ShowString(0, 0, (uint8_t*)"Close Led", 16); } else { printf("iot-explorer open the light\r\n"); LED_OPEN; HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET); OLED_Clear(); OLED_ShowString(0, 0, (uint8_t*)"Open Led", 16); }}
- power_switch1 参数
控制彩灯
调用iot_explorer_handle_power_switch1
函数处理。
/**************************************************************** 函数名称: iot_explorer_handle_power_switch* 说 明: 根据power switch控制彩灯开关***************************************************************/static void iot_explorer_handle_power_switch1(int power_switch){ if (0 == power_switch) { printf("iot-explorer close the color light\r\n"); Controld_Color_LED = 0 ; OLED_Clear(); OLED_ShowString(0, 0, (uint8_t*)"Close Color Led", 16); } else { printf("iot-explorer open the color light\r\n"); Controld_Color_LED = 1 ; OLED_Clear(); OLED_ShowString(0, 0, (uint8_t*)"Open Color Led", 16); }}
- week 参数
控制热敏打印机打印一周的某一天的情书
调用iot_explorer_handle_week
函数处理。
/**************************************************************** 函数名称: iot_explorer_handle_week* 说 明: 根据week控制打印机***************************************************************/static void iot_explorer_handle_week(int week){ //略...}
- cloud_print 参数
控制热敏打印机打印下行字符串
调用iot_explorer_handle_string
函数处理。
/**************************************************************** 函数名称: iot_explorer_handle_string* 说 明: 根据string控制打印机打印字符串***************************************************************/static void iot_explorer_handle_string(char *str){ /*收到情书,则蜂鸣器鸣叫3声进行提醒*/ uint8_t count = 0 ; for(count = 0 ; count < 6 ; count++) { HAL_GPIO_TogglePin(BUZZER_GPIO_Port, BUZZER_Pin); tos_task_delay(500); } HAL_GPIO_WritePin(BUZZER_GPIO_Port, BUZZER_Pin, GPIO_PIN_RESET); printf("云端数据:%s\n", str); OLED_Clear(); OLED_ShowString(0, 0, (uint8_t*)str, 16);}
3.3、热敏打印机模块
热敏打印机用的是上次参加腾讯连连比赛MC-EH205:
【腾讯连连IoT开发大赛】基于TencentOS tiny云打印机&智能达特甲醛探测系统
之前MCU用的是M4的架构,但厂家提供了M3对应的lib和头文件却可以直接被编译兼容,所以驱动起来非常简单,只需要包含对应的库然后调用对应的函数即可:
而本次用的是M0的架构MCU,编译的时候提示不兼容,所以lib也就不适用了,但是没关系,直接参考指令集手册来驱动打印机模块也是可以的。
根据项目要求,我们需要提供发送指令和发送数据的两个函数:
//发送单个字节给打印机void Printf_send_byte(uint8_t data){ /*调度器上锁*/ tos_knl_sched_lock(); HAL_UART_Transmit(&huart3, &data, 1, 1000); while(__HAL_UART_GET_FLAG(&huart3, UART_FLAG_TXE) != SET); /*调度器解锁*/ tos_knl_sched_unlock();}//发送字符串给打印机static void Printf_send_command(char* str){ /*调度器上锁*/ tos_knl_sched_lock(); while(*str) { Printf_send_byte(*str); str++; } /*调度器解锁*/ tos_knl_sched_unlock();}
模块上电需要发送初始化指令:
/*初始化打印设备*/void init_print_device(void){ Printf_send_byte(0x1B); Printf_send_byte(0x40);}
手册说明如下:
接下来就可以愉快的发送字符串给模块打印纸条了,如果发送的字符串显示在纸条上需要对齐的话,则需要根据需求发送文本对齐指令,然后再发送字符串,这样的话打印出来的效果就会按照设定要求进行:
如下所示:
模块的可玩性很高,指令集也兼容了市面上常见的热敏打印机,可以开发出很多有趣好玩的产品。
4、项目开源地址
本节代码已同步到码云的代码仓库中,获取方法如下:
码云仓库:
https://gitee.com/morixinguan/personal-open-source-project/tree/master/6.Love_Letter_printer
获取项目方法:
git clone https://gitee.com/morixinguan/personal-open-source-project.git
我还将之前做的一些项目以及练习例程在近期内全部上传完毕,与大家一起分享交流,如果有任何问题或者对该项目感兴趣,欢迎加我微信:morixinguan一起交流学习。
往期精彩
开源作品:基于RT-Thread 智慧农业监测系统产品级开发
从SD卡拷贝UI资源到QSPI Flash文件系统(仿串口终端显示拷贝过程)
开源作品:基于TencentOS tiny英国达特甲醛探测仪产品级开发(二)
觉得本次分享的文章对您有帮助,随手点[在看]
并转发分享,也是对我的支持。
本文分享自微信公众号 - 嵌入式云IOT技术圈(gh_d6ff851b4069)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。