1# i2cpwmdemo 2## 作品简介 3i2c读取温度湿度后,可控制舵机转到温度或者湿度对应的角度,也会在屏幕上显示出来温度或者湿度,以及温湿度指针 4## 开发环境简介 51. 搭载OpenHarmony-3.2-Beat5版本的Unionpi Tiger开发板 62. DevEco Studio 3.1.0.0 73. 温湿度模块SHT3x-DIS 84. SG90舵机 9## 舵机控制部分 10详见 [PWM舵机调试](../../hardware/pwm/README.md) 11## 温湿度传感器采集部分 12详见 [I2C读写及温湿度传感器使用](../../hardware/i2c/README.md) 13## NAPI 14全称 Native API,是OpenHarmony系统中的一套原生模块拓展开发框架,基于N-API开发,为开发者提供了JS与C/C++不同语言模块之间的相互访问,交互的能力。它可以用于规范化封装IO、OS底层等,并可以提供相应的JS接口供开发者调用。 15### 编写子系统组件 16在`vendor/unionman/unionpi_tiger/sample/napi/napisubsys`目录下新建`pwmnapipart/i2cpwmdemo`,`i2cnapipart/i2cpwmdemo`文件夹,分别对应`pwm`操作组件以及`i2c`操作组件 17#### 编写GN构建脚本 18`pwmnapipart/i2cpwmdemo/BUILD.gn` 19```python 20import("//build/ohos.gni") 21import("//drivers/hdf_core/adapter/uhdf2/uhdf.gni") 22 23ohos_shared_library("pwmnapi") { 24 sources = [ 25 "pwm_napi.cpp", 26 "pwm/pwm_ctl.cpp" 27 ] 28 deps = [ 29 "//foundation/arkui/napi:ace_napi", 30 "//drivers/hdf_core/adapter/uhdf2/platform:libhdf_platform" 31 ] 32 include_dirs = [ 33 "//base/hiviewdfx/hilog/interfaces/native/innerkits/include", 34 ] 35 36 external_deps = [ 37 "hiviewdfx_hilog_native:libhilog", 38 ] 39 40 relative_install_dir = "module" 41 part_name = "pwmnapi" 42 subsystem_name = "napisubsys" 43} 44``` 45`i2cnapipart/i2cpwmdemo/BUILD.gn` 46```python 47import("//build/ohos.gni") 48import("//drivers/hdf_core/adapter/uhdf2/uhdf.gni") 49 50ohos_shared_library("i2cnapi") { 51 sources = [ 52 "i2c_napi.cpp", 53 "i2c/i2c_ctl.cpp" 54 ] 55 56 include_dirs = [ 57 "//drivers/hdf_core/framework/include/platform", 58 "//base/hiviewdfx/hilog/interfaces/native/innerkits/include", 59 ] 60 61 external_deps = [ 62 "hiviewdfx_hilog_native:libhilog", 63 ] 64 65 deps = [ 66 "//foundation/arkui/napi:ace_napi", 67 "//drivers/hdf_core/adapter/uhdf2/platform:libhdf_platform" 68 ] 69 70 relative_install_dir = "module" 71 part_name = "i2cnapi" 72 subsystem_name = "napisubsys" 73} 74``` 75#### 定义组件 76打开`unionpi_tiger/sample/napi/napisubsys/ohos.build`配置文件,在`"parts":`字段中添加下列语句,用于注册组件并列出组件需要的模块列表 77```JSON 78"i2cnapi":{ 79 "variants": [ 80 "phone" 81 ], 82 "module_list": [ 83 "//vendor/unionman/unionpi_tiger/sample/napi/napisubsys/i2cnapipart/i2cpwmdemo:i2cnapi" 84 ] 85}, 86"pwmnapi":{ 87 "variants": [ 88 "phone" 89 ], 90 "module_list": [ 91 "//vendor/unionman/unionpi_tiger/sample/napi/napisubsys/i2cpwmdemo:pwmnapi" 92 ] 93} 94``` 95#### 将组件添加进子系统列表中 96打开`vendor/unionman/unionpi_tiger/config.json`文件,在`"subsystems":napisubsys`的`components`字段中添加下列语句 97```JSON 98{ 99 "component": "i2cnapi", 100 "features": [] 101}, 102{ 103 "component": "pwmnapi", 104 "features": [] 105} 106``` 107### 编写TS接口定义文件 108编写好NAPI代码之后,需要编写TS接口定义文件(.d.ts),这样开发OpenHarmony应用时,编译器才知道模块定义了哪些函数以及对应的返回值,参数列表等。 109`@ohos.i2cnapi.d.ts` 110```TypeScript 111declare namespace i2c_ctl { 112 export class TemHum { 113 /// @brief 摄氏度 114 temperatureC: number; 115 /// @brief 湿度 116 humidity: number; 117 /// @brief 华氏度 118 temperatureF: number; 119 } 120 /// @brief 获取温湿度数据 121 function getDataAsync(): Promise<TemHum>; 122} 123 124export default i2c_ctl; 125``` 126`@ohos.pwmnapi.d.ts` 127```TypeScript 128declare namespace pwm_ctl { 129/// @brief 设置舵机角度(单位为°) 130 function setAngleAsync(Angle: number): Promise<void>; 131} 132 133export default pwm_ctl 134``` 135 136## 构建 137进入`OpenHarmony`源代码的根目录,执行编译 138>./build.sh --product-name unionpi_tiger –ccache 139 140如果开发板已经烧录了同版本的`OpenHarmony`操作系统,可以在`out/unionpi_tiger/[子系统名]/[组件名]`文件夹中找到组件对应的动态库,然后使用hdc工具发送到开发板的`/system/lib/module`目录中即可,省去了烧录所花的时间 141> hdc_std file send libxxx.z.so /system/lib/module 142 143在发送时,可能出现以下错误 144>[Fail]Error opening file: read-only file system, path:/system/lib/module/libxxx.z.so 145 146这是因为`system`分区被开机挂载为只读分区,解决方案是重新挂载`system`分区为可读写分区 147>hdc_std shell mount / -o rw,remount 148 149然后再重新发送动态库至开发板即可 150## OpenHarmony应用开发 151打开`DevEco Studio`,新建一个`empty ability`项目 152 153将先前编写的TS接口定义文件放入`entry/src/main`文件夹中,IDE便会自动识别此TS接口定义文件 154 155### 相关代码 156#### 读取温湿度数据并刷新页面 157设置三个文本框,并设置相应的string变量与之绑定,在ui加载完毕事件的事件处理函数中,打开一个1s执行一次的定时器,每1s读取一次温湿度传感器的数值,然后根据选择框的选项计算对应的角度,设置舵机的角度以及调用flushDraw在屏幕上画出对应的指针,更新string变量,由于string变量设置了@State,文本框的显示也会相应更新。 158```TypeScript 159setInterval(async () => { 160 let data = await i2c_ctl.getDataAsync(); 161 this.temperatureC = '摄氏度: ' + data.temperatureC.toFixed(2) + '°C'; 162 this.temperatureF = '华氏度:' + data.temperatureF.toFixed(2) + '℉'; 163 this.humidity = '湿度:' + data.humidity.toFixed(2) + '%'; 164 let drawData: number; 165 switch (this.selectIndex) { 166 case 0: 167 drawData = data.temperatureC; 168 break; 169 case 1: 170 drawData = data.humidity; 171 break; 172 default: 173 drawData = 0; 174 break; 175 } 176 this.flushDraw(drawData / 100 * Math.PI); 177 pwm_ctl.setAngleAsync(180 - (drawData / 100 * 180)); 178}); 179``` 180#### Canvas画出指针 181首先获取绘画区的大小,再清除绘画区,调用`translate()`将坐标系的圆点移到指针的中心位置,再调用`rotate()`旋转坐标系到对应的角度,然后调用`drawImage()`画出指针并还原之前的设置 182```TypeScript 183flushDraw(rad: number): void { 184 let width = this.context.width; 185 let height = this.context.height; 186 187 this.context.clearRect(0, 0, width, height); 188 this.context.translate(width / 2, height - this.ih * 3); 189 this.context.rotate(rad); 190 191 this.context.drawImage(this.img, -129, -this.ih / 2); 192 193 this.context.rotate(-rad); 194 this.context.translate(-width / 2, -(height - this.ih * 3)); 195} 196``` 197 198## 演示效果 199 200## 参考链接 201[SHT3x-DIS驱动及应用详解(附源码和手册)](https://blog.csdn.net/qq_33194301/article/details/103652311) 202[OpenHarmony 源码解析之JavaScript API框架(NAPI)](https://ost.51cto.com/posts/8390)