elomax

[ Techniek ] [ Shop ] [ Site map
Inleiding ] Processor ] Ontwikkelomgeving ] Interrupts ] Digitale I/O ] Seriele communicatie ] Timers ] A/D Conversie ] Puls teller ] SPI ] Watchdog ] Clock monitor ] EEPROM ] Configuratie ] Ontwerp technieken ] [ Toepassings voorbeeld ]

Terug
Omhoog

Een toepassing realiseren

In dit deel wordt beschreven hoe een toepassing voor de SIMPLEX tot stand komt. De beschrijving is stap- voor stap, en resulteert uiteindelijk in een luxe en intelligente thermostaat voor een tropisch aquarium. Het gaat bij dit voorbeeld vooral om de wijze waarop het ontwerp tot stand komt.

De manier waarop tot het eindresultaat gekomen wordt is voor elke toepassing te gebruiken.

Stap 1: Probleemstelling

Als eerste moet zo nauwkeurig mogelijk omschreven worden wàt we nu eigenlijk willen maken. Eerst een probleemschets:

Tropische vissen voelen zich het prettigst bij ongeveer 24 graden Celcius. In ons land betekent dit meestal dat het water verwarmd dient te worden. 's Zomers echter kan het voorkomen dat gedurende langere tijd (een paar dagen) de buitentemperatuur meer dan 24 graden wordt. Het aquariumwater zal dan vanzelf ook warmer dan 24 graden worden. De vissen kunnen hier gelukkig goed tegen. Waar vissen over het algemeen niet tegen kunnen, is plotselinge veranderingen van de temperatuur. Wanneer b.v. na een hittegolf plotseling een veel koelere periode aanbreekt, kan de temperatuur van het aquariumwater te snel zakken. We willen nu een intelligente thermostaat bouwen, die:

  • Het water zo goed mogelijk op 24 graden Celcius houdt.

  • Als het water 25 graden of warmer wordt, een LED aan zet.

  • Ervoor zorgt dat het water in 4 uur niet meer dan 1 graad afkoelt.

Stap 2: De hardware

In de tweede stap wordt bepaald welke hardware er nodig is om de gevraagde toepassing te kunnen realiseren, en op welke wijze de SIMPLEX deze hardware moet gaan besturen.

In deze toepassing moeten de volgende zaken gemeten en bestuurd worden:

  • De watertemperatuur moet gemeten worden.

  • Er moet een LED bestuurd worden.

  • Er moet een elektrische verwarming aan- en uitgezet kunnen worden.

De temperatuurmeting.

Voor het meten van de watertemperatuur is een temperatuursensor nodig. Een voor de hand liggende keus is een NTC (een weerstand waarvan de waarde verandert met de temperatuur.) Een NTC kan in een spanningsdeler configuratie worden opgenomen en dan direct tussen aarde en één van de analoge ingangen van poort E van de SIMPLEX aangesloten worden. Als nu bekend is welke waarde de NTC zal hebben bij verschillende temperaturen, kan berekend worden welke NTC-temperatuur bij de spanning op de analoge ingang van de micro-controller hoort. Daarmee wordt het mogelijk om de temperatuur te meten. Dit is slechts één voorbeeld, om temperaturen te meten zijn veel oplossingen mogelijk.

Een andere mogelijkheid is om een speciale temperatuursensor te gebruiken, één die door de fabrikant al is afgeregeld en waarmee heel nauwkeurig gemeten kan worden. Deze SMARTEC temperatuursensor is verkrijgbaar in een uitvoering waarbij de sensor is ondergebracht in een metalen huisje zoals ook voor transistoren wordt gebruikt, dus eenvoudig in te bouwen. De sensor moet gevoed worden met 5 Volt, en geeft als uitgangs signaal een blokgolf op TTL niveau. De duty-cycle van dit signaal (de verhouding tussen de periodetijd en de tijd dat het signaal een '1' is), is een maat voor de temperatuur. Vanwege de nauwkeurigheid, en omdat de sensor een signaal op TTL niveau afgeeft, kiezen we voor deze SMARTEC sensor.

De temperatuursensor geeft een signaal af, waarvan de duty-cycle gemeten moet worden. Dit betekent dus, dat er in feite twee tijden gemeten moeten worden: een periodetijd, en de tijd gedurende welke het signaal een '1' is in één periode. Voor het meten van tijden zijn de timer-ingangen van de micro-controller het meest geschikt. De sensor kan dus het beste worden aangesloten op een timer-ingang, bijvoorbeeld op bit2 van poort A. De 5 Volt voeding voor de sensor is beschikbaar op de connector.

De LED.

De LED die nodig is, is al aanwezig op de SIMPLEX zelf. Voor de andere LED kan nog een toepassing bedacht worden. De tweede LED kan bijvoorbeeld gebruikt worden om aan te geven dat de verwarming aan staat.

De sturing van de verwarming.

De verwarming wordt gevoed vanuit het lichtnet. Voorzichtigheid is hier dus op zijn plaats! Het beste kan de verwarming bestuurd worden middels een goed relais. De contacten van dit relais moeten uiteraard berekend zijn op het vermogen dat de verwarming heeft. Voorts moet het relais geschikt zijn om 230 Volt te schakelen.

De spoel van het relais kan worden bestuurd vanuit één van de uitgangen van poort A. Met een eenvoudige transistor schakeling kan het relais worden aangestuurd. Denk aan een goede isolatie van de 230 Volt indien U deze schakeling daadwerkelijk bouwt!

Stap 3: De software

Nu bekend is welke hardware gebruikt zal gaan worden, en op welke wijze deze op de micro-controller aangesloten is, kan aan het programma begonnen worden. Evenals voor de hardware, moet ook voor de software een ontwerp gemaakt worden. Hiervoor zijn vele technieken bedacht, maar een eenvoudige en goed te begrijpen manier is om dit door middel van een stroom-diagram te doen (flow-chart.) Hierin wordt een actie die door de micro-controller moet worden ondernomen, weergegeven in een rechthoek. Een beslissing die door de micro-controller moet worden genomen is weergegeven in een ruit.

Het stroom-diagram van het hoofdprogramma is eenvoudig, en voor bijna alle toepassingen hetzelfde. Na Reset moet de micro-controller zijn stackpointer laden, eventueel het RAM initialiseren, en daarna de I/O goed zetten. Hierna kan het hoofdprogramma gestart worden. Het hoofdprogramma wordt doorlopen totdat de SIMPLEX weer wordt uitgeschakeld.

 

Het blok 'doe hoofdprogramma' bevat het eigenlijke programma, dus dat moet verder uitgewerkt worden.

In deze toepassing wordt de temperatuur van het water in een aquarium geregeld. Overal waar iets geregeld moet worden zijn steeds twee waarden van belang:

  • De werkelijke waarde

  • De gewenste waarde

Zolang deze waarden niet aan elkaar gelijk zijn, moet er kennelijk nog iets gebeuren. Het doel van de regeling is immers ervoor te zorgen dat de werkelijke temperatuur uiteindelijk gelijk wordt aan de gewenste temperatuur.

Naast deze temperatuur regeling moet het programma nog een LED besturen. Zo kan het stroom-diagram van het hoofdprogramma worden opgesteld:

Eerst moet de werkelijke temperatuur van het water gemeten worden. Als deze temperatuur meer dan 25 graden Celcius is, dan wordt de LED aan gezet. Als deze temperatuur 25 graden of minder is, dan mag de LED uit. De besturing voor de LED is hiermee klaar.

Daarna wordt gekeken of de verwarming aan- of uitgezet moet worden. Als de temperatuur hoger is dan de gewenste temperatuur, dan moet de verwarming uitgezet worden. Als de temperatuur van het water lager is dan de gewenste temperatuur, dan moet de verwarming aangezet worden. Als de temperatuur precies gelijk is aan de gewenste temperatuur, dan mag de verwarming blijven staat zoals hij stond. De temperatuur is dan goed, en er hoeft niets te gebeuren.

Het programma is nu zóver, dat het aquariumwater zo goed mogelijk gebracht zal worden op de in het programma ingestelde gewenste temperatuur. Als deze gewenste temperatuur altijd gelijk zou zijn, bijvoorbeeld 24 graden Celcius, dan zou het programma nu klaar zijn. Er is echter een eis gesteld aan de snelheid waarmee de temperatuur mag veranderen. Als het water door zomers weer bijvoorbeeld 28 graden wordt, dan moet de thermostaat ervoor zorgen dat het water in de volgende 4 uur niet verder afkoelt dan 1 graad, dus tot 27 graden. Als na deze 4 uur de temperatuur 27 graden is geworden, dan moet het water in de volgende 4 uur verder afkoelen tot 26 graden, en zo verder totdat uiteindelijk na 16 uur het water weer op 24 graden is gekomen. Hieruit blijkt dat de in het programma in te stellen gewenste temperatuur variabel is. Deze gewenste temperatuur moet dus elke keer opnieuw ingesteld worden. Dit gebeurt in het blokje 'pas gewenste temperatuur aan'. Datgene wat er in dit blok gebeurt is ook weer verder uitgewerkt in een stroom-diagram.

De gewenste temperatuur moet worden verhoogd als het water in het aquarium te warm is geworden. Als aangenomen wordt dat de thermostaat het water precies op de gewenste temperatuur kan houden, dan is een te hoge temperatuur blijkbaar door andere omstandigheden veroorzaakt. De thermostaat moet er dan voor gaan zorgen dat deze hoge temperatuur weer langzaam afgebouwd wordt. Een te hoge temperatuur kan worden geconstateerd als het water meer dan 1 graad warmer is dan de temperatuur waarop de thermostaat het water probeert te brengen. Dus als de gemeten temperatuur groter is dan de gewenste temperatuur + 1 graad, dan moet de thermostaat deze graad teveel in 4 uur afbouwen. Hiertoe wordt een urenteller op 0 gezet, en de gewenste temperatuur wordt ingesteld op de gemeten temperatuur - 1 graad. Dit betekent dat de temperatuur gedurende 4 uur geregeld wordt naar een temperatuur die 1 graad onder de (te hoge) gemeten temperatuur ligt, zodat het water in 4 uur ten hoogste 1 graad af kan koelen. Dit is wat er gerealiseerd moet worden.

Als nu de gewenste temperatuur groter is dan 24 graden, dan is de thermostaat blijkbaar bezig het water langzaam af te laten koelen. Deze gewenste temperatuur mag na 4 uur met 1 graad worden verlaagd, dus als de urenteller op 4 staat, mag de gewenste temperatuur met 1 worden verlaagd, en gaat er een nieuwe periode van 4 uur in. Als de gewenste temperatuur niet hoger is dan de standaard 24 graden, dan is er blijkbaar geen sprake van een afkoelperiode, dus dan hoeft er verder niets speciaals te gebeuren.

Stap 4: De software detailleren

Nu het hoofdprogramma vast ligt, kunnen de verschillende onderdelen daarvan nader bekeken worden.

De alarm LED en het relais voor de verwarming zijn rechtstreeks aangesloten op poort A. Deze hoeven niet verder bekeken te worden, het is eenvoudig om poort A te besturen.

Daarnaast moet er een urenteller gerealiseerd worden. Deze teller moet:

  • Terug op 0 gezet kunnen worden.

  • Het aantal uren tellen dat is verstreken sinds hij op 0 werd gezet.

Voor de urenteller is een tijdbasis nodig. Een tijdbasis kan worden afgeleid uit het kristal dat op de micro-controller is aangesloten. Hiervoor kan de 'Real Time Interrupt' gebruikt worden, of één van de output-compare timers. De real-time interrupt kan zodanig worden ingesteld dat op regelmatige tijdstippen een interrupt gegenereerd wordt. De tijd tussen twee interrupts kan worden gekozen uit 4 mogelijkheden. De output-compare timers kunnen een interrupt geven na een tijd die instelbaar is in eenheden van 0.5µs, en zijn dus veel nauwkeuriger in te stellen. We zullen kiezen voor een output-compare timer, bijvoorbeeld timer 1.

De timer wordt ingesteld op een tijdbasis van 25ms. Dit zijn 50.000 pulsen van elk 0.5 µs. Er gaan 40 interrupts in één seconde. In 1 uur gaan 3600 seconden. Er moet daarom één teller komen die interrupts telt, totdat er een seconde verstreken is. Deze teller mag één byte groot zijn. Na het verstrijken van één seconde wordt deze teller terug op 0 gezet, en mag er een seconde in de secondeteller worden bijgeteld. De secondeteller moet tot 3600 kunnen tellen, en dus twee bytes groot zijn. Als er 3600 seconden zijn verstreken wordt de urenteller met één verhoogd. De tijd wordt eenvoudig teruggezet op 0 door alle tellers op 0 te zetten. In de vorige lessen is meer informatie over de output-compare timers te vinden.

Als laatste moet de temperatuur gemeten worden. Dit komt neer op het meten van de duty-cycle op een input-capture ingang.

De berekening van de duty-cycle vereist twee metingen, die van de periodetijd van het signaal, en die van de tijd dat het signaal een '1' is. Beide tijden kunnen met een input-capture timer gemeten worden. De meting wordt gestart als het ingangssignaal van een '1' naar een '0' gaat (een neergaande flank.) Dit is het begin van een periode van het signaal. De tijd waarop dit gebeurt wordt onthouden. Als daarna het signaal van een '0' naar een '1' gaat (een opgaande flank) is dit het begin van de tijd dat het signaal een '1' is. De tijd waarop dit gebeurt wordt ook onthouden. Als daarna het signaal weer van een '1' naar een '0' gaat, is de periode afgelopen en kan worden uitgerekend hoe lang de periode geduurt heeft, en hoe lang het signaal een '1' was. Dit moment is tevens de start van een nieuwe meting. In de vorige lessen is meer informatie over de input-capture timers te vinden.

Na de meting zijn zowel de periodetijd als de '1' tijd van het signaal bekend, en wel in eenheden van 0.5µs. Dit moet nog worden omgerekend naar de temperatuur die hierbij hoort. Volgens het data-sheet van de SMARTEC sensor is de duty-cycle afhankelijk van de temperatuur volgens de formule:

d.c. = 0.31924 + 0.00472 x Temperatuur (graden Celcius)

Hieruit volgt, dat de temperatuur is: 211.9 x ( d.c. - 0.31924) De cijfers achter de komma moeten weggerekend worden. Dit kan door de formule aan beide zijden met 216 (65536) te vermenigvuldigen. Er onstaat dan:

Temperatuur x 65536 = 211.9 x ( 216 x d.c. - 20922)

Ofwel:

309 x Temperatuur = 216 x d.c. - 20922

Het getal d.c. x 216 kan eenvoudig berekend worden door de '1' tijd van het signaal en de periodetijd van het signaal op elkaar te delen via de 'fdiv' instructie. Deze instructie kan twee 16-bits getallen op elkaar delen, maar vermenigvuldigt eerst het deeltal met 216 voordat het gedeeld wordt. Dat is precies wat in dit geval nodig is. Van dit resultaat moet dan 20922 worden afgetrokken. Wat overblijft is een getal, dat 309 keer het aantal graden celcius is dat we zoeken. Zo levert bijvoorbeeld een temperatuur van 25 graden een resultaat op van ongeveer 25 x 309 = 7725. Het is eenvoudig om met deze getallen verder te rekenen.

De frequentie van het signaal van de sensor ligt tussen de 1 en 4 kHz. Dat betekent dat elke milliseconde een nieuwe meetwaarde beschikbaar is. Dat is veel sneller dan nodig. Daarvan kan gebruik gemaakt worden, door niet over één, maar over bijvoorbeeld 256 perioden te meten. De tijden die voor ieder van de 256 perioden worden gemeten worden opgeteld, en later wordt de som weer door 256 gedeeld. De metingen duren dan ongeveer ¼ seconde. Dat is snel genoeg. Omdat over een langere tijd gemeten wordt, zullen de meetwaarden beter bepaald kunnen worden, en vanwege het middelen minder gevoelig zijn voor storingen.

Stap 5: Het assembler programma

Nu volledig is uitgezocht wat het programma moet gaan doen, en hoe de verschillende onderdelen daarvan gerealiseerd kunnen worden, kan het programma worden ingevoerd in de assembler.

De assembler programma's die als voorbeelden zijn opgenomen in deze cursus hebben allemaal een gelijke opbouw. Hierin wordt eerst de definitie gemaakt van het RAM en programma geheugen, daarna worden de interrupt-vectoren benoemd. Het laden van de stack-pointer en het op 0 initialiseren van het RAM volgt daar op. Vervolgens wordt de code ingevoerd voor de verschillende modulen. Daarna volgt, aan het einde van de file, het hoofdprogramma.

De modulen hebben ook een eigen opbouw. Eerst wordt dataruimte voor de module gereserveerd (indien nodig). Hierop volgt initialisatie code. Deze code wordt afgesloten met een sprong-opdracht, die naar het eind van de module springt. Tussen deze sprongopdracht en het eind van de module staan de verschillende subroutines. Door deze opbouw te kiezen, wordt de initialisatiecode voor een module automatisch doorlopen wanneer de micro-controller gereset wordt. Het is verstandig om onderscheid te maken tussen routines die voor gebruik door de module zelf zijn bedoeld, en routines die door het hoofdprogramma aangeroepen mogen worden. Dit onderscheid voorkomt vergissingen later. Door middel van commentaar kan duidelijk aangeven worden, welke routine waarvoor bedoeld is.

In deze toepassing zijn de volgende modulen te herkennen:

  • De alarm LED

  • De verwarming

  • De urenteller

  • De temperatuur meter

De alarm LED.

Deze module heeft twee routines die vanuit het hoofdprogramma aangeroepen moeten kunnen worden: 'alarm_aan', en 'alarm_uit'.

De verwarming.

Deze module heeft twee routines die vanuit het hoofdprogramma aangeroepen moeten kunnen worden: 'verw_aan', en 'verw_uit'.

De urenteller.

Deze module heeft twee routines die vanuit het hoofdprogramma aangeroepen moeten kunnen worden: 'uren_op_0', en 'aantal_uren'.

De temperatuur meter.

Deze module heeft één routine die vanuit het hoofdprogramma aangeroepen moet kunnen worden: 'meet_temperatuur'.

Stap 6: Het testen

Wanneer de code voor een module in de assembler is ingevoerd kan deze getest worden. Hiervoor moet een klein hoofdprogramma geschreven worden, dat de module gebruikt op de manier zoals het uiteindelijke hoofdprogramma dat ook zou doen. Omdat het testprogramma maar klein is, en er maar één module tegelijkertijd aanwezig hoeft te zijn, is testen op deze wijze eenvoudiger dan het hele programma in één keer te testen. Om de urenteller te testen zou bijvoorbeeld een LED 4 uur aangezet kunnen worden, en daarna weer 4 uur uit, etc. De temperatuurmeter kan getest worden door de gemeten waarde via de seriële interface naar de PC te sturen, en daar te beoordelen. In de eerder gegeven voorbeelden kunt U vinden hoe de seriële poort bestuurd moet worden, en hoe de SIMPLEX communiceert met een PC.

Als alle modulen naar behoren werken, kan het hoofdprogramma ingevoerd worden. Omdat nu zeker is dat de modulen correct werken, is het ook eenvoudiger om eventuele fouten uit het hoofdprogramma te halen.

Hieronder is de code gegeven waarvan eventueel uitgegaan kan worden wanneer U de thermostaat wilt gaan maken. Bedenk dat de thermostaat in deze vorm nog niet volledig betrouwbaar is. Een storing van buitenaf zou bijvoorbeeld de micro-controller in de war kunnen brengen, waardoor het programma niet goed meer wordt uitgevoerd. De 'watchdog' die in de micro-controller zit kan helpen om in dit geval het programma weer in het goede spoor te brengen.

De thermostaat is ook niet beveiligd tegen een losgeraakte sensor. Als de sensor los is, zal er geen blokvormig signaal meer op de micro-controller binnenkomen. Hierdoor zal de meting nooit 256 perioden van het signaal kunnen meten, waardoor het programma oneindig lang gaat wachten op signaal van de sensor. De watchdog biedt ook hier een oplossing voor.

Als uitgangspunt is de hieronder gegeven code natuurlijk prima te gebruiken.

Het programma

*************************************************
* definieren van de geheugen map
*************************************************
		incl 'mapS3.asm'
*************************************************
* start van het programma
*************************************************
PROGRAM		space		|kies het programma?gebied
reset		equ $		|na reset begint de micro op deze plaats
		lds #stackend	|begin met de stackpointer te laden
		ldx #databeg	|en zet dan het volledige datagebied op 00
clearram	clr 0,x
		inx
		cpx #dataend
		bls clearram
		ldx #regsbeg	|laat IX op de bank met I/O registers wijzen
*************************************************
* De alarm indicator
*************************************************
PROGRAM	space
alarmstart	equ $		|het beginadres van deze module
* hardware adressen
alarmport	equ porta	|Op deze poort is de LED aangesloten
alarmbit	equ bit6	|Deze pin wordt gebruikt voor de LED
* initialisatie
PROGRAM		space
		bsr alarm_uit	|neem aan dat er geen alarm is
		bra alarmend	|einde van de initialisatie
* subroutine voor het uitzetten van de alarmindicator
PROGRAM		space
alarm_uit	equ $
		pshb		|bewaar het B register op de stack
		ldab alarmport	|haal de stand van de poort op
		andb #not(alarmbit)
		stab alarmport	|en maak het betreffende bit een '0'
		pulb		|haal daarna register B terug van de stack
		rts
* subroutine voor het aanzetten van de alarmindicator
PROGRAM		space
alarm_aan	equ $
		pshb		|bewaar het B register op de stack
		ldab alarmport	|haal de stand van de poort op
		orab #alarmbit
		stab alarmport	|en maak het betreffende bit een '1'
		pulb		|haal daara register B terug van de stack
		rts
alarmend	equ $		|einde van de alarm module
*************************************************
* De besturing van de verwarming
*************************************************
PROGRAM		space
verwstart	equ $		|het beginadres van deze module
* hardware adressen
verwport	equ porta	|Op deze poort is het relais aangesloten
verwbit		equ bit0	|Deze pin wordt gebruikt voor het relais
* initialisatie
PROGRAM		space
		bsr verw_uit
		bra alarmend	|einde van de initialisatie
* subroutine voor het uitzetten van de verwarming
PROGRAM		space
verw_uit	equ $
		pshb		|bewaar het B register op de stack
		ldab verwport	|haal de stand van de poort op
		andb #not(verwbit)
		stab verwport	|en maak het betreffende bit een '0'
		pulb		|haal daara register B terug van de stack
		rts
* subroutine voor het aanzetten van de verwarming
PROGRAM		space
verw_aan	equ $
		pshb		|bewaar het B register op de stack
		ldab verwport	|haal de stand van de poort op
		orab #verwbit
		stab verwport	|en maak het betreffende bit een '1'
		pulb		|haal daara register B terug van de stack
		rts
verwend		equ $		|einde van de alarm module
*************************************************
* De urenteller
*************************************************
* Deze module gebruikt output-compare 1 om eenheden van 25ms te tellen
* Na 40 van deze eenheden wordt een seconde teller verhoogd
* Na 3600 seconden wordt een urenteller verhoogd
PROGRAM		space
urenstart	equ $		|het beginadres van deze module
ms25		equ 50000	|het aantal klokperioden per interrupt
				|een klokperiode duurt 0.5 micro?seconden
intspersec	equ 40		|er gaan 40 interrupts in 1 seconde
secsperuur	equ 3600	|aantal seconden in 1 uur
DATA		space
oc1count	rmb 1		|deze teller wordt bij elke interrupt verhoogd
seconden	rmb 2		|hierin worden de seconden geteld
uren		rmb 1		|hierin worden de uren geteld
* initialisatie van de output?compare interrupt
PROGRAM		space
		ldd tcnt	|haal de systeemtijd
		addd #ms25	|en zet deze 25 ms verder voor de eerste
		std toc1	|interrupt, clear dan een eventuele interrupt
		ldab #oc1f
		stab tflg1	|enable daarna de interrupt van oc1
		bset tmsk1?regsbeg,x,oc1i
		bra urenend	|einde van de initialisatie
* subroutine voor de afhandeling van de output?compare interrupt
PROGRAM		space
oc1entry	equ $
		ldab #oc1f
		stab tflg1	|reset de interrupt?vlag
		ldab oc1count	|en tel de interrupt
		addb #1
		stab oc1count
		cmpb #intspersec
		blo oc1entry9	|kijk of er 1 seconde verstreken is
		clr oc1count	|zoja, zet dan de interrupt teller op 0
		ldd seconden	|en verhoog de secondenteller
		addd #1
		std seconden
		cpd #secsperuur	|kijk of er al 1 uur verstreken is
		blo oc1entry
		ldd #0		|zoja, zet dan de secondenteller op 0
		std seconden
		inc uren	|en verhoog de urenteller
oc1entry9	ldd toc1	|haal de tijd op het moment van de interrupt
		addd #ms25	|en zet deze 25 ms verder voor de volgende
		std toc1	|interrupt
		rti
***** routines die door het hoofdprogramma gebruikt mogen worden
PROGRAM		space
* haal het aantal verstreken uren op in register B
aantal_uren  	equ $
		ldab uren
		rts
* zet de urenteller op 0
* deze routine houdt de interrupts tijdelijk tegen, omdat anders het gevaar
* bestaat dat een interrupt van de output?compare de tellers verandert
* terwijl deze routine nog bezig is de tellers op 0 te zetten. Dit kan tot
* foutieve resultaten leiden.
uren_op_0	equ $
		psha		|bewaar register A op de stack
		tpa		|copieer het condition?code register naar A
		psha		|en zet het dan (via A) op de stack
		sei		|hou de interrupts tijdelijk tegen
		clra
		staa oc1count	|en zet dan alle tellers op 0
		staa seconden+1
		staa seconden
		staa uren
		pula		|haal het condition?code register terug
		tap		|via register A
		pula		|en haal register A terug van de stack
		rts
urenend		equ $		|einde van de urenteller module
*************************************************
* Temperatuur meting
*************************************************
* De temperatuurmeting telt gedurende 'nogtedoen' perioden van het ingangs?
* signaal de periodetijden op bij 'periodesom', en de tijden dat het signaal
* een '1' is op bij 'signaalsom'. Aan het eind van elke periode wordt
* 'nogtedoen' met 1 verlaagd. Als 'nogtedoen' op 0 komt, is de meting klaar
* en worden de sommen niet langer aangepast. De vlag 'meting_aan' wordt dan
* ook op '0' gezet. Om een meting te starten moet de vlag 'meting_aan' op
* '1' gezet worden, en 'nogtedoen' moet geinitialiseerd worden op het aantal
* perioden dat tijdens de meting gesommeerd moet worden. Ook moeten de
* sommen op 0 gezet worden.
PROGRAM		space
tempstart	equ $
* datagebied voor de temperatuur meting
DATA		space
nogtedoen	rmb 1		|aantal perioden dat nog gemeten moet worden
meting_aan	rmb 1		|vlag om aan te geven dat er een meting loopt
periodesom	rmb 3		|som van de periodetijden
signaalsom	rmb 3		|som van de tijd dat het signaal een '1' is
periodestart 	rmb 2		|starttijd van een periode
starttijd1	rmb 2		|tijdstip waarop het signaal een '1' wordt
* initialisatie voor de temperatuur meting
PROGRAM		space
		ldab #$7E	|zet de interrupt vector goed
		stab tic1int
		ldd #sensorint
		std tic1int+1
		ldx #regsbeg	|start het meten met een neergaande flank
		bclr tctl2+regsbeg,x,edg1a
		bset tctl2+regsbeg,x,edg1b
		ldab #ic1f	|clear mogelijke interrupt
		stab tflg1+regsbeg,x
		bset tmsk1+regsbeg,x,ic1i
		bra tempend
* subroutines voor de temperatuur meting
PROGRAM		space
******* input capture interrupt routine *******
sensorint	equ $
		ldx #regsbeg	|laat X op de I/O registers wijzen
* eerst de interrupt-vlag op '0' zetten
		ldab #ic1f
		stab tflg1+regsbeg,x
* daarna uitzoeken of het een op- of neergaande flank was
		brclr tctl2+regsbeg,x,edg1a,sensorint1
* als het een opgaande flank is, dan zitten we in het midden van een meting
* onthoud de tijd waarop de flank kwam
		ldd tic1+regsbeg,x
		std starttijd1
* en wacht vervolgens op een neergaande flank
		bclr tctl2+regsbeg,x,edg1a
		bset tctl2+regsbeg,x,edg1b
		bra sensorint9
* als het een neergaande flank is, dan zitten we aan het eind van een meting
* het eind van een meting is tevens het begin van een nieuwe meting
sensorint1	tst meting_aan	|kijk of de meting gedaan moet worden
		beq sensorint4
* als de meting gedaan moet worden:
* bereken de nieuwe som van de tijd dat het signaal een '1' is
		ldd tic1+regsbeg,x
		subd starttijd1	|reken uit hoe lang het signaal een '1' was
		addd signaalsom+1
		std signaalsom+1
		bcc sensorint2
		inc signaalsom	|en tel dat op bij de som
* bereken de nieuwe som van de periodetijd van het signaal
sensorint2	ldd tic1+regsbeg,x
		subd periodestart
		addd periodesom+1
		std periodesom+1
		bcc sensorint3
		inc periodesom	|idem voor de periodetijd
* en verlaag het aantal perioden dat nog gemeten moet worden
sensorint3	dec nogtedoen
		bne sensorint4
* als er geen perioden meer gemeten hoeven te worden, is de meting klaar
		clr meting_aan
* leg de starttijd van de nieuwe periode vast
sensorint4	ldd tic1+regsbeg,x
		std periodestart
* en ga op een opgaande flank wachten
		bclr tctl2+regsbeg,x,edg1b
		bset tctl2+regsbeg,x,edg1a
sensorint9	rti
* een meting van 256 perioden starten
startmeting	equ $
		tpa		|bewaar (via A) het conditie?code register
		psha		|op de stack
		sei		|houd de interrupts tijdelijk tegen
		ldd #0
		staa nogtedoen	|256 perioden sommeren
		std periodesom	|de periodesom op 0
		staa periodesom+2
		std signaalsom	|de signaalsom op 0
		staa signaalsom+2
		ldab #1		|de meting starten
		stab meting_aan
		pula		|haal (via A) het condition?code register
		tap		|terug van de stack
		rts
***** routines die door het hoofdprogramma gebruikt mogen worden
PROGRAM	space
* Meet de temperatuur, en laat het resultaat achter in D. Dit resultaat
* is 309 * het aantal graden in Celcius.
graad		equ 309
meet_temp	equ $
		pshx		|bewaar het IX register op de stack
		bsr startmeting	|start een meting van 256 perioden
meet_temp0	tst meting_aan	|wacht totdat de meting klaar is
		bne meet_temp0
		ldx periodesom	|de tijden worden door 256 gedeeld door
		ldd signaalsom	|alleen de twee meest significante bytes te
				|gebruiken van de 3 bytes waarin de som staat
		fdiv		|bereken de duty?cycle
		xgdx		|zet het resultaat van de deling in D
		subd #20922	|corrigeer daarna (zie de tekst in het manual)
		pulx		|haal X terug van de stack
		rts
tempend		equ $		|einde van de temperatuur meet?module
*************************************************
* het hoofdprogramma
*************************************************
alarmtemp	equ 25*graad	|temperatuur waarbij alarm gegeven wordt
optimaal	equ 24*graad	|de optimale temperatuur
houdtijd	equ 4		|aantal uren dat de temperatuur wordt vastge?
				|houden bij afkoelen
DATA		space
gemeten		rmb 2		|de gemeten temperatuur
gewenst		rmb 2		|de gewenste temperatuur
PROGRAM		space
		cli		|laat interrupts toe
		jsr meet_temp	|meet de temperatuur voor de eerste keer
		ldd #optimaal
		std gewenst	|stel gewenste temperatuur in op optimaal
mainloop	equ $		|de hoofdlus
		jsr meet_temp	|meet de huidige temperatuur
		std gemeten
		cpd #alarmtemp	|moet alarm gegeven worden?
		bls mainloop0
		jsr alarm_aan	|zoja, geef alarm
		bra mainloop1
mainloop0	jsr alarm_uit	|zonee, zet het alarm uit
mainloop1	cpd gewenst	|huidige temperatuur > gewenst?
		bls mainloop2
		jsr verw_uit	|zoja, zet de verwarming uit
mainloop2	cpd gewenst	|huidige temperatuur < gewenst?
		bhs mainloop3
		jsr verw_aan	|zoja, zet de verwarming aan
mainloop3	ldd gewenst
		addd #graad
		cpd gemeten	|gemeten > gewenst + 1 graad?
		bhs mainloop4
		ldd gemeten	|zoja, gewenst = gemeten ? 1 graad
		subd #graad
		std gewenst
		jsr uren_op_0	|en start de urenteller
mainloop4	ldd gewenst
		cpd #optimaal	|gewenste temperatuur > optimale temperatuur?
		bls mainloop	|zoniet, dan is de lus klaar
		jsr aantal_uren
		cmpb #houdtijd	|al voldoende tijd verstreken?
		blo mainloop	|zoniet, dan gewenst nog niet aanpassen
		ldd gewenst	|zoja, de gwenste temperatuur verlagen
		subd #graad	|met 1 graad
		std gewenst
		jsr uren_op_0	|de urenteller terugzetten
		bra mainloop	|en de lus herhalen
		end
 

© 2005...2008 Elomax [Voorwaarden ]