[AVR] Lập trình đo dòng điện, điện áp sử dụng bộ chuyển đổi ADC

Thảo luận trong 'AVR' bắt đầu bởi XuanHoa.MCA, 8/8/19.

  1. XuanHoa.MCA

    XuanHoa.MCA New Member

    Xin chào các bạn!
    Hôm nay mình sẽ hướng dẫn các bạn đo điện áp và dòng điện sử dụng vi điều khiển Atmega16. Dải đo điện áp của mạch nằm trong khoảng 0-30V sai số ± 0.015V và dải đo dòng điện 0-8A sai số ± 0.01A (trường hợp điều kiện lí tưởng).
    I. Sơ đồ nguyên lí
    [​IMG]
    Trong đó:
    R1,R2,R6 là trở 1/4W
    R3,R4 là trở công suất 10W
    R5 là tải
    II. Lập trình phần mềm.
    1. Phương pháp tính toán.
    Để có thể đo được điện áp chúng ta cần sử dụng một mạch cầu phân áp vì điện áp mà bộ chuyển đổi ADC của AVR chỉ có thể chuyển đổi tín hiệu có điện áp tối đa bằng điện áp nguồn cung cấp cho VĐK là 5V. Ở bài này chúng ta chọn điện áp tham chiếu là điện áp tham chiếu nội 2.56v.
    Như vậy điện áp tối đa đặt lên chân ADC0 của VĐK sẽ là 2,56. Với yêu cầu điện áp tối đa đo được là 30v ta chọn cầu phân áp như trong nguyên lí. Như vậy điện áp đặt lên ADC0 là: UADC0=U*(R2/(R2+R1+R6))=U*((4.7+4.7+47)/4.7)=> U= UADC0*12
    ADC của ATmega16 có độ phân giải 10 bit => UADC0=ADC0_Value*(2.56/1024)
    =>U=ADC0_Value*(2.56/1024)*12
    Để đo dòng điện chúng ta sử dụng 2 con điện trở 0.5 ohm công suất 10W. Ta mắc song song 2 con điện trở để có được điện trở tương đương là 0.25 ohm để tiện tính toán vì ở đây chúng ta chọn điện áp tham chiếu là 2.56 như vậy mỗi bước của ADC là 2.56/1024=0.0025. Hơn nữa khi mắc song song 2 điện trở dải đo dòng điện còn được tăng lên do dòng điện mà mỗi điện trở phải chịu sẽ giảm đi. Như vậy để đo dòng điện ta dụng định luật Ohm:
    I=UADC1/((R3*R4)/(R3+R4)) =(ADC1_Value*(2.56/1024))/0.25
    2. Chương trình cho VĐK
    Trước tiên ta cần kích hoạt bộ ADC và cấu hình hệ số chia tần số, điện áp tham chiếu. Ở đây ta chọn hệ số chia tần số là 64, điện áp tham chiếu là điện áp tham chiếu nội 2.56v. Để thực hiện các công việc này ta tạo hàm void ADC_Init().
    Mã:
    void ADC_Init()
    {
       ADCSRA |= ((1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)); //Kích hoạt ADC, Chọn hệ số chia tần số là 64
       ADMUX = INTRERNAL_MODE; // Chọn điện áp tham chiếu nội 2,56v
       
    }
    
    Tiếp theo chúng ta có thể tiến hành đọc điện áp trên các kênh ADC.
    Mã:
    unsigned int ADC_READ(unsigned char ADC_Chanel)
    {
       ADMUX = INTRERNAL_MODE|ADC_Chanel; //Chọn kênh ADC
       ADCSRA |=  (1<<ADSC); // Bắt đầu quá trình chuyển đổi
       loop_until_bit_is_set(ADCSRA,ADIF); // đợi đến khi cờ ADIF báo quá trình chuyển đổi hoàn tất
       ADCSRA|=(1<<ADIF); // Xóa cờ báo
       return ADCW; // trả về giá trị mà ADC đọc được
       
    }
    
    Để hiển thị kết quả ra màn hình ta dùng LCD. Các sử dụng và thư viện của LCD mình đã trình bày ở bài trước.
    Trước tiên ta cần định nghĩa một số giá trị của các điện trở của cầu phân áp và trở shunt.
    Mã:
    #define R1 4700
    #define R2 4700
    #define R6 47000
    #define R3 0.5
    #define R4 0.5
    
    Với chương trình chính ta cần gọi hàm LCD_Init() và ADC_Init() để tiến hành thiết lập cho LCD và ADC.
    Mã:
    int main(void)
    {
       ADC_Init();
       LCD_Init();
    
    Tiếp theo ở vòng lặp vô hạn while(1). Ta tiến hành tính toán và in kết quả ra màn hình.
    Mã:
    while (1)
        {
           unsigned int ADC_UValueAverage=0, ADC_IValueAverage=0;
           for (unsigned char i=0;i<20;i++)
           {
           unsigned int ADC_UValue;
           ADC_UValue= ((ADC_READ(0)*(2.56/1024)*((R1+R2+R6)/R1))*100); // nhân với 100 để lấy 2 chữ số sau dấu phẩy
           ADC_UValueAverage +=ADC_UValue;   
           _delay_ms(10);
           unsigned int ADC_IValue;
           ADC_IValue= (((ADC_READ(1)*(2.56/1024))/((R3*R4)/(R3+R4)))*100);
           ADC_IValueAverage += ADC_IValue;
           _delay_ms(10);
           }
           ADC_IValueAverage = ADC_IValueAverage/20;
           ADC_UValueAverage = ADC_UValueAverage/20;
           unsigned char ADC_Value_V=ADC_UValueAverage/100;
           unsigned char ADC_Value_mV=ADC_UValueAverage%100;
           LCD_Gotoxy(0,0);
           LCD_Puts("Volgate:");
           LCD_PutChar((ADC_Value_V/10)+48);
           LCD_PutChar((ADC_Value_V%10)+48);
           LCD_PutChar('.');
           LCD_PutChar((ADC_Value_mV/10)+48);
           LCD_PutChar((ADC_Value_mV%10)+48);
           LCD_PutChar('V');
       
           
           unsigned char ADC_Value_A=ADC_IValueAverage/100;
           unsigned char ADC_Value_mA=ADC_IValueAverage%100;
           LCD_Gotoxy(0,1);
           LCD_Puts("Current:");
           LCD_PutChar((ADC_Value_A/10)+48);
           LCD_PutChar((ADC_Value_A%10)+48);
           LCD_PutChar('.');
           LCD_PutChar((ADC_Value_mA/10)+48);
           LCD_PutChar((ADC_Value_mA%10)+48);
           LCD_PutChar('A');
           
        }
    Như vậy là bạn đã có thể đo được dòng điện và điện áp với VĐK.
    Các bạn có thể tải về mạch nguyên lí, PCB, CODE tại đây.
     

trang này