5iMX宗旨:分享遥控模型兴趣爱好

5iMX.com 我爱模型 玩家论坛 ——专业遥控模型和无人机玩家论坛(玩模型就上我爱模型,创始于2003年)
查看: 5612|回复: 44
打印 上一主题 下一主题

usart-GPU制作的1~6S锂电池电压彩屏显示器(含源代码)【正式推出】

[复制链接]
跳转到指定楼层
楼主
发表于 2014-12-10 13:05 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 apachectl 于 2014-12-23 19:31 编辑

玩航模的都知道对电池的保养非常重要,否则价值不菲的航模电池极容易鼓肚,这就离不开锂电池电压显示仪,这个得必要性和保养方法这里就不再累述了,玩航模的都知道。

      现在市面上的显示器,大多数是由数码管构成的,最大的不方便之处就是显示信息量太小,只能一个一个的将信息分时显示出来,非常不直观,因此我们制作了这个使用高分彩屏的电压显示器;


在电路设计上,我们采用了带4key的Usart-GPU,串口液晶屏,其电路和
这款串口屏完全一样,只是考虑到便携性,采用了一块非常不常见的2.0吋320X240的液晶屏(平常的2.0吋是220X176分辨率的),这种高分屏显示的效果非常细腻;

在单片机上,我们采用的是stm32的单片机,这种单片机使用的是12位AD,且是32位单片机,在AD采样上带DMA传输,速度和精度都有保障;

下面谈谈显示仪的精度问题:

    查查某宝上的同类产品,大多数产品使用的非stm32的单片机,有用stm8的,有用avr的,这类单片机的AD都是10位的,也就是说分辨率是1024级,当检测6S 24V(实际应该更高)的时候,分辨率是24V/1024=0.024V,按照惯例,AD有+-3LSB的误差范围,也就是说,直接测量会在0.072V之间跳动,如果考虑到某节电池是2个电压相减得到,那么极端误差可能到0.144V(上一节电池-3LSB,这一节电池+3LSB,当然,这种极端情况较少出现),什么0.01V的精度,都是扯淡;能保证0.1V的精度就不错了;

   对于我们的产品,在精度方面也是同样的,只是采用了12位AD,因此分辨率是4096级,按照上面的计算,24V/3096=0.006V,3LSB误差0.018V,也就是说单独测量最高6S勉强达到0.01V精度,电池电压相减,极端误差0.036V;另外,在分压网络的选择上,低电压,比如1S那个,选择了6V满量程,2S选择10.7V满量程,这样在常用的3S上精度可以更高;

测量3S电池的情况:


本程序全部开源,因此很多界面以及功能都是可以修改的,比如,电池电压与电量的百分比:

// 0 10 20 30 40 50 60 70 80 90 100
uc16 Liqx[11]={300,350,368,373,377,381,385,390,395,408,419};

可以自行修改;


在主板的布局上,左边是GPU电路,用于控制液晶屏的显示,右边是CPU电路,用于采样电池电压,其实单片机的还有很多管脚没有使用,但是都引出了,因此此板实际上还可以当单片机的核心板使用;电阻分压网络实际做到了8S,但是考虑到用户较少,因此产品只设计的6S;

由于管脚都引出了,因此可以通过MOS管控制蜂鸣器,可以根据每节电池的电压,控制放电通路MOS的关断等等,让这块板子很容易升级制作成放电仪之类的东西;

在使用上,下侧排插,左边为GND,右边分别为1S 2S 3S.......将锂电池插上既可以显示;4个按钮目前只有左下角一个按钮有用,其他3个按钮留作以后扩展使用;在接电状态,按下左下角按钮,就可以进入debug界面,显示测量的AD值;







100mhz给设计的简单外壳:




断开跳线,本产品可以当一个4key的串口屏使用,可以当stm32f030f4p6的核心板,开发板使用,也是一个串口屏不错的评估板;




资料下载:
源代码工程文件包:http://pan.baidu.com/s/1i3029Qd
gpumaker资源文件包:http://pan.baidu.com/s/1eQ7uuKa
编译好的CPU文件:http://pan.baidu.com/s/1Cmk26

淘宝链接:http://item.taobao.com/item.htm?id=42843185420




37楼增加精度测试



代码:







欢迎继续阅读楼主其他信息

主题

  • 没有相关信息
  • 没有相关信息
  • 没有相关信息
沙发
 楼主| 发表于 2014-12-10 13:08 | 只看该作者
本帖最后由 apachectl 于 2014-12-10 13:11 编辑

上面是主程序代码,这里的看点是,串口屏处理按键形成的主消息处理体的模型,可以从结构上看出,把所有的窗体显示都编上号,这样就可以很方便的进行各个界面的消息处理以及界面切换,很容易编写复杂界面的软件,再多界面也不怕!

大家可以研究下示例中的复杂界面是如何显示和刷新的,这点很重要
再则是如何构建一个消息循环的多页面体系

这点在用单片机编辑多界面体系非常有用,全部代码请参见源代码的工程文件,这里仅抛砖引玉一把




  1. //=============================================================================
  2. //文件名称:main.c
  3. //功能概要:key
  4. //版权所有:apachectl
  5. //淘宝网店:http://shop104540872.taobao.com/
  6. //版本更新:2014-04-12
  7. //=============================================================================

  8. int main(void)
  9. {        
  10.         system_init();
  11.         USART_ENABLE_REV();
  12.         Delayms(2000000);
  13.         LoadROM();
  14.         GpuSend("DR2;CLS(0);SPG(1);\r\n");
  15.         winnum=1;

  16.         cjs=0;
  17.         iscmd=0;
  18.         iscmdok=0;
  19.         loopcount=0;
  20.         iswaiting=0;
  21.         setup();
  22.         
  23.         while(1)
  24.         {               
  25.                 if (iscmdok==1) {onkey();iscmdok=0;};
  26.                
  27.                 loopcount++;
  28.                 if (loopcount==100000)
  29.                 {        if (iswaiting==0) loop();
  30.                         loopcount=0;
  31.                 }
  32.                
  33.         }
  34. }


  35. void setup(void)
  36. {        switch (winnum)
  37.         {        case 1:        
  38.                         GpuSend("DR2;CLS(0);DS24(4,0,'锂电池电压',1);DS24(160,0,'总电压:',4);BOX(0,30,319,130,11);\r\n");
  39.                         break;
  40.                 case 2:        
  41.                         GpuSend("DR2;CLS(0);SPG(2);\r\n");
  42.                         break;
  43.                 case 3:        
  44.                         GpuSend("DR2;CLS(0);DS16(0,0,'Debug:',1);\r\n");
  45.                         break;
  46.         }
  47.         Delayms(200000);
  48. }


  49. void loop(void)
  50. {        switch(winnum)
  51.         {                case 1:
  52.                                 showwin1();
  53.                                 break;
  54.                         case 3:
  55.                                 showdebug();
  56.                                 break;
  57.         }
  58. }


  59. void onkey(void)
  60. {                //BC:0001   BA:0001  BB:0000
  61.         
  62.         switch (winnum)
  63.         {        case 1:
  64.                         if ((cmd[0]=='B') &(cmd[1]=='C') &(cmd[6]=='1'))
  65.                         {        //A按键单击
  66.                                 gowin(3);
  67.                         }
  68.                         if ((cmd[0]=='B') &(cmd[1]=='A') &(cmd[6]=='1'))
  69.                         {        //A按键长按击
  70.                                 gowin(2);
  71.                                 iswaiting=1;        //进入按钮释放等待循环中
  72.                                 
  73.                         }
  74.                         if ((cmd[0]=='B') &(cmd[1]=='B'))
  75.                         {        iswaiting=0;        //长按按键释放
  76.                         }
  77.                         break;
  78.                 case 2:
  79.                         if ((cmd[0]=='B') &(cmd[1]=='C') &(cmd[6]=='1'))
  80.                         {        //A按键单击
  81.                                         Set5VBase();
  82.                                         SaveROM();
  83.                                         gowin(1);
  84.                         }
  85.                         break;
  86.                 case 3:
  87.                         if ((cmd[0]=='B') &(cmd[1]=='C') &(cmd[6]=='1'))
  88.                         {        //A按键单击
  89.                                         gowin(1);
  90.                         }
  91.                         break;

  92.                

  93.         }
  94.         //if(cmd[0]==
  95. }


  96. void showwin1(void)
  97. {                u8 i,y,c;
  98.                 u16 x1,x2;
  99.                 CompADC();
  100.                 CompVol();
  101.                 CompLi();
  102.                 CompCellPer();
  103.                 min=99;max=0;argv=0;
  104.                 js=0;
  105.                 for (i=0;i<6;i++)
  106.                 {        if (Li[i]>1)
  107.                         {        argv+=Li[i];
  108.                                 js++;        
  109.                                 if (Li[i]<=min) min=Li[i];
  110.                                 if (Li[i]>max) max=Li[i];
  111.                         }
  112.                 }
  113.                 if (min==99) min=0;
  114.                 argv=argv/js;
  115.                 for (i=0;i<6;i++)
  116.                 {        x1=i*54+10;x2=x1+30;
  117.                         if (Li[i]>1)
  118.                         {        sprintf(buf,"ICON(%d,165,1,11,1,%d);DS16(%d,224,'%.2f',4);",54*i,CellPer[i],54*i+4,Li[i]);
  119.                                 GpuSend(buf);
  120.                                 y=(Li[i]-argv)*100;
  121.                                 y=80-y;
  122.                                 c=2;
  123.                                 if (y>130) {y=130;c=1;};
  124.                                 if (y<30) {y=30;c=1;};
  125.                                 sprintf(buf,"BOXF(%d,31,%d,%d,0);BOXF(%d,%d,%d,129,%d);",x1,x2,y,x1,y,x2,c);
  126.                                 GpuSend(buf);
  127.                         }
  128.                         else
  129.                         {        sprintf(buf,"ICON(%d,165,1,11,1,10);DS16(%d,224,' --- ',4);BOXF(%d,31,%d,79,0);BOXF(%d,81,%d,129,0);",54*i,54*i+4,x1,x2,x1,x2);
  130.                                 GpuSend(buf);
  131.                                 
  132.                         }
  133.                 }
  134.                 sprintf(buf,"DS24(240,0,'%.2fV',4);DS16(10,140,'最高:%.2fV   平均:%.2fV   最低:%.2fV',3);",LV[js-1],max,argv,min);
  135.                 GpuSend(buf);
  136.                 GpuSend("PL(0,80,320,80,11);\r\n");
  137.                 Delayms(1000000);
  138. }
复制代码




3
发表于 2014-12-10 13:41 | 只看该作者
技术贴 沙发
4
发表于 2014-12-10 13:51 | 只看该作者
不错,谁来整些福利

5
发表于 2014-12-10 13:54 | 只看该作者
顶楼主,如果再把内阻测试带上就更完美了!
来自安卓客户端来自安卓客户端
6
发表于 2014-12-10 13:54 | 只看该作者
不错  arm7的  当年研究过stc51的自己做过玩玩  享受乐趣
来自苹果客户端来自苹果客户端
7
发表于 2014-12-10 14:16 | 只看该作者
不错哦 只可惜自己不懂电子
8
发表于 2014-12-10 14:16 | 只看该作者
对内阻测试也加上
9
发表于 2014-12-10 14:17 | 只看该作者
归巢雁 发表于 2014-12-10 13:54
顶楼主,如果再把内阻测试带上就更完美了!

。。。同感,内阻测试也相当重要

10
发表于 2014-12-10 14:22 | 只看该作者
内阻测试带上就更完美!!!!!!!
11
发表于 2014-12-10 14:57 | 只看该作者
有焊好的成品卖不?
12
发表于 2014-12-10 15:21 | 只看该作者
赞一个
13
发表于 2014-12-10 15:47 | 只看该作者
很好,出个成品或套件。
14
发表于 2014-12-10 15:58 | 只看该作者
支持楼主..
15
发表于 2014-12-10 16:02 | 只看该作者
期待成品,只要不是太多、贵
16
发表于 2014-12-10 16:20 | 只看该作者
有成品卖就好了..
17
发表于 2014-12-10 16:31 | 只看该作者
高大上啊 表示坐等福利,另外要是能测内阻会是个大卖点
18
 楼主| 发表于 2014-12-10 16:35 | 只看该作者
本帖最后由 apachectl 于 2014-12-22 13:47 编辑

有成品和外壳,不多,怕版主管,没敢上上链接,
也是希望更多的玩家,尤其会单片机开发的来玩,这是一个核心板,比如加一个MOS和一个黄金电阻,就可以做成放电器,通过软件可以调整,比如设置到3.8V,放电到有一节电池到3.8V就关闭MOS,停止放电就可,这个实现其实比较简单;


关于内阻测试,可能得加一些模拟电路了,但是在这个框架中也不是很复杂;

还有就是和普通的没界面的充电器结合在一起,做充电的控制显示,也是很不错的,看大家怎么玩了,出这个板子且开源的目的就是抛砖引玉,贵在折腾。




19
发表于 2014-12-10 17:49 | 只看该作者
一块单片机能完成的工作却用了两块。。。坑爹的“GPU”
20
 楼主| 发表于 2014-12-10 19:16 | 只看该作者
本帖最后由 apachectl 于 2014-12-10 19:31 编辑
wangmingjie 发表于 2014-12-10 17:49
一块单片机能完成的工作却用了两块。。。坑爹的“GPU”

按你说,
  独 立 显 卡 就没有意义了,intel的cpu都带显卡部分的,一个处理器能干的,却用2块?
问题是:
1、如果只用一块处理器你就得动用更高档次的处理器,要达成同样的功能,恐怕比这2个处理器加起来都贵;
2、大家都知道,系统越复杂,调试难度也越复杂,没有GPU,恐怕这个电显得代码没有这么简单吧?
3、协议封装是大势所趋,按你得逻辑说,你计算机的CPU强大功能完全能胜任读写SD卡,为什么封装出一个USB协议,靠处理USB协议的单片机去读写SD卡,为什么CPU不直接去读SD卡?同理,SATA的硬盘内部也有一颗控制器;虽然电显比较简单,但是这也是一个典型系统,分离封装是大系统的一个基本,在不增加太多成本的情况下,肯定优势明显;

通过协议封装,让大多数入门程序员可以编写复杂的界面程序,这才是根本!



===============================
发现论坛一个bug ,输入连续4个字   独 立 显 卡  ,一提交,一定变成: 单独显卡











您需要登录后才可以回帖 登录 | 我要加入

本版积分规则

关闭

【站内推荐】上一条 /2 下一条

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