Temat oszczędzania energii jest bliski sercu każdemu Polakowi. Szczególnie jak co miesiąc patrzy na rachunek za prąd, wodę i gaz :). Każdy z nas prędzej czy później z tym tematem się spotka również i w mikrokontrolerach. Tam gdzie możemy oszczędzać energię to róbmy to :) PIC32MM daje nam takie możliwości , więc trzeba się im przyjrzeć. Znajdziemy w nim z grubsza cztery tryby zmniejszające pobór prądu oraz dodatkowo takie funkcjonalności jak wyłączanie poszczególnych modułów peryferyjnych. Generalnie temat nie jest trywialny dlatego, że stosowanie w praktyce trybów energooszczędnych wiąże się z braniem pod uwagę wielu aspektów nie tylko samego poboru prądu ale np. czasu czy wymaganych metod wybudzania . Szersze spojrzenie na temat przedstawia tutorial zamieszczony na łamach Elektroniki Praktycznej, który znajdziemy w linkach. Warto się z nim zapoznać.
Intuicyjnie możemy postawić tezę, że metodami zmniejszającymi pobór energii w mikrokontrolerze może być :
- wyłączanie nie używanych peryferiów, wyłączanie CPU
- zmniejszanie częstotliwości zegara lub wyłączenie go
- obniżanie napięcia zasilania.
Tryby obniżające pobór prądu w każdym MCU mogą być mieszanką wyżej wymienionych metod. Wracając do bohatera naszych rozważań czyli PIC32MM , spełnia on standardy XLP Technology (eXtreme Low-Power) jest to standard Microchipa zaimplementowany w wybranych MCU PIC. Więcej o tej technologi doczytamy tutaj. Podstawowym trybem pracy każdego mikrokontrolera jest tryb Run Mode, jest to normalny tryb pracy w którym wszystkie peryferia są dostępne, zegar pracuje, rdzeń wykonuje operacje lub jest w pełnej gotowości do ich wykonania i nie jest wstrzymywany. Czyli taki tryb pracy na co dzień. Natomiast na szczególne okazje mamy do dyspozycji tryby oszczędzania energii.
W PIC32MM mamy do dyspozycji następujące tryby oszczędzania energii :
- Idle
- Sleep Mode
- Standby Sleep Mode
- Retention Sleep Mode
W artykule zajmiemy się dwoma pierwszymi trybami czyli Idle i Sleep.
Tryb Idle inaczej tryb bezczynności to tryb w którym mamy do dyspozycji szybki czas pobudki do pełnej gotowości bojowej mikrokontrolera, zegar systemowy w tym trybie pracuje, CPU jest "zatrzymany" . Oszczędności energii mamy tu na poziomie ok. 25% w stosunku do trybu Run Mode tak wynika z dokumentacji XLP. W zasadzie dla nas istotne informacje są takie jak w ten tryb wprowadzić mikrokontroler i jakie mamy możliwości wybudzenia z tego trybu. Najpierw zerknijmy jak wprowdzić w tryb Idle. Służy do tego rejestr OSCCON: OSCILLATOR CONTROL REGISTER i bit SLPEN: Sleep Mode Enable bit
Idle
Tryb Idle inaczej tryb bezczynności to tryb w którym mamy do dyspozycji szybki czas pobudki do pełnej gotowości bojowej mikrokontrolera, zegar systemowy w tym trybie pracuje, CPU jest "zatrzymany" . Oszczędności energii mamy tu na poziomie ok. 25% w stosunku do trybu Run Mode tak wynika z dokumentacji XLP. W zasadzie dla nas istotne informacje są takie jak w ten tryb wprowadzić mikrokontroler i jakie mamy możliwości wybudzenia z tego trybu. Najpierw zerknijmy jak wprowdzić w tryb Idle. Służy do tego rejestr OSCCON: OSCILLATOR CONTROL REGISTER i bit SLPEN: Sleep Mode Enable bit
bit SLPEN musi być ustawiony na 0 no i w sumie po starcie mikrokontrolera tak domyślnie jest. Czyli nic nie musimy ustawiać w tym przypadku.
W opisie tego bitu czytamy, że aby wejść w tryb Idle musi być wykonana jakaś magiczna komenda Wait. A jak ją wywołać pokazuję poniżej do wyboru mamy dwie opcje :
asm volatile("wait"); // put device in selected power-saving mode
lub
_wait();
Przykład użycia w kodzie znajdziemy w dokumencie dotyczącym ogólnie rodziny PIC32 - Reference Manual Power Modes ale nie sprawdzałem czy ten kod z dokumentacji działa.
Ale my to przećwiczymy w praktyce. Na razie jednak wspomnijmy coś o możliwościach wybudzenia z trybu Idle. Jak podaje dokumentacja mamy do dyspozycji trzy główne metody pobudki są to :
- dowolne przerwania , które musi mieć priorytet wyższy niż core CPU,
- każde źródło sprzętowego resetu, o resecie doczytamy tutaj
- WDT czyli Watchdog Timer jest to rodzaj timera , który po ustawionym czasie wybudza nam mikrokontroler. Mamy tu do dyspozycji 25-bitowy licznik.
No dobrze coś tam mniej więcej wiemy o trybie Idle i metodach wybudzenia w tym trybie ,czas na zajęcia praktyczne. Spróbujemy fizycznie wprowadzić mikrokontroler w tryb uśpienia Idle . Mam nadzieję , że nie uśpię mikrokontrolera na amen :)
Do testów użyję swojej autorskiej płytki developerskiej dla PIC32MM0256GPM048 ver.2.0 , szkoda mi uśpić na amen płytki Microchipa Curiosity bo mam tylko jedną :). Do testów przygotowałem specjalnie płytkę tj. wlutowałem tylko niezbędne elementy do poprawnej pracy MCU. Przy pierwszym podejściu do testów na płytce miałem wlutowany regulator LDO ale okazało się , że pobiera on kilka mA prądu wstecznego i to mi całkowicie zafałszowało pierwsze pomiary. Płytka testowa wygląda jak poniżej :
Płytkę zasilam zasilaczem zewnętrznym +3.3 V, napięcie podaję bezpośrednio na listę kołkową z pinami zasilania. Pierwsze uruchomienie płytki bez żadnej ingerencji w ustawienia MCU czyli tak jak go fabryka wypuściła w świat wykazuje pobór prądu na poziomie 2.74 mA . Pomiary dokonuję miernikiem uniwersalnym automatycznym firmy V&A model VA21 minimalny zakres 4000 uA obawiam się , że na skrajnie niskich pułapach mierzonego prądu błąd pomiaru zacznie nam doskwierać. Nie jest to niestety idealny sprzęt do robienia pomiarów prądu w MCU ale innego na razie nie mam.
Uruchamiamy zatem MPLABX-IDE i tworzymy projekt o nazwie pic32mm_Idle
Po utworzeniu projektu odpalamy MCC, zegar ustawiamy tak jak poniżej, odłączamy zbędny w naszym przypadku Fail Save Monitor i Secondary Oscillator. Ustawienia jakie powinniśmy zrobić wyglądają jak poniżej :
Run Mode
Laboratorium : zegar FRC 8 MHz. PMDx = 0. Piny tak jak fabryka ustawiła czyli bez naszej ingerencji.
Ucc 3.296 V
Zmierzony prąd pobierany przez MCU wynosi : Imcu = 3.76 mA
Do dalszych rozważań przyjmuję :
Run Mode 8 MHz (FRC) = 3.76 mA
Tak dla porównania dla mniejszej wartości zegara :
Run Mode 1 MHz (FRC) =1.1 mA
Spójrzmy dla ciekawości jak w dokumentacji wyglądają teoretyczne parametry "energetyczne" dla trybu Run Mode :
Widzimy tutaj poziom max 3.7 mA dla 3.3 V i zegara 8 MHz , zwracam uwagę jednak na informację, że są to wartości dla celów projektowych i nie mierzone . Czyli można podejrzewać, że wartości te zostały stworzone przez jakiś symulator programowy. Nasz pomiar 3.76 mA , odbiega od danych producenta o 0.06 mA ale nie mamy spełnionych warunków podanych pod tabelką. W warunkach tych mamy m.in oscylator zewnętrzny w trybie EC a my używamy generatora RC w trybie Fast. Widzimy stąd, że dla oszczędzania energii w PIC32MM kwarc zewnętrzny jest prawdopodobnie lepszym wyborem aczkolwiek przy wewnętrznym RC mamy szybsze czasy stabilizacji niż przy zewnętrznym kwarcu ,więc ja bym wolał w bateryjnych zastosowaniach zostać przy RC a obniżyć częstotliwość. To co możemy spróbować spełnić z rzeczy podanych poniżej tabelki na powyższym rysunku to :
- wszystkie piny ustawić na wyjścia
- wyłączenie wszystkich nie używanych peryferium za pomocą rejestrów PMDx
Te dwa powyższe punkty możemy spełnić. Zatem zróbmy to. Zamknijmy wszystkie kłódki w wierszu Output z wyjątkiem RB0 i RB1 bo tam mamy programator. Tam gdzie piny są oznaczone jako Analog zostawiamy je tak. Klikamy Generate aby MCC wygenerował nam nowe pliki, kompilujemy i wgrywamy do MCU.
Robimy pomiar prądu i sprawdzamy wpływ ustawienia wszystkich pinów jako wyjścia :
Run Mode
Laboratorium : zegar FRC 8 MHz ,wszystkie piny ustawione na wyjścia :
Ucc 3.296 V
Zmierzony prąd pobierany przez MCU wynosi : Imcu = 2.9 mA
Brawo !!! tylko spełnieniem jednego wymagania weszliśmy w zakres wartości , które podaje Microchip (patrz tabelka wyżej).
Teraz spróbujemy wyłączyć peryferia. Z poziomu MCC nie udało mi się tego skutecznie zrobić dlatego robię to manualnie. W tym celu w pliku main.c tworzę sobie funkcję za pomocą, której wyłączę peryferia odpowiednimi wpisami do rejestrów , wszystkie rejestry PMDx (PMD1...PMD7) ustawiam na wszystkich bitach 1 . W funkcji pojawia się coś takiego jak SYSTEM_RegUnlock() i SYSTEM_RegLock() używamy tego jeśli chcemy grzebać w istotnych żywotnie rejestrach MCU , w datasheet jest spis takich rejestrów.
Aby robić wpisy w rejestry PMDx potrzebne jest zdjęcie dodatkowej blokady za pomocą rejestru PMDCON i bit PMDLOCK :
Definicje funkcji dałem w pliku mcc.c wygenerowanym przez MCC a deklarację w pliku mcc.h (nie zwracać uwagi, że nazwę projektu mam inną) :
kompiluję i wgrywam wsad.
Run Mode
Laboratorium : zegar FRC 8 MHz ,wszystkie piny ustawione na wyjścia , wszystkie rejestry PMDx = 1 :
Ucc 3.296 V
Zmierzony prąd pobierany przez MCU wynosi : Imcu = 3.4 mAWyłączenie peryferiów w trybie Run Mode lekko pogorszyło pobór ?. Zatem wycofuję się z tej zmiany a za optymalną w trybie Run Mode zmianę uznaję ustawienie pinów jako wyjścia.
Idle Mode
Czas zatem zająć się wprowadzeniem MCU w tryb Idle . W tryb Idle wprowadzamy za pomocą magicznej formuły :
asm volatile("wait"); // put device in selected power-saving mode lub w prostszy sposób _wait(); w sumie proste jak budowa cepa.
kompilujemy program i wgrywamy wsad. MCU wprowadzony w tryb Idle będzie w nim cały czas tkwił na razie nie zajmujemy się kwestią wybudzenia.
Robimy pomiary.
Idle Mode
Laboratorium : zegar FRC 8 MHz ,wszystkie piny ustawione na wyjścia
Ucc 3.296 V
Zmierzony prąd pobierany przez MCU wynosi : Imcu = 1.44 mA
Procentowo uzyskaliśmy w trybie Idle 50% mniejsze zużycie prądu niż w trybie Run Mode. Procentowo wygląda bardzo dobrze . Spójrzmy na wartości możliwe do uzyskania teoretycznie , które podaje producent :
Widzimy tutaj poziom max 1.7 mA dla 3.3 V i zegara 8 MHz
Nasz pomiar 1.44 mA , wygląda na tle danych bardzo dobrze. Brawo !!!
Zrobiłem drugi test dla trybu Idle z wyłączonymi peryferiami uzyskałem tutaj poprawę wyniku : 1.39 mA
SLEEP MODE
Przejdziemy teraz do trybu Sleep Mode. Na początek kilka podstawowych informacji. Tryb ten charakteryzuje się następującymi cechami :
- CPU jest zatrzymany,
- Zegar systemowy jest wyłączony, jeśli używamy WDT to zegar chodzi tylko na użytek tego modułu najczęściej jest to LPRC - 32kHz,
- Peryferia wyłączone ale niektóre peryferia mogą w tym trybie być aktywne jeśli ich potrzebujemy są to np. WDT, RTCC, ADC, UART
Metody pobudki są takie same jak w trybie Idle :
- dowolne przerwania , które musi mieć priorytet wyższy niż core CPU,
- każde źródło sprzętowego resetu, o resecie doczytamy tutaj
- WDT czyli Watchdog Timer jest to rodzaj timera , który po ustawionym czasie wybudza nam mikrokontroler.
W/g dokumentacji docelowe prądy zasilania w teorii dla tego trybu możliwe do uzyskania to ok 5 - 30 uA (rozpatrujemy wariant DC61)
ale trzeba spełnić podane poniżej warunki .
Aby wejść w tryb Sleep Mode należy w rejestrze OSCCON: OSCILLATOR CONTROL REGISTER ustawić bit SLPEN: Sleep Mode Enable bit ,fizycznie robimy to magiczną formułą jak poniżej :
SYSTEM_RegUnlock(); //unlock
OSCCONbits.SLPEN=1; //enable sleep mode
SYSTEM_RegLock(); //lock
OSCCONbits.SLPEN=1; //enable sleep mode
SYSTEM_RegLock(); //lock
Przed ingerencją w rejestr OSCCON musimy odblokować systemową możliwość zapisu do tego rejestru . Podawałem wyżej zdjęcie na którym było pokazane w przypadku , których rejestrów taką procedurę odblokowania i po zmianie zablokowania należy zastosować.
Modyfikujemy nasz program tak aby wprowadzić mikrokontroler w tryb SLEEP MODE :
kompilujemy , wgrywamy wsad i przechodzimy do pomiarów :
Sleep Mode
Laboratorium : zegar FRC 8 MHz ,wszystkie piny ustawione na wyjścia , wszystkie rejestry PMDx = 1
Ucc 3.296 V
Zmierzony prąd pobierany przez MCU wynosi : Imcu = 36 uA Ciut gorzej niż producent podaje ale bez spełnienia jego wytycznych a tu już się liczą szczegóły. Wynik i tak jak dla mnie rewelacyjny tym bardziej , że to nie ekstremalny tryb Power Saving jaki mamy do dyspozycji w PIC32MM
Krótko podsumujmy nasze dotychczasowe dokonania. Pomimo, że nie mamy spełnionych zaleceń co do uzyskania optymalnych warunków w trybach energooszczędnych. . To możemy sobie jakieś pojęcie w temacie przybliżyć. I tak :
W trybie Run Mode FRC 8MHz odczytaliśmy pobór prądu MCU na poziomie : 3.76 mA
W trybie Run Mode FRC 8MHz (+ piny ALL Output) odczytaliśmy pobór prądu MCU na poziomie : 2.9 mA
W trybie Run Mode FRC 8MHz (+ piny ALL Output) odczytaliśmy pobór prądu MCU na poziomie : 2.9 mA
W trybie Idle FRC 8MHz (+ piny ALL Output) odczytaliśmy pobór prądu MCU na poziomie : 1.44 mA czyli 50 % mniej niż w trybie Run Mode
W trybie Sleep Mode FRC 8MHz (+ piny ALL Output + OFF peryferia) odczytaliśmy pobór prądu MCU na poziomie : 36 uA
Do dyspozycji mamy jeszcze dwa tryby energetyczne Standby Sleep Mode i Retention Sleep Mode. Ale nie podejmę się walki z nimi bo mój miernik z najniższym zakresem 4000 uA będzie mi wnosił istotne błędy i wtedy zabawa nie ma sensu. Tryb Sleep Mode w którym uzyskałem pobór 36 uA jest w/g mnie optymalny pod względem poboru prądu i jeszcze w miarę szybkiego czasu wybudzenia. Gdyby jednak priorytetem był czas wybudzenia wtedy należy zmodyfikować w trybie Sleep Mode rejestr PWRCON i ustawić bity VREGS = 1 i RETEN = 0 wtedy pobór prądu będzie na poziomie 126 uA ale znacznie szybszy czas pobudki.
WDT - wake-up
Teraz zajmiemy się bardzo ciekawym aspektem czyli spróbujemy wyprowadzić nasz mikrokontroler z trybu uśpienia za pomocą mechanizmu jaki oferuje nam WDT (Watchdog Timer). Mechanizm ten kojarzy nam się z resetem mikrokontrolera i słusznie my jednak wykorzystamy go do wake-up z trybu uśpienia. Mechanizm ten polega na tym, że po odliczeniu przez WDT ustawionego czasu , mikrokontroler zostanie wybudzony i przejdzie do wykonywaniu kodu znajdującego się za komendą usypiającą "wait". Przećwiczymy to w praktyce. Zatem czas na zajęcia praktyczne :
Czas dla WDT skonfigurujemy sobie wygodnie w MCC , do obsługi WDT można skorzystać z prostych funkcji przygotowanych przez Microchipa w pliku watchdog.h (plik trzeba dołączyć do main.c) wygenerowanym automatycznie przez MCC i dołączonym do projektu . Poniżej zawartość tego pliku :
widzimy tutaj w sumie trzy wygodne funkcje do włączania, wyłączania i zerowania WDT. Zauważmy, że zapisy bezpośrednio do rejestru są tak samo proste jak te funkcje :) I to jest sympatyczna strona wszystkich PIC-ów. Ja jednak nie będę korzystał z tego dobrodziejstwa bo wolę mieć kontakt z rejestrami bezpośrednio wtedy mam wrażenie, że to ja steruję MCU a nie MCU mną :).
Przechodzimy do konfiguracji WDT, chcemy ustawić czas po którym nasz królewicz się obudzi i zacznie kontynuować program. Przyjmijmy , że będzie to 4 sekundy, czyli po 4 sekundach jeśli WDT będzie włączony nastąpi wybudzenie mikrokontrolera i kontynuowanie kodu znajdującego się za instrukcją "wait"
Uruchamiamy zatem MCC dla naszego projektu. W okienku System Module w MCC czyli tam gdzie ustawiamy zegar , skrolujemy okienko niżej aż zobaczymy belkę z napisem Watchdog.
Jedyne co w tym miejscu zmienimy to wartość Timer Postscaler na 1:4096 , Time out Period ustawi się wtedy na 4,096 s. Nic więcej nie tykamy z ustawień dla WDT !!!!!. Jeśli chcemy zobaczyć jakie rejestry przynależą do WDT to kliknąć zakładkę Registers wszystkie nazwy rejestrów mamy wtedy jak na tacy. Klikamy Generate i zamykamy MCC. Teraz bardzo ważna rzecz !!!! posłuchajcie i zróbcie to co teraz napiszę . Otwieramy plik mcc.c w naszym projekcie i przechodzimy do sekcji zaznaczonej na rysunku poniżej :
Sprawdzamy czy w zapisie #pragma config SWDTPS = PS4096 jest wartość 4096 czyli ustawiony przez nas w MCC preskaler jeśli nie to musimy tutaj to ręcznie zrobić. SWDTPS dotyczy trybu Sleep Mode a RWDTPS trybu Run Mode
Przechodzimy do pliku main.c modyfikujemy go i wstawiamy bardzo fajną funkcję obsługującą WDT , jej postać poniżej :
Funkcja sleep() realizuje nam całą magię wprowadzania mikrokontroler w tryb uśpienia , konfiguracji Idle / Sleep i obsługi WDT. Jest to bardzo wygodna funkcja. Jako argument funkcji podajemy ilość uśpień i wybudzeń z trybu Idle lub Sleep. Czas dla WDT mamy ustawiony na ok 4 s, jak wywołamy funkcję z argumentem np. 3 - sleep(3) to kod za wywołaniem funkcji sleep() zacznie się wykonywać po ok. 3 x 4s = 12 s.
W efekcie działania programu wywołana zostanie funkcja sleep(1), która uśpi nam mikrokontroler w trybie Sleep i wybudzi go po ok 4s.
W praktycznych realizacjach lepiej usypiać raz np 12s a nie trzy razy po 4s to tak na marginesie.
Po wybudzeniu będzie wykonywany kod znajdujący się za funkcją sleep().
Po wybudzeniu będzie wykonywany kod znajdujący się za funkcją sleep().
Ponieważ z forum Microchipa dowiedziałem się , że po wejściu w tryby uśpienia wyłączane są globalne przerwania. Dlatego po wywołaniu komendy "wait" w funkcji sleep() musimy te przerwania włączyć i robimy to na przykład poniższym zapisem :
Ponieważ przy pierwszym podejściu do pomiarów zrobiłem kardynalny błąd związany z obecnością regulatora LDO na płytce A tu jest historia mojego pytania na forum Microchipa : Forum Microchipa . Wtedy jeszcze nie wiedziałem , że przyczyną zawyżonych pierwszych pomiarów był obecny na płytce regulator LDO. Myślałem , że nie będzie on miał wpływu na pomiary bo napięcie podawałem na jego wyjście a nie wejście.
Tak przy okazji informuję o ciekawych funkcjonalnościach w PIC32MM, na które natrafiłem podczas wertowania dokumentacji. Mianowicie PIC32MM ma możliwość umieszczania kodu programu w pamięci RAM. Drugą odkrytą funkcjonalnością jest unikalny zaszyty przez producenta kod UNIQUE DEVICE IDENTIFIER (UDID) na 160 bitach (łoł) , którym możemy identyfikować konkretny MCU a to może się przydać np w sieciach.
Wnioski :
Z analizy podstawowych trybów Power Saving wynika, że PIC32MM doskonale nadaje się do wszelkich zastosowań bateryjnych i będzie pracował na baterii przez długie lata. Podane przez producenta dla PIC32MM0256GPM048 w najniższym trybie uśpienia 400 nA wydaje się być możliwe do osiągnięcia ale jeśli dodamy do tego zdrowo rozsądkowo pobór prądu np. przez WDT to wejdziemy na ok 600 nA. Co wydaje mi się realną wartością do zastosowania w praktyce. Podczas dalszych zabaw z ustawieniami trybu Sleep Mode udało mi się zejść do poziomu 4 uA ale myślę , że to już przesada macać takie poziomy na zakresie miernika 4000 uA :)
Z analizy podstawowych trybów Power Saving wynika, że PIC32MM doskonale nadaje się do wszelkich zastosowań bateryjnych i będzie pracował na baterii przez długie lata. Podane przez producenta dla PIC32MM0256GPM048 w najniższym trybie uśpienia 400 nA wydaje się być możliwe do osiągnięcia ale jeśli dodamy do tego zdrowo rozsądkowo pobór prądu np. przez WDT to wejdziemy na ok 600 nA. Co wydaje mi się realną wartością do zastosowania w praktyce. Podczas dalszych zabaw z ustawieniami trybu Sleep Mode udało mi się zejść do poziomu 4 uA ale myślę , że to już przesada macać takie poziomy na zakresie miernika 4000 uA :)
Sytuacja się zmienia dynamicznie . Z forum Microchipa otrzymałem wiadomość w wątku TUTAJ Howard Long był uprzejmy podać swoją konfigurację i ustawienia w którym uzyskał rekordowe wręcz wartości prądów dla PIC32MM w wersji GPL. Jeśli wzrok mnie nie myli to Standby & retention 327 nA !!!!! toż to jakiś rekord świata ustanowił. Martwiłem się zegarem FRC ale on też takiego użył.
Poniżej podaję tabelkę , która może być pomocna w ustawieniu trybów Power Saving i której brakuje w datasheet dla PIC32MM0256GPM :
Bardzo dziękuję Howardowi Long z forum Microchipa, za cenne podpowiedzi i za rekord 324 nA !!!!!! jaki ustanowił w głębokich trybach dla PIC32MM. Szkoda , że u nas w kraju nie ma takiego normalnego forum gdzie ludzie do siebie odnoszą się z szacunkiem i życzliwością a nie przekrzykują kto jest od kogo mądrzejszy a ego moderatorów przerasta ich samych .
UWAGA warto zapoznać się z tym wątkiem1 i wątkiem2 na forum Microchipa. Z grubsza chodzi o to, że bawiąc się trybami głębokiego uśpienia w PIC32MM warto mieć uruchomione mechanizmy wybudzania bo inaczej uśpimy procka na amen i programator nam nie pomoże. Najbezpieczniej przy pierwszych zabawach z głębokimi trybami uśpienia dać delay-a przed uśpieniem tak ok 7 s. Problem nie dotyczy trybów lekkich , które omawialiśmy w tym artykule bo w nich programator wybudzi MCU bez problemu.
Na koniec artykułu pokażę ustawienia, którymi Howard Long z Forum Microchipa uzyskał wyniki poniżej 1 uA w PIC32MM0256GPM064.
VREGS / RETEN / RETVR / MODE - Current
1 / 0 / OFF (1) / Normal 139uA
0 / 0 / OFF (1) / Standby 5.02uA
1 / 1 / ON (0) / Retention only 2.70uA
0 / 1 / ON (0) / Standby & retention 384nA !!!
Mnie się udało zobaczyć na tych ustawieniach na moim mierniku ze skalą 4000 uA odczyt 1uA , błąd pomiaru wynikający z za dużej skali miernika uniemożliwia mi zobaczenie wartości , które prezentuje Howard
Aby uzyskać najniższe wartości poboru prądu należy zmodyfikować ustawienia w pliku mcc.c (wygenerowanym przez MCC). To co mamy w tym pliku z rozszerzeniem #pragma config .... trzeba zakomentować a wkleić poniższe ustawienia :
// FDEVOPT
#pragma config SOSCHP = OFF // Secondary Oscillator High Power Enable bit (SOSC oprerates in normal power mode.)
#pragma config ALTI2C = OFF // Alternate I2C1 Pins Location Enable bit (Primary I2C1 pins are used)
#pragma config FUSBIDIO = OFF // USBID pin control (USBID pin is controlled by the USB module)
#pragma config FVBUSIO = OFF // VBUS Pin Control (VBUS pin is controlled by the USB module)
#pragma config USERID = 0xFFFF // User ID bits (Enter Hexadecimal value)
// FICD
#pragma config JTAGEN = OFF // JTAG Enable bit (JTAG is disabled)
#pragma config ICS = PGx2 // ICE/ICD Communication Channel Selection bits (Communicate on PGEC2/PGED2)
// FPOR
#pragma config BOREN = BOR0 // Brown-out Reset Enable bits (Brown-out Reset disabled in hardware; SBOREN bit disabled)
#pragma config RETVR = ON // Retention Voltage Regulator Enable bit (Retention regulator is enabled and controlled by RETEN bit during sleep)
#pragma config LPBOREN = OFF // Downside Voltage Protection Enable bit (Low power BOR is disabled)
// FWDT
#pragma config SWDTPS = PS4096 // Sleep Mode Watchdog Timer Postscale Selection bits (1:1048576)
#pragma config FWDTWINSZ = PS25_0 // Watchdog Timer Window Size bits (Watchdog timer window size is 25%)
#pragma config WINDIS = OFF // Windowed Watchdog Timer Disable bit (Watchdog timer is in non-window mode)
#pragma config RWDTPS = PS4096 // Run Mode Watchdog Timer Postscale Selection bits (1:1048576)
#pragma config RCLKSEL = LPRC // Run Mode Watchdog Timer Clock Source Selection bits (Clock source is LPRC (same as for sleep mode))
#pragma config FWDTEN = OFF // Watchdog Timer Enable bit (WDT is disabled)
// FOSCSEL
#pragma config FNOSC = FRCDIV // Oscillator Selection bits (Fast RC oscillator (FRC) with divide-by-N)
#pragma config PLLSRC = FRC // System PLL Input Clock Selection bit (FRC oscillator is selected as PLL reference input on device reset)
#pragma config SOSCEN = OFF // Secondary Oscillator Enable bit (Secondary oscillator is disabled)
#pragma config IESO = OFF // Two Speed Startup Enable bit (Two speed startup is disabled)
#pragma config POSCMOD = OFF // Primary Oscillator Selection bit (Primary oscillator is disabled)
#pragma config OSCIOFNC = ON // System Clock on CLKO Pin Enable bit (System clock is connected to CLKO/OSC2 pin)
#pragma config SOSCSEL = OFF // Secondary Oscillator External Clock Enable bit (SOSC pins configured for Crystal mode)
#pragma config FCKSM = CSECMD // Clock Switching and Fail-Safe Clock Monitor Enable bits (Clock switching is enabled; Fail-safe clock monitor is disabled)
// FSEC
#pragma config CP = OFF // Code Protection Enable bit (Code protection is disabled)
Modyfikujemy plik main.c :
Koniecznie trzeba dać delay przed uśpieniem bo inaczej nie zaprogramujemy już więcej naszego MCU.
Howard wybudzał swojego procka za pomocą przerwania zewnętrznego.
Pozdrawiam
picmajster.blog@gmail.com
Linki:
PIC32MM0256GPM048 - strona producenta
PIC32 Family - eXtreme Low Power
PIC32 Family - Power Saving Modes
PIC32 Family - Watchdog Timer and Power Saving Modes
PIC32 Family - dual Watchdog Timer
PIC32 Family - Resets
PIC - Low Power Tips and Tricks
EP cz. 1
EP cz. 2
EP cz. 3
EP cz. 4
EP cz. 5
EP cz. 7
EP cz. 8
EP cz. 9
OdpowiedzUsuńMusze przyznać że trochę rozczarowały Mnie Piki serii MM gdzie Microchip reklamuje je jako super energooszczędne. Myślałem że już w podstawowych trybach XLP będzie szał a tu szału nie ma :(, i raczej zgodzę się z Twoimi pomiarami PicMajstrze (Spróbuję jeszcze Sam w ramach eksperymentu dokonać pomiaru na czystym procku ).
A gdzie tu osiągnąć wartości w uA by mikrocontroler był w miarę użyteczny ,Ciekawe .. ale jak to mówią sprawa rozwojowa i Tutoriale też mam nadzieję Pozdrawiam
OdpowiedzUsuńPlease see my response to your post on the Microchip forum, which includes my source code.
FWIW I get the following sleep figures all at 3.3V, all peripherals off on a PIC32MM0064GPL028. INT0 falling edge will wake up.
Be very careful with retention sleep modes, or you risk bricking your chip!!!!
Run:
8MHz 3.43mA
Sleep (see DS60001324C Table 22-2):
Normal 136uA
Standby only 4.98uA
Retention only 2.52uA
Standby & retention 327nA
Hi Howard Long
OdpowiedzUsuńThank you very much for answering and your program, I will check at home how it works .
The Microchip forum is the best :)
No i o to chodziło, Kawał dobrej roboty PicMajstrze . Ja już mam plany co do "procka 32mm" Szukałem mikrokontrolera do budowy czujnika warunków pogodowych zasilanego bateryjne, Piki lubię bardzo tylko właśnie ten tryb niskiego poboru mocy tego Mi brakowało, jeszcze do tego jakiś moduł RF okiełznać bibliotekę dla BME280 i duet idealny
OdpowiedzUsuńWalik
Odnośnie modułów , przyszły do mnie z bardzo dalekiego wschodu milutkie moduły radiowe oparte na SI4463 z dedykowanymi antenami wprost do wlutowania wygodnie w płytkę. Coś cudnego i pięknego.I muszę znaleźć czas aby się nimi zająć, bo leżą i się uśmiechają do mnie :) a właśnie z myślą o takim zastosowaniu mniej więcej jak piszesz je kupiłem :)
OdpowiedzUsuńA tak dla ciekawości informacja to najbardziej energooszczędny MCU 32-bitowy jaki obecnie posiada w swojej ofercie Microchip to ATSAML11 i chyba jest to najbardziej "energetyczny" MCU na rynku na tę chwilę. W trybie RUN MODE mamy tu poziomy 0.45 mA przy 8 MHz. Ale żeby tryby uśpienia w nim pomierzyć to jeszcze takiego miernika nie wyprodukowali :)
OdpowiedzUsuń