#夏日挑战赛# 开发一个折叠屏micro的智能风扇案例 原创 精华
一.前言
自从去年12月底无意中得知小熊派发布了一款折叠屏开发板,就一直心心念念的想要弄一块玩玩,当然花钱买是不能买的,就等着哪天意外能得到,这次意外终于来了,开发板顺利到手,因为一直在智能家居物联网行业,肯定先做一个物联网的智能家居小案例出来啦.
先爆美照:
二.开发环境搭建和代码获取
因为我也算"老鸿蒙"了,自己亲手和不亲手搭建的环境有一百多份了,搭建环境这肯定难不到我了,然后就是代码拉取了,跑到小熊派官方仓库去:https://gitee.com/bearpi/bearpi-hm_micro_small
先fork到自己仓库来,然后克隆下载一气呵成,美滋滋.
三.驱动编写
驱动这块就是用的官方的E53案例的驱动,使用的是IA1智慧农业,唯一不同的是我这边风扇不是直接GPIO驱动的,而是采用PWM驱动,具体请看代码:
int E53_IA1_Init(void)
{
E53_GPIOInit(E53_IA1_LIGHT_GPIO,E53_GPIO_Out_PullNone);
#if (defined MOTOR_WITH_PWM )&& (MOTOR_WITH_PWM==1)
E53_PWMOpen(3);
E53_PWMSetPeriod(4000);
E53_PWMSetPolarity(0);
// E53_PWMSetDuty(1);
// E53_PWMStart();
#else
E53_GPIOInit(E53_IA1_MOTOR_GPIO,E53_GPIO_Out_PullNone);
#endif
E53_IICOpen();
int ret0, ret1;
ret0 = Init_BH1750();
ret1 = Init_SHT30();
OsalMDelay(180);
return ret0 | ret1;
}
int E53_IA1_SetFanLevel(int level)
{
int ret = -1;
#if (defined MOTOR_WITH_PWM )&& (MOTOR_WITH_PWM==1)
if(level == 0){
ret = E53_PWMStop();
}else{
if(level >5){
level = 5;
}
E53_PWMSetDuty( (level*20)*MOTOR_DEFAULT_PERIOD/100 - 1);
ret = E53_PWMStart();
}
#else
ret = E53_GPIOWrite(E53_IA1_LIGHT_GPIO,level? 1:0);
#endif
return ret;
}
这里采用PWM通道3来达到控制风扇的目的,至于为什么是通道3,那个pwm的hcs文件里面写了呀(由原理图可知,风扇就在PA6):
还有一点需要注意的:这里的E53_PWMSetDuty()接口传入的并不是常见的百分比,而是一个实际的数字,如果我们需要按百分比调节马达的转速,需要自己去进行转化.
四.界面编写
界面这里用DevcoStudio3Beta4编写,首先要去官网下载工具,然后再创建工程,注意创建工程的时候选择(Lite)Empty Ablility,如下图:
然后是相关参数的填写,注意设备类型选SmartVision智慧屏:
然后就进入工程界面了,等待一会等系统配置好工程之后,打开右边的模拟器,添加一个新设备或者修改设备的分辨率为800*480,如下图:
做好这些事情之后就可以安心的编写界面了,值得一提的是,API6还有好多东西不支持,比如button组建,竟然没有,比如图片的缩放属性:object-fit就没有 用图片的时候就相当难受了,只能忍一忍吧,还能怎么办,期待早点做好.
值得一提的是,咱们OpenHarmony的北向编程是有专门的教程网址的,大家可别迷路了:
https://docs.openharmony.cn/pages/v3.1/zh-cn/application-dev/application-dev-guide.md/
下面是我的拙作及相关代码:
模拟器界面:
实际界面会有点不同:
相关hml代码:
<div class="container">
<div class="title-view">
<text class="btn_exit" onclick="onExit">
{{textExit}}
</text>
<text onclick="onSetting">
设置
</text>
</div>
<text class="title">
{{ title }}
</text>
<image class="img" src="/common/head.png"> </image>
<text >当前风速:{{currentLevel}}</text>
<slider class="fan-level" min="0" max="5" value="0" step="1" mode="inset" showtips="true" onchange="setLevel"></slider>
<div class="led-div">
<text >LED灯</text>
<switch class="led-switch" showtext="true" texton="open" textoff="close" checked="true" @change="switchChange"></switch>
</div>
</div>
css代码:
.container {
width: 100%;
height: 100%;
justify-content: flex-start;
align-items: center;
flex-direction: column;
}
.title {
width: 100%;
font-size: 30px;
justify-content: center;
text-align: center;
/* align-items: center;*/
/* flex-direction: row;*/
}
.img{
width:120px;
height: 120px;
justify-content: center;
object-fit: cover;
}
.led-div{
flex-direction: row;
width:100%;
height: 50;
justify-content: space-around;
}
.title-view{
width:100%;
height: 50;
flex-direction: row;
justify-content: space-between;
}
.fan-level{
flex-direction: row;
scrollbar-color: aqua;
background-color: #b7e3f3;
width:400;
height: 50;
}
.btn_exit{
font-size: 30fp;
background-color: red;
align-items: center;
/* width:60;*/
/* height: 30;*/
}
.led-switch{
width: 50;
height: 50;
}
.prg{
width:100px;
height: 100px;
justify-content: center;
/* object-fit: contain;*/
}
然后是js代码:
import app from "@system.app"
export default {
data: {
textExit:"<退出",
title: "物联风景-智能风扇",
currentLevel:0,
},
onInit() {
},
onExit() {
console.log("on exit")
app.terminate()
},
setLevel(e){
this.currentLevel = e.value;
console.debug("fan level " +e.value+" send success")
app.fan_level({
level:e.value,
success:(res) =>{
console.log("fan level send success:"+res)
} ,
fail:(res,code) =>{
console.log("fan level send failed:"+res+",code:"+code)
} ,
complete:() =>{
console.log("fan level complete")
} ,
})
},
switchChange(e){
if(e.checked){
console.debug("打开灯")
}else{
console.debug("关闭灯")
}
app.set_led({
onOff:e.checked ? 1 : 0 ,
success:(res) =>{
console.debug("set_led send success:"+res)
} ,
fail:(res,code) =>{
console.debug("set_led send failed:"+res+",code:"+code)
} ,
complete:() =>{
console.debug("set_led complete")
} ,
})
},
}
五.JSI接口添加
在liteOS-a内核上,想要用UI控制硬件,就必须制作JSI接口,这个在小熊派官方文档里面也有介绍,制作JSI接口之前必须保证命令行方式绑定服务和驱动都OK,这里给出小熊派的官方文档吧:
https://gitee.com/bearpi/bearpi-hm_micro_small/blob/master/applications/BearPi/BearPi-HM_Micro/docs/device-dev/通过JS应用控制LED灯.md
然后是北向编程的文档地址:
https://gitee.com/bearpi/bearpi-hm_micro_app/blob/master/docs/led控制案例.md
有的这些地址,你也能通过漂亮的UI界面来控制硬件了.
下面的我的代码示例:
JSIValue AppModule::FanLevel(const JSIValue thisVal, const JSIValue* args, uint8_t argsNum)
{
HILOG_INFO(HILOG_MODULE_ACE, "==> FanLevel\n");
struct HdfIoService *serv = HdfIoServiceBind(E53_IA1_SERVICE);
if (serv == NULL)
{
HILOG_ERROR(HILOG_MODULE_ACE,"fail to get service %s\n", E53_IA1_SERVICE);
return JSI::CreateUndefined();
}
if ((args == nullptr) || (argsNum == 0) || (JSI::ValueIsUndefined(args[0]))) {
return JSI::CreateUndefined();
}
JSIValue success = JSI::GetNamedProperty(args[0], CB_SUCCESS);
JSIValue fail = JSI::GetNamedProperty(args[0], CB_FAIL);
JSIValue complete = JSI::GetNamedProperty(args[0], CB_COMPLETE);
int cmd = E53_IA1_FanLevel;
// int32_t cmd = (int32_t)JSI::GetNumberProperty(args[0], "cmd");
int level= (int)JSI::GetNumberProperty(args[0], "level");
char data =level+'0';
HILOG_ERROR(HILOG_MODULE_ACE, "cmd is: %d\n", cmd);
HILOG_ERROR(HILOG_MODULE_ACE,"level is: %d\n", level);
HILOG_ERROR(HILOG_MODULE_ACE,"data is: %c\n", data);
char *replyData;
if (E53IA1Control(serv, cmd, &data, &replyData))
{
HILOG_ERROR(HILOG_MODULE_ACE,"fail to send event\n");
JSI::CallFunction(fail, thisVal, nullptr, 0);
JSI::CallFunction(complete, thisVal, nullptr, 0);
JSI::ReleaseValueList(success, fail, complete);
return JSI::CreateUndefined();
}
JSIValue result = JSI::CreateObject();
JSI::SetStringProperty(result, "fan level", replyData);
JSIValue argv[ARGC_ONE] = {result};
JSI::CallFunction(success, thisVal, argv, ARGC_ONE);
JSI::CallFunction(complete, thisVal, nullptr, 0);
JSI::ReleaseValueList(success, fail, complete, result);
HdfIoServiceRecycle(serv);
return JSI::CreateUndefined();
}
JSIValue AppModule::SetLed(const JSIValue thisVal, const JSIValue* args, uint8_t argsNum)
{
HILOG_INFO(HILOG_MODULE_ACE, "==> SetLed\n");
struct HdfIoService *serv = HdfIoServiceBind(E53_IA1_SERVICE);
if (serv == NULL)
{
HILOG_ERROR(HILOG_MODULE_ACE,"fail to get service %s\n", E53_IA1_SERVICE);
return JSI::CreateUndefined();
}
if ((args == nullptr) || (argsNum == 0) || (JSI::ValueIsUndefined(args[0]))) {
return JSI::CreateUndefined();
}
JSIValue success = JSI::GetNamedProperty(args[0], CB_SUCCESS);
JSIValue fail = JSI::GetNamedProperty(args[0], CB_FAIL);
JSIValue complete = JSI::GetNamedProperty(args[0], CB_COMPLETE);
int cmd = E53_IA1_SetLight;
// int32_t cmd = (int32_t)JSI::GetNumberProperty(args[0], "cmd");
int onOff= (int)JSI::GetNumberProperty(args[0], "onOff");
const char *data = onOff ? "ON" : "OFF";
HILOG_ERROR(HILOG_MODULE_ACE, "cmd is: %d\n", cmd);
HILOG_ERROR(HILOG_MODULE_ACE,"data is: %s\n", data);
char *replyData;
if (E53IA1Control(serv, cmd, data, &replyData))
{
HILOG_ERROR(HILOG_MODULE_ACE,"fail to send event\n");
JSI::CallFunction(fail, thisVal, nullptr, 0);
JSI::CallFunction(complete, thisVal, nullptr, 0);
JSI::ReleaseValueList(success, fail, complete);
return JSI::CreateUndefined();
}
JSIValue result = JSI::CreateObject();
JSI::SetStringProperty(result, "set led", replyData);
JSIValue argv[ARGC_ONE] = {result};
JSI::CallFunction(success, thisVal, argv, ARGC_ONE);
JSI::CallFunction(complete, thisVal, nullptr, 0);
JSI::ReleaseValueList(success, fail, complete, result);
HdfIoServiceRecycle(serv);
return JSI::CreateUndefined();
}
六.安装Hap包
安装Hap包首先需要编译然后导出hap包,在编译出的hap包上右键选择在文件管理器打开:
然后需要准备一张SD卡和读卡器,按照小熊派官方的教程很轻松就能做到.
文档地址:https://gitee.com/bearpi/bearpi-hm_micro_small/blob/master/applications/BearPi/BearPi-HM_Micro/docs/device-dev/如何在开发板上安装HAP应用.md
实际过程如图所示:
七.作品展示
到这一步就算完成作品了,请看视频效果:
https://ost.51cto.com/show/15314
楼主试过小马达带风扇的效果如何吗?
这个小马达不好带风扇,中间的轴是圆的,感觉是选型没选好