html 如何实现一条竖线边上有 刻度_在鸿蒙开发板上实现一个简易数字温度计!...

利用开发板上的OLED屏幕和温湿度传感器AHT20,实现了一个简易数字温度计。通过I2C接口通信,结合HTML刻度,展示了从9点钟到3点钟角度的表盘,以及动态画指针和刻度的功能。
摘要由CSDN通过智能技术生成

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

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

初步的打算是做一个仪表盘,用指针指示温度和湿度,但是由于 OLED 只有 128*64,因此仪表盘不会很清晰,我们在旁边再用数字直接显示一下。

虽然简陋一点,但是只要原理学会了,其他复杂的仪表盘我们同样可以做出来。 2e1bb3726f5de547763cd458c2a81d78.png

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

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

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

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

01

OLED 驱动

OLED 驱动开发方法,参考许思维老师的代码:(此处不再赘述)
https://gitee.com/hihopeorg/harmonyos-ssd1306

02

温湿度传感器 AHT20 驱动

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

03

画表盘

由于表盘是半个圆,而且一般是从 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     {
        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;
}

04

画指针

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

难点是如何将指针的角度和实际的温度值对应起来。假设温度的范围为 -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);
}

05

画刻度

画刻度的方法,可以参考上面画指针的方法,从同一个角度画出的直线,与两个同圆心不同半径的圆的交点,将这两个交点连接起来就是刻度:
/*
画一条刻度线
*/
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);
}

06

使用上面几个函数,画出温度表

//更新温度和湿度
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();
}

07

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();
    }
}
2aca0f34f0067c7d51979faf301072e4.gif

点“阅读原文”下载源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值