Pagina 1 di 3

PIC12F509 in modalità SLEEP

MessaggioInviato: 13 apr 2010, 17:02
da davidde
Ciao a tutti.

E' un paio di giorni che cerco di mandare in modalità SLEEP il PIC12F509.
Il PIC è settato con oscillatore interno (4MHz) e quindi non riesco a vedere tramite i pin normalmente collegati al quarzo se effettivamente l' oscillatore viene spento.
Per capire se enti o meno in stand by l' unica verifica che posso fare è quella di montare in serie a Vdd un' amperometro tramite il quale misurare l' assorbimento nella condizione di normale funzionamento e l' assorbimento dopo l' esecuzione dell' istruzione SLEEP.

Il problema è proprio qui, infatti l' assorbimento non varia di nulla rimane costante a circa 350µA. Guardando il datasheet invece mi risulta che dovrebbe calare vistosamente nonostante la mia tensione di alimentazione sia a 5V invece che a 2V come indicato in tabella:

assorbimento.png
assorbimento.png (12.24 KiB) Osservato 6327 volte


Inoltre se simulo (MPLAB sim) il programma noto che nel registro STATUS il POWER DOWN BIT (cioè il bit 3) cambia stato portandosi a zero subito dopo la lettura dell' istruzione SLEEP, e questo se non erro dovrebbe segnalare l' entrata in stand by del microcontrollore:

Registro STATUS.png
Registro STATUS.png (125.41 KiB) Osservato 6325 volte


I bit di configurazione sono così settati:

Configuration bits.png
Configuration bits.png (42.54 KiB) Osservato 6323 volte


Ed infine la parte di codice che potrebbe interessare (ancora priva di commenti):

Codice: Seleziona tutto
#include P12F509.INC                         
__CONFIG    B'000000001010'

TIMER_1        ORG 50H
TIMER_2        ORG 51H
TIMER_3        ORG 52H
CONTEGGIO      ORG 53H
CONTEGGIO_ACC  ORG 54H
CONTEGGIO_LAMP ORG 55H
         
         ORG 60H

CLRF   GPIO
MOVLW  B'00011100'     
TRIS   GPIO   

MOVLW  B'01000000'   
OPTION

BCF    GPIO,0

BCF    GPIO,1

MOVLW  D'255'
MOVWF  TIMER_1

MOVLW  D'255'
MOVWF  TIMER_2

MOVLW  D'3'
MOVWF  TIMER_3

MOVLW  D'10'
MOVWF  CONTEGGIO

MOVLW  D'100'
MOVWF  CONTEGGIO_ACC

MOVLW  D'10'
MOVWF  CONTEGGIO_LAMP


INIT            BTFSC GPIO,3
                GOTO LED_SPENTO
                GOTO LED_ACCESO

..............
..............
..............

LUCE         BSF GPIO,0
                BTFSC GPIO,3
                GOTO LUCE_RECUPERO
                BCF GPIO,0
                CALL RITARDO
                CALL RITARDO
                CALL RITARDO
                CALL RITARDO
                CALL RITARDO               
                SLEEP

END




Dunque vi chiedo, è corretto controllare come sto facendo io l' entrata del microcontrollore in modalità SLEEP ?
Dovrei effettivamente notare un calo di corrente ?

Ciao e grazie !!

David

Re: PIC12F509 in modalità SLEEP

MessaggioInviato: 13 apr 2010, 17:16
da c1b8
Ciao, solo una domandina: perché inizi il programma dalla locazione 60H e non dalla 0h?

Re: PIC12F509 in modalità SLEEP

MessaggioInviato: 13 apr 2010, 17:49
da davidde
Ciao,

a dire il vero partivo dalla 0H poi, prove facendo, sono arrivato fino alla 60H :) .Scherzi a parte, perché questo PIC ha l' oscillatore interno che può essere calibrato attraverso il registro OSCCAL. Tale registro deve essere precaricato ad ogni accensione (se interessa che l' oscillatore sia preciso). Dopo aver "accidentalmente" resettato la cella di memoria contenete la precalibrazione fatta in fabbrica da Microchip in un paio di PIC, ho provato, dopo aver montato un nuovo microcontrollore a leggerne il contenuto e " ho scoperto" che oltre al valore della precalibrazione (contenuta all' indirizzo 3FF) questo componente contiene all' interno un intero programma che va dalla cella 0H fino alla 40H.

Visto che non sapevo più dove sbattere la testa, ho provato per non cancellare il programma originale a partire da più avanti, per capire se fosse dovuto a ciò il fatto che il micro non mi entrasse in SLEEP. Purtroppo anche questa prova è stata vana, quel programma non c' entra nulla, probabilmente serve soltanto alla Microchip al momento della calibrazione dell' oscillatore interno.

Concluse le prove non mi sono più preoccupato di partire dalla 0H ed anche quando ho postato il messaggio non mi è venuto in mente di aggiornare il codice..... ora provvedo :wink: ...

Re: PIC12F509 in modalità SLEEP

MessaggioInviato: 13 apr 2010, 20:38
da c1b8
La mia era pura curiosità.

Dovresti tentare le seguenti modifiche:
- Impostare ad '1' il bit 7 del registro OPTION (come già fatto per il bit 6)
- Immediatamente prima di eseguire la SLEEP leggere la porta con una MOVLW GPIO

Verificherei inoltre lo stato delle uscite al momento dello SLEEP, se hai uscite che pilotano carichi (led) potrebbero essere questi la causa del continuo eccessivo consumo.

Fammi sapere.

Re: PIC12F509 in modalità SLEEP

MessaggioInviato: 13 apr 2010, 23:00
da Paolino
Questo è un PIC "povero", non ha quel granché di periferiche. Però, come dice c1b8, se lasci delle periferiche attive (in questo caso I/O su carichi), è normale che si assorba più corrente.
Puoi provare, per vedere se i consumi previsti dal datasheet li riscontri, a caricare un fw che non fa nulla se non uno misero SLEEP. Metti le porte in INPUT e poi SLEEP... Secondo me il consumo si abbassa.
Ciao.

Paolo.

Re: PIC12F509 in modalità SLEEP

MessaggioInviato: 14 apr 2010, 11:08
da davidde
Ciao ragazzi, grazie mille, abbiamo risolto !

Ho seguito il suggerimento di c1b8, disabilitando il "wake-up on pin change bit" ed ho visto da subito che il microcontrollore riusciva ad entrare in SLEEP. Per come è strutturato il programma però mi serve proprio che il risveglio del PIC avvenga per cambio di stato di GP3 e perciò non potevo lasciare disabilitata tale funzione.

Ho quindi settato nuovamente il registro TRIS GPIO configurando tutti i pin I/O (a parte GP3) come uscite ed impostandole a livello logico basso. Fatto ciò ho riabilitato il "wake-up on pin change bit" e il programma ha funzionato da subito perfettamente.

Gli assorbimenti attuali sono di 350µA con il microcontrollore acceso e di soli 0,3µA con il microcontrollore in SLEEP, adesso tutto torna, come indicato dai grafici 11-2 e 11-3 del datasheet.

A conti fatti quindi mi sa proprio che il microcontrollore in SLEEP ci entrasse ma fosse risvegliato subito dopo da un cambio di stato (dovuto a qualche disturbo) di un qualsiasi ingresso (GP0, GP1, GP3) che prima era lasciato flottante e non fissato da nessuna resistenza di pull-down o pull-up :oops: ...

Metto qui lo schema utilizzato attualmente e il codice che permette di far lampeggiare i due led secondo le tempistiche che mi servono:

Schema elettrico.png
Schema elettrico.png (3.51 KiB) Osservato 6253 volte


Codice: Seleziona tutto
#include P12F509.INC                         
__CONFIG    B'000000001010'

TIMER_1        ORG 70H
TIMER_2        ORG 71H
TIMER_3        ORG 72H
CONTEGGIO      ORG 73H
CONTEGGIO_ACC  ORG 74H
CONTEGGIO_LAMP ORG 75H
         
         ORG 0H

INIT            MOVF  3FFH,W   
                MOVWF OSCCAL

                MOVLW  B'00001000'  ;DEFINISCE GP3 COME INGRESSO, GLI ALTRI COME USCITE
                TRIS   GPIO   

                MOVLW  B'00000000'  ;PORTA A LIVELLO LOGICO BASSO TUTTE LE USCITE
                MOVWF  GPIO   

                MOVLW  B'01000000'   
                OPTION

                MOVLW  D'255'
                MOVWF  TIMER_1

                MOVLW  D'255'
                MOVWF  TIMER_2

                MOVLW  D'8'
                MOVWF  TIMER_3

                MOVLW  D'10'
                MOVWF  CONTEGGIO

                MOVLW  D'100'
                MOVWF  CONTEGGIO_ACC

                MOVLW  D'10'
                MOVWF  CONTEGGIO_LAMP


MAIN            BTFSS GPIO,3
                GOTO LED_SPENTO
                GOTO LED_ACCESO

LED_SPENTO      BCF GPIO,0
                GOTO INIT

LED_ACCESO      BSF GPIO,0
                GOTO SEGNALE_FISSO

SEGNALE_FISSO   CALL RITARDO
                CALL RITARDO
                CALL RITARDO 
                CALL RITARDO
                CALL RITARDO
                CALL RITARDO
                CALL RITARDO
                CALL RITARDO
                GOTO SEGNALE_LAMP

SEGNALE_LAMP    BCF GPIO,0
                CALL RITARDO
                BSF GPIO,0
                CALL RITARDO           
                DECFSZ CONTEGGIO
                GOTO SEGNALE_LAMP
                MOVLW D'10'
                MOVWF CONTEGGIO               
                BCF GPIO,0
                GOTO ACCENSIONE

ACCENSIONE      BSF GPIO,1     
                CALL RITARDO
                DECFSZ CONTEGGIO_ACC
                GOTO ACCENSIONE
                MOVLW D'100'
                MOVWF CONTEGGIO_ACC
                BCF GPIO,1               
                GOTO ACCENSIONE_LAMP

ACCENSIONE_LAMP BCF GPIO,1
                CALL RITARDO_LENTO
                BSF GPIO,1
                CALL RITARDO           
                DECFSZ CONTEGGIO_LAMP
                GOTO ACCENSIONE_LAMP
                MOVLW D'10'
                MOVWF CONTEGGIO_LAMP               
                BCF GPIO,1
                GOTO LUCE_RECUPERO

LUCE_RECUPERO   BSF GPIO,0
                BTFSS GPIO,3
                GOTO LUCE_RECUPERO
                BCF GPIO,0
                CALL RITARDO
                CALL RITARDO
                CALL RITARDO
                CALL RITARDO
                CALL RITARDO 
                CALL RITARDO
                CALL RITARDO
                CALL RITARDO
                CALL RITARDO
                CALL RITARDO
                CALL RITARDO
                CALL RITARDO
                CALL RITARDO
                CALL RITARDO
                CALL RITARDO           
                SLEEP                     

RITARDO         NOP
                DECFSZ TIMER_1
                GOTO RITARDO
                MOVLW D'255'
                MOVWF TIMER_1
                NOP
                DECFSZ TIMER_2
                GOTO RITARDO
                MOVLW D'255'
                MOVWF TIMER_2
                RETURN

RITARDO_LENTO   DECFSZ TIMER_1
                GOTO RITARDO_LENTO
                MOVLW D'255'
                MOVWF TIMER_1
                DECFSZ TIMER_2
                GOTO RITARDO_LENTO
                MOVLW D'255'
                MOVWF TIMER_2
                DECFSZ TIMER_3
                GOTO RITARDO_LENTO
                MOVLW D'8'
                MOVWF TIMER_3
                RETURN

END


Adesso vado a litigare un po' con il registro OSCCAL perché non sono ancora riuscito a capire se mi da retta o se mi prende in giro...

Ancora grazie ad entrambi per la disponibilità :!:

P.S
Già che ci sono apro un' altro topic perché la tua domandina, c1b8, mi ha fatto venire alcuni dubbi :) .....

Re: PIC12F509 in modalità SLEEP

MessaggioInviato: 14 apr 2010, 11:45
da c1b8
Ciao, guardando il codice noto che dopo la SLEEP non hai istruzioni che impediscano al micro di entrare nella routine RITARDO senza CALL e quindi incappare in un RETURN che a mio avviso porterebbe al reset del PIC.
E' corretto?

Re: PIC12F509 in modalità SLEEP

MessaggioInviato: 14 apr 2010, 13:27
da davidde
Si, quello che mi interessa fare è questo:

- al tocco dell' interruttore il micro deve eseguire il programma e farmi lampeggiare i led secondo le tempistiche volute.

- dopo aver eseguito tutti i vari lampeggi il programma si ferma con il led collegato al pin GP0 acceso (entra cioè nel sottoprogramma LUCE_RECUPERO e continua a testare il pin GP3).

- a questo punto per spegnere anche il led collegato a GP0 bisogna toccare nuovamente l' interruttore (GP3). Dopo averlo toccato il microcontrollore porta a livello logico basso il pin d' uscita GP0 spegnendo il relativo led, poi comincia a chiamare il sottoprogramma RITARDO per dare il tempo (in totale 6 secondi circa) a chi utilizza il dispositivo di togliere il dito dall' interruttore senza che il ciclo ricominci da capo.

- trascorso questo tempo il microcontrollore entra in SLEEP eseguendo appunto l' ultima istruzione del sottoprogramma LUCE_RECUPERO. Il programma è quindi terminato e il micro in standby.

- toccando nuovamente l' interruttore il micro si resetta e il programma riparte da capo.


Questo è quello che mi interesserebbe fare, a livello pratico tutto sembra funzionare correttamente ma con ciò non escludo che il programma contenga errori o possa comunque essere migliorato. Non riesco a capire bene cosa intendi con il tuo ultimo discorso e se alla luce di questi ultimi aggiornamenti ritieni ancora "scorrette" le modalità di SLEEP...

Ciao e grazie !

Re: PIC12F509 in modalità SLEEP

MessaggioInviato: 14 apr 2010, 13:45
da Paolino
davidde ha scritto:Non riesco a capire bene cosa intendi con il tuo ultimo discorso e se alla luce di questi ultimi aggiornamenti ritieni ancora "scorrette" le modalità di SLEEP...

Intende dire che, nono appena il PIC si riprende dallo SLEEP, in effetti non viene resettato il micro bensì il program counter continua con le istruzioni che seguono. Questo significa che esegue le istruzioni della routine RITARDO.

Prova a mettere giù un flow-chart. Secondo me l'uso che fai dei GOTO è, in alcuni punti del codice, inutile. Ad esempio:
Codice: Seleziona tutto
    LED_ACCESO      BSF GPIO,0
                    GOTO SEGNALE_FISSO

SEGNALE_FISSO   CALL RITARDO

lo cambierei in:
Codice: Seleziona tutto
    LED_ACCESO      BSF GPIO,0

SEGNALE_FISSO   CALL RITARDO


Molte delle funzioni che chiami con GOTO potrebbero diventare suroutine ed essere chiamate con CALL e RETURN.

Ciao.

Paolo.

Re: PIC12F509 in modalità SLEEP

MessaggioInviato: 14 apr 2010, 13:59
da c1b8
Non volevo criticare il programma (o il programmatore :mrgreen: ) ma far notare una situazione che a mio parere è fonte di possibili comportamenti inaspettati.
In particolare mi riferisco a questa parte di codice:
Codice: Seleziona tutto
                    .
                    .
                    .
                    CALL RITARDO
                    CALL RITARDO           
                    SLEEP                     

RITARDO       NOP
                    DECFSZ TIMER_1
                    GOTO RITARDO
                    .
                    .
                    RETURN

Quando viene eseguita la sleep il PIC si ferma, in uscita dalla sleep (pressione del tasto in GP3) il programma entra nella routine RITARDO che si conclude con un RETURN. La return, come sai, carica il registro PC con l'indirizzo presente nello stack (l'indirizzo della memoria flash dell'ultima istruzione call), ma in questo caso lo stack è vuoto: cosa farà il PIC?
Potrebbe resettarsi (molto probabile) o forse finire in un punto imprecisato del programma.
Personalmente avrei visto bene una GOTO MAIN dopo la sleep.
Questo era il mio dubbio.

Se posso permettermi farei alcune modifiche al codice, più per gusto personale che funzionale.
Anzitutto la dichiarazione delle variabili (TIMER_1, ...) fatta indicando indirizzi fissi di memoria (nel tuo caso hai utilizzato la ORG per ogni variabile, in altri casi si vede la EQU con le stesse finalità) non mi piace perché il codice è poco manutenibile.
Se hai bisogno di inserire una variabile tra TIMER_3 e CONTEGGIO o portare da 8 a 16 bit una variabile, sei costretto a ricalcolare tutti gli indirizzi. Peggio se hai necessità di spostare tutto il blocco di variabili (vedi ad esempio cambio di PIC).
Io preferisco utilizzare la RES:
Codice: Seleziona tutto
     ORG     070H

    TIMER_1        RES  1
    TIMER_2        RES  1
    TIMER_3        RES  1
    CONTEGGIO      RES  1
    CONTEGGIO_ACC  RES  1
    CONTEGGIO_LAMP RES  1

Basta spostare la ORG iniziale o modificare la dimensione delle RES senza dover ricalcolare gli indirizzi.

Vi sono nel codice GOTO tipo questo:
Codice: Seleziona tutto
LED_ACCESO      BSF GPIO,0
                         GOTO SEGNALE_FISSO

SEGNALE_FISSO   CALL RITARDO

che non servono a nulla se non a perdere tempo (2 cicli macchina), in questo caso preferisco la sintassi GOTO $+1 che a mio avviso diventa più leggibile in quanto evidenzia subito che si tratta di un goto "perdi tempo" e non di un goto vero.

Ripeto che le mie sono solo osservazioni a carattere puramente personale sulla leggibilità che mi piace avere nel codice che scrivo, non prenderle come critiche.

EDIT: Noto che Paolino mi ha anticipato, ma posto lo stesso il mio messaggio per le considerazioni diverse dallo sleep.