本篇內(nèi)容主要講解“如何實(shí)現(xiàn)溫度傳感器和OLED”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“如何實(shí)現(xiàn)溫度傳感器和OLED”吧!
站在用戶的角度思考問題,與客戶深入溝通,找到陽西網(wǎng)站設(shè)計(jì)與陽西網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:網(wǎng)站設(shè)計(jì)、成都網(wǎng)站設(shè)計(jì)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、域名注冊(cè)、雅安服務(wù)器托管、企業(yè)郵箱。業(yè)務(wù)覆蓋陽西地區(qū)。
1. OLED驅(qū)動(dòng)
2. 溫濕度傳感器AHT20驅(qū)動(dòng)
3. 畫表盤
由于表盤是半個(gè)圓,而且一般是從9點(diǎn)鐘方向開始,順指針旋轉(zhuǎn),與實(shí)際的溫度值相對(duì)應(yīng),9點(diǎn)鐘對(duì)應(yīng)最小值,3點(diǎn)鐘對(duì)應(yīng)最大值,
因此我們畫表盤的時(shí)候最好從9點(diǎn)鐘對(duì)應(yīng)的角度為0, 12點(diǎn)鐘對(duì)應(yīng)的角度90度,3點(diǎn)鐘對(duì)應(yīng)的角度為180度。
畫表盤就是設(shè)置好圓心(x,y)和半徑r,然后計(jì)算圓周上的兩個(gè)點(diǎn),將相鄰的兩個(gè)點(diǎn)調(diào)用畫直線函數(shù)連接起來。
/*DrawArc.畫一個(gè)半圓 * start_angle in degree * sweep in degree * x,y是圓心的位置 * radius是半徑 * start_angle 起始角度,9點(diǎn)鐘作為0角度 * sweep 掃描角度 * 從9點(diǎn)鐘開始作為0角度,順時(shí)針旋轉(zhuǎn) */ 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.畫指針
畫指針比較簡單,就是在圓周上找一個(gè)點(diǎn),將這個(gè)點(diǎn)和圓心連接,就變成了一個(gè)指針,改變半徑的大小,就可以實(shí)現(xiàn)指針的長短。
難點(diǎn)是如何將指針的角度和實(shí)際的溫度值對(duì)應(yīng)起來。假設(shè)溫度的范圍為-15攝氏度到45攝氏度,共60攝氏度,則每一個(gè)角度對(duì)應(yīng)的溫度值為60/180;
如果當(dāng)前溫度是20度,則對(duì)應(yīng)的角度為20*60/180度。
/* 畫一條圓心到圓周的直線,實(shí)現(xiàn)指針 */ 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. 畫刻度
畫刻度的方法,可以參考上面畫指針的方法,從同一個(gè)角度畫出的直線,與兩個(gè)同圓心不同半徑的圓的交點(diǎn),將這兩個(gè)交點(diǎn)連接起來就是刻度
/* 畫一條刻度線 */ 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. 使用上面幾個(gè)函數(shù),畫出我們?cè)O(shè)計(jì)的溫度表
//更新溫度和濕度 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管腳的初始化和任務(wù)初始化
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(); } }
到此,相信大家對(duì)“如何實(shí)現(xiàn)溫度傳感器和OLED”有了更深的了解,不妨來實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!