16x84 opdracht 1 : knipperen

Dit is de eenvoudigste 16x84 schakeling: een knipperende LED. Het schema is:

kipper LED schema kipper LED foto

Let op: de onderdelen van het basisschema zijn niet weergegeven.

Het bijbehorende programma is:

   include 16c84_10
   include jlib
   pin_a0_direction = output 
   forever loop
      pin_a0 = high 
      delay_10mS( 50 )
      pin_a0 = low 
      delay_10mS( 50 )
   end loop

De eerste regel geeft aan wat voor een 16x84 je gebruikt en met wat voor een kristal. Pas deze regel aan als je iets anders gebruikt dan een 16c84 met een 10Mhz kristal

De tweede regel geeft aan dat je de jlib file wilt kunnen gebruiken. In de jlib staan allerlei dingen die je niet zelf wilt programmeren.

De eerste echte regel zorgt er voor dat pin A0 een uitgang wordt. Zonder deze regel kunnen we van alles met de pin doen zonder dat we daar aan de buitenkant van het IC iets van merken.

De andere regels vormen een loop (lus) die in dit geval eeuwig (forever) herhaald wordt. Eerst wordt de A0 pin high (hoog) gemaakt. Dan volgt een wachttijd (delay) van 50 maal 10 mS = 500 mS (een halve seconde). Dan maken we de pin low (laag) en wachten weer een halve seconde om vervolgens weer vooraan de lus te beginnen.

Het effect is dat de LED knippert met een frequentie van 1 Hz (1 keer knipperen per seconde).

De delay_10mS regels kunnen we naar behoefte aanpassen om de LED sneller of langzamer te laten knipperen, of om de verhouding tussen de aan en uit tijd te veranderen. Tussen haakjes moet een getal van 0 tot 255 staan. Als dat niet genoeg is (voor aan langere of kortere tijd) moet je een andere delay procedure gebruiken, b.v. delay_1mS of delay_100mS. De delay is steeds het getal tussen de haakjes maal de delay die de naam van de procedure aangeeft.

opdracht knipper1.jal
Bouw de schakeling en programmeer de 16x84.

opdracht knipper2.jal
Pas nu het programma aan zodat de LED knippert met een frequentie van 1/5 Hz (een knippering duurt dan 5 seconden) waarbij de LED steeds 4 seconden uit is en 1 seconde aan.

opdracht knipper3.jal
Neem twee extra LEDs en weerstanden (totaal 1 rode, 1 orange en 1 groene LED). Gebruik de pinnen A0 (rood), A1 (oranje) en A2 (groen). Maak een stoplicht dat deze cyclus doorloopt:

De aanduidingen high end low zijn nogal onduidelijk, vooral omdat high overeenkomt met LED uit. Met het volgende stukje programma kan je aan en uit definieren.

   const bit aan = low
   const bit uit = high

opdracht knipper4.jal
Voeg de aan en uit regels toe aan je programma en gebruik aan en uit in plaats van low en high.

opdracht knipper5.jal
Het stoplicht wat je hebt gemaakt is Nederlands. Maak nu een Engels stoplicht dat dat de volgende cyclus doorloopt:

In Engeland geeft rood + oranje aan dat het stoplicht bijna op groen gaat.

opdracht knipper6.jal
Neem nog 3 extra LEDs en weerstanden. Gebruikt nu ook de pinnen B0 (rood), B1 (oranje) en B2 (groen). Maak twee stoplichten die op een kruising staan. Schrijf eerst op welke cyclus de stoplichten samen doorlopen. Denk er aan dat sommige automobilisten door rood rijden, dus als het ene stoplicht op rood springt moet je niet meteen het andere stoplicht op groen zetten. Als je voor de Engelse cyclus kiest moet oranje + rood van het ene stoplicht niet vallen in het groen van het andere licht, want sommig automobilisten beginnen bij oranje + rood al te rijden. Je zult je verschillende tijden ook wat moeten aanpassen.

Het laatste programma is niet erg overzichtelijk. We kunnen het programma veel duidelijker maken door een procedure aan te roepen voor iedere fase. In die procedure zetten we alle lichten op de voor die fase juiste stand en vervolgens wachten we het juiste aantal seconden.

   const byte rood   = 0
   const byte oranje = 1
   const byte groen  = 2

   procedure fase(
      byte in seconden,
      byte in hoofdweg,
      byte in zijweg
   ) is
      pin_a0 = ! ( hoofdweg == rood   ) 
      pin_a1 = ! ( hoofdweg == oranje ) 
      pin_a2 = ! ( hoofdweg == groen  ) 
      pin_b0 = ! ( zijweg == rood     ) 
      pin_b1 = ! ( zijweg == oranje   ) 
      pin_b2 = ! ( zijweg == groen    ) 
      delay_1S( seconden )      
   end procedure
Het eerste stuk van deze procedure declaratie is de header. Daarin wordt aangegeven hoe de procedure kan worden aangeroepen, in dit geval met 3 parameters, die aangeven:

In het de loop zetten we nu voor iedere fase een aanroep van de procedure.

   forever loop
      fase( 1, rood,   rood   )
      fase( 5, groen,  rood   )
      fase( 1, oranje, rood   )
      fase( 1, rood,   rood   )
      fase( 3, rood,   groen  )
      fase( 1, rood,   oranje )
      fase( 1, rood,   rood   )
   end loop

opdracht knipper7.jal
Pas je programma aan.

opdracht knipper8.jal
Pak nog twee LEDs (rood en groen) en sluit die aan op de pinnen B3 en B4. Deze LEDS vormen de voetgangers lichten (een voetgangers licht heeft geen oranje). Pas de procedure en de loop aan om ook deze LEDs aan te sturen. Je kunt kiezen of je de voetgangers groen geeft bij iedere wisseling van hoofdweg naar zijweg, of pas als zowel de hoofdweg als de zijweg geweest zijn.

De stoplichten die we nu gemaakt hebben geven altijd gelegenheid aan de voetgangers, ook als die er niet zijn. De meeste kruisingen hebben tegenwoordig drukknoppen voor de voetgangers. Sluit een drukknop aan tussen pin A4 en de massa, en een weerstand van 10k van pin A4 naar de Vcc.

Het is voor een voetganger prettig om te zien dat zijn druk op de knop door het stoplicht systeem herkend is. Sluit dus en een extra LED (geel) aan op pin B5. Deze LED moet aan gaan als er op de knop is gedrukt, en weer uit zodra de voetgangers groen krijgen.

kruispunt schema

We moeten nu ergens in het programma gaan kijken of de schakelaar is ingedrukt. Op zich is dat niet zo moeilijk. We kunnen met een IF statement een stuk programma alleen laten uitvoeren als b.v. de pin B4 laag is.

   if pin_a4 == aan then
      pin_b5 = aan 
   end if
Met dit stukje code hebben we al bereikt dat de gele LED aan gaat als er op de knop wordt gedrukt. Het probleem is alleen dat we dit stukje code dan voortduren moeten uitvoeren. Ons programma is echter steeds en paar seconden bezig in de delay_1S procedure.

We kunnen dit oplossen door in plaats van de delay_1S procedure een eigen procedure te gebruiken die telkens de schakelaar bekijkt en dan weer even wacht, net zo lang totdat de wachttijd voorbij is. Als de dat wachten kort genoeg houden (b.v. 10mS) dan lijkt het alsof we altijd naar de schakelaar kijken. Voor de overzichtelijkheid gebruiken we twee procedures.

   var bit voetgangers = no

   procedure schakelaar is
      for 100 loop
         if pin_a4 == aan then
            pin_b5 = aan 
            voetgangers = yes
         end if
         delay_10mS( 1 )
      end loop
   end procedure
Deze procedure bevat een for loop. Zo'n loop wordt net zo vaak uitgevoerd als tussen de for en de loop staat, in dit geval dus 100 keer. In de loop kijken we eerste of de schakelaar is ingedrukt. Zo ja dan zetten we de LED aan en we ztten de variable voetgangers op yes zodat we later (in de hoofd loop) weten of we tijd moeten inruimen voor de voetgangers. Vervolgens wachten we 10mS. 100 * 10mS = 1S, dus de hele procedure duurt precies 1 seconde.
   procedure wacht( byte in seconden ) is
      for seconden loop
         schakelaar
      end loop
   end procedure

De tweede procedure is wat eenvoudiger: er moet een aantal seconden gewacht worden, dus we roepen gewoon zo vaak de procedure schakelaar aan als het aantal seconden dat we moeten wachten.

In de hoofd loop hoeven we nu alleen nog maar rekening te houden met de voetgangers als er door de schakelaar procedure is gedetecteerd dat er op de knop is gedrukt.

   pin_b5 = uit
   forever loop
      fase( 1, rood,   rood,    rood )
      fase( 5, groen,  rood,    rood )
      fase( 1, oranje, rood,    rood )
      fase( 1, rood,   rood,    rood )
      fase( 3, rood,   groen,   rood )
      fase( 1, rood,   oranje,  rood )
      fase( 1, rood,   rood,    rood )
      if voetgangers then
         pin_b5 = uit
         fase( 10, rood, rood,  groen )  
         voetgangers = no
         fase( 10, rood, rood,  rood )  
      end if
   end loop
De voegangers lichten staan meestal op rood, dus er is van uitgegaan dat dat de default is.

opdracht knipper9.jal
Voeg de voetgangers LEDs en de schakelaar toe. Pas het programma aan.