[PIC®/AVR® MCU]

【CuriosityNano测评报告】+ AVR64DD32ADC多路电压表实验

[复制链接]
307|2
手机看帖
扫描二维码
随时随地手机跟帖
hu9jj|  楼主 | 2022-11-24 13:21 | 显示全部楼层 |阅读模式
AD, ADC, AN, AVR, IO
#申请原创#

    在之前的测评计划中是准备做一个8路电压表+1路电流表的实验,实验的电路图如下:
ADC_7.jpg

    下面是整个实验的装置照片:
ADC_a.jpg

    其中显示器左边是一个可调电源。鼠标边上的盒子是一个用于测量电流的负载,其实就是对盒子里的锂电池进行充电。右边则是ADC采样电阻和AVR64DD32核心板。
    MCC的配置如下:
    开通了10个通道,目前仅测试了8路电压转换和1路电流转换,预留的一个通道是准备日后监测锂电池电压的:
ADC_4.jpg

    各个通道的编号在列表中可以查到:
ADC_6.jpg

    比较参照电压选择2.048v:
ADC_5.jpg

    电压采样电阻的比例是0.2/4.7,电流采样电阻是5毫欧。采样滤波是连续采样8次,然后取平均值并与之前的数据各占50%。代码如下:
        ADC_Val = 0;                            //读取电压通道1
        for(i=0; i<8; i++){
            ADC_Val += ADC0_GetConversion(ADC_MUXPOS_AIN18_gc);
            DELAY_milliseconds(1);
        }
        value[1] = value[1]/2 + ADC_Val>>6;     //当前转换值(8次相加)除以8(右移3位)再取50%(右移1位)与之前数值的50%相加,得到享受滤波值
//        value[1] = ADC_Val>>6;
        LCD_write_GT_value(14,2,3,1,0,1,value[1]);//x,y,L,D,N,val :座标、长度、前导零(1显示 0不显示)、字体(0大字体 1中字体)、变量


    开始测试时数据波动很大,而且后续通道的读数会受到之前通道数据的影响,最后在每次采样后延时1毫秒,这样读数才比较稳定。
    经过反复修改,实际数值为右移6位时,电压数值与实际比较接近,当可调电源的电压输出为1.4v时,采样转换的数值为1.5v:
ADC_c.jpg

ADC_b.jpg

    两者相差0.1v,这点误差应该可以忽略不计,因为可调电源的电压表也不是很准确,而我又没有高位电压表来校准,在实际使用过程中也没有那么高的需求。
    经过测试,8路电压表除了第一通道有初始值0.1外,其他通道均基本正常,只是电流检测不正常,无论是否接负载,检测结果没有变化。按照电路设计,采样电阻为5毫欧时,如果有1安电流通过,采样电阻两端将产生5毫伏电压,而MCU的ADC分辨率应为2.048v/4096=0.5毫伏,应该可以检测到0.1安的电流变化,我采用的锂电池充电负载电流约为0.2~0.5安,理论上完全可以检测得到变化,但实际测试过程中却毫无变化,下一步准备降低参照电压再试试看。
    下面是主函数代码:
int main(void)
{
    uint8_t i=0,j=0;
    uint32_t ADC_Val;
    SYSTEM_Initialize();
//    USART0_Enable();
    printf("Hello World\r\n");

    SW0_SetDigitalInput();
    SW0_SetPullUp();
    SW0_EnableInterruptForFallingEdge();         //设置引脚的中断模式
    PF6_SetInterruptHandler(SW0_Handler);        //指定中断处理的函数

    LCD_init();                                  //LCD初始化
    display_begin();
    DELAY_milliseconds(2000);
   
    display_main();
   
    TCA0_EnableInterrupt();
    Led0_SetHigh();
   
    while(1)
    {
        ADC_Val = 0;                            //读取电流值
        for(i=0; i<8; i++){
            ADC_Val += ADC0_GetConversion(ADC_MUXPOS_AIN17_gc);
            DELAY_milliseconds(1);
        }
//        value[0] = value[0]/2 + ADC_Val>>1 - 600;  //当前转换值(8次相加)除以8(右移3位)再取50%(右移1位)与之前数值的50%相加,得到享受滤波值
        value[0] = ADC_Val>>3;
        LCD_write_GT_value(106,6,5,3,0,1,value[0]);//x,y,L,D,N,val :座标、长度、小数、前导零(1显示 0不显示)、字体(0大字体 1中字体)、变量
        
        ADC_Val = 0;                            //读取电压通道1
        for(i=0; i<8; i++){
            ADC_Val += ADC0_GetConversion(ADC_MUXPOS_AIN18_gc);
            DELAY_milliseconds(1);
        }
        value[1] = value[1]/2 + ADC_Val>>6;     //当前转换值(8次相加)除以8(右移3位)再取50%(右移1位)与之前数值的50%相加,得到享受滤波值
//        value[1] = ADC_Val>>6;
        LCD_write_GT_value(14,2,3,1,0,1,value[1]);//x,y,L,D,N,val :座标、长度、前导零(1显示 0不显示)、字体(0大字体 1中字体)、变量
        
        ADC_Val = 0;                            //读取电压通道2
        for(i=0; i<8; i++){
            ADC_Val += ADC0_GetConversion(ADC_MUXPOS_AIN7_gc);
            DELAY_milliseconds(1);
        }
        value[2] = value[2]/2 + ADC_Val>>6;     //当前转换值(8次相加)除以8(右移3位)再取50%(右移1位)与之前数值的50%相加,得到享受滤波值
//        value[2] = ADC_Val>>6;
        LCD_write_GT_value(64,2,3,1,0,1,value[2]);//x,y,L,D,N,val :座标、长度、前导零(1显示 0不显示)、字体(0大字体 1中字体)、变量

        ADC_Val = 0;                            //读取电压通道3
        for(i=0; i<8; i++){
            ADC_Val += ADC0_GetConversion(ADC_MUXPOS_AIN27_gc);
            DELAY_milliseconds(1);
        }
        value[3] = value[3]/2 + ADC_Val>>6;     //当前转换值(8次相加)除以8(右移3位)再取50%(右移1位)与之前数值的50%相加,得到享受滤波值
//        value[3] = ADC_Val>>6;
        LCD_write_GT_value(114,2,3,1,0,1,value[3]);//x,y,L,D,N,val :座标、长度、前导零(1显示 0不显示)、字体(0大字体 1中字体)、变量
        
        ADC_Val = 0;                            //读取电压通道4
        for(i=0; i<8; i++){
            ADC_Val += ADC0_GetConversion(ADC_MUXPOS_AIN1_gc);
            DELAY_milliseconds(1);
        }
        value[4] = value[4]/2 + ADC_Val>>6;     //当前转换值(8次相加)除以8(右移3位)再取50%(右移1位)与之前数值的50%相加,得到享受滤波值
//        value[4] = ADC_Val>>6;
        LCD_write_GT_value(164,2,3,1,0,1,value[4]);//x,y,L,D,N,val :座标、长度、前导零(1显示 0不显示)、字体(0大字体 1中字体)、变量
        
        ADC_Val = 0;                            //读取电压通道5
        for(i=0; i<8; i++){
            ADC_Val += ADC0_GetConversion(ADC_MUXPOS_AIN6_gc);
            DELAY_milliseconds(1);
        }
        value[5] = value[5]/2 + ADC_Val>>6;     //当前转换值(8次相加)除以8(右移3位)再取50%(右移1位)与之前数值的50%相加,得到享受滤波值
//        value[5] = ADC_Val>>6;
        LCD_write_GT_value(14,4,3,1,0,1,value[5]);//x,y,L,D,N,val :座标、长度、前导零(1显示 0不显示)、字体(0大字体 1中字体)、变量
        
        ADC_Val = 0;                            //读取电压通道6
        for(i=0; i<8; i++){
            ADC_Val += ADC0_GetConversion(ADC_MUXPOS_AIN19_gc);
            DELAY_milliseconds(1);
        }
        value[6] = value[6]/2 + ADC_Val>>6;     //当前转换值(8次相加)除以8(右移3位)再取50%(右移1位)与之前数值的50%相加,得到享受滤波值
//        value[6] = ADC_Val>>6;
        LCD_write_GT_value(64,4,3,1,0,1,value[6]);//x,y,L,D,N,val :座标、长度、前导零(1显示 0不显示)、字体(0大字体 1中字体)、变量

        ADC_Val = 0;                            //读取电压通道7
        for(i=0; i<8; i++){
            ADC_Val += ADC0_GetConversion(ADC_MUXPOS_AIN2_gc);
            DELAY_milliseconds(1);
        }
        value[7] = value[7]/2 + ADC_Val>>6;     //当前转换值(8次相加)除以8(右移3位)再取50%(右移1位)与之前数值的50%相加,得到享受滤波值
//        value[7] = ADC_Val>>6;
        LCD_write_GT_value(114,4,3,1,0,1,value[7]);//x,y,L,D,N,val :座标、长度、前导零(1显示 0不显示)、字体(0大字体 1中字体)、变量
        
        ADC_Val = 0;                            //读取电压通道8
        for(i=0; i<8; i++){
            ADC_Val += ADC0_GetConversion(ADC_MUXPOS_AIN3_gc);
            DELAY_milliseconds(1);
        }
        value[8] = value[8]/2 + ADC_Val>>6;     //当前转换值(8次相加)除以8(右移3位)再取50%(右移1位)与之前数值的50%相加,得到享受滤波值
//        value[8] = ADC_Val>>6;
        LCD_write_GT_value(164,4,3,1,0,1,value[8]);//x,y,L,D,N,val :座标、长度、前导零(1显示 0不显示)、字体(0大字体 1中字体)、变量
        
        printf("电流值=%d\r\n",value[0]);
        printf("电压通道1=%d\r\n",value[1]);
        printf("电压通道2=%d\r\n",value[2]);
        printf("电压通道3=%d\r\n",value[3]);
        printf("电压通道4=%d\r\n",value[4]);
        printf("电压通道5=%d\r\n",value[5]);
        printf("电压通道6=%d\r\n",value[6]);
        printf("电压通道7=%d\r\n",value[7]);
        printf("电压通道8=%d\r\n\r\n",value[8]);
        
        if(ms>wait){
            ms = 0;
            Led0_Toggle();
        }
    }   
}


    这是通过串口收到的数据截图:
ADC_d.jpg

使用特权

评论回复
pzsh| | 2022-11-28 15:19 | 显示全部楼层
很棒的创作,谢谢分享

使用特权

评论回复
hu9jj|  楼主 | 2022-11-29 10:39 | 显示全部楼层
pzsh 发表于 2022-11-28 15:19
很棒的创作,谢谢分享

谢谢夸奖!待解决了电流采样检测问题,完善了电路图之后准备重新打板,将整个装置放在小盒子中使用。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则