Model termometru na bazie układów TLC549 oraz MCP9700 Aplikacja komputerka CA80 |
|
Pomiar temperatury to chyba jeden z najwdzięczniejszych tematów do elektronicznej dłubaniny. Nie wyrywa się, nie ucieka, przetworniki różnorakie i sensory w sumie tanie i łatwo dostępne, częstokroć jako próbki układowe. Cały wic w tym, aby zabawkę poskładać i ożywić jakimś mniej lub bardziej ambitnym programem. W wątku o Księżniczce Motoroli kolejne wyciągane z pudełka przetworniki A/C z wyjściem równoległym są maltretowane do znudzenia wręcz, tu nieco zmienimy klimat. Wystąpi dla odmiany szeregowy ośmiobitowy przetwornik A/C typu ⇨ TLC549, ale celem odetchnięcia na moment od Motki pomiarami sterować będzie mój ulubieniec CA80, ale w tej starej wersji. Schemat zabawki prosty jest niezmiernie, no ale porządek musi być, zatem: ![]() Przetwornik TLC549 zapięty do portu PC układu 8255 (PIO użytkownika), ponieważ jest potrzeba posiadania jednej linii wejściowej oraz dwóch wyjściowych, wybór padł na port C, który można funkcjonalnie podzielić sobie na pół. Wybór bitów dla sygnałów: na dane PC.7, ponieważ to ładnie wyrównany najstarszy bit i nie będzie kombinowania w programie, jako CLK i /CS - dwa najmłodsze. Ze względu na malusie wartości wejściowe (jako czujnik T mamy naparapetowy MCP9700) napięcie referencyjne pobieram z LT431 w kwocie 2.5V. Z dokumentacji przetwornika wynika, że niżej już nie bardzo, zatem stanęło na 2.5V co mi daje mniej więcej 10mV/bit, łatwo wtenczas wyniki przeliczyć na fizyczne wartości (MCP9700 też ma 10mV/°C). Dodatkowo dla testów pojawiło się na płytce stykowej źródełko 1.2V na bazie LM385, na nim były wstępne uruchomienia programiku. Sama budowa modelu, to jak łatwo zgadnąć plątanina kolejna malownicza, czyli - jak zwykle. Sygnały CS,DATA, CLK z portu PC użytkownikowego układu 8255. W starym CA80 nie okablowałam sobie złącza DB50, no to teraz takie oto sztukowania się dzieją. Na podobnej zasadzie podkradamy masę, +5V i sygnał /RESET z grzebyka ZS (Złącze Systemowe). Wprawne oko zauważy - odwrotnie wpięta sonda emulacyjna AVT270, no...szczerze napiszę - fala gorąca mnie zalała, a to co warknęłam to się tutaj nie nadaje do zacytowania. Ale szczęściem zasilacz mam chytry z podcięciem no i stare dobre polskie konstrukcje, i emulator i CA. Po poprawieniu złączki - maszyneria ruszyła radośnie, a Pani z Kosą schowała się w cieniu, ona cierpliwa jest. Na niewielkiej płytce stykowej kadłubek układu, przetwornik na brzeżku ponieważ jeszcze miejsce tam będzie mi potrzebne. CA80 zgłoszony jak zwykle, ale już pod kontrolą emulatora AVT270. Pierwsze uruchomienia programiku, zasadniczo wszystko super tylko kierunek rotowania bitów mi się pomylił i wynik od czapki, no zdarza się. Pomiar źródełka testowego 1.24V z LM385: $80 = 128, 128 * 10mV = 1.28V - jak na pierwszy raz i taki druciak, to wynik jest do przyjęcia. A to już wyniki z MCP9700 na parapecie, kruszeje sobie na mrozie. Zakres V640 przestawiłam z 1.5V na 500mV, widać ładnie jakieś 475mV, co daje -25mV poniżej progowego 0°C=500mV, czyli mamy około -2°C za oknem. No a CA80 pokazywał $2E..$2F czyli 46..47, po przeliczeniu na miliwolty a potem na °C w miarę się zgadza, jest całkiem fajnie. Rzut oka na grządkę z przetwornikiem i napięciami odniesienia i zabieramy się za program. Całością zabawki zarządza prościutki programik w assemblerze Z80, kompletny kod tu: ⇨ TLC549-1.asm (tak, to ponownie SB-Assembler, tylko z overlay Z80), a ja zwyczajowo wspomnę o ciekawszych fragmentach. Z programiku kluczowe w sumie jest rozmawianie z przetwornikiem przy pomocy procedurki getADC, zrobione na podstawie lektury dokumentacji i wygląda tak: getADC: push BC ; /CS = L ld A,%0000.0000 out (USER8255+PC),A ; reset vars ld B, 8 ; bits ld C, 0 ; keep A/D val. .continue: ; get bit from ADC in A, (USER8255+PC) and A,%1000.0000 or A,C ; A := A|C rlca ; >> wziuuuu ld C,A ; put in C back ; clock _/~\_ ld A,%0000.0010 out (USER8255+PC),A ; /cs = L, CLK = H ld A,%0000.0000 out (USER8255+PC),A ; /cs = L, CLK = L ; get next bit djnz .continue ; /CS = H ld A,%0000.0001 out (USER8255+PC),A ; /cs = H, CLK = L ld A,C ; result pop BC ret No i tu widać, dlaczego do obsługi lini danych padło na najstarszy (choć mogło też na najmłodszy) bit portu. Po przerotowaniu rozkazem rlca osiem razy biciki wróca na swoje miejsce, ponieważ TLC549 wystawia najstarszy bit na początek transmisji. Program główny to ustawienie stosu, a potem cykliczny odczyt przetwornika (wywołanie getADC) o pokazywanie wyniku, póki co szesnastkowo na wykasowanym ekraniku CA80, tu mam gotowe funkcje systemowe, no cała fura tego, dla ciekawości można poczytać: ⇨ MIK09A (1) ⇨ MIK09A (2) Programik uplasowany od adresu $4000, to drugi bank systemowy, tam zapięłam emulator, ale przy odrobinie wysiłku można by ten kod zrobić w pełni relokowalnym i zapuszczać z dowolnej lokalizacji, może kiedyś... Przebiegi generowane przez CA80 i odbierane dane pokazuje rysunek poniżej, interpretacja SPI w AD2 to megaprzydatna rzecz! ![]() No i bardziej dynamiczny pokaz działania: No i w ten oto sposób mamy model termometru zaokiennego na bazie procesora Z80. Temat może być rozwojowy - uładnienie programu, aby obsługiwał liczby ujemne i tak ogólnie pokazywał po ludzku, czyli dziesiętnie. Może dwie T - zarówno na dworze jak i ciepełko w pokoju, jest w czym dłubać. Aby nie było, że to tak niby łatwo i przyjemnie - stary CA80 dłuższy czas był wyłączony, po zasileniu ruszył jakoś. Tylko się okazało, że zasiedlająca bank $4000 kostka NVRAM...kuleje. Odczytywała się ciągle ta sama wartość, dla wszelkich adresów, zapis był ignorowany. No i panika, bo tam chciałam ręcznie wpisywać programiki sterujące, a była obawa, że to coś z komputerkiem, a może zimne luty ... Na kartce skrobane testy, aby tylko dekoder adresowy i sygnały na podstawce wymusić, schematy i próbnik w ruch - sytuacja jakby kryzysowa nieco. Chwila zawahania - a zaaplikować może EEPROM-y? Ale jednak nie i stanęło na emulatorze. O, a tak szybko ładuje się kod do CA80 przez emulałkę i konwerter USB/LPT. Podczas ładowania CA80 jest trzymany na resecie, aby się nie wyrywał, potem może normalnie wystartować, ale już z nową zawartością emulowanego banku pamięci. Ciąg dalszy prac nad zabawką, ale tym razem majstrowanie raczej w assemblerze. Aby choć odrobinę budowla ma użyteczną w domu była dla innych to jednak będzie wyświetlanie temperatury dziesiętnie. Stąd też powstała procedurka showTemperature, która to surową wartość z Aku przerabia na zawartość wyświetlacza, opatrzoną znakiem minus w przypadku wystąpienia mrozów. ;--------------------------------------------------------------- ; shows outdoor temperature showTemperature: push AF push BC push HL call SYS_CLR ; clear disp. .db $80 ; pwys - full displ ld HL,message call SYS_PRINT .db $80 ; pwys call getADC ; A - raw data from TLC549 ; do something with sample ld C, $00 ; empty place for MINUS sub 50 ; - 50(0)mV jp NC,.whenPositive neg ld C,$40 ; MINUS code for leter .whenPositive ; print '-' or ' ' push AF call SYS_COM .db $14 pop AF call bin2bcd call SYS_LBYTE ; print Accu .db $42 ; pwys pop HL pop BC pop AF ret ; message .db $5C,$1C,$00,$00,$00,$00,$63,$39,$FF ; |ou__-nn`C| ; Dla dodatnich temperatur wyniki miałam zza okna, no ale widać, że nie do końca jakby zimowe. Testowanie ujemnych temperatur bez czekania na zminę pogody wymagało drobnego poprawienia wyniku z ADC, ot, odjęłam sobie deczko i brrrrrr! Widać, że procedurka dobrze liczy, co jest w sumie miłe. Potem dołożone inne znaki na wyświetlaczu, stopnie C i 'ou' że niby od outdoor, bo korci mnie termometr dwupunktowy, z indoor. Z temperaturą problem jest taki drobny, że powoli się zmienia, co na filmikach wygląda niemedialnie czyli nudno. Aby więc uatrakcyjnić zabawkę powstał pomysł na efekty specjalne na wyświetlaczu oraz zamienne pokazywanie temperatury i bieżącego czasu. Procedurka scrollująca, pierwsze próby...no cóż, początki bywają z sękami. Potem szło mi coraz lepiej: Tu już dla prawdziwych odczytów z parapetu: I nowy efekt: Procedurek do udziwniania zawartości wyświetlacza jest aktualnie trzy (czwarta w trakcie uruchamiania): scrollLeft - przewija zawartość w lewo jednocześnie kasując display scrollDownAll - przewija zawartość w dół, wszystkie cyfry na raz scrollDownSequence - przewija zawartość w dół, ale kolejno z opóźnieniem, takie jakby spadanie Dwie powyższe procedurki posiłkują się małym przydasiem, który przewija w dół jedną załadowaną do Aku zawartość pola wyświetlacza - scrollDown, jest ona taka: scrollDown: ld D,0 >MOVE_SEGMENTS SEG_F,SEG_E >MOVE_SEGMENTS SEG_G,SEG_D >MOVE_SEGMENTS SEG_A,SEG_G >MOVE_SEGMENTS SEG_B,SEG_C ld A,D ret Tu bardzo przydały się operacje bitowe Z80, czyli rozkazy BIT/SET/RES można nimi przekładanki na bitach robić w miarę wygodnie. Równie łatwo pogubić się, który segment ma przechodzić w który, a co ma znikać, zatem numery segmentów ponazywałam symbolami, a operacje bitowe ubrałam w makra. W kodzie źródłowym w miarę widać teraz jak transformowana jest zawartość pola odczytowego. Cały program tu: ⇨ TLC549-termometr-2.asm. A tu wersja mocno rozwojowa, jako ciekawostka ⇨ TLC549-termometr-1.asm Muszę teraz zastanowić się, jak zapakować procedurki do efektów w tabelę i jakoś wywoływać po indeksie...Szkoda że Z80 ma tylko JP (HL) i JP (nn) a nie ma CALL (HL), byłoby wtenczas wygodnie, no ale nic, coś tam wymyślę sobie. Finalnie cała aplikacja pracuje tak jak na filmiku i autentycznie przyciąga uwagę tych, co odwiedzają moją jaskinię. I oto chodzi. A tak na marginesie, skompilowany do *.bin opisywany tu programik ma odrobinę ponad 350 bajtów, a działa całkiem sympatycznie. Czyli, że nawet posiadacze ekonomicznej wersji starego CA80, z 1kB RAM na układach 2114 mogli się komputerkiem cieszyć. Milusińscy moi z Texas Instrument jak zawsze poratowali w potrzebie, naprawdę TI to jest super firma, oto garstka LM385 ale w wersji regulowanej, ha! Tym oto prostym sposobem schemat zabawki mej termometrowej ewoluował w kierunku dwupunktowego pomiaru temperatury a także sprawdzenia, jakby mogło wyglądać źródełko napięcia odniesienia o wartości 2.56V na bazie LM385. Schemat poniżej ze znanym już multiplekserem analogowym MAC24: ![]() Odnośnie napięcia referencyjnego - niech będzie choć namiastka dokładności, zatem aby ładnie wszystko wydzieliło się przez 256 to Uref potrzeba nie 2.5 ale 2.56 no tak... Przy wartościach rezystorów obok LM385 jak na schemacie (R=100K, pot=10K) zakres napięć dla skrajnych położeń potencjometru jest: Urefmin = 1.24 * (1 + 100/110) = 2.36V Urefmax = 1.24 * (1 + 110/100) = 2.60V co pozwala się wpasować w potrzebną mi wartość z całkiem dobrą dokładnością. Do regulacji z maniakalnym uporem wykorzystuję V640, ja po resztą teraz już do wszystkiego tego cudnego mierniczka używam, jest genialny! Kilka zdjęć nowej instalacji, zaczynam przemyślenia nad utrwaleniem zabawki na płytce drukowanej w formie typowej przystawki do CA80...no zobaczymy jeszcze jak to będzie. Oczywiście pojawienie się multipleksera spowodowało drobne zmiany w programie, najważniejsza to obsługa ADC z wielokanałowością. Sztuka polega na tym, ze w wybranym cyklu odczytujemy z TLC549 wyniki poprzedniej konwersji, jednocześnie startując nową, której wyniki odczytamy sobie następnym razem... No więc problem taki, ze musimy ustawić kanał i z niego właśnie mierzyć. Zmieniłam zatem procedurkę getADC tak, aby po ustawieniu bitu sterującego multiplekserem wykonywała jeden pusty odczyt ale i pomiar zarazem. Jego wynik zbieram sobie w drugim obiegu i gra. Procedura taka: ;------------------------------------------------------------- ; reads 8-bit value from TLC549 a/d converter ; 8255.PC0 - /CS (o) ; 8255.PC1 - CLK (o) ; 8255.PC3 - MUX.A0 line ; ; 8255.PC7 - DATA (i) ; ; result in ACC getADC: push BC push DE ; << prep MUX control bit (bit no 3) rlca rlca rlca and A,$08 ld D,A ; keep channel in D for easy OR ; ; dummy read sequence to skip old result ; and force conversion with brand new channel set ld A,%0000.0000 ; /CS = L or A,D ; keep channel bit (D.3) out (USER8255+PC),A ld B, 8 .dummy: ld A,%0000.0010 ; clock _/~\_ or A,D ; keep channel bit (D.3) out (USER8255+PC),A ; /cs = L, CLK = H ld A,%0000.0000 or A,D ; keep channel bit (D.3) out (USER8255+PC),A ; /cs = L, CLK = L djnz .dummy ; do next tick ; release /CS ld A,%0000.0001 ; /CS = H or A,D ; keep channel bit (D.3) out (USER8255+PC),A ; /cs = H, CLK = L ; halt ; 2ms ; ; /CS = L ld A,%0000.0000 or A,D ; keep channel bit (D.3) out (USER8255+PC),A ; reset vars ld B, 8 ; bits ld C, 0 ; keep A/D val. .continue: ; get bit from ADC in A, (USER8255+PC) and A,%1000.0000 or A,C ; A := A|C rlca ; >> wziuuuu ld C,A ; put in C back ; clock _/~\_ ld A,%0000.0010 or A,D ; keep channel bit (D.3) out (USER8255+PC),A ; /cs = L, CLK = H ld A,%0000.0000 or A,D ; keep channel bit (D.3) out (USER8255+PC),A ; /cs = L, CLK = L ; get next bit djnz .continue ; /CS = H ld A,%0000.0001 or A,D ; keep channel bit (D.3) out (USER8255+PC),A ; /cs = H, CLK = L ld A,C ; result pop DE pop BC ret ; Zmianie uległy ekraniki, stylizowane napisy 'ind' oraz 'out' wymagają pewnej wyobraźni: Cały programik oczywiście tu: ⇨ TLC549-termometr-3.asm Test na sucho nowych ekraników: I cała zabawka w działaniu, pomiar temperatury na dworze i w pokoju z zegarkiem w międzyczasie: #slowanawiatr, luty-czerwiec 2018 |
![]() |
![]() |
![]() |