Salta la barra di navigazione [1] - Vai alla barra di navigazione [3] - Scrivimi una mail [4]

Usare l'ADCC con MCC

PIC18 in C - Sommario - Novità - Tutorial - Progetti - Risorse - Non solo elettronica

PIC18LF26K42

In fase di sviluppo Stesura preliminare In fase di sviluppo

In questa pagina è descritto come usare l'ADC with computation module interno al PIC18F2xK42insieme a MPLAB Code Configurator. Prima di proseguire, consiglio la lettura di Usare l'ADC con MCC - Utilizzo di base

L'hardware dell'ADCC

L'ADCC del PIC18F2xK42 permette di effettuare una serie di operazioni indipendentemente dalla CPU. Due i vantaggi:

In questa pagina è descritta (al momento...) una sola modalità di funzionamento:

La struttura di un ADCC è costituta:

Burst Average

Questa modalità permette di effettuare automaticamente la media tra N misure di tensione, al fine di migliorare il rapporto segnale rumore della misura. La configurazione dell'ADCC può essere fatta con MCC:

Impostazione dell'ADCC

Sono evidenziati i tre parametri specifici di questa modalità:

Il codice non è molto diverso rispetto all'uso della modalità base dell'ADCC:

void main(void) {
    volatile float VoltageAcc, VoltageLowNoise, Voltage;

    SYSTEM_Initialize(); // Initialize the device

    while (1) {
        Voltage = ADCC_GetSingleConversion(A0); // Start AD conversion and get last ADC result
        if (!ADCC_HasAccumulatorOverflowed()) { // Accumulator overflow?
            VoltageLowNoise = ADCC_GetFilterValue(); // Get average value
            VoltageAcc = ADCC_GetAccumulatorValue(); // Get accumulato value
        }
        NOP();
        __delay_ms(100);
    }
}

Ovviamente il tempo di conversione è pari alla somma dei tempi di conversione singoli; con i numeri mostrati servono circa 2,8 ms.

Da notare che è necessario usare la funzione MCC ADCC_GetSingleConversion() per avviare la serie delle conversioni, azzerare automaticamente ADACC e ADCNT, attendere il termine della conversione multipla; successivamente occorre leggere il registro ADFLTR e/o ADACC con le funzioni MCC corrispondenti; è inoltre necessario verificare che non ci sia stato un overflow nel registro ADACC, cosa possibile se si sommano molti valori e questi sono grandi (nota 2).

L'uso della media permette di migliorare il rapporto segnale/rumore. Non ho fatto misure rigorose, ma indicativamente il passaggio dal singolo campione alla media di 16 oppure 64 valori porta il SNR da 71 dB a 81 dB a 88 dB, rispettivamente (nota 3).

Conversione in SLEEP

Una delle cause del rumore di conversione è il funzionamento stesso della CPU. Per questo è una buona idea spegnere il processore mentre funziona l'ADC. Al termine della conversione una interruzione risveglierà la CPU che riprenderà il programma dove era stato sospeso

Per fare ciò è possibile configurare l'ADCC sia in Basic Mode che in Burst Average, come mostrato nelle due figure seguenti, alternative tra di loro:

Conversione in Sleep mode, Basic Mode

Conversione in Sleep mode, burts average

Ho evidenziato nelle immagini precedenti alcune particolarità:

La lettura può essere fatta con una funzione simile alla seguente, scritta sulla falsariga di quella presente in MCC, scegliendo il valore di ritorno a cui si è interessati:

adc_result_t ADCC_LowNoise(adcc_channel_t channel) {
    CPUDOZEbits.IDLEN = 0; // Sleep CPU, not doze
    ADPCH = channel; // select the A/D channel
    ADCON0bits.ADON = 1; // Turn on the ADC module
    ADCON0bits.ADCONT = 0; //Disable the continuous mode.
    ADCON0bits.ADGO = 1; // Start the conversion
    SLEEP(); // Sleep CPU. Wakeup from interrupt
    return (ADCC_GetConversionResult()); // Conversion finished, return the result (single conversion)
    // return (ADCC_GetFilterValue()); // Conversion finished, return the result (average)
}

Due le differenze:

Il main() è praticamente identico al precedente, con l'unica avvertenza di attivare le interruzioni:

void main(void) {
    volatile float ADCmeas;
    SYSTEM_Initialize(); // Initialize the device
    INTERRUPT_GlobalInterruptHighEnable(); // Enable high priority global interrupts
    while (1) {
        ADCmeas = ADCC_LowNoise(channel_Temp);
    }
    NOP();
    __delay_ms(10);
}

Si noti l'assenza di Interrupt Service Routine in quanto l'unica funzione della interruzione è il risveglio del processore.

Anche in questo caso non ho misure definitive sul miglioramento del SNR. Nel test preliminare ed usando il riferimento interno per misurare la temperatura, ho osservato un miglioramento del SNR di 3 dB abbondanti usando la modalità SLEEP. Si tratta comunque di misure da prendere con le pinze in quanto realizzate utilizzando un debugger e quindi in condizioni piuttosto diverse da quelle un circuito reale.

Osservazioni

  1. In realtà sono 3 registri, costituiti da 8 + 8 + 2 bit
  2. Se si sommano fino a 64 valori non è possibile un overflow visto che il registro ADACC è costituito da 18 bit e la risoluzione dell'ADCC è di 12 bit
  3. I valori riportati sono il rapporto tra una tensione fissa vicina al fondoscala e la deviazione standard riferita a ADACC e quindi non è utilizzabile per esempio per calcolare l'ENOB oppure il confronto con i dati dei datasheet (che comunque Microchip non pubblica)


Data di creazione di questa pagina: luglio 2019
Ultima modifica: 26 luglio 2019


PIC18 in C

Appendici:

Qualche utile informazione integrativa: C per sistemi embedded

Licenza Creative Commons Attribuzione 4.0 Internazionale


EN - Pagina principale - Sommario - Accessibilità - Note legali e privacy policy - Posta elettronica

XHTML 1.0 Strict - CSS 3