我用鸿蒙开发一台机器人【萌萌的那种】
目录
0. 说明
大家好我是Hello Kun,正式接触鸿蒙也快9个月了,一直想做一个有意思的极客项目:既能用到鸿蒙特性【ArkUI、原子化服务、碰一碰等】、涉及南北向开发,又能融入实际生活。断断续续,从南到北,粗略过了一遍,终于,近期实现了这一想法。今天,向大家展示个人极客项目–智慧终端机器人MRobot,如下图:





1. 方案设计
1.1 功能需求分析
MRobot = 快捷启动 + 自由移动 + APP交互 + 多设备互联 + 云端控制 + 其他拓展(语音、趣味功能)

- 快捷启动:碰一碰拉起配网页面 | 在“我的服务”中使用卡片启动APP | 桌面卡片 ;
- 自由移动:具备转向、前进、后退等基本运动能力;
- APP交互: 控制机器人移动;
- 多设备互联:通过机器人控制其他设备,如门锁、台灯、风扇、浇水机等;
- 云端控制:基于mqtt协议控制互联设备,无需与机器人配网即可控制,一是解决机器人不在身边的情形(如归家开门),二是提供web端供其他人使用(如舍友手机不是HarmonyOS系统);
- 其他拓展:离线语音交互,对机器人喊话就能控制一切; 可控磁吸配件(给小朋友准备的。),如发光环、交通灯、迷你风扇
1.2 结构设计与硬件选型
参考猫、飞船返回舱等元素,花一天设计出了MRobot,萌不萌仁者见仁啦。硬件选型方面,机器人控制核心毫无疑问hi3861模组;N20小功率电机以及驱动;语音模块使用SU03T;一块800mAh锂电池以及TypeC充放管理模块;蓝牙用于与互联设备通信;几块磁铁预备做配件;左耳有触摸传感,提供oled显示模块或MPU6050选择(不同时使用)。

1.3 控制数据流
- APP:北向APP
- Web: 云端iot服务
- MRobot:智慧终端机器人 小萌
- Union Devices:互联设备,门锁台灯等
- Speaker:语音模块
- Human: 万恶之源

2. 北向App开发
APP基于ArkUI的类web开发范式,大部分使用JS开发。APP将完成各功能页面展示、消息下发功能。整个工程主要参考HarmonyOS Connect设备开发实现,去除掉模板JAVA实现板块,使用JS接口替代。
2.1 新建原子化服务APP
使用OneHop模板新建原子化服务工程,命名MRobot。可参考分享贴碰一碰分享总贴

删除不需要的control模块(基于JAVA),新建一个jscontrol page,这是将是控制主页。参考1.抛除束缚,自定义设备

2.2 UI设计
根据需求分析设计UI,因为第一次写APP,渲染样式没有概念,所以在图片上做文章,对设计的MRobot模型进行渲染后导出图片置于APP中,所有的UI主要用到button、switch、swiper组件,先基于可视化低代码开发,后转为hml(jsctronl page是)。ui总览如下;

- 碰一碰拉起,进入配网页面,提供两个选项,一是正常配网,二是直接进入云端web页面秒控设备。
- 首页作为主控页面(jscontrol page),从上往下依次是:MRobot机器人运动控制、秒控设备(发送消息给机器人,实现互联设备控制)、表情聊天(点击表情发送消息给机器人,机器人做出运动、语音反应);
- 点击更多,将会打开一些隐藏页面,如随机计算、认识宇宙等,主要是面对小朋友,未来增加通关解锁相应技能。
下面总结常用的一些UI能力,方便调试与开发:
2.3 NAN-JS通信
在新建的jsctronl 中需要调用JS通信接口在建立的NAN通道中发送数据,详细参考:2.拥抱JS通信接口,因为是调用JS接口,获取NAN通道deviceInfo十分容易。
例如,发送机器人前进核心代码如下:
在南向开发中对消息进行匹配即可进行相应动作。
2.4 真机测试
APP真机调试算基本技能了,为什么我要单独拿出来呢,因为我入门北向时,遇到一个坑。装双系统的深有体会,Windows时间会慢,于是我给直接调到了UTC+14:00 圣诞岛,现在我已经在过520了(doge);
那么问题来了:AGC平台签名会校验时间,时间不对签名会失败,所以一直用另一台电脑做应用开发,折腾好久才发现自己笔记本时间不对导致签名失败。。。 事实证明,有些问题,坚持下去总会解决的。
3. 南向开发
南向完成MRobot开发、互联设备开发。基于OpenHarmony 1.0.1 LTS对 hi3861 进行资源分配、各模块调试、整机调试、功能验证。
南向难免要面向硬件,MRobot与互联设备电气原理图如下:



3.1 获取OpenHarmony源码
以下是我获取源码的操作以及过程遇到的问题以及解决方法。
顺便提一下,我并没有使用ubuntu环境进行设备开发,因为我发现 DevEco Tools Beta3.1 可以直接编译1.0.1源码。大家可以尝试下windows一站式开发。源码需要修改,配置build选项开启I2C、UART等(MRobot使用了两个串口)。具体操作可参考:0.1.2。
3.2 MRobot碰一碰配网交互
结合winder demo很快就能找出配网接口,配网之后即可接收数据进行设备控制。整体控制流程如下:
核心代码如下(详情可参考:3.南向开发-设备配网):
3.3 互联设备开发

互联设备包括门锁、风扇、台灯、浇水机均使用hi3861模组作为核心板,若有更多设备可以快捷添加。每台设备支持使用蓝牙串口控制、基于mqtt的云端控制。增加web端选择也让非HarmonyOS移动设备控制互联设备,让更多的人享受便利。
下面以门锁为例,给出开发方案:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "wifi_connect.h"
#include "MQTTClient.h"
#include "wifiiot_errno.h"
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"
#include "wifiiot_adc.h"
#include "wifiiot_uart.h"
#include "wifiiot_pwm.h"
#include "hi_uart.h"
#define UART_BUFF_SIZE 1000
#define MQTT_BUFF_SIZE 1000
static const char *data = "MRobot_door\r\n";
uint8_t uart_buff[UART_BUFF_SIZE] = {0};
uint8_t *uart_buff_ptr = uart_buff;
char mqtt_buff[MQTT_BUFF_SIZE] = {0};
static unsigned char sendBuf[1000];
static unsigned char readBuf[1000];
Network network;
void messageArrived(MessageData *data)
{
printf("Message arrived on topic %.*s: %.*s\n", data->topicName->lenstring.len, data->topicName->lenstring.data,
data->message->payloadlen, data->message->payload);
strcpy(mqtt_buff,data->message->payload);
printf("mqtt_buff%s \n",mqtt_buff);
}
static void MyUartInit(void)
{
uint32_t ret;
WifiIotUartAttribute uart_attr = {
.baudRate = 115200,
.dataBits = 8,
.stopBits = 1,
.parity = 0,
};
ret = UartInit(WIFI_IOT_UART_IDX_1, &uart_attr, NULL);
if (ret != WIFI_IOT_SUCCESS)
{
printf("Failed to init uart! Err code = %d\n", ret);
return;
}
}
static void DoorInit(void)
{
GpioInit();
IoSetFunc(WIFI_IOT_IO_NAME_GPIO_10, WIFI_IOT_IO_FUNC_GPIO_10_GPIO);
GpioSetDir(WIFI_IOT_GPIO_IDX_10, WIFI_IOT_GPIO_DIR_OUT);
GpioSetOutputVal(WIFI_IOT_GPIO_IDX_10, 1);
}
void My_servo(int angle)
{
int j = 0;
int k = 20000 / 200;
angle = k * angle;
for (j = 0; j < 5; j++)
{
GpioSetOutputVal(WIFI_IOT_GPIO_IDX_10, 1);
usleep(angle);
GpioSetOutputVal(WIFI_IOT_GPIO_IDX_10, 0);
usleep(20000-angle);
}
}
static void DoorCtr(void)
{
hi_uart_read_timeout(WIFI_IOT_UART_IDX_1, uart_buff_ptr, UART_BUFF_SIZE,10);
printf("Uart1 read door data:%s \n", uart_buff_ptr);
if (uart_buff[0] == '2' && uart_buff[1] == '1')
{
printf("******* 开 门 *****\n");
My_servo(100);
uart_buff[0] ='5';
}
if (mqtt_buff[0] == '2' && mqtt_buff[1] == '1')
{
printf("******* 开 门 *****\n");
My_servo(100);
mqtt_buff[0] ='5';
}
My_servo(180);
printf("******* 门 机 械 复 位 *****\n");
}
static void MQTT_DoorTask(void)
{
WifiConnect("r1", "88888889");
printf("Starting ...\n");
int rc, count = 0;
MQTTClient client;
NetworkInit(&network);
printf("NetworkConnect ...\n");
MyUartInit();
DoorInit();
begin:
NetworkConnect(&network, "我的服务器地址iot页面", 1883);
printf("MQTTClientInit ...\n");
MQTTClientInit(&client, &network, 2000, sendBuf, sizeof(sendBuf), readBuf, sizeof(readBuf));
MQTTString clientId = MQTTString_initializer;
clientId.cstring = "MRobot";
MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
data.clientID = clientId;
data.willFlag = 0;
data.MQTTVersion = 3;
data.keepAliveInterval = 0;
data.cleansession = 1;
printf("MQTTConnect ...\n");
rc = MQTTConnect(&client, &data);
if (rc != 0)
{
printf("MQTTConnect: %d\n", rc);
NetworkDisconnect(&network);
MQTTDisconnect(&client);
osDelay(200);
goto begin;
}
printf("MQTTSubscribe ...\n");
rc = MQTTSubscribe(&client, "web_door_btn", 2, messageArrived);
if (rc != 0)
{
printf("MQTTSubscribe: %d\n", rc);
osDelay(200);
goto begin;
}
while (++count)
{
DoorCtr();
MQTTMessage message;
char payload[30];
message.qos = 2;
message.retained = 0;
message.payload = payload;
sprintf(payload, "message number %d", count);
message.payloadlen = strlen(payload);
if ((rc = MQTTPublish(&client, "door", &message)) != 0)
{
printf("Return code from MQTT publish is %d\n", rc);
NetworkDisconnect(&network);
MQTTDisconnect(&client);
goto begin;
}
osDelay(50);
printf("----- count = %d ------\r\n",count);
}
}
static void MQTT_Door(void)
{
osThreadAttr_t attr;
attr.name = "MQTT_DoorTask";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = 10240;
attr.priority = osPriorityNormal;
if (osThreadNew((osThreadFunc_t)MQTT_DoorTask, NULL, &attr) == NULL)
{
printf("[MQTT_Door] Falied to create MQTT_DoorTask!\n");
}
}
APP_FEATURE_INIT(MQTT_Door);
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
- 145.
- 146.
- 147.
- 148.
- 149.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
- 171.
- 172.
- 173.
- 174.
- 175.
- 176.
- 177.
- 178.
- 179.
- 180.
- 181.
- 182.
- 183.
- 184.
- 185.
- 186.
- 187.
- 188.
- 189.
- 190.
- 191.
- 192.
- 193.
- 194.
- 195.
- 196.
- 197.
- 198.
- 199.
- 200.
- 201.
- 202.
- 203.
- 204.
- 205.
- 206.
- 207.
- 208.
- 209.
- 210.
- 211.
- 212.
- 213.
- 214.
- 215.
- 216.
- 217.
- 218.
- 219.
- 220.
- 221.
- 222.
- 223.
- 224.
- 225.
- 226.
- 227.
- 228.
- 229.
- 230.
- 231.
- 232.
- 233.
- 234.
- 235.
- 236.
- 237.
- 238.
- 239.
- 240.
3.4 南向开发框架总结
MRobot文件框架:

互联设备文件框架:

3.5 趣味配件
给小朋友准备的,大朋友跳过吧。

4. 机器人 demo
直接见视频吧:MRobot 、B站
个人总结
没什么好说的,很多不会,继续坚持,深挖、死磕。
520,恰好生日,给个免费的赞吧! (biu~❤)
一文贯通南北,开发变趣味
哈哈 谢谢总结
有创意,给你点赞
感谢认可!
不明觉厉
完成度非常高,这是下了大功夫了。牛啊!
非常不错值得学习!
太强了,我也想和你一样做一个属于自己的机器人向你学习
一起学习,冲冲冲
硬核啊!兄弟
所以,我们可以云养猫了吗!
好可爱,咱就是说你这卖吗
总结的很全面,优秀
围观学习
哈哈 还没到卖产品的水平,有空了再优化优化