DIY云端情书打印机(基于腾讯定制开发板)

Stella981
• 阅读 669

如下图所示,这就是腾讯定制开发板EVB_G0开发板啦:

DIY云端情书打印机(基于腾讯定制开发板)

关于这款开发板的介绍,详细资料可以参考以下TencentOS官方公众号的两篇DIY作品的文章:

TencentOS Tiny手把手教您自制智能甲醛监测仪

基于TencentOS Tiny&腾讯连连的炫酷物联网智能灯,你值得拥有!

1、DIY项目展示

为了DIY这个简单的小项目,我把它改造成下面这个样子,也加了不少模块,有些功能并没有实现:

DIY云端情书打印机(基于腾讯定制开发板)

DIY云端情书打印机(基于腾讯定制开发板)

DIY云端情书打印机(基于腾讯定制开发板)

先来看下目前的基本功能演示:

DIY云端情书打印机(基于腾讯定制开发板)

2、项目整体框架

DIY云端情书打印机(基于腾讯定制开发板)

DIY云端情书打印机(基于腾讯定制开发板)

3、项目软件主要逻辑

3.1、STM32CubeMX配置

DIY云端情书打印机(基于腾讯定制开发板)

这个模板直接拷贝TencentOS tiny官方内核BSP包里的,然后我自己再加了一些别的配置进去做了下简单的修改。

DIY云端情书打印机(基于腾讯定制开发板)

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": []}

在腾讯云平台以及腾讯连连小程序上数据模板展示效果如下:

DIY云端情书打印机(基于腾讯定制开发板)

DIY云端情书打印机(基于腾讯定制开发板)

光强属于上行指令:

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);}

DIY云端情书打印机(基于腾讯定制开发板)

DIY云端情书打印机(基于腾讯定制开发板)

除了光强以外,其余的参数属性属于下行指令,当平台下发指令时,会触发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和头文件却可以直接被编译兼容,所以驱动起来非常简单,只需要包含对应的库然后调用对应的函数即可:

DIY云端情书打印机(基于腾讯定制开发板)

而本次用的是M0的架构MCU,编译的时候提示不兼容,所以lib也就不适用了,但是没关系,直接参考指令集手册来驱动打印机模块也是可以的。

DIY云端情书打印机(基于腾讯定制开发板)

根据项目要求,我们需要提供发送指令和发送数据的两个函数:

//发送单个字节给打印机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);} 

手册说明如下:

DIY云端情书打印机(基于腾讯定制开发板)

接下来就可以愉快的发送字符串给模块打印纸条了,如果发送的字符串显示在纸条上需要对齐的话,则需要根据需求发送文本对齐指令,然后再发送字符串,这样的话打印出来的效果就会按照设定要求进行:

DIY云端情书打印机(基于腾讯定制开发板)

如下所示:

DIY云端情书打印机(基于腾讯定制开发板)

模块的可玩性很高,指令集也兼容了市面上常见的热敏打印机,可以开发出很多有趣好玩的产品。

4、项目开源地址

本节代码已同步到码云的代码仓库中,获取方法如下:

DIY云端情书打印机(基于腾讯定制开发板)

码云仓库:

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一起交流学习。

DIY云端情书打印机(基于腾讯定制开发板)

往期精彩

一个超酷的开源uHand2.0机械手掌项目

开源作品:基于RT-Thread 智慧农业监测系统产品级开发

从SD卡拷贝UI资源到QSPI Flash文件系统(仿串口终端显示拷贝过程)

开源作品:基于TencentOS tiny英国达特甲醛探测仪产品级开发(二)

觉得本次分享的文章对您有帮助,随手点[在看]并转发分享,也是对我的支持。

本文分享自微信公众号 - 嵌入式云IOT技术圈(gh_d6ff851b4069)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Stella981 Stella981
3年前
Docker 部署SpringBoot项目不香吗?
  公众号改版后文章乱序推荐,希望你可以点击上方“Java进阶架构师”,点击右上角,将我们设为★“星标”!这样才不会错过每日进阶架构文章呀。  !(http://dingyue.ws.126.net/2020/0920/b00fbfc7j00qgy5xy002kd200qo00hsg00it00cj.jpg)  2
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这