[maXimator] Projekt cyfrowego termometru z sensorem analogowym STLM20 i „graficznym” wskaźnikiem temperatury na LED-RGB WS2812

Przedstawiamy projekt cyfrowego miernika temperatury na zestawie maXimator, wyposażonego w dodatkowy wskaźnik temperatury, wykonany na LED-RGB. Zmierzona temperatura jest pokazywana na 3-pozycyjnym, 7-segmentowym wyświetlaczu LED oraz na pasku z LED WS2812B świecących na różne kolory, zależne od zakresu temperatury.

 Kompletny projekt dla programu Quartus Prime Lite wraz z plikami źródłowymi jest dostępny do pobrania na stronie maximator-fpga.org.

Termometr prezentowany w artykule jest przeznaczony do mierzenia temperatur w zakresie wartości od 0 do +51,1 stopni Celsjusza z dokładnością do 0,1 stopnia. Wynik pomiaru jest wyświetlany na wyświetlaczu LED oraz na pasku diod LED-RGB, na których są wyświetlane kombinacje kolorów i liczby świecących elementów, odpowiadające temperaturom z zakresu +12…+36,6oC. Na wskaźniku diodowym uzyskujemy rozdzielczość pomiaru 0,5oC. Wartość można odczytać na podstawie koloru i liczby zapalonych diod zgodnie z tabelą 1.

Tab. 1. Wartość temperatury wskazywanej za pomocą LED-RGB

Kolor\Liczba świecących diod 1 2 3 4 5 6 7 8
Niebieski 12,0 12,5 13,0 13,5 14,0 14,5 15,0 15,5
Jasnoniebieski 16,0 16,5 17,0 17,5 18,0 18,5 19,0 19,5
Zielony 20,0 20,5 21,0 21,5 22,0 22,5 23,0 23,5
Żółty 24,0 24,5 25,0 25,5 26,0 26,5 27,0 27,5
Czerwony 28,0 28,5 29,0 29,5 30,0 30,5 31,0 31,5
Różowy 32,0 32,5 33,0 33,5 34,0 34,5 35,0 35,5

Prezentowany w artykule projekt wymaga zastosowania shielda maXimator Expander (na którym umieszczono wyświetlacze LED oraz sensor temperatury STLM20 – fotografia 1) oraz linijki z 8 diodami LED-RGB WS2812B.

Fot. 1. Rozmieszczenie elementów peryferyjnych zestawu maXimator, używanych w projekcie
Fot. 1. Rozmieszczenie elementów peryferyjnych zestawu maXimator, używanych w projekcie

Ze względu na wygodę, w przykładzie użyto moduł KAmodWS2812-8, który dołączono do układu FPGA za pomocą pinów UART-a (fotografia 2):

WS8212B → maXimator

GND → GND,

+VDD → +5V,

Din → TxD

Wszystkie oznaczenia są umieszczone na płytkach, jak widać na fotografii. Układ zacznie działać od razu po włączeniu zasilania.

Fot. 2. Sposób dołączenia LED-RGB do zestawu maXimator
Fot. 2. Sposób dołączenia LED-RGB do zestawu maXimator

Opis projektu

Projekt składa się z czterech plików napisanych w języku VHDL. Plik główny rgb_termometr (najwyższy poziom w hierarchii) zawiera wszystkie niezbędne elementy do odczytania wartości napięcia z przetwornika analogowo-cyfrowego oraz przekazuje te wartości do bloków obsługujących wyświetlacz i diody RGB.

Blok opisany w pliku wysw (rysunek 3) odpowiada za obsługę wyświetlacza siedmiosegmentowego oraz algorytmy do uśredniania i obliczania temperatury w stopniach Celsjusza.

Rys. 3. Schemat blokowy projektu
Rys. 3. Schemat blokowy projektu

Opisy modułów funkcjonalnych

led_sterownik

Nazwa Kierunek Szerokość Opis
clock IN 1 zegar 10MHz
reset IN 1 brak funkcji
if_last IN 1 czy będą podawane na wejście kolejne kolory.
color_in IN 24 kolor do wyświetlenia w formacie GRB
load_next OUT 1 jeżeli 1 to można podawać następny kolor na wejście
diodes_LED OUT 1 sygnał sterujący diodami RGB-LED WS2812B

 

Blok opisany w pliku led_gen pobiera wartość temperatury z bloku wysw i na tej podstawie ustala ile i jakich kolorów powinno być wyświetlonych na diodach RGB.

Blok opisany w pliku led_sterownik zamienia kod koloru podawany przez led_gen na sygnał szeregowy, który jest wysyłany na linijkę diod.

Blok led_sterownik jest zrealizowany jako maszyna stanów, przechodząca przez 5 stanów: wysoka jedynka (h1), niska jedynka (l1), wysokie zero (h0), niskie zero (l0) oraz stan reset (resett). Automat zaczyna cykl pracy od zapamiętania wejścia color_in do sygnału color_24. Licznik color_counter_high liczy, który bit koloru jest w danym momencie czytany – dane wysyła od najważniejszych bitów. W zależności od wartości tego bitu wchodzi w stan h1 albo h0. Każdy stan ma licznik, który wskazuje przez jaki czas maszyna ma pozostać w tym stanie. Po upływie tego czasu przechodzi do następnego stanu, którym jest l1 po stanie h1 lub l0 po stanie h0. Znowu czeka w tym stanie na odliczenie licznika do zadanej wartości. O tym, do którego stanu przejdzie dalej decyduje kolejny przeczytany bit. Jeżeli licznik color_counter_high jest większy od zera to przechodzi do odpowiedniego dla kolejnego bitu stanu h1 albo h0. Kiedy wynosi 0 to w zależności od wartości sygnału wejścia if_last zaczyna czytać bity od początku (23 bit) lub – jeżeli if_last = 1 – to przechodzi do stanu resett, który trwa określony czas. Po tym czasie przechodzi do stanu h1 lub h0, jeżeli sygnał if_last będzie mieć wartość 1. W przeciwnym przypadku ponownie wchodzi w stan resett.

W module występuje sygnał wyjściowy load_next. Informuje on, że można w tym czasie zmienić kolor na wejściu. Zmiana koloru raz w czasie całego stanu wysokiego. Jest on zapamiętywany, kiedy sygnał load_next jest równy 0. Sygnał reset nie ma żadnej funkcjonalności. Sygnał zegarowy musi mieć wartość 10MHz (domyślna w maXimatorze), aby sygnał do diod miał odpowiedni „kształt” w funkcji czasu. Sygnał wyjściowy sterujący diodami LED przyjmuje wartość 1 dla stanów h1 i h0 oraz 0 dla pozostałych stanów.

led_gen

Nazwa Kierunek Szerokość Opis
clock IN 1 zegar 10MHz
reset IN 1 brak funkcji
temperature_b_2 IN 7 temperatura w stopniach Celsjusza podzielona przez 2
load_next IN 1 informacja otrzymywana z bloku led_sterownik z informacją, czy należy podać następny kolor na wyjście
selected_color OUT 24 kolor podawany do bloku led_sterownik w formacie GRB
if_last OUT 1 informacja wysyłana do bloku led_sterownik informująca czy dany kolor jest ostatnim wysyłanym

Blok led_gen odpowiada za wygenerowanie odpowiednich kolorów dla 8 diod RGB-LED WS2812B. Na wejściu przyjmuje 7-bitową wartość temperatury w stopniach Celsjusza, gdzie najmłodszy bit jest równy 0,5 stopnia. Zakres temperatur które może przyjąć led_gen wynosi od 0 do 63,5 stopnia.

Moduł wybiera nowy kolor, kiedy sygnał load_next – pochodzący z modułu led_sterownik – jest równy 1. Na podstawie 4 najwyższych bitów wartości temperatury wejściowej temperature_b_2 określa, w jakim kolorze będzie wyświetlana temperatura. Progi kolorów wyglądają następująco:

12 – 15,5       Ciemnoniebieski

16 – 19,5       Jasnoniebieski

20 – 23,5       Zielony

24 – 27,5       Żółty

28 – 31,5       Czerwony

32,0 – 35,5    Różowy

Kod koloru jest zapisywany do sygnału temp_color. Na podstawie wartości 3 najmłodszych bitów ustalane jest, ile z ośmiu diod modułu KAmodWS2812-8 powinno być włączonych. Dla wartości 0 jest to 1 dioda. Kiedy na 3 najmniej znaczących bitach w sygnale temperature_b_2 są same jedynki, to włączone są wszystkie diody.

Kody kolorów są wysyłane jeden po drugim. Licznik count_diodes odlicza, ile kolorów diod powinno być jeszcze wysłanych i ustala na wyjściu selected_color wartość temp_color jeżeli dioda ma się świecić lub same zera, jeżeli dioda nie powinna się świecić. Po ośmiu kolorach licznik count_diodes przyjmuje wartość 8 i ustawia bit if_last, który sygnalizuje, że więcej kolorów nie będzie wysyłanych.

wysw

Nazwa Kierunek Szerokość Opis
clock IN 1 zegar 10MHz
temperature_adc IN 12 temperatura z przetwornika ADC
brightness IN 4 jasność wyświetlacza siedmiosegmentowego
temperature_b_16 OUT 10 temperatura w stopniach Celsjusza podzielona przez 16
seg7_8 OUT 8 sygnał na katody wyświetlacza siedmiosegmentowego
seg7_4 OUT 4 sygnał na anody wyświetlacza siedmiosegmentowego

Moduł wysw jest odpowiedzialny za konwertowanie temperatury z przetwornika ADC do zadanych formatów oraz wyświetlaniu jej na wyświetlaczu siedmiosegmentowym.

W module występuje sygnał slow_clk, który jest inkrementowany przy każdym zboczu narastającym zegara. Służy on jako wejście ‚clock enable’ do wyzwalania procesów, które należy włączać z dużo mniejszą częstotliwością niż częstotliwość głównego sygnału zegarowego.

Proces odczytywania temperatury jest uruchamiany co 4096 taktów zegara. Za każdym razem aktualna wartość z przetwornika ADC z pinu podłączonego do analogowego termometru STLM20 jest dodawana do sygnału temperature_temp1. Dodawane jest 128 pomiarów. Kiedy dodane zostanie taka liczba pomiarów, temperaturą jest 12 najwyższych bitów sumy (sygnału temperature_temp1). Odjęta jest od danej wartości (0xBE7) i pomnożona przez odpowiedni współczynnik, zgodnie ze wzorem:

 temperature_temp2 = 3047 – temperature_temp1;

  temperature_b_10 = temperature_temp2* 8 +  temperature_temp2/4 +  temperature_temp2/32 +  temperature_temp2/64;

W ten sposób otrzymana jest temperatura w stopniach Celsjusza, gdzie bity  temperature_b_10(12 downto 4) oznaczają temperaturę pomnożoną przez 10 (np. 0x018 to 2,4 stopnia).

W tym samym miejscu jest wyliczana temperatura przestawiona jako binarna wartość w stopniach Celsjusza, gdzie najmniej znaczący bit to 0,5 stopnia (temperature_b_2). Przekazywana jest ona do modułu, gdzie jest wykorzystywana do wyświetlania temperatury na diodach RGB. W procesie tym przeliczana jest także temperatura z postaci binarnej do kodu BCD za pomocą funkcji to_bcd – najwyższe bity sygnału temperature_b_10(12 downto 4) przekształcane do sygnału BDC temperature_decimal_10. Po cztery kolejne bity odpowiadają za kolejne cyfry.

Wyświetlanie na wyświetlaczach 7-segmentowych jest realizowane poprzez przypisanie selektywne. W zależności od wartości slow_clk(12 downto 11) wybierane jest jedna anoda i odpowiednie 4 bity z sygnału temperature_decimal_10, które następnie są konwertowane na format 7-segmentowy, który jest wpisywany do seg7_8_temp.

Moduł daje możliwość wybrania jasności wyświetlacza siedmiosegmentowego poprzez wybranie na wejściu brightness odpowiedniej wartości od 0 do 15. Zrealizowane jest poprzez sprawdzanie czy 4 bity rejestru slow_clk(7 downto 4) są mniejsze, czy większe od wartości brightness. Jeżeli warunek jest spełniony, to wyświetlacz jest gaszony. W projekcie termometru jasność na stałe jest ustawiona na wartość maksymalną.

termometr_rgb

Nazwa Kierunek Szerokość Opis
clk IN 1 zegar 10MHz
seg7_8 OUT 8 sygnał na katody wyświetlacza siedmiosegmentowego
seg7_4 OUT 4 sygnał na anody wyświetlacza siedmiosegmentowego
diodes_LED OUT 1 sygnał sterujący diodami RGB-LED WS2812B

Najwyżej położony w hierarchii moduł opisowy w VHDL, łączy wszystkie wyżej wymienione modułu oraz zawiera przetwornik ADC, który pobiera wartość z pinu wejścia analogowego numer 0. Jest on podłączony do kanału 15. Przetwornik zawiera moduły adc, fingertemp_adc_sequencer oraz pętlę pll generującą zegary na podstawie zegara wejściowego 10MHz. Wartość z przetwornika jest zapisywana do sygnału counter, który jest wysyłany do bloku wysw. Blok ten zwraca sygnały które są kierowane na piny do obsługi wyświetlacza siedmiosegmentowego oraz przekazuje sygnał z informacją o temperaturze do bloku led_gen. Blok ten przekazuje i dobiera sygnały z bloku led_sterownik, który na podstawie otrzymanej wartości koloru tworzy sygnał diodes_LED, który jest wyprowadzony na pin do sterowania diodami RGB.

Projekt powstał w Katedrze Elektroniki Wydziału Informatyki, Elektroniki i Telekomunikacji AGH, pod kierunkiem dr inż. Pawła Rajdy i dr inż. Jerzego Kasperka.

O autorze