README.md
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)