logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

ADC w ATxmega32A4U-AU: Nieprawidłowe odczyty napięcia z zewnętrznego pinu

lupin22 19 Lip 2024 14:55 177 2
REKLAMA
  • #1 21160522
    lupin22
    Poziom 10  
    Cześć,

    mam problem z odczytem ADC w kontrolerze ATxmega32A4U-AU. Odczytuję dwie wartości, VCC oraz podpięte na zewnętrznym pinie napięcie z baterii litowo jonowej podzielone dzielnikiem napięcia przez 4.

    ADC konfiguruję w ten sposób:
    void battery_management_init()
    {
       // Setup battery input
       PORTA.DIRCLR = PIN0_bm;
       PORTA.PIN0CTRL = PORT_ISC_INPUT_DISABLE_gc;
    
       // Setup general ADC characteristics
       ADCA.REFCTRL = ADC_REFSEL_INT1V_gc| ADC_BANDGAP_bm;         // Internal 1V reference source
       ADCA.CTRLB = ADC_CONMODE_bm;                        // Signed measurement to avoid offset
       ADCA.PRESCALER=ADC_PRESCALER_DIV16_gc;
    
       // Setup channel 0 to measure battery voltage
       ADCA.CH0.MUXCTRL = ADC_CH_MUXPOS_PIN0_gc;
       ADCA.CH0.CTRL = ADC_CH_INPUTMODE_SINGLEENDED_gc;
    
       // Setup channel 1 to measure internal VCC/10
       ADCA.CH1.CTRL = ADC_CH_INPUTMODE_INTERNAL_gc;
       ADCA.CH1.MUXCTRL = ADC_CH_MUXINT_SCALEDVCC_gc;
    
       ADCA.CALL = ReadCalibrationByte(offsetof(NVM_PROD_SIGNATURES_t, ADCACAL0));
       ADCA.CALH = ReadCalibrationByte(offsetof(NVM_PROD_SIGNATURES_t, ADCACAL1));
    
       // Enable ADC
       ADCA.CTRLA=ADC_ENABLE_bm;
    }


    Wykorzystuję wewnętrzne napięcie odniesienia o wartości 1V. Do mierzenia wartości wykorzystuję następującą funkcję:
    uint16_t adc_measure_channel(ADC_CH_t* channel)
    {
       uint16_t result = 0;
       for (uint8_t i = 0; i < 6; i++)
       {
          channel->CTRL |= ADC_CH_START_bm;
          while(!(channel->INTFLAGS & ADC_CH_CHIF_bm));
          channel->INTFLAGS = ADC_CH_CHIF_bm;
          if (i > 0) result += channel->RES;
       }
       return result/5;
    }

    Pięć pomiarów (z pominięciem pierwszego), uśrednione.

    Gdy mierzę napięcie zasilania procesora na kanale 1, przy 3.3V zasilania uzyskuję wynik 650-660.
    Biorąc pod uwagę, że zakres pomiaru to 0-2047, oznacza to, że zmierzone napięcie wynosi 10*660/2047 (wewnętrznie podpięte od adc zasilanie jest podzielone dziesięciokrotnie), co daje mi wynik 3.22V Niezupełnie tak, jak być powinno, ale różnica wynosi 2,5%, mi to wystarczy.

    Problem pojawia się, gdy mierzę zasilanie z zewnętrznego pinu, które zmierzyłem dla dwóch napięć - 1.01V oraz 0.93V. Napięcie zmierzone woltomierzem bezpośrednio na pinie pomiaru (PA0).

    Dla wartości 1.01V otrzymuję wynik odczytu 1810, natomiast dla wartości 0,93V wynik to 1670. Już pierwszy wynik wydaje się być oczywistym błędem, bo przy pomiarze względem napięcia odniesienia 1V powinienem otrzymać wynik 2047. Dla 0,93 powinienem dostać wynik 1903.

    Jak nietrudno zauważyć, 1810-1670 = 140, a 2047-1903 = 144. Czyli wygląda to tak, jakby "skala" pomiaru była właściwa, natomiast był on przesunięty o mniej więcej 0.1V Według datasheetu przy pomiarze signed, którego dokonuję, żadnego offsetu być nie powinno:
    Tabela z wynikami ADC w trybie signed i unsigned dla ATxmega32A4U.

    Co może być przyczyną tego stanu rzeczy?
  • REKLAMA
  • #2 21160687
    drunek
    Poziom 23  
    Daj schemat podłączenia mikrokontrolera.
  • #3 21160778
    lupin22
    Poziom 10  
    >>21160687
    Schemat obwodu z komponentami, takimi jak rezystory, cewki i kondensatory.
    EDIT: Na schemacie jest pomyłka, rezystor oczywiście 82k, a nie 82.
REKLAMA