DIY云端情书打印机(基于腾讯定制开发板)
扫描二维码
随时随地手机看文章
如下图所示,这就是腾讯定制开发板EVB_G0开发板啦:
关于这款开发板的介绍,详细资料可以参考以下TencentOS官方公众号的两篇DIY作品的文章:
TencentOS Tiny手把手教您自制智能甲醛监测仪
基于TencentOS Tiny&腾讯连连的炫酷物联网智能灯,你值得拥有!
1、DIY项目展示
为了DIY这个简单的小项目,我把它改造成下面这个样子,也加了不少模块,有些功能并没有实现:
先来看下目前的基本功能演示:
2、项目整体框架
3、项目软件主要逻辑
3.1、STM32CubeMX配置
这个模板直接拷贝TencentOS tiny官方内核BSP包里的,然后我自己再加了一些别的配置进去做了下简单的修改。
3.2、云端与设备交互逻辑
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. 订阅数据模板 topic
size = 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一起交流学习。
免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!