您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“如何實(shí)現(xiàn)溫度傳感器和OLED”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“如何實(shí)現(xiàn)溫度傳感器和OLED”吧!
1. OLED驅(qū)動
2. 溫濕度傳感器AHT20驅(qū)動
3. 畫表盤
由于表盤是半個圓,而且一般是從9點(diǎn)鐘方向開始,順指針旋轉(zhuǎn),與實(shí)際的溫度值相對應(yīng),9點(diǎn)鐘對應(yīng)最小值,3點(diǎn)鐘對應(yīng)最大值,
因此我們畫表盤的時候最好從9點(diǎn)鐘對應(yīng)的角度為0, 12點(diǎn)鐘對應(yīng)的角度90度,3點(diǎn)鐘對應(yīng)的角度為180度。
畫表盤就是設(shè)置好圓心(x,y)和半徑r,然后計算圓周上的兩個點(diǎn),將相鄰的兩個點(diǎn)調(diào)用畫直線函數(shù)連接起來。
/*DrawArc.畫一個半圓 * start_angle in degree * sweep in degree * x,y是圓心的位置 * radius是半徑 * start_angle 起始角度,9點(diǎn)鐘作為0角度 * sweep 掃描角度 * 從9點(diǎn)鐘開始作為0角度,順時針旋轉(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.畫指針
畫指針比較簡單,就是在圓周上找一個點(diǎn),將這個點(diǎn)和圓心連接,就變成了一個指針,改變半徑的大小,就可以實(shí)現(xiàn)指針的長短。
難點(diǎn)是如何將指針的角度和實(shí)際的溫度值對應(yīng)起來。假設(shè)溫度的范圍為-15攝氏度到45攝氏度,共60攝氏度,則每一個角度對應(yīng)的溫度值為60/180;
如果當(dāng)前溫度是20度,則對應(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. 畫刻度
畫刻度的方法,可以參考上面畫指針的方法,從同一個角度畫出的直線,與兩個同圓心不同半徑的圓的交點(diǎn),將這兩個交點(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. 使用上面幾個函數(shù),畫出我們設(shè)計的溫度表
//更新溫度和濕度 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(); } }
到此,相信大家對“如何實(shí)現(xiàn)溫度傳感器和OLED”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。