Model termometru na bazie układów TLC549 oraz MCP9700
Aplikacja komputerka CA80

charakterystyka i informacje ogólne
książki / dokumentacja (literatura)
ulotki i broszurki MIK (literatura)
skany artykułów z prasy (literatura)
programator EPROM (aplikacje)
dwupunktowy termometr (aplikacje)
licznik-timer Z80-CTC i dioda RGB (aplikacje)
Direct Memory Loader - ładowarka do pamięci (akcesoria)
próbnik stanów logicznych MIK03C (akcesoria)
zdalnie sterowana klawiatura (akcesoria)
przegląd procedur systemowych (programowanie)
interfejs RS-232 z układem Z80-SIO/0
hex2wav - ładowanie programów do CA80 z plików audio
sterownik mikroprocesorowy CA82

☘☘☘☘☘☘

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
 tasza  2004-2021 | archiwum kabema 2021