OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 6113|回复: 3

关于OLED显示电池电量的简易方法

[复制链接]

2

主题

4

帖子

0

精华

新手上路

积分
23
金钱
23
注册时间
2018-5-28
在线时间
2 小时
发表于 2018-6-2 08:01:47 | 显示全部楼层 |阅读模式
如何采集电源电压大家可能都熟悉,stm32的ADC+DMA能很方便迅速的帮我们采集到自己想要的电压数据。使用DMA进行数据搬运也能很好的减轻CPU的一部分压力。但是这样只是第一步——数据。
用户想看到的有时候并不是数据,他们想要更直观方便的看到自己设备的电量。这就要求我们能在显示屏上通过更直观的方法显示电量。(怎么样,下面这样够直观吧。)
这也是现在嵌入式设备中常用的方法,用一个小电池图标表示,不同的电量里面就是不同的填充度。这样可以很直观的看到设备的剩余电量。
其实说是电量,实际就是用采样来的电压除以总电压,得到一个百分比,然后根据这个百分比显示不同的电池模式,就可以实现不同电量的刷新。一开始看到有人用一个小框框,然后框框里面用一个百分数表示当前的电量百分比,但我觉得那种方法不是很好。还是电池的饱和度更直观一点。
关于stm32的ADC采集电源电压可以看我的上一篇博客,或者网上也有很多优秀的文章,这里暂且假设我们已经获取了电源电压了。而获取电源电压只是第一步,还需要对电源电压进行一下简单的均值滤波。这里我每次在DMA中断里面每30个数取一个平均,得到较为稳定的电源电压。

[mw_shl_code=c,true]static void ADC_filter(void)  
{  
    int sum = 0;  
    u8 i = 0;  
    for(i = 0;i < N;i++)  
    {  
        sum+= AD_value;  
    }  
    after_filter = sum / N;    //每一次调用这个函数after_filter就更新一次;  
}[/mw_shl_code]
上面得到的实际上是ADC的16位原始数据,需要进一步处理成我们需要的实际电压值:
[mw_shl_code=c,true]float ADC_cal_aveg(void)  
{  
    float temp = 0;  
    temp = (float)(after_filter) * (3.3 / 4096);//计算电压  
    return temp;  
}[/mw_shl_code]
这样就完成了第一阶段。后面就是利用OLED的显示操作把数字显示成更直观的电池图标。
我的OLED屏是128*64分辨率的,我想在右上角显示一个电池小图标,用PCtoLCD2002取模软件进行图片取模。我选取电池规格为8*16的像素,(我不会告诉你上面这些点都是我一点点点上去的。。)
然后在这个电池里面进行填充,每填充一格就取一次模,所以一共可以取14个模型出来,也就是说电池可以14级电量显示。
这是取出来的部分模型:
3.3V的电压用14级显示出来,那么每3.3/14 = 0.24V就可以刷新一次电池。
所以我就想了可以这样处理,就是把采集来的电压,先除以0.24,得数的整数部分就是他的级数,
3.3V / 0.24 = 13  级,也就是满电量。
2.8V / 0.24 = 11  级
这个级数正好可以被显示函数使用,显示函数就是根据不同的电量级数显示不同的电池模型的。
[mw_shl_code=c,true]void OLED_Show_RealTime_Battery(u8 x,u8 y)  
{  
    float ADC_Val = 0;  
    unsigned int ADC_Int = 0;     
    ADC_Val = ADC_cal_aveg();  
    ADC_Int = (int)(ADC_Val / 0.24);  //这个0.24为 3.3/14 得来的数,就是每一级的步长,然后采样电压值除以步长就是级数  
    OLED_Show_Battery(x,y,ADC_Int);   //上面的级数直接在这里面使用,配合电池模型顺序即可。     
}[/mw_shl_code]
最后一个函数为OLED的显示函数,可以在屏上显示自己取出的字模。
最后吧这个函数放在主函数的while循环里,不断采样电池电压,不断根据电压刷新电池模型的显示。目前的问题就是不知道这个方法获得的电压是不是稳定。可能还是需要更精确的ADC滤波算法。
到此,就可以在显示屏上面显示不同的电池图标了

PS:之前都是在这个网站查资料,这次楼主第一次来到论坛发帖,希望能与大家多多交流。互相学习。

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

64

主题

249

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1073
金钱
1073
注册时间
2017-6-10
在线时间
279 小时
发表于 2018-6-2 08:11:02 | 显示全部楼层
很不错。
楼主能把函数 :  OLED_Show_Battery(x,y,ADC_Int);   贴出来吗?
回复 支持 反对

使用道具 举报

2

主题

4

帖子

0

精华

新手上路

积分
23
金钱
23
注册时间
2018-5-28
在线时间
2 小时
 楼主| 发表于 2018-6-2 09:30:34 | 显示全部楼层
rjx007 发表于 2018-6-2 08:11
很不错。
楼主能把函数 :  OLED_Show_Battery(x,y,ADC_Int);   贴出来吗?

恩,可以的,只是这个函数其实我就是对官方的OLED写函数进行了封装,实质都是刷新像素。
void OLED_Show_Battery(u8 x,u8 y,u8 n)
{
        u8 t = 0;
       
        OLED_Coord(x,y);
    for(t=0;t<16;t++)  //每行16个元素,一个电池模型取模之后只有一行16进制数据
        {
                SPI_Write(BMP[n][t],OLED_Data);
    }
}

其中SPI_Write就是对OLED的写函数了。具体可以参考我的这篇博客:
回复 支持 反对

使用道具 举报

2

主题

4

帖子

0

精华

新手上路

积分
23
金钱
23
注册时间
2018-5-28
在线时间
2 小时
 楼主| 发表于 2018-6-2 09:31:05 | 显示全部楼层
Andrew55 发表于 2018-6-2 09:30
恩,可以的,只是这个函数其实我就是对官方的OLED写函数进行了封装,实质都是刷新像素。
void OLED_Show ...

哎,为什么我不能贴出URL链接?提示我没有权限?
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-1 02:36

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表