2020征文-鸿蒙开发板6.WiFi IoT智能家居套件 - 温度传感器和OLED实践

开发 前端
在开发板套件中,有一个OLED屏幕扩展板,温湿度传感器扩展板,本次我们就用这两个扩展板来实现一个简易数字温度计。

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com/#zz

这是一份迟来的文章,代码写好几天了,由于太忙,一直没来得及上传。

在开发板套件中,有一个OLED屏幕扩展板,温湿度传感器扩展板,本次我们就用这两个扩展板来实现一个简易数字温度计。初步的打算是做一个仪表盘,用指针指示温度和湿度,但是由于OLED只有128*64,因此仪表盘不会很清晰,我们在旁边再用数字直接显示一下。虽然简陋一点,但是只要原理学会了,其他复杂的仪表盘我们同样可以做出来。


OLED屏幕为128*64的点阵,通信接口为I2C0,从机地址为0x3C

温湿度传感器AHT20,通信接口也是I2C0,从机地址为0x38

熟悉I2C的朋友都知道,I2C是多从机模式,只要从机地址不同,我们可以挂在同一个总线下,进行复用。

既然如此,那我们就可以同时使用这两个扩展板。

1. OLED驱动

OLED驱动开发方法,参考许思维老师的代码 https://gitee.com/hihopeorg/harmonyos-ssd1306

此处不再赘述

2. 温湿度传感器AHT20驱动

参考许思维老师的代码 https://gitee.com/hihopeorg/harmonyos-aht20

此处不再赘述。

3. 画表盘

由于表盘是半个圆,而且一般是从9点钟方向开始,顺指针旋转,与实际的温度值相对应,9点钟对应最小值,3点钟对应最大值,

因此我们画表盘的时候最好从9点钟对应的角度为0, 12点钟对应的角度90度,3点钟对应的角度为180度。

画表盘就是设置好圆心(x,y)和半径r,然后计算圆周上的两个点,将相邻的两个点调用画直线函数连接起来。

  1. /*DrawArc.画一个半圆 
  2.  
  3. * start_angle in degree 
  4.  
  5. * sweep in degree 
  6.  
  7. * x,y是圆心的位置 
  8.  
  9. * radius是半径 
  10.  
  11. * start_angle 起始角度,9点钟作为0角度 
  12.  
  13. * sweep 扫描角度 
  14.  
  15. * 从9点钟开始作为0角度,顺时针旋转 
  16.  
  17. */ 
  18.  
  19. void ssd1306_DrawArc_from9(uint8_t x, uint8_t y, uint8_t radius, uint16_t start_angle, uint16_t sweep, SSD1306_COLOR color) { 
  20.  
  21. float approx_degree; 
  22.  
  23. uint32_t approx_segments; 
  24.  
  25. uint8_t xp1,xp2; 
  26.  
  27. uint8_t yp1,yp2; 
  28.  
  29. uint32_t count = 0; 
  30.  
  31. uint32_t loc_sweep = 0; 
  32.  
  33. float rad; 
  34.  
  35. loc_sweep = ssd1306_NormalizeTo0_360(sweep); 
  36.  
  37. count = (ssd1306_NormalizeTo0_360(start_angle)); 
  38.  
  39. approx_segments = loc_sweep; 
  40.  
  41. approx_degree = 1; 
  42.  
  43. while(count < approx_segments) 
  44.  
  45.  
  46. rad = ssd1306_DegToRad(count*approx_degree); 
  47.  
  48. xp1 = x - (int8_t)(cos(rad)*radius); 
  49.  
  50. yp1 = y - (int8_t)(sin(rad)*radius); 
  51.  
  52. count++; 
  53.  
  54. if(count != approx_segments) 
  55.  
  56.  
  57. rad = ssd1306_DegToRad(count*approx_degree); 
  58.  
  59.  
  60. else 
  61.  
  62.  
  63. rad = ssd1306_DegToRad(loc_sweep); 
  64.  
  65.  
  66. xp2 = x - (int8_t)(cos(rad)*radius); 
  67.  
  68. yp2 = y - (int8_t)(sin(rad)*radius); 
  69.  
  70. ssd1306_DrawLine(xp1,yp1,xp2,yp2,color); 
  71.  
  72.  
  73. return
  74.  

 4.画指针

画指针比较简单,就是在圆周上找一个点,将这个点和圆心连接,就变成了一个指针,改变半径的大小,就可以实现指针的长短。

难点是如何将指针的角度和实际的温度值对应起来。假设温度的范围为-15摄氏度到45摄氏度,共60摄氏度,则每一个角度对应的温度值为60/180;

如果当前温度是20度,则对应的角度为20*60/180度。

  1. /* 
  2.  
  3. 画一条圆心到圆周的直线,实现指针 
  4.  
  5. */ 
  6.  
  7. void ssd1306_draw_line_of_arc(uint8_t x, uint8_t y, uint8_t radius, uint16_t angle,SSD1306_COLOR color) 
  8.  
  9.  
  10. float approx_degree; 
  11.  
  12. uint8_t xp1; 
  13.  
  14. uint8_t yp1; 
  15.  
  16. uint32_t count = 0; 
  17.  
  18. float rad; 
  19.  
  20. count = (ssd1306_NormalizeTo0_360(angle)); 
  21.  
  22. approx_degree = 1; 
  23.  
  24. rad = ssd1306_DegToRad(count*approx_degree); 
  25.  
  26. xp1 = x - (int8_t)(cos(rad)*radius); 
  27.  
  28. yp1 = y - (int8_t)(sin(rad)*radius); 
  29.  
  30. ssd1306_DrawLine(x, y, xp1, yp1, color); 
  31.  

 5. 画刻度

画刻度的方法,可以参考上面画指针的方法,从同一个角度画出的直线,与两个同圆心不同半径的圆的交点,将这两个交点连接起来就是刻度

  1. /* 
  2.  
  3. 画一条刻度线 
  4.  
  5. */ 
  6.  
  7. void ssd1306_draw_line_of_kedu(uint8_t x, uint8_t y, uint8_t radius, uint16_t angle,SSD1306_COLOR color) 
  8.  
  9.  
  10. float approx_degree; 
  11.  
  12. uint8_t xp1,xp2; 
  13.  
  14. uint8_t yp1,yp2; 
  15.  
  16. uint32_t count = 0; 
  17.  
  18. float rad; 
  19.  
  20. count = (ssd1306_NormalizeTo0_360(angle)); 
  21.  
  22. approx_degree = 1; 
  23.  
  24. rad = ssd1306_DegToRad(count*approx_degree); 
  25.  
  26. xp1 = x - (int8_t)(cos(rad)*radius); 
  27.  
  28. yp1 = y - (int8_t)(sin(rad)*radius); 
  29.  
  30. xp2 = x - (int8_t)(cos(rad)*(radius-4));//刻度线的长度为4 
  31.  
  32. yp2 = y - (int8_t)(sin(rad)*(radius-4)); 
  33.  
  34. ssd1306_DrawLine(xp1, yp1, xp2, yp2, color); 
  35.  

 6. 使用上面几个函数,画出我们设计的温度表

  1. //更新温度和湿度 
  2.  
  3. void ssd1306_update_temper(float tempfloat humi) 
  4.  
  5.  
  6. int angle = 0; 
  7.  
  8. char buf[100] = {0}; 
  9.  
  10. ssd1306_Fill(Black); 
  11.  
  12. uint8_t x,y,r; 
  13.  
  14. //温度表盘,半圆形 
  15.  
  16. x=30; 
  17.  
  18. y=28; 
  19.  
  20. r=28; 
  21.  
  22. ssd1306_DrawCircle(x,y,2,White); 
  23.  
  24. ssd1306_SetCursor(x-r, y); 
  25.  
  26. ssd1306_DrawString("-15", Font_6x8, White); 
  27.  
  28. ssd1306_SetCursor(x+r-6, y); 
  29.  
  30. ssd1306_DrawString("45", Font_6x8, White); 
  31.  
  32. ssd1306_SetCursor(x-6, y-r+6); 
  33.  
  34. ssd1306_DrawString("15", Font_6x8, White); 
  35.  
  36. ssd1306_DrawArc_from9(x, y, r, 0, 180, White); 
  37.  
  38. //ssd1306_DrawArc_from9(x, y, r-1, 0, 180, White); 
  39.  
  40. ssd1306_draw_line_of_kedu(x,y,r,45,White); 
  41.  
  42. ssd1306_draw_line_of_kedu(x,y,r,90,White); 
  43.  
  44. ssd1306_draw_line_of_kedu(x,y,r,135,White); 
  45.  
  46. angle = (int)((temp + 15 )*180/60); 
  47.  
  48. ssd1306_draw_line_of_arc(x, y, r-2,angle, White); 
  49.  
  50. ssd1306_SetCursor(x+r+6, y-r/2); 
  51.  
  52. sprintf(buf, "%.1fC"temp); 
  53.  
  54. ssd1306_DrawString(buf, Font_7x10, White); 
  55.  
  56. //湿度表盘,半圆形 
  57.  
  58. x=30; 
  59.  
  60. y=55; 
  61.  
  62. r=22; 
  63.  
  64. ssd1306_DrawCircle(x,y,2,White); 
  65.  
  66. ssd1306_SetCursor(x-r-4, y); 
  67.  
  68. ssd1306_DrawString("20", Font_6x8, White); 
  69.  
  70. ssd1306_SetCursor(x+r-6, y); 
  71.  
  72. ssd1306_DrawString("100", Font_6x8, White); 
  73.  
  74. ssd1306_SetCursor(x-6, y-r+6); 
  75.  
  76. ssd1306_DrawString("60", Font_6x8, White); 
  77.  
  78. ssd1306_DrawArc_from9(x, y, r, 0, 180, White); 
  79.  
  80. //ssd1306_DrawArc_from9(x, y, r-1, 0, 180, White); 
  81.  
  82. ssd1306_draw_line_of_kedu(x,y,r,45,White); 
  83.  
  84. ssd1306_draw_line_of_kedu(x,y,r,90,White); 
  85.  
  86. ssd1306_draw_line_of_kedu(x,y,r,135,White); 
  87.  
  88. angle = (int)((humi - 20 )*180/80); 
  89.  
  90. ssd1306_draw_line_of_arc(x, y, r-2,angle, White); 
  91.  
  92. ssd1306_SetCursor(x+r+6, y-r/2); 
  93.  
  94. sprintf(buf, "%%%.1f", humi); 
  95.  
  96. ssd1306_DrawString(buf, Font_7x10, White); 
  97.  
  98. //ssd1306_TestArc(); 
  99.  
  100. ssd1306_UpdateScreen(); 
  101.  

 7. I2C管脚的初始化和任务初始化

  1. void Ssd1306TestTask(void* arg) 
  2.  
  3.  
  4. (void) arg; 
  5.  
  6. uint32_t retval = 0; 
  7.  
  8. GpioInit(); 
  9.  
  10. IoSetFunc(WIFI_IOT_IO_NAME_GPIO_13, WIFI_IOT_IO_FUNC_GPIO_13_I2C0_SDA); 
  11.  
  12. IoSetFunc(WIFI_IOT_IO_NAME_GPIO_14, WIFI_IOT_IO_FUNC_GPIO_14_I2C0_SCL); 
  13.  
  14. I2cInit(WIFI_IOT_I2C_IDX_0, OLED_I2C_BAUDRATE); 
  15.  
  16. WatchDogDisable(); 
  17.  
  18. usleep(20*1000); 
  19.  
  20. ssd1306_Init(); 
  21.  
  22. ssd1306_Fill(Black); 
  23.  
  24. ssd1306_SetCursor(0, 0); 
  25.  
  26. ssd1306_DrawString("Hello HarmonyOS!", Font_7x10, White); 
  27.  
  28. uint32_t start = HAL_GetTick(); 
  29.  
  30. ssd1306_UpdateScreen(); 
  31.  
  32. uint32_t end = HAL_GetTick(); 
  33.  
  34. printf("ssd1306_UpdateScreen time cost: %d ms.\r\n"end - start); 
  35.  
  36. // 
  37.  
  38. retval = AHT20_Calibrate(); 
  39.  
  40. printf("AHT20_Calibrate: %d\r\n", retval); 
  41.  
  42. TestGetTick(); 
  43.  
  44. while (1) { 
  45.  
  46. float temp = 0.0, humi = 0.0; 
  47.  
  48. //retval = AHT20_StartMeasure(); 
  49.  
  50. //printf("AHT20_StartMeasure: %d\r\n", retval); 
  51.  
  52. retval = AHT20_GetTemperHumi(&temp, &humi); 
  53.  
  54. printf("AHT20_GetMeasureResult: %d, temp = %.2f, humi = %.2f\r\n", retval, temp, humi); 
  55.  
  56. ssd1306_update_temper(temp, humi); 
  57.  
  58. sleep(1); 
  59.  
  60. //ssd1306_TestAll(); 
  61.  
  62.  

 想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com/#zz

 

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2020-12-29 09:59:01

鸿蒙HarmonyOS智能家居

2020-12-30 11:02:34

鸿蒙HarmonyOS智能家居

2020-11-10 12:08:25

开发框架

2020-11-04 13:20:14

HiSpark

2020-11-13 11:53:52

4.WiFi IoT

2020-10-26 10:21:39

Wi-Fi IoT智能家居套件

2020-12-16 10:05:48

鸿蒙开发板Onenet平台

2020-10-21 10:01:47

HiSpark Wi-智能家居套件

2015-09-24 13:41:28

物联网智能家居传感器

2020-11-23 13:09:42

HI3861

2020-12-15 09:33:40

鸿蒙Hi3861开发板

2022-09-30 13:50:07

设备开发鸿蒙

2020-11-24 10:05:54

人工智能

2020-12-07 12:34:33

开发板鸿蒙hello world

2020-12-15 11:57:49

Hi3861 HarmonyOS开发板

2020-06-22 14:17:23

智能家居5GWiFi 6

2015-08-26 10:14:28

2023-07-28 15:32:26

鸿蒙操作系统

2023-09-22 13:40:12

2023-03-12 15:21:57

传感器Wi-Fi
点赞
收藏

51CTO技术栈公众号