GUIDA ALLA PROGRAMMAZIONE IN C DEL PIC, 15° PARTE

Nella Quindicesima Parte della Guida si Parlerà del Watchdog Timer e della Funzione Sleep Mode per Risparmiare Energia…

 

 

 
 



 

INTRO

Molte volte succede di avere la necessità di un controllo sul flusso del codice per evitare che il microchip rimanga bloccato in un loop senza che ne esca, bloccando il normale funzionamento del codice. Supponiamo ad esempio di avere un codice per leggere due ingressi, con un “if” controllo se il primo ingresso diventa alto e se diventa alto vado avanti, con un altro “if” controllo il secondo ingresso e se diventa alto vado avanti. Per qualche motivo il primo ingresso non diventa mai alto, ma il programma deve continuare a funzionare, quindi serve qualche funzione che rileva i loop e resetti il microcontrollore, cercando di correggere il loop.

Un loop può succedere per un qualsiasi motivo, ad esempio una routine di lettura ADC che va in loop, una routine di scrittura su SD o altre, o addirittura vi può essere un loop causato da un disturbo elettrico, in questo caso è essenziale il WATCHDOG TIMER  (Timer cane di guardia letteralmente) che controlla se avvengono loop e resetta il microcontrollore, facendo funzionare il programma se ad esempio il loop era stato causato da un disturbo elettrico.

Questo timer può inoltre “svegliare” dalla modalità di SLEEP il microcontrollore perché la rete RC di clock a bassa potenza è sempre alimentata.

La modalità di SLEEP dei microcontrollori è un meccanismo molto utile per minimizzare il consumo di potenza quando non serve che il microcontrollore sia in funzione. Il microcontrollore può essere mandato il modalità SLEEP via software e poi essere riattivato dal WDT, da un reset esterno, da un interrupt esterno e altri.

Nella modalità SLEEP il microcontrollore (supponiamo una PIC18F252) consuma una corrente di 200nA circa rispetto ad esempio a 1.6mA con alimentazione di 5V e frequenza di funzionamento di 4MHz. Si passa quindi da 8mW quando il PIC18F è in funzione a 1uW quando è in SLEEP, ovvero una potenza 8000 Volte minore, fattore molto importante quando si lavora con batterie o tensioni provenienti da fonti di energy harvesting.

 





 

IL WATCHDOG TIMER

Il watchdog timer è un timer che utilizza un circuito RC (resistenza e condensatore) per generare una frequenza di clock indipendente dal clock principale. In base a questa frequenza di clock o a una divisione di essa il timer counter si incrementa a partire da 0 fino a 255. Se arriva a 255 il watchdog timer resetta il microcontrollore. Il funzionamento è molto semplice; se il ciclo infinito nel peggiore dei casi dura ad esempio 20ms si setta un prescaler del clock del timer counter in modo tale che per contare da 0 a 255 il timer counter impieghi un tempo maggiore di 20ms. Alla fine del ciclo infinito si va a resettare il watchdog timer così che riparti il ciclo infinito. Se vi è qualche errore il watchdog timer raggiunge 255 e resetta tutto il sistema.

Per funzionare non ha bisogno di componenti esterni, ha bisogno solo di essere configurato e avviato settando gli appositi registri e i fuses prima della programmazione. I registri da settare nel caso del PIC18F252 sono i seguenti:

WDTCON è il registro che contiene il bit SWDTEN per l’accensione via software del watchdog timer; WDTCON.SWDTEN=1 il modulo è acceso, altrimenti è spento e di base è spento.

RCON.TO è settato a 1 dopo l’accensione del microcontrollore mentre è a livello logico 0 se un overflow del watchdog timer, è un bit di flag.

RCON.PD è anch’esso un bit di flag ed è settato a 1 quando il microcontrollore viene acceso oppure è 0 se il microcontrollore è stato mandato in SLEEP.

CONFIG2H con i bit CONFIG2H.WDTPS2, CONFIG2H.WDTPS1, CONFIG2H.WDTPS0 serve per settare il postscaler del watchdog timer ovvero la frequenza di funzionamento con il quale si incrementa il conteggio. Considerando CONFIG2H.WDTPS2 come MSB e CONFIG2H.WDTPS0 come LSB si ha un prescaler con valori 1 (000), 2 (001), 4 (010), 8 (011), 16 (100), 32 (101), 64 (110) e 128 (111).

CONFIG2H.WDTEN accende se settato a 1 il watchdog timer oppure lo spegne se settato a 0.

Il watchdog timer viene resettato con l’istruzione assembly “CLRWDT”.

La frequenza di clock del watchdog timer non è fissa, purtroppo essendo i componenti dell’oscillatore (resistore e condensatore) integrati, vi sono delle tolleranze alte. Per il PIC18F252 si ha un periodo per mandare il watchdog timer senza prescaler in overflow tipico di 18mS con valore massimo di 33mS e minimo di 7mS. Se utilizzo un postscaler 2 (CONFIG2H.WDTPS2-CONFIG2H.WDTPS0=001) il watchdog timer resetterà il microcontrollore dopo un tempo di circa 36ms se non si va a resettare il contatore via software.

Un codice di esempio è il seguente:

void main() {                //Programma principale

  WDTCON.SWDTEN = 1;         //Attiva WDT software
  TRISB = 0;                 //PortB uscite

  while(1){                  //Ciclo infinito

    PORTB.F0 = 1;            //Lampeggio LED
    delay_ms(400);
    PORTB.F0 = 0;
    delay_ms(400);
    PORTB.F0 = 1;

    while(1);                //Loop infinito di blocco
    asm CLRWDT;              //Resetta WDT
  }
}

Si va a configurare il WDT postscaler tramite i FUSES perché purtroppo mikroc non permette la configurazione di questo registro, ma si può fare con i fuses come segue:

Si configurano anche le PORTB  come uscite. Nel ciclo infinito si va a fare un lampeggio e poi si inserisce un ciclo “while” infinito che simula l’errore software. Come si può vedere l’immagine della simulazione il WDT interviene resettando il microcontrollore. Senza WDT il led rimaneva acceso e il microcontrollore chiuso nel loop.

Eliminando il loop, come avviene nella figura di destra nell’immagine dei circuiti, si vece che il microcontrollore non si resetta perché ci pensa l’istruzione assembly (asm) “asm CLRWDT;” a resettare il WDT.

Nella simulazione il tempo di reset è quello tipico, ovvero 18mS. Se però state programmando un microcontrollore reale dovete considerare che i tempi sono con tolleranza da un minimo di 7ms ad un massimo 33ms, quindi se bisogna fare un controllo molto veloce non si può fare più veloce di 33mS mentre se si ha un programma molto lento a cui serve il WDT potrebbe concludersi correttamente se più lungo di 892ms perché nel caso peggiore il tempo massimo è questo.
 

MODALITÀ SLEEP MICROCONTROLLORE

Una volta in modalità SLEEP il microcontrollore consumerà una potenza molto piccola perché rimangono in funzione solo alcune strutture come il WDT, Timer Counter e le strutture di interrupt. Alcune strutture devono necessariamente rimanere alimentate perché sono necessarie per riattivare il microcontrollore dallo stato di sleep.

Solitamente tutte le fonti di interrupt possono essere usate per riattivare il microcontrollore dalla fase di sleep, e per quanto riguarda il PIC18F252 si ha l’interrupt del timer counter 0 e 1, il cambio del valore sulle PORTB, gli interrupt esterni delle PORTB, il pin MCLR di reset, il WDT, l’interrupt della comunicazione SPI, I2C e USART, il convertitore ADC  e l’interrupt della memoria EEPROM in grado di riattivare il microcontrollore.

Queste funzioni sono molto utili, ad esempio supponiamo di avere un microcontrollore che quando riceve un dato esegue una funzione e poi non fa nulla finche non riceve un altro dato. Supponiamo inoltre che riceve un dato ogni ora. Sarebbe molto comodo spegnere il microcontrollore quando non serve che sia acceso e riattivarlo solo quando arriva un dato. Grazie all’interrupt sui moduli di comunicazione (SPI, I2C o USART) questo è possibile.

È possibile inoltre spegnere il microcontrollore mentre si aspetta che l’ADC converta un valore, lasciandolo funzionare con il circuito RC interno e risparmiando parte dell’energia.

Per mandare il microcontrollore in modalità SLEEP si utilizza la stringa assembly asm SLEEP; . Dopo questa istruzione le uscite rimangono allo stato in cui si trovavano precedentemente, il clock principale si spegne e il program counter (è la porzione di circuito che esegue le istruzioni) entra in modalità SLEEP riducendo al minimo il consumo.

Supponiamo per un codice di esempio di voler realizzare un programma che cambi lo stato di accensione di due led ogni 2 secondi circa. Si potrebbe fare con due delay da 2 secondi ognuno, accendo il primo led e spengo il secondo, delay di due secondi, spengo il primo led e accendo il secondo e altro delay da due secondi in un ciclo infinito. In questo modo, per 4 secondi, il microcontrollore consuma circa 4mA e questo per tutti gli altri cicli a seguire.

Supponiamo invece di accendere il primo led, spegnere il secondo, mandare in sleep il microcontrollore, riattivarlo dopo due secondi, cambiare di nuovo lo stato dei led spegnendo il primo e accendendo il secondo, e poi inserire un delay di due secondi sempre nel ciclo infinito. In questo modo avremo 2 secondi di delay in cui il program counter e il clock funzionano e due secondi di sleep e possiamo valutare il diverso consumo di corrente con un amperometro nelle due fasi.

Per riattivare il microcontrollore dopo due secondi usiamo il WDT, visto che appena si manda in sleep il microcontrollore il WDT viene resettato e in modalità sleep continua a contare.

Il codice è il seguente:

sbit LED1 at RB0_bit;       //PORTB RB0 USCITA CON LED
sbit LED2 at RB1_bit;       //PORTB RB0 USCITA CON LED

void main() {
TRISB = 0b00000000;         //PORTB USCITE

while(1) {
  LED1 = 1;                //LED1 acceso LED2 spento
  LED2 = 0;
  asm sleep;               //Modalità sleep, WDT azzerato
                           //Corrente minore
                           
  LED1 = 0;                //LED1 spento LED2 acceso
  LED2 = 1;
  asm CLRWDT;              //Pulisci WDT
  Delay_ms(2000);          //Program counter e clock accesi
                           //Consumo corrente maggiore
  }
}

Si vanno a definire i led, nel programma principale si vanno a porre uscite le PORTB e nel ciclo infinito si va ad accendere il primo led e si spegne il secondo, poi si manda in sleep il microcontrollore che verrà riattivato dopo circa 2 secondi dall’overflow del WDT. Finito lo stato di sleep si inverte lo stato dei due led e si usa un delay software per attendere altri 2 secondi prima di ricominciare il ciclo.

Grazie a questo codice è possibile capire la reale durata del periodo del WDT (teoricamente 18ms ma in realtà sarà il periodo di accensione del LED1 diviso 128) ed è inoltre possibile misurare la corrente assorbita e quindi la potenza nelle due diverse fasi, ovvero modalità sleep e modalità di normale funzionamento.

Il circuito per testare entrambi i codici è il seguente:

L’alimentazione del circuito viene fatta con una tensione continua e stabilizzata con valore di 5V e il terminale positivo dell’alimentazione è connesso al pin 20 del microcontrollore e ad un capo della resistenza R1. Il terminale negativo è connesso ai pin 8 e 19 del microcontrollore, a un capo dei condensatori C1 e C2, e ai catodi dei due LED.

X1, il cristallo da 4MHz e C1, C2 formano il circuito che genera il clock mentre R1 mantiene in funzione il microcontrollore. R2 ed R3 seno le due resistenze di protezione che fan si che giunga la giusta corrente per accendere D1 e D2 ovvero i due diodi LED.

 

DOWNLOAD

Potete scaricare la simulazione del circuito con PROTEUS  e i codici compilati con MIKROC al seguente LINK!!!



 

[Voti Totali: 0 Media Voti: 0]
Segui la Nostra Pagina Facebook: Facebook

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *