如何实现温度传感器和OLED
本篇内容主要讲解“如何实现温度传感器和OLED”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何实现温度传感器和OLED”吧!
站在用户的角度思考问题,与客户深入沟通,找到阳西网站设计与阳西网站推广的解决方案,凭借多年的经验,让设计与互联网技术结合,创造个性化、用户体验好的作品,建站类型包括:网站设计、成都网站设计、企业官网、英文网站、手机端网站、网站推广、域名注册、雅安服务器托管、企业邮箱。业务覆盖阳西地区。
1. OLED驱动
2. 温湿度传感器AHT20驱动
3. 画表盘
由于表盘是半个圆,而且一般是从9点钟方向开始,顺指针旋转,与实际的温度值相对应,9点钟对应最小值,3点钟对应最大值,
因此我们画表盘的时候最好从9点钟对应的角度为0, 12点钟对应的角度90度,3点钟对应的角度为180度。
画表盘就是设置好圆心(x,y)和半径r,然后计算圆周上的两个点,将相邻的两个点调用画直线函数连接起来。
/*DrawArc.画一个半圆 * start_angle in degree * sweep in degree * x,y是圆心的位置 * radius是半径 * start_angle 起始角度,9点钟作为0角度 * sweep 扫描角度 * 从9点钟开始作为0角度,顺时针旋转 */ void ssd1306_DrawArc_from9(uint8_t x, uint8_t y, uint8_t radius, uint16_t start_angle, uint16_t sweep, SSD1306_COLOR color) { float approx_degree; uint32_t approx_segments; uint8_t xp1,xp2; uint8_t yp1,yp2; uint32_t count = 0; uint32_t loc_sweep = 0; float rad; loc_sweep = ssd1306_NormalizeTo0_360(sweep); count = (ssd1306_NormalizeTo0_360(start_angle)); approx_segments = loc_sweep; approx_degree = 1; while(count < approx_segments) { rad = ssd1306_DegToRad(count*approx_degree); xp1 = x - (int8_t)(cos(rad)*radius); yp1 = y - (int8_t)(sin(rad)*radius); count++; if(count != approx_segments) { rad = ssd1306_DegToRad(count*approx_degree); } else { rad = ssd1306_DegToRad(loc_sweep); } xp2 = x - (int8_t)(cos(rad)*radius); yp2 = y - (int8_t)(sin(rad)*radius); ssd1306_DrawLine(xp1,yp1,xp2,yp2,color); } return; }
4.画指针
画指针比较简单,就是在圆周上找一个点,将这个点和圆心连接,就变成了一个指针,改变半径的大小,就可以实现指针的长短。
难点是如何将指针的角度和实际的温度值对应起来。假设温度的范围为-15摄氏度到45摄氏度,共60摄氏度,则每一个角度对应的温度值为60/180;
如果当前温度是20度,则对应的角度为20*60/180度。
/* 画一条圆心到圆周的直线,实现指针 */ void ssd1306_draw_line_of_arc(uint8_t x, uint8_t y, uint8_t radius, uint16_t angle,SSD1306_COLOR color) { float approx_degree; uint8_t xp1; uint8_t yp1; uint32_t count = 0; float rad; count = (ssd1306_NormalizeTo0_360(angle)); approx_degree = 1; rad = ssd1306_DegToRad(count*approx_degree); xp1 = x - (int8_t)(cos(rad)*radius); yp1 = y - (int8_t)(sin(rad)*radius); ssd1306_DrawLine(x, y, xp1, yp1, color); }
5. 画刻度
画刻度的方法,可以参考上面画指针的方法,从同一个角度画出的直线,与两个同圆心不同半径的圆的交点,将这两个交点连接起来就是刻度
/* 画一条刻度线 */ void ssd1306_draw_line_of_kedu(uint8_t x, uint8_t y, uint8_t radius, uint16_t angle,SSD1306_COLOR color) { float approx_degree; uint8_t xp1,xp2; uint8_t yp1,yp2; uint32_t count = 0; float rad; count = (ssd1306_NormalizeTo0_360(angle)); approx_degree = 1; rad = ssd1306_DegToRad(count*approx_degree); xp1 = x - (int8_t)(cos(rad)*radius); yp1 = y - (int8_t)(sin(rad)*radius); xp2 = x - (int8_t)(cos(rad)*(radius-4));//刻度线的长度为4 yp2 = y - (int8_t)(sin(rad)*(radius-4)); ssd1306_DrawLine(xp1, yp1, xp2, yp2, color); }
6. 使用上面几个函数,画出我们设计的温度表
//更新温度和湿度 void ssd1306_update_temper(float temp, float humi) { int angle = 0; char buf[100] = {0}; ssd1306_Fill(Black); uint8_t x,y,r; //温度表盘,半圆形 x=30; y=28; r=28; ssd1306_DrawCircle(x,y,2,White); ssd1306_SetCursor(x-r, y); ssd1306_DrawString("-15", Font_6x8, White); ssd1306_SetCursor(x+r-6, y); ssd1306_DrawString("45", Font_6x8, White); ssd1306_SetCursor(x-6, y-r+6); ssd1306_DrawString("15", Font_6x8, White); ssd1306_DrawArc_from9(x, y, r, 0, 180, White); //ssd1306_DrawArc_from9(x, y, r-1, 0, 180, White); ssd1306_draw_line_of_kedu(x,y,r,45,White); ssd1306_draw_line_of_kedu(x,y,r,90,White); ssd1306_draw_line_of_kedu(x,y,r,135,White); angle = (int)((temp + 15 )*180/60); ssd1306_draw_line_of_arc(x, y, r-2,angle, White); ssd1306_SetCursor(x+r+6, y-r/2); sprintf(buf, "%.1fC", temp); ssd1306_DrawString(buf, Font_7x10, White); //湿度表盘,半圆形 x=30; y=55; r=22; ssd1306_DrawCircle(x,y,2,White); ssd1306_SetCursor(x-r-4, y); ssd1306_DrawString("20", Font_6x8, White); ssd1306_SetCursor(x+r-6, y); ssd1306_DrawString("100", Font_6x8, White); ssd1306_SetCursor(x-6, y-r+6); ssd1306_DrawString("60", Font_6x8, White); ssd1306_DrawArc_from9(x, y, r, 0, 180, White); //ssd1306_DrawArc_from9(x, y, r-1, 0, 180, White); ssd1306_draw_line_of_kedu(x,y,r,45,White); ssd1306_draw_line_of_kedu(x,y,r,90,White); ssd1306_draw_line_of_kedu(x,y,r,135,White); angle = (int)((humi - 20 )*180/80); ssd1306_draw_line_of_arc(x, y, r-2,angle, White); ssd1306_SetCursor(x+r+6, y-r/2); sprintf(buf, "%%%.1f", humi); ssd1306_DrawString(buf, Font_7x10, White); //ssd1306_TestArc(); ssd1306_UpdateScreen(); }
7. I2C管脚的初始化和任务初始化
void Ssd1306TestTask(void* arg) { (void) arg; uint32_t retval = 0; GpioInit(); IoSetFunc(WIFI_IOT_IO_NAME_GPIO_13, WIFI_IOT_IO_FUNC_GPIO_13_I2C0_SDA); IoSetFunc(WIFI_IOT_IO_NAME_GPIO_14, WIFI_IOT_IO_FUNC_GPIO_14_I2C0_SCL); I2cInit(WIFI_IOT_I2C_IDX_0, OLED_I2C_BAUDRATE); WatchDogDisable(); usleep(20*1000); ssd1306_Init(); ssd1306_Fill(Black); ssd1306_SetCursor(0, 0); ssd1306_DrawString("Hello HarmonyOS!", Font_7x10, White); uint32_t start = HAL_GetTick(); ssd1306_UpdateScreen(); uint32_t end = HAL_GetTick(); printf("ssd1306_UpdateScreen time cost: %d ms.\r\n", end - start); // retval = AHT20_Calibrate(); printf("AHT20_Calibrate: %d\r\n", retval); TestGetTick(); while (1) { float temp = 0.0, humi = 0.0; //retval = AHT20_StartMeasure(); //printf("AHT20_StartMeasure: %d\r\n", retval); retval = AHT20_GetTemperHumi(&temp, &humi); printf("AHT20_GetMeasureResult: %d, temp = %.2f, humi = %.2f\r\n", retval, temp, humi); ssd1306_update_temper(temp, humi); sleep(1); //ssd1306_TestAll(); } }
到此,相信大家对“如何实现温度传感器和OLED”有了更深的了解,不妨来实际操作一番吧!这里是创新互联网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
名称栏目:如何实现温度传感器和OLED
浏览路径:http://myzitong.com/article/ggjspi.html