Program sterujący napisano w środowisku MPLAB X i skompilowano bezpłatnym kompilatorem MPLAB XC8. Do konfigurowania układów peryferyjnych użyto wtyczki MPLAB Code Configurator (MCC). Wszystkie te narzędzia są dostępne bezpłatnie i można je pobrać ze strony firmy Microchip. Mikrokontroler PIC16F1769 jest stosunkowo nowy, więc trzeba użyć najnowszych wersji oprogramowania wspierających ten układ.
Przetworniki C/A, źródło napięcia odniesienia i wzmacniacze operacyjne
Do regulacji napięcia i prądu wyjściowego jest potrzebne regulowane źródło napięcia odniesienia. W typowych rozwiązaniach stosuje się stabilne (stabilizowane) źródło napięcia dzielone przez precyzyjny potencjometr. W sterownikach mikroprocesorowych funkcję regulowanego źródła napięcia referencyjnego pełni przetwornik C/A. Mikrokontroler PIC16F1769 ma wbudowane dwa 10-bitowe i dwa 5-bitowe przetworniki C/A. W sterowniku użyłem obu przetworników 10-bitowych. Jeden jest źródłem regulowanego napięcia odniesienia i służy do zmiany napięcia wyjściowego, a drugi jest źródłem regulowanego napięcia odniesienia do zmiany natężenia prądu zabezpieczenia prądowego.
Przed użyciem moduł przetwornika C/A musi być skonfigurowany. Jak już wspomniałem, wszystkie moduły peryferyjne będą konfigurowane za pomocą wtyczki MCC środowiska IDE MPALB X. Konfiguracja przetwornika cyfrowo-analogowego w MCC jest bardzo łatwa. Trzeba włączyć moduł (opcja „Enable DAC”), wybrać dodatnie napięcie referencyjne oraz odblokować wyjście napięcia na wyprowadzenie DACOUT1, jak na rysunku 9. W konfiguracji nie zaznaczono „Enable DACOUT”. Wyjście przetwornika zostanie wewnętrznie połączone z wejściem wbudowanego wzmacniacza operacyjnego pracującego jako bufor. W tym celu należy skonfigurować moduł wzmacniacza operacyjnego, tak aby wejście nieodwracające było połączone z wyjściem przetwornika, jak na rysunku 10. Po zaznaczeniu opcji „Unity Gain Configuration” wzmacniacz zaczyna pracować jako standardowy bufor (rysunek 11). Nie ma wtedy znaczenia, co zostanie wybrane jako sygnał doprowadzony do wejścia odwracającego w konfiguracji wzmacniacza operacyjnego.
Dla napięcia referencyjnego FVR_Buffer2 równego 4,096 V rozdzielczość wynosi 4,096/1024=4 mV. Napięcie z modułu FVR jest ustawiane z niepewnością 1…2%, a niepewność samego konwertera wynosi ±1,5 LSB. Dla naszego zastosowania jest to zupełnie wystarczające. Zapisanie do przetwornika wartości 1000 powoduje ustawienia napięcia na wyjściu wzmacniacza równego 4 mV×1000=4 V. To upraszcza obliczenia, które musi wykonać mikrokontroler.
MCC generuje kilka funkcji związanych z obsługą przetwornika DAC1, z których użyjemy tylko dwóch: pokazanej na listingu 1 DAC1_Initialize(void) oraz DAC1_Load10bitInputData(uint16_t input10BitData) z listingu 2.
Na listingu 3 pokazano pętlę główną ustawiania napięcia wyjściowego zasilacza. Po odczytaniu statusu procedury obsługi enkodera i wykryciu stanu obrócenia ośki napięcie jest zwiększane lub zmniejszane o 0,5 V. Zmienna volt typu float zawiera wartość modyfikowaną o 17,85 przy każdym obrocie enkodera. Potem ta wartość jest zapisywana do przetwornika poprzez jawne rzutowanie typu unsigned int. Następnie program czeka 80 ms na ustabilizowanie się napięcia, mierzy oraz wyświetla napięcie wyjściowe i prąd obciążenia zasilacza. Jeżeli ośka enkodera nie jest obracana, to pomiary napięcia i prądu są wykonywane automatycznie co 0,5 sekundy (wyzwalane za pomocą funkcji Frame_ms(500)). Ta funkcja wykorzystuje procedury obsługi przerwań od licznika wywoływane co 1 ms. Po odliczeniu 500 ms jest ustawiana flaga frtime, wykonywany pomiar napięcia i prądu, następnie flaga frtime jest zerowana i cykl się powtarza. Przyciśnięcie ośki powoduje wejście do procedury ustawiania progu zabezpieczenia prądowego.
Pomiar napięcia i prądu jest wykonywany przez przetwornik A/C (rysunek 13). W przetworniku zastosowano konwerter SAR. Prędkość konwersji (maksymalnie 100 kSa/s) jest dostosowana do wydajności 8-bitowego rdzenia. Próbkowane napięcie jest doprowadzane przez multiplekser do kondensatora wejściowego o małej pojemności. Po uruchomieniu konwersji jest ustawiany bit bit GO w rejestrze ADCON lub następuje zdarzenie wyzwalające automatycznie konwersję. Kondensator jest odłączany od wejścia i jest wykonywana konwersja analogowo-cyfrowa. Jej wynik jest zapisywany w 16-bitowym rejestrze ADRES. Źródłem taktowania przetwornika może być wewnętrzny oscylator RC (Frc) o stałej częstotliwości ok. 500 kHz. Taki tryb taktowania pozwala na pracę przetwornika w trybie ograniczonego poboru mocy (sleep), kiedy wszystkie przebiegi taktujące są wyłączone. Do taktowania można też użyć podzielonego przebiegu zegarowego rdzenia. Częstotliwość taktująca przetwornik nie była wyższa niż maksymalna częstotliwość taktowania przetwornika (Tad>=1 ms).
Przy napięciu wyjściowym +28 V na wyjściu dzielnika powinno panować napięcie +4 V, a identycznie jak na wyjściu układu pomiaru prądu przy natężeniu prądu obciążenia wynoszącym 3 A. Przy okazji omawiania modułu źródła napięcia referencyjnego FVR wspomniałem, że bufor FVR_buf1 jest zaprogramowany na 4,096 V i jego napięcie będzie wykorzystywane jako napięcie referencyjne dla przetwornika analogowo- cyfrowego A/C.
Wyświetlenie pomiaru napięcia w woltach wymaga obliczeń. Napięciu +28 V odpowiada +4 V po podzieleniu przez dzielnik. Czyli inaczej mówiąc, napięciu +28 V odpowiada wynik konwersji równy 1000 dla napięcia referencyjnego 4,096 V. Zmiana napięcia na najmłodszym bicie odpowiada zmianie napięcia wyjściowego o 28 V/1000=0,028 V. Aby obliczyć wartość odczytaną z przetwornika na napięcie w woltach, trzeba ją pomnożyć przez 0,028. Procedura pomiaru napięcia rozpoczyna się od obliczenia średniej z kolejnych 10 pomiarów wykonywanych w odstępie co 2 ms. Potem średnia wartość odczytana z przetwornika jest mnożona przez 0,028, a właściwie mnożona przez 2,8 i dzielona przez 100 (listingu 6).
Do sformatowania wyniku pomiaru użyłem funkcji sprintf z biblioteki stdio.h. Znaki są zapisywane do bufora. Wskaźnik do tego bufora jest argumentem funkcji. Jeżeli napięcie jest mniejsze niż 10 V, to jest wyświetlane w postaci dwóch cyfr: jedności i cyfry po przecinku. Dla napięcia powyżej 10 V wyświetlane są trzy cyfry: dziesiątki, jedności i cyfra po przecinku. Funkcję wyświetlającą napięcie pokazano na listingu 7. Jej argumenty to napięcie w formacie zmiennoprzecinkowym oraz współrzędne początku wyświetlania na ekranie.
Analogicznie jest wykonywany pomiar natężenia prądu. Maksymalne napięcie, które występuje na wyjściu układu pomiarowego, powinno wynosić 4 V dla prądu o natężeniu 3 A. Większy prąd nie powinien płynąć, bo na taką wartość ustawiono domyślne, maksymalne zabezpieczenie prądowe. Funkcja pomiaru prądu rozpoczyna się od wykonania 10 pomiarów i obliczenia średniej. Potem następuje przeliczenie odczytanej wartości na ampery. Wartości 3 A odpowiadają 4 V, czyli liczba 1000 z przetwornika. Zmiana wartości na najmłodszym bicie odpowiada 3 A/1000= 0,003 A, więc aby obliczyć natężenie prądu, należy liczbę z przetwornika pomnożyć przez 0,003. W programie ta wartość jest mnożona przez 3 i dzielona przez 1000, jak na listingu 8.
Próg zabezpieczenia prądowego jest wykonywany przez funkcję SetI(void) – listing 9. Po naciśnięciu ośki impulsatora na ekranie w linii wyświetlającej nastawiony próg zabezpieczenia jest wyświetlany komunikat „<–Set”. Kręcąc ośką, zmieniamy nastawiony próg z krokiem 0,1 A. Nastawiana wartość po przeliczeniu jest wysyłana do przetwornika DAC2 i wyświetlana przez procedurę DispIogr(). Po odliczeniu 80 ms program mierzy i wyświetla napięcie na wyjściu oraz prąd pobierany z zasilacza. Pozwala to na bezpośrednią obserwację wpływu zmiany progu zabezpieczenia prądowego. Po naciśnięciu ośki funkcja kończy działanie i program przechodzi do pętli głównej, w której można ustawiać napięcie wyjściowe i jest wykonywany pomiar napięcia i prądu.
Zmiana każdej nastawy jest zapamiętywana w nieulotnej pamięci Flash mikrokontrolera. Po każdym włączeniu zawartość zapisanych wartości jest odczytywana z pamięci Flash i zasilacz jest ustawiony tak jak przed wyłączeniem. Uwalnia nas to od każdorazowego ustawiania na nowo napięcia wyjściowego i zabezpieczenia prądowego po włączeniu zasilania.
Do zapamiętywania danych użytkownika w pamięci nieulotnej w rodzinach PIC16F Microchip stosował odrębną pamięć EEPROM. W rodzinie PIC16F1xxx zrezygnowano zapewne z powodu kosztów produkcji z pamięci EEPROM, ale w zamian dodano możliwość zapisu danych użytkownika w pamięci programu Flash. Na końcu przestrzeni pamięci programu wydzielono przestrzeń mieszczącą 128 słów, spełniającą funkcję pamięci EEPROM. Tych 128 słów ma podwyższoną liczbę cykli kasowanie/zapis. Kasowanie i zapisywanie danych odbywa się w porcjach (wierszach) mających 32 słowa 14-bitowe. Nie można zapisać jednego słowa – zapisują się od razu 32 słowa całego wiersza. Dlatego w praktyce dane przeznaczone do zapisywania w tej nieulotnej pamięci są przechowywane w buforze RAM mieszczącym 32 słowa 16-bitowe. Również adresowanie podlega pewnym ograniczeniom. Adres początkowy wiersza musi być wielokrotnością liczby 32. Jeżeli tak nie jest, to układy kontrolne zablokują zapis danych. Podobnie jak w pamięci EEPROM, musi być wykonana sekwencja kontrolna polegająca na zapisaniu danych do rejestrów w określonej sekwencji.
Gotowe funkcje zapisu i odczytu są generowane przez wtyczkę MCC. Na listingu 10 pokazano funkcję odczytującą dane z pamięci Flash. Adres komórki jest argumentem procedury, a odczytana wartość jest zwracana w formie liczby 14-bitowej umieszczonej w rejestrze 16-bitowym. Funkcję zapisującą dane pokazano na listingu 11. Pierwszy argument to adres, który musi być początkiem wiersza, a drugi jest wskaźnikiem na bufor z 32 słowami zapisywanymi w jednym cyklu zapisu.
Tomasz Jabłoński, EP