Beginners mini-cursus (deel 5)

Weerstand meten zonder AD-Converter

POT Leest stand van een potentiometer in van een ingang
RCIN Meet puls breedte op een ingang

 


POT

De PIC16F628(A) heeft helaas geen ADC, analogue to digital converter (= analoog naar digitaal omzetter) aan boord.
Maar met behulp van een kleine condensator kan toch de weerstandswaarde van bijvoorbeeld een LDR (= fotoweerstand), NTC, PTC (= thermistor) of de stand van een potmeter (= potentiometer) worden gemeten.
Meting van de weerstand gebeurt dan door te meten hoe lang het duurt om de condensator te ontladen via deze weerstand.
Hiervoor heeft PIC Basic een standaard functie, genaamd POT (van potmeter).

De syntaxis
Variabele = POT pin, schaal

De functie POT leest een 25k potmeter in.

pin - Is een Port.Pin constante die aangeeft op welke I/O poort de variabele weerstand is aangesloten, bijvoorbeeld PORTA.1.
schaal - Hiermee kun je de POT functie zo instellen dat bijvoorbeeld een potmeter bij maximale instelling een waarde van 255 oplevert.
Als de (lineaire) potmeter dan in het midden staat, is het resultaat ongeveer 127 en als de potmeter op minimale instelling staat, levert het (bijna) een 0 op.
De afregeling hiervoor wordt verderop besproken.
Variabele - Hierin komt de waarde (0 ... 255), afhankelijk van de gemeten weerstand.
Maximale weerstand levert tegen de 255 op, minimale weerstand (bijna) een 0.


De functie POT leest een variabele weerstand en geeft een waarde (0 ... 255) die overeenkomt met de tijd die het duurt om een condensator te ontladen via deze variabele weerstand.
De ene zijde van de weerstand wordt verbonden met een poort van de PIC en de andere zijde via een condensator aan de 0V (GND, massa), zie schemaatje rechtsbovenaan.


Voorbeelden
Sluit nu eerst een potmeter van 25k in serie met een condensator van 100n aan op PORTA.1 (zie schema hieronder).
De 2 LED's en 2 druktoetsen van cursus deel 4 mogen blijven zitten, die worden straks weer gebruikt.
Let op: het is belangrijk dat het een 25k potmeter is, want hier zijn de voorbeelden op gebaseerd.


Schema potmeter met condensator en een HD44780 display.

Het onderstaande programma laat op het display een waarde zien van 0 ... 255, afhankelijk van de stand van de potmeter.
Als er aan de potmeter wordt gedraaid verandert de waarde op het display mee.

DEVICE 16F628A                ;Gebruik een 16F628A type
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
ALL_DIGITAL TRUE              ;Alle ingangen digitaal

CLEAR                         ;Wis alle RAM geheugen
DELAYMS 500                   ;LCD stabilisering

CLS                           ;LCD scherm wissen
WHILE 1 = 1                   ;Oneindig door blijven meten
  PRINT AT 1, 1, DEC POT PORTA.1, 255, "  " ;Zet gemeten waarde op het display 
WEND                          ;Terug naar WHILE

END                           ;Einde programma

De functie POT is hier rechtstreeks in de instructie PRINT geschreven.
Er staat dus in 1 regel: Meet potmeterwaarde (met POT) die aangesloten is op PORTA.1 en zet de DECimale waarde linksboven in het display.
Vergeet de 2 spaties achteraan de PRINT opdracht niet.
Als je wilt weten waarvoor die 2 spaties dienen moet je de PIC maar eens programmeren zonder deze spaties en dan aan de potmeter draaien.


De waarde van Schaal van de functie POT
Het zal je opgevallen zijn dat maar één helft van de 25k potmeter werkt, bij het overige deel blijft het display op 255 staan.
Met de parameter Schaal in de functie POT kun je dit aanpassen zodat het hele bereik van de potmeter het doet.
De waarde voor Schaal kun je bepalen door experimenteren, maar je kunt de waarde voor Schaal ook automatisch laten bepalen.
In de programmavoorbeelden hierna staan voor Schaal steeds 3 vraagtekens (???).
Hiervoor moet je de waarde invullen die door het Automatisch Schaal Bepalen programmaatje is gegeven.

Dus nu eerst de Schaal bepalen voordat je verder met de cursus gaat.


Onderstaand programma doet eigenlijk precies hetzelfde als het vorige programma.
Alleen plaatst het nu de waarde eerst in een BYTE variabele (met de naam 'Weerstand').
Hierdoor kun je dingen met die variabele gaan doen die afhankelijk zijn van de gemeten potmeterstand, zoals de overige voorbeeldprogramma's straks laten zien.
Vergeet niet om eerst de waarde voor Schaal in te vullen (in de plaats van de 3 vraagtekens) anders krijg je de foutmelding  Value Expected!  bij het compileren.

DEVICE 16F628A                ;Gebruik een 16F628A type
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
ALL_DIGITAL TRUE              ;Alle ingangen digitaal

;Variabele declareren
DIM Weerstand AS BYTE         ;Deze variabele bevat straks de stand van de potmeter  

CLEAR                         ;Wis alle RAM geheugen
DELAYMS 500                   ;LCD stabilisering

CLS                           ;LCD scherm wissen
WHILE 1 = 1                   ;Oneindig door blijven meten
  Weerstand = POT PORTA.1, ???;<<<<< HIER DUS EERST DE WAARDE VOOR SCHAAL OPGEVEN
  PRINT AT 1, 1, "Potmeter = ", DEC Weerstand, "  " ;Zet gemeten waarde op het display 
WEND                          ;Terug naar WHILE

END                           ;Einde programma

Wanneer de potmeter voluit staat, moet de waarde op het display tegen de 255 aanliggen.
Is de waarde op het display nog lang geen 255, dan moet de waarde voor Schaal van de functie POT worden vergroot (max.255).
Staat Schaal echter al op 255, dan moet je een potmeter met een hogere weerstandswaarde nemen.
De condensatorwaarde verhogen kan ook, maar komt de stabiliteit niet ten goede.
Staat de waarde op het display al op 255 maar de potmeter nog niet helemaal op maximum, dan moet de waarde voor Schaal in het programma worden verkleind.
 

Expres lager zetten
Maar je kunt Schaal natuurlijk ook expres heel laag zetten, als bijvoorbeeld de verdeling van de potmeter maar van 0 ... 9 hoeft te zijn (een soort traploze stappenschakelaar ), dan moet je voor Schaal een veel lagere waarde opgeven (bijvoorbeeld 5).
Bij de potmeter helemaal dicht is Variabele = 0 en bij potmeter helemaal open is Variabele = 9.


Sluit nu 2 LED's met serieweerstanden en 2 pulsschakelaars aan op de PIC.
De opzet van het schema is gelijk aan die van cursus deel 4, alleen is hier de potmeter met condensator bij gekomen.


Schema voor de volgende voorbeelden.

De aansluiting van de loper van de potmeter (de middelste aansluiting) is volgens het schema aangesloten aan de kant waar ook de condensator van 100n aan zit.
Dit is niet verplicht.
De loper mag ook worden verbonden met de zijde die aan PORTA.1 zit.
Alleen wordt hierdoor de draairichting van de potmeter andersom.
Anders gezegd; was eerst potmeter rechtsom het maximum, dan is nu linksom het maximum.
 

Compileer nu het volgende programma:

DEVICE 16F628A                ;Gebruik een 16F628A type
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
ALL_DIGITAL TRUE              ;Alle ingangen digitaal

;Logische constanten
SYMBOL OFF          = 0
SYMBOL ON           = 1

;Poortnamen
SYMBOL Potmeter     = PORTA.1 ;Potmeter aangesloten via een condensator aan GND
SYMBOL LED_Rood     = PORTA.3 ;Rode LED aangesloten op PORTA.3

;Variabele declareren
DIM Weerstand AS BYTE         ;Deze variabele bevat straks de stand van de potmeter  

;        76543210
TRISA = %11110111             ;PORTA.3 omschakelen als uitgang voor de LED

CLEAR                         ;Wis alle RAM geheugen
DELAYMS 500                   ;LCD stabilisering


;Hoofdprogramma
CLS                           ;Wis display scherm
WHILE 1 = 1                   ;Oneindig door blijven meten
  Weerstand = POT Potmeter, ???;<<<<< DE WAARDE VAN Schaal VOOR DE POT FUNCTIE HIER INVULLEN 
  PRINT AT 1, 1, "Instelling: ", DEC Weerstand, "  " ;Zet stand op regel 1 van display 

  IF Weerstand > 75 THEN      ;Als de potmeter boven waarde 75 uitkomt dan...
    LED_Rood = ON             ;...de rode LED aanzetten
  ELSE                        ;...anders...
    LED_Rood = OFF            ;...de rode LED uitzetten
  ENDIF
WEND                          ;Terug naar WHILE

END                           ;Einde programma

Het zal al snel duidelijk zijn wat dit programma doet.
De functie POT meet de stand van de potmeter en geeft die stand door aan de variabele 'Weerstand'.
In de regel daarna wordt de variabele 'Weerstand' (met de stand van de potmeter dus) met PRINT op het display gezet.

Daarna wordt met IF...THEN bekeken of de 'Weerstand' een waarde heeft die groter is ( > ) dan 75 en zo ja, dan de LED aanzetten, anders (= ELSE) de LED uitzetten.

Dit alles staat in een lus die oneindig blijft doorgaan (WHILE 1 = 1 ... WEND).


Het programma hieronder laat de rode en groene LED om de beurt knipperen, waarvan de snelheid van het knipperen (knipperfrequentie) is te regelen met de potmeter (hier wordt geen display gebruikt).

DEVICE 16F628A                ;Gebruik een 16F628A type
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
ALL_DIGITAL TRUE              ;Alle ingangen digitaal

;Poortnamen
SYMBOL Potmeter     = PORTA.1 ;Potmeter aangesloten via een condensator aan GND
SYMBOL LED_Groen    = PORTA.2 ;Groene LED 
SYMBOL LED_Rood     = PORTA.3 ;Rode LED (brandt straks tegengesteld aan de groene LED)

;Variabele declareren
DIM Weerstand AS BYTE         ;Deze variabele bevat straks de stand van de potmeter  

;        76543210
TRISA = %11110011             ;PORTA.3 en PORTA.2 omschakelen als uitgang voor de LED's

CLEAR                         ;Wis alle RAM geheugen


;Hoofdprogramma
WHILE 1 = 1                   ;Oneindig door blijven knipperen
  Weerstand = POT Potmeter, ???;Stand van potmeter (0...255) aan variabele 'Weerstand' geven 

  DELAYMS (Weerstand * 4) + 50;Wachttijd 4x de waarde van 'Weerstand' + 50 milliseconden 
  LED_Groen = LED_Groen ^ 1   ;Toggle de groene LED
  LED_Rood  = LED_Groen ^ 1   ;De rode LED moet branden als de groene LED uit is
WEND                          ;Terug naar WHILE

END                           ;Einde programma

De werking van het programma moet duidelijk te begrijpen zijn, alles is behandeld in de cursus tot nu toe.

Bij DELAYMS wordt de variabele 'Weerstand' met 4 vermenigvuldigd en daar nog eens 50 bij opgeteld.
Stel dat de potmeter op de minimale stand staat, dan is de variabele 'Weerstand' (bijna) 0.
De berekening is dan (0 × 4) + 50, de minimale wachttijd is dan 50 milliseconden.
Stel dat de potmeter op de maximale stand staat, dan is de variabele 'Weerstand' (bijna) 255.
De berekening is dan (255 × 4) + 50, de maximale wachttijd is dan dus 1070 milliseconden.
Kortom:
De snelste snelheid (potmeter dicht) wordt bepaalt door die 50 die bij de vermenigvuldiging op wordt geteld.
Als je die waarde kleiner maakt, dan wordt de snelste knippersnelheid nog sneller.
De langzaamste snelheid (potmeter helemaal open) wordt mede bepaalt door de vermenigvuldigingsfactor, in dit geval is dat die 4.


Het volgende programma doet het anders en laat de rode en groene LED alleen knipperen als je aan de potmeter draait.
De groene LED brandt als de potmeterwaarde een even getal is en de rode LED als het een oneven getal betreft.

DEVICE 16F628A                ;Gebruik een 16F628A type
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
ALL_DIGITAL TRUE              ;Alle ingangen digitaal

;Logische constanten
SYMBOL OFF          = 0
SYMBOL ON           = 1

;Poortnamen
SYMBOL Potmeter     = PORTA.1 ;Potmeter aangesloten via een condensator aan GND
SYMBOL LED_Groen    = PORTA.2 ;Groene LED
SYMBOL LED_Rood     = PORTA.3 ;Rode LED (brandt straks tegengesteld aan de groene LED)

;Variabele declareren
DIM Weerstand AS BYTE         ;Deze variabele bevat straks de stand van de potmeter  

;        76543210
TRISA = %11110011             ;PORTA.3 en PORTA.2 omschakelen als uitgang voor de LED's

CLEAR                         ;Wis alle RAM geheugen
DELAYMS 500                   ;LCD stabilisering


;Hoofdprogramma
CLS                           ;Wis display
WHILE 1 = 1                   ;Oneindig door blijven meten
  Weerstand = POT Potmeter, ???;Stand van potmeter (0...255) aan variabele 'Weerstand' geven 
  PRINT AT 1, 1, "Potmeter is ", DEC Weerstand, "  " ;Zet stand op regel 1 van display 

  IF (Weerstand // 2) = 0 THEN;Als 'Weerstand' een even getal is dan...
    LED_Groen = ON            ;Groene LED aanzetten
  ELSE                        ;...anders...
    LED_Groen = OFF           ;Groene LED uitzetten
  ENDIF

  LED_Rood = LED_Groen ^ 1    ;De rode LED brandt alleen als de groene LED uit is

  DELAYMS 5
WEND                          ;Terug naar WHILE

END                           ;Einde programma

Je hebt in de praktijk verder weinig aan bovenstaand programma. 

Het onderscheiden van even- en oneven getallen gaat met ' // ' (modulus berekening) (= restwaarde van een deling).
Meer over de modulus berekening.


Hoe doet POT zijn werk?
Extra informatie voor degenen die meer over de functie POT willen weten.

 

Van links naar rechts:
normale 'mono' potmeter,
stereo potmeter,
potmeter met schakelaar,
10-slagen potmeter.
Diverse instelpotmeters (trimmers).
Rechtsboven 3 soorten meer-slagen trimmers.

 

Soms zie je in schema's dat één vaste zijde van de potmeter niet is aangesloten.
Dit kun je beter wel doen.
Stel je voor dat de loper van de potmeter door slijtage of vuil niet altijd goed contact meer maakt, dan wordt de weerstand oneindig hoog.
Als de loper is verbonden met een vaste zijde van de potmeter, kan de weerstand nooit hoger worden dan de weerstandswaarde van de potmeter, altijd nog beter dan een oneindige weerstand (= contactbreuk).

Het volgende voorbeeld is al weer wat moeilijker, maar als je de listing (= het programma) rustig bekijkt, is het aardig te volgen.
Het programma laat een soort VU-meter met peak-hold zien op het display en de uitslag van die meter is afhankelijk van de potmeterstand.
Let op: De waarde voor Schaal moet nu bij SYMBOL worden ingevuld.

DEVICE 16F628A                ;Gebruik een 16F628A type
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
ALL_DIGITAL TRUE              ;Alle ingangen digitaal

;Logische constanten
SYMBOL HOOG         = 1       ;Een hoog signaal is hetzelfde als een '1'
SYMBOL LAAG         = 0       ;Een laag signaal is hetzelfde als een '0'

;Algemene constanten
SYMBOL Blokje       = 255     ;ASCII waarde van een blokje op het display
SYMBOL Lengte       = 16      ;Getal bepaalt max.uitslag VU-meter blokjes (=display breedte)
SYMBOL Schaal       = ???     ;<<<<< DE WAARDE VAN Schaal VOOR DE POT FUNCTIE HIER INVULLEN

;Poortnamen
SYMBOL Potmeter     = PORTA.1 ;Potmeter aangesloten via een condensator aan GND
SYMBOL Mode         = PORTB.0 ;Ingang: Laag maken = DOT / Hoog maken = BAR
SYMBOL PeakHold     = PORTB.1 ;Ingang: Lage puls = Reset / Laag = Peak uit / Hoog = Peak aan

;Variabelen declareren
DIM PeakPlek        AS BYTE   ;Onthoud de cursorplek waar het blokje van peak-hold staat
DIM Som             AS BYTE   ;Bevat de uitkomst van de som: (Weerstand * Lengte) / 256
DIM Weerstand       AS BYTE   ;Bevat de gemeten weerstandswaarde van de potmeter

PORTB_PULLUPS ON              ;On-chip pull-up weerstanden actief (voor de schakelaars)
CLEAR                         ;Wis alle RAM geheugen
DELAYMS 500                   ;LCD stabilisering


;Hoofdprogramma
CLS                                     ;Met een schoon LCD scherm beginnen (LCD wissen dus)
WHILE 1 = 1
  Weerstand = POT Potmeter, Schaal      ;Geef nieuw gemeten waarde aan 'Weerstand'
  PRINT AT 1, 1, DEC Weerstand, "  "    ;Zet actuele stand van 'Weerstand' op eerste regel

  Som = (Weerstand * Lengte) / 256      ;Bereken cursor (dot mode) / lengte balk (bar mode)

  IF Mode = LAAG THEN                   ;Als 'Mode' pin (PORTB.0) laag is dan in DOT mode
    PRINT AT 2, 1, REP " "\Som,_        ;Wis links van blokje oude meetuitslag op regel 2
                   Blokje,_             ;Plaats het blokje afhankelijk van stand potmeter
                   REP " "\Lengte - Som ;Wis rechts van blokje oude meetuitslag op regel 2
    PeakPlek = Som                      ;Reset:'PeakPlek' gelijk aan huidige potmeterstand
  ELSE                                  ;...anders... (als 'Mode' pin hoog is, dan BAR mode)
    PRINT AT 2, 1, REP Blokje\Som + 1   ;Aantal blokjes afhankelijk van stand potmeter

    IF PeakHold = HOOG  THEN            ;Als PeakHold pin hoog is gemaakt dan...
      IF Som > PeakPlek THEN PeakPlek = Som ;Als uitslag boven de oude peak komt nieuwe peak
      IF Som < PeakPlek THEN PRINT REP " "\PeakPlek - (Som + 1);Wis blokjes tussen BAR - PEAK
    ELSE                                ;...anders...(peak reset of peakhold uitgeschakeld)
      PeakPlek = Som                    ;Reset:'PeakPlek' gelijk aan huidige potmeterstand
      PRINT REP " "\Lengte - Som        ;Wis display rechts van BAR balk
    ENDIF

  ENDIF
WEND

END                                     ;Einde programma

Dit programma laat op displayregel 1 de decimale waarde van de potmeterstand zien.
De aanwijzing op displayregel 2 is afhankelijk van PORTB.0, met de naam Mode.
Als Mode hoog wordt gemaakt (of gewoon open laten want PORTB pull-ups is ingeschakeld), dan wordt de potmeterstand als een soort VU-meter weergegeven, hoe groter de weerstand van de potmeter, hoe meer blokjes er zijn.
Dit wordt BAR-mode genoemd.

Wanneer Mode laag wordt gemaakt (PORTB.0 met GND (0V) verbinden), dan staat de VU-meter in DOT-mode en dat houdt in dat er maar 1 blokje (= dot) tegelijk zichtbaar is.

Zowel DOT als BAR maken gebruik van dezelfde berekening: (Weerstand x Lengte) / 256.
Aangezien deze berekening op verschillende plaatsen nodig is wordt de uitkomst van deze som eerst in de variabele 'Som' geplaatst, die daarna in verschillende programmaregels wordt gebruikt.
Anders zou de PIC op al die plaatsen steeds opnieuw dezelfde berekening moeten doen, wat tijd en geheugenruimte kost.

Peakhold
In de BAR-mode stand heeft de VU-meter een peak-hold mogelijkheid.
Ingang PORTB.1 (met de naam PeakHold) heeft 3 mogelijkheden met betrekking tot de peak-hold.

1. Als de PeakHold pin niet wordt aangesloten (PORTB pull-up) dan is de peak-hold functie ingeschakeld.
Het hoogst gemeten niveau blijft dan zichtbaar doordat daar een blokje blijft staan.
2. Een laag pulsje op de PeakHold pin reset de peak-hold en begint de meter weer van onderaf aan te meten.
3. Door PeakHold constant laag te maken is de peak-hold functie uitgeschakeld.
 

Het volgende programma is ook een VU-meter, maar deze geeft geen grove blokjes weer, zoals in het vorige programma, maar doet dit met hele dunne streepjes.
Hierdoor is de resolutie drie maal hoger dan in het vorige VU-meter programma.

DEVICE 16F628A                ;Gebruik een 16F628A type
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
ALL_DIGITAL TRUE              ;Alle ingangen digitaal

;Algemene constanten
SYMBOL Lengte       = 16      ;Vul hier in hoeveel karakters breed de VU-meter moet zijn
SYMBOL Schaal       = ???     ;<<<<< DE WAARDE VAN Schaal VOOR DE POT FUNCTIE HIER INVULLEN 

;Poortnamen
SYMBOL Potmeter     = PORTA.1 ;Potmeter aangesloten via een 100n condensator aan GND

;Variabelen declareren
DIM Half            AS BYTE   ;Bevat het halve karakter | of ||
DIM Som             AS BYTE   ;Bevat de uitkomst van de som: (Weerstand * Lengte) / 85
DIM Vol             AS BYTE   ;Bevat het aantal te printen "volle" karakters: |||
DIM Weerstand       AS BYTE   ;Bevat de gemeten weerstandswaarde van de potmeter

CLEAR                         ;Wis alle RAM geheugen
DELAYMS 500                   ;LCD stabilisering

;Teken drie eigen karakters
PRINT $FE,$40,$15,$15,$15,$15,$15,$15,$15,$15,_ ;karakter 0 = |||
              $10,$10,$10,$10,$10,$10,$10,$10,_ ;karakter 1 = |
              $14,$14,$14,$14,$14,$14,$14,$14   ;karakter 2 = ||
              

;Hoofdprogramma
CLS                           ;Met een schoon LCD scherm beginnen (LCD wissen dus)
WHILE 1 = 1
  Weerstand = POT Potmeter, Schaal ;Geef nieuw gemeten waarde aan 'Weerstand'
  PRINT AT 1, 1, @Weerstand, "  "  ;Zet actuele stand van 'Weerstand' op eerste regel

  Som  = (Weerstand * Lengte) / 85 ;De waarde 85 komt van 256 / 3
  Vol  = Som / 3              ;Bereken het aantal volle karakters |||
  Half = Som // 3             ;Bereken de restwaarde van de deling (uitkomst is 0, 1 of 2)

  PRINT AT 2, 1, REP 0\Vol    ;Plaats eerst het aantal volle karakters ||| (= karakter 0)
  IF Half > 0 THEN PRINT Half ;Als de waarde niet 0 is, dan print karakter (1 of 2)
  PRINT REP " "\Lengte - Vol  ;Wis het overige van de barregel
WEND

END                           ;Einde programma

De beschrijving van de drie eigengemaakte karakters en deze VU-meter op zich staat beschreven in cursus deel 4.
Het enige dat hier is toegevoegd is de functie POT.


Het is je misschien opgevallen dat in de VU-meter voorbeelden nergens TRISA en/of TRISB staat.
Dat is daar niet per se nodig omdat de instructie PRINT (voor het display) de poort zelf in de juiste stand zet.
Ook de functie POT schakelt de poort zelf, omdat de poort de ene keer heel even een uitgang is (om de condensator op te laden) en daarna omschakelt naar ingang, om de potmeterstand te lezen.
En ook voor de 2 schakelaars (eerste VU-meter) is geen TRIS instelling nodig omdat een PIC altijd opstart met alle poorten als ingang, dus als je niets opgeeft blijven ze ingang.
Het volgende voorbeeld stuurt 2 LED's aan, dus nu moet TRISA wel opgegeven worden om deze 2 poorten om te schakelen als uitgang:

DEVICE 16F628A                ;Gebruik een 16F628A type
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
ALL_DIGITAL TRUE              ;Alle ingangen digitaal

;Logische constanten
SYMBOL LAAG         = 0       ;Een laag signaal is hetzelfde als een '0'
SYMBOL OFF          = 0
SYMBOL ON           = 1

;Algemene constanten
SYMBOL Schaal       = ???     ;<<<<< DE WAARDE VAN Schaal VOOR DE POT FUNCTIE HIER INVULLEN

;Poortnamen
SYMBOL Potmeter     = PORTA.1 ;Potmeter aangesloten via een condensator aan GND
SYMBOL LED_Groen    = PORTA.2 ;Brandt als potmeter onder een in te stellen niveau komt
SYMBOL LED_Rood     = PORTA.3 ;Brandt als potmeter boven een in te stellen niveau komt
SYMBOL S1           = PORTB.0 ;Toets om grenswaarden van instelling potmeter vast te leggen

;Variabelen declareren
DIM BovenGrens      AS BYTE   ;Bevat de bovengrenswaarde waarop de rode LED schakelt
DIM OnderGrens      AS BYTE   ;Bevat de ondergrenswaarde waarop de groene LED schakelt
DIM Weerstand       AS BYTE   ;Bevat de gemeten weerstandswaarde van de potmeter

;        76543210
PORTA = %00000000             ;Alle PORTA uitgangen uit (laag maken)
TRISA = %11110011             ;PORTA.3 en PORTA.2 omschakelen als uitgang voor de LED's

PORTB_PULLUPS ON              ;On-chip pull-up weerstanden actief (voor S1)
CLEAR                         ;Wis alle RAM geheugen
DELAYMS 500                   ;LCD stabilisering


;Hoofdprogramma
CLS                                     ;Alles van het LCD scherm wissen
PRINT          "Stel ondergrens"        ;Plaats tekst op het LCD
PRINT AT 2, 1, "Druk op S1"

REPEAT
  OnderGrens = POT Potmeter, Schaal     ;Geef nieuw gemeten waarde aan 'OnderGrens' 
  PRINT AT 2, 13, DEC OnderGrens, "  "  ;Geef potmeterinstelling rechtsonder op LCD weer
UNTIL S1 = LAAG                         ;Ondergrens is in te stellen totdat op S1 is gedrukt

DELAYMS 25                              ;Tegen contactdender van S1
WHILE S1 = LAAG : WEND                  ;Wacht tot toets is losgelaten (Zolang S1 laag is...) 

PRINT AT 1, 6, "boven"                  ;Wijzig tekst op LCD 'onder'grens in 'boven'grens

REPEAT
  BovenGrens = POT Potmeter, Schaal     ;Geef nieuw gemeten waarde aan 'BovenGrens' 
  PRINT AT 2, 13, DEC BovenGrens, "  "  ;Geef potmeterinstelling rechtsonder op LCD weer
UNTIL S1 = LAAG AND BovenGrens > OnderGrens;Wacht op S1 EN bovengrens groter is dan ondergrens

CLS                                     ;Wis de tekst van het instellen op het LCD

WHILE 1 = 1                             ;Programma continu uitvoeren
  Weerstand = POT Potmeter, Schaal      ;Geef nieuw gemeten waarde aan 'Weerstand'
  PRINT AT 1, 1, DEC Weerstand, "  "    ;Zet actuele stand van 'Weerstand' op eerste regel

  IF Weerstand > BovenGrens THEN        ;Als potmeter boven de bovengrens komt dan...
    LED_Groen = OFF                     ;Groene LED moet uit zijn
    LED_Rood  = ON                      ;Rode LED aanzetten
  ELSEIF Weerstand < OnderGrens THEN    ;...anders, als potmeter onder ondergrens komt dan...
    LED_Groen = ON                      ;Groene LED aanzetten
    LED_Rood  = OFF                     ;Rode LED moet uit zijn
  ELSE                                  ;...anders...
    LED_Groen = OFF                     ;Moeten beide LED's uit zijn
    LED_Rood  = OFF
  ENDIF
WEND

Dit programma laat de groene LED branden als de potmeter onder een in te stellen waarde komt en laat de rode LED branden als de potmeter boven een andere (grotere) in te stellen waarde komt.
Als de PIC wordt opgestart vraagt hij eerst om met de potmeter die 2 grenzen in te stellen.

 
Gebruiksaanwijzing van bovenstaand programma:
Stel eerst met de potmeter de ondergrens in (een lage waarde, bijvoorbeeld 50) en bevestig met de S1 toets, aangesloten op PORTB.0.
Merk op dat op het display het woordje "ondergrens" is verandert in "bovengrens".
Stel nu met de potmeter die bovengrens in en bevestig opnieuw met de S1 toets.
De waarde van de bovengrens moet groter zijn dan de ondergrens, anders accepteert S1 de instelling niet (UNTIL S1 = LAAG AND BovenGrens > OnderGrens).
Als beide waarden zijn ingesteld, komt het programma in een lus (WHILE 1 = 1).
Door de potmeter te verdraaien gaat de groene LED branden als de potmeterstand onder de ingestelde ondergrens komt en gaat uit als de potmeter weer boven die ondergrens komt.
Voor de rode LED geldt hetzelfde, alleen dan voor de zojuist ingestelde bovengrens.

 
De werking van het hoofdprogramma:
Eerst wordt de tekst op het display gezet.
Dan komt er een REPEAT ... UNTIL lus.
Deze lus herhaalt (= repeat) continu de meting van de potmeter en stopt het resultaat van die meting steeds weer in de variabele 'OnderGrens' zodat deze steeds de actuele instelling van de potmeter bevat.
Tevens wordt daarbij die actuele waarde van 'OnderGrens' op het display weergegeven.
De herhalingslus gaat zo continu door, totdat schakelaar S1 laag is (= until S1 = LAAG).
Als dat gebeurd dan is er blijkbaar op S1 gedrukt en springt het programma uit zijn REPEAT ... UNTIL lus.

Dan volgt er een vertraging van 25 milliseconden tegen contactdender (zie cursus deel 3).
Die is nodig omdat zodadelijk S1 opnieuw wordt ingelezen, om te kijken of de toets wordt losgelaten.
Als er contactdender optreedt dan heb je kans dat de PIC dat ziet alsof de toets is losgelaten (wat dus niet zo is maar alleen maar contactdender is).

Daarna wacht het programma dus met WHILE S1 = Laag : WEND  tot de gebruiker toets S1 los heeft gelaten.
Dit moet, want als deze regel er niet stond, dan zou de REPEAT ... UNTIL van de BovenGrens (zodadelijk) meteen een ingedrukte toets zien (dat zou dan dus nog die toetsindruk voor het bevestigen van de ondergrens zijn) en dan zou je de bovengrens nooit in kunnen stellen.
Nu moet de gebruiker toets S1 wel eerst loslaten, anders loopt het programma niet verder.

Let wel, de variabele 'OnderGrens' heeft nu nog steeds de waarde van de laatst gemeten potmeter instelling bij zich.

Zodra S1 wordt losgelaten loopt het programma verder en wordt in de tekst op het display "onder" vervangen door "boven", terwijl de overige tekst blijft staan zoals het staat, want die is verder hetzelfde.
Dit kan mooi omdat "onder" en "boven" allebei uit 5 karakters bestaan, "boven" schrijft dus over "onder" heen.

Dan opnieuw een REPEAT ... UNTIL lus, alleen nu voor de variabele 'BovenGrens'.
Ook deze lus meet continu de potmeter instelling, totdat uit deze lus wordt gesprongen.
Echter, deze lus wordt alleen beëindigd als aan 2 voorwaarden is voldaan.
Allereerst moet natuurlijk S1 ingedrukt zijn, maar nu moet ook de waarde van variabele 'BovenGrens' groter zijn dan de variabele 'OnderGrens'.
Dit wordt bereikt met: UNTIL S1 = LAAG AND BovenGrens > OnderGrens.
Als niet aan deze twee voorwaarden is voldaan, dan blijft het programma rondlopen in deze REPEAT ... UNTIL lus.
Anders gezegd; het programma springt pas uit de lus als beide beweringen waar (= TRUE) zijn.

Nu hoeft er geen wachttijd tegen contactdender te komen omdat S1 verderop toch niet meer wordt bekeken.

Nadat uit de laatste REPEAT ... UNTIL lus is gesprongen heeft de variabele 'OnderGrens' dus nog steeds de waarde van de allereerste potmeterinstelling, en de variabele 'BovenGrens' de waarde van de tweede instelling en waarvan we zeker weten dat deze groter is dan de waarde van 'OnderGrens'.

Nog net voordat we in de vaste lus komen (WHILE 1 = 1) wordt het instellingsscherm nog gewist van het display.

Ook in deze WHILE 1 = 1 ... WEND lus wordt continu de potmeter instelling gemeten maar nu wordt de gemeten waarde steeds in de variabele 'Weerstand' gestopt.
Steeds na iedere potmeter meting wordt eerst de actuele stand op het display gezet.

Daarna wordt bekeken of 'Weerstand' groter is dan ( > ) 'BovenGrens', die we dus eerder hebben ingesteld.
Zo ja, dan de groene LED uitzetten (mocht die aan staan) en de rode LED aanzetten.
Zo nee, dan wordt bekeken of 'Weerstand' misschien kleiner is dan ( < ) 'OnderGrens'.
Zo ja, dan de groene LED aanzetten en de rode LED uitzetten (mocht die aan staan).
Zo nee, dan moeten beide LED's uit zijn.

En dan staat er nog WEND, dus weer terugkeren naar WHILE 1 = 1, zodoende loopt het programma altijd door in deze lus (als het moet jarenlang).


Tot slot een variant van bovenstaand programma, alleen nu met maar 1 LED.
De werking is vrijwel hetzelfde als bovenstaand programma.
De rode LED gaat aan als de potmeter boven de ingestelde bovengrens komt maar gaat pas weer uit als de potmeter onder de ingestelde ondergrens komt.
Het gebied dat tussen de LED aan en de LED uit zit, wordt hysteresis genoemd.

DEVICE 16F628A                ;Gebruik een 16F628A type
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
ALL_DIGITAL TRUE              ;Alle ingangen digitaal

;Logische constanten
SYMBOL HOOG         = 1       ;Een hoog signaal is hetzelfde als een '1'
SYMBOL LAAG         = 0       ;Een laag signaal is hetzelfde als een '0'
SYMBOL OFF          = 0
SYMBOL ON           = 1

;Algemene constanten
SYMBOL AntiDender   = 25      ;mSec, tegen contactdender van toetsen
SYMBOL Schaal       = ???     ;<<<<< DE WAARDE VAN Schaal VOOR DE POT FUNCTIE HIER INVULLEN

;Poortnamen
SYMBOL Potmeter     = PORTA.1 ;Potmeter aangesloten via een condensator aan GND
SYMBOL LED_Rood     = PORTA.3 ;Brandt als potmeter boven een in te stellen niveau komt
SYMBOL S1           = PORTB.0 ;Toets om grenswaarden van instelling potmeter vast te leggen

;Variabelen declareren
DIM BovenGrens      AS BYTE   ;Bevat de bovengrenswaarde waarop de rode LED aangaat
DIM OnderGrens      AS BYTE   ;Bevat de ondergrenswaarde waarop de rode LED uitgaat
DIM Weerstand       AS BYTE   ;Bevat de gemeten weerstandswaarde van de potmeter

;        76543210
PORTA = %00000000             ;Alle PORTA uitgangen uit (laag maken)
TRISA = %11110111             ;PORTA.3 omschakelen als uitgang voor de rode LED

PORTB_PULLUPS ON              ;On-chip pull-up weerstanden actief (voor S1)
CLEAR                         ;Wis alle RAM geheugen
DELAYMS 500                   ;LCD stabilisering


;Hoofdprogramma
CLS                                     ;Wis LCD scherm
PRINT          "Stel ondergrens"        ;Plaats tekst op het LCD
PRINT AT 2, 1, "Druk op S1"

REPEAT
  OnderGrens = POT Potmeter, Schaal     ;Geef nieuw gemeten waarde aan 'OnderGrens'
  PRINT AT 2, 13, DEC OnderGrens, "  "  ;Geef potmeterinstelling rechtsonder op LCD weer
UNTIL S1 = LAAG                         ;Ondergrens is in te stellen totdat S1 is ingedrukt 

DELAYMS AntiDender                      ;Tegen contactdender van S1
WHILE S1 = LAAG : WEND                  ;Wacht tot toets is losgelaten (Zolang S1 laag is...)

PRINT AT 1, 6, "boven"                  ;Wijzig tekst op LCD 'onder'grens in 'boven'grens

REPEAT
  BovenGrens = POT Potmeter, Schaal     ;Geef nieuw gemeten waarde aan 'BovenGrens'
  PRINT AT 2, 13, DEC BovenGrens, "  "  ;Geef potmeterinstelling rechtsonder op LCD weer
UNTIL S1 = LAAG AND BovenGrens > OnderGrens ;Wacht op S1 EN bovengrens moet > de ondergrens

CLS                                     ;Wis LCD scherm
PRINT "Potmeter:"

WHILE 1 = 1                             ;Programma continu uitvoeren
  Weerstand = POT Potmeter, Schaal      ;Geef nieuw gemeten waarde aan 'Weerstand'
  PRINT AT 1, 11, DEC Weerstand, "  "   ;Zet actuele stand van 'Weerstand' op eerste regel

  IF Weerstand > BovenGrens THEN        ;Als potmeter boven de bovengrens komt dan...
    LED_Rood  = ON                      ;Rode LED aanzetten
  ELSEIF Weerstand < OnderGrens THEN    ;...anders, als potmeter onder ondergrens komt dan...
    LED_Rood  = OFF                     ;Rode LED uitzetten
  ENDIF
WEND

END                                     ;Einde programma

 


 
LDR, (dag)licht afhankelijk weerstand
Een LDR is een lichtgevoelige weerstand, hoe meer licht, hoe minder weerstand.
Als het dus pikdonker is, is de weerstand heel hoog en laat de LDR vrijwel geen stroom door.
Met behulp van een LDR kun je dus een programma maken dat lampen inschakelt als de weerstand boven een bepaalde waarde komt of luxaflex automatisch laten sluiten als de weerstand onder een bepaalt niveau komt.

Alle bovenstaande voorbeeldprogramma's werken ook met een LDR in plaats van met een potmeter.
Als de LDR door een gloeilamp of TL wordt verlicht in plaats van gewoon daglicht, moet je er rekening mee houden dat de weerstand niet mooi stabiel is (hysteresis in je programma bouwen).
Dit komt omdat (TL) lampen 100x per seconde knipperen (230V netfrequentie van 50Hz), dus de ene keer meet de LDR iets meer licht dan een andere keer.
Daglicht is wel mooi stabiel.
Door een DELAYMS van bijvoorbeeld 400 milliseconden ergens tussen de WHILE 1 = 1 en WEND lus te plaatsen is de meting al niet zo zenuwachtig meer omdat dan maar om de 0,4 seconde een meting gebeurt.

Ook moet je een hysteresis in je programma bouwen zoals in het laatste potmeter voorbeeldprogramma.
Onder een bepaalt niveau gaat de LED dan aan, maar als de LED dan eenmaal aan is, moet het niveau eerst een stuk hoger zijn, voordat de LED weer uit gaat, dit wordt hysteresis genoemd.
Dit voorkomt dat de LED (of lampen, of luxaflex) de hele tijd staat te wisselen tussen aan en uit als het lichtniveau rond het schakelniveau is.
 

De waarde voor Schaal
Als een LDR pikdonker is dan hebben de meeste types (niet alle) een bijna oneindig hoge weerstand.
Om het programma niet in de war te sturen moet er een weerstand van 22k parallel over de LDR komen.
Hierdoor is de maximale weerstand als het donker is 22k.
Laat de waarde voor Schaal bepalen samen met die 22k weerstand als de LDR donker is (afdekken met zwart isolatieband).
Er zit overigens veel verschil tussen de diverse types LDR's.
Een beetje experimenteren met de waarde van de weerstand en de waarde voor Schaal is hier dus nodig.

DEVICE 16F628A                ;Gebruik een 16F628A type
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
ALL_DIGITAL TRUE              ;Alle ingangen digitaal

;Logische constanten
SYMBOL OFF          = 0
SYMBOL ON           = 1

;Algemene constanten
SYMBOL BovenGrens   = 200     ;De bovengrens waarop de rode LED aan schakelt (LDR donker) 
SYMBOL OnderGrens   = 100     ;De ondergrens waarop de rode LED uit schakelt
SYMBOL Schaal       = ???     ;<<<<< DE WAARDE VAN Schaal VOOR DE POT FUNCTIE HIER INVULLEN 

;Poortnamen
SYMBOL LDR          = PORTA.1 ;LDR aangesloten via een condensator aan GND
SYMBOL LED_Rood     = PORTA.3 ;Brandt als LDR boven een in te stellen niveau komt

;Variabele declareren
DIM Weerstand       AS BYTE   ;Bevat de gemeten weerstandswaarde van de LDR

;        76543210
PORTA = %00000000             ;Alle PORTA uitgangen uit (laag maken)
TRISA = %11110111             ;PORTA.3 omschakelen als uitgang voor de rode LED

CLEAR                         ;Wis alle RAM geheugen
DELAYMS 500                   ;LCD stabilisering


;Hoofdprogramma
CLS                                   ;Wis LCD scherm
PRINT "LDR:"

WHILE 1 = 1                           ;Programma continu uitvoeren
  Weerstand = POT LDR, Schaal         ;Geef nieuw gemeten waarde aan 'Weerstand'
  PRINT AT 1, 6, DEC Weerstand, "  "  ;Zet actuele stand van 'Weerstand' op eerste regel

  IF Weerstand >= BovenGrens THEN     ;Als LDR boven de bovengrens komt dan...
    LED_Rood  = ON                    ;Rode LED aanzetten
  ELSEIF Weerstand <= OnderGrens THEN ;...anders, als LDR onder de ondergrens komt dan...
    LED_Rood  = OFF                   ;Rode LED uitzetten
  ENDIF

  DELAYMS 400                         ;Om de 0,4 seconde lichtsterkte van LDR opmeten
WEND

END                                   ;Einde programma

In dit programma is de instelling niet van buitenaf in te stellen maar zijn de waarden voor OnderGrens en BovenGrens in het programma vastgelegd, als je die wilt wijzigen moet je dat dus zelf eerst in het programma zelf wijzigen.
In het voorbeeld gaat de LED branden als de LDR donkerder dan 200 is en gaat pas weer uit als de LDR lichter dan 100 is.

Denk eraan, als je iets bouwt met een LDR, dat de LDR niet in het geregelde lichtbereik zit.
Dus plaats de LDR buiten het licht van de lamp die hij schakelt.
Want anders denkt de PIC: Het is donker dus de lamp aanzetten.
De LDR zou dan door de lamp verlicht worden en de PIC denkt: Het is licht dus de lamp kan uit.
De LDR wordt weer donker en de PIC denkt: Het is donker dus... enz.
Het resultaat is dat de lamp de hele tijd staat te knipperen.


NTC en PTC, temperatuurafhankelijke weerstanden

Een NTC is een temperatuurafhankelijke weerstand, hoe hoger de temperatuur, hoe lager de weerstand.
Een PTC doet dat net andersom, dus hoe hoger de temperatuur, des te hoger ook de weerstand.
Ze zijn handig als temperatuursensor voor een thermostaat, bijvoorbeeld als koelplaat bewaking.
Als de temperatuur van een koellichaam dan boven een bepaalde temperatuur uitkomt kan het betreffende apparaat worden uitgeschakeld, een rode LED gaan branden, er kan een alarm afgaan of een ventilator worden ingeschakeld.

De weerstandswaarde van een NTC en PTC is gebaseerd op de weerstand bij 25°C.
Een NTC van 10k bijvoorbeeld heeft bij 25°C dus een weerstand van 10k, bij een hogere temperatuur is de weerstand lager dan 10k en bij een lagere temperatuur is de weerstand hoger dan 10k.

Sluit voor het volgende voorbeeld een NTC van 10k aan op PORTA.0 en via een condensator aan GND (zie schema).

In het thermostaatprogramma hieronder worden 2 weerstanden met elkaar vergeleken, namelijk een NTC en een potmeter.
Met de potmeter is het schakelpunt van de thermostaat in te stellen wanneer de rode LED moet gaan branden.
De rode LED gaat branden als de temperatuur boven de potmeterinstelling is gekomen.
Ook al gaat de temperatuur weer omlaag, dan blijft de rode LED branden totdat er op de reset druktoets (aangesloten op PORTB.0) wordt gedrukt.
Is de temperatuur echter nog niet laag genoeg dan doet de resettoets niets en blijft de rode LED branden.

DEVICE 16F628A                ;Gebruik een 16F628A type
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
ALL_DIGITAL TRUE              ;Alle ingangen digitaal

;Logische constanten
SYMBOL AAN          = 0       ;Geinverteerd AAN
SYMBOL OFF          = 0       ;UIT
SYMBOL ON           = 1       ;AAN

;Algemene constanten
SYMBOL Schaal       = ???     ;<<<<< DE WAARDE VAN Schaal VOOR DE POT FUNCTIE HIER INVULLEN 

;Poortnamen
SYMBOL NTC          = PORTA.0 ;10k NTC aangesloten via een condensator aan GND
SYMBOL Potmeter     = PORTA.1 ;Potmeter voor het instellen van de thermostaat
SYMBOL LED_Rood     = PORTA.3 ;Rode LED brandt als temperatuur van NTC te hoog is 
SYMBOL ResetToets   = PORTB.0 ;Hiermee is LED weer uit te zetten (als temp. laag genoeg is)

;        76543210
PORTA = %00000000             ;Alle PORTA uitgangen uit (laag)
TRISA = %11110111             ;PORTA.3 omschakelen als uitgang voor de rode LED

PORTB_PULLUPS ON              ;On-chip pull-up weerstanden actief (voor S1)
CLEAR                         ;Wis alle RAM geheugen


;Hoofdprogramma
WHILE 1 = 1                   ;Oneindige lus
  IF POT NTC, 255 < POT Potmeter, Schaal THEN ;Als temp. hoger is dan de potmeter instelling 
    LED_Rood = ON             ;LED aanzetten
  ELSEIF ResetToets = AAN THEN;...anders, als er op reset wordt gedrukt
    LED_Rood = OFF            ;de LED uitzetten 
  ENDIF
WEND                          ;Terug naar WHILE

END                           ;Einde programma

Aangezien dit programma zonder display werkt moet het als volgt worden ingesteld:
Draai aan de potmeter totdat de rode LED gaat branden.
Draai de potmeter iets terug en druk op S1 zodat de LED uitgaat.
Mocht de LED niet uitgaan, dan de potmeter nog iets verder terugdraaien en opnieuw de resettoets indrukken.
Het is ook mogelijk om S1 ingedrukt te houden terwijl de potmeter wordt ingesteld.

Als de NTC nu wordt opgewarmd gaat de LED bij een bepaalde temperatuur branden (en blijft dus branden totdat de gebruiker op de resettoets drukt).
Let op, om temperatuurverschillen te maken moet je een föhn (of punt van soldeerbout) gebruiken om de NTC te verwarmen.
Even met de hand beet pakken om hem warm te maken kan de meting verstoren, vooral als je daarbij de draden van de NTC aanraakt, misschien zou warme adem wel kunnen.


Het volgende programma is een soort centraleverwarming thermostaat.
Met de potmeter is een temperatuur in te stellen die op het display wordt weergegeven.
Als er een aantal seconden niet aan de potmeter wordt gedraaid dan verdwijnt de instelling van het display en komt de actuele NTC temperatuur er voor in de plaats.
Zodra er weer aan de potmeter wordt gedraaid, is de instelling weer zichtbaar.
De LED gaat aan zodra de temperatuur van de NTC onder de met de potmeter ingestelde waarde komt.

DEVICE 16F628A                ;Gebruik een 16F628A type
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
ALL_DIGITAL TRUE              ;Alle ingangen digitaal

;Logische constanten
SYMBOL OFF          = 0       ;UIT
SYMBOL ON           = 1       ;AAN

;Algemene constanten
SYMBOL Hysteresis   = 5       ;Het verschil van temperatuur tussen aan en uit van de LED
SYMBOL MaxTijd      = 50      ;Tijd in perioden voordat display naar NTC temperatuur gaat 
SYMBOL Schaal       = ???     ;<<<<< DE WAARDE VAN Schaal VOOR DE POT FUNCTIE HIER INVULLEN

;Poortnamen
SYMBOL NTC_Poort    = PORTA.0 ;10k NTC aangesloten via een condensator aan GND
SYMBOL Potmeter     = PORTA.1 ;Potmeter voor het instellen van de thermostaat
SYMBOL LED_Rood     = PORTA.3 ;Brandt als temperatuur van NTC onder potmeterinstelling komt

DIM Instelling      AS BYTE   ;Bevat de ingestelde temperatuur
DIM InstellingPot   AS BYTE   ;Bevat de actuele potmeterstand instelling
DIM NTC             AS BYTE   ;Bevat de NTC temperatuur waarde
DIM Tijd            AS BYTE   ;Bevat lopende tijd dat potinstelling zichtbaar is op het LCD
DIM BD1             AS BYTE   ;Byte Dummy 1

;        76543210
PORTA = %00000000             ;Alle PORTA uitgangen uit (laag maken)
TRISA = %11110111             ;PORTA.3 omschakelen als uitgang voor de rode LED

PORTB_PULLUPS ON              ;On-chip pull-up weerstanden actief (voor S1)
CLEAR                         ;Wis alle RAM geheugen
DELAYMS 500                   ;LCD stabilisering


;Hoofdprogramma
CLS                           ;Wis display
WHILE 1 = 1                   ;Oneindige lus

;*** Potmeter instelling
  InstellingPot = (POT Potmeter, Schaal) - Hysteresis

  BD1 = ABS (InstellingPot - Instelling) ;Verschil tussen instelling en actuele potmeter
  IF BD1 > 3 OR Tijd > 0 THEN ;Als het verschil > 3 OF als de tijd loopt dan...
    IF Instelling <> InstellingPot THEN Tijd = MaxTijd ;Als potmeter is gewijzigd tijd op max.
    Instelling = InstellingPot;Maak variabele 'Instelling' weer up-to-date met potmeter
  ENDIF

;*** Display weergave
  IF Tijd > 0 THEN            ;Als tijd nog niet voorbij is dan...
    DEC Tijd                  ;Tijd terugtellen
    PRINT AT 1, 1, " Instelling:", DEC Instelling, "  " ;Zet insteltemp op display
  ELSE                        ;...anders... (loopt er geen tijd (Tijd = 0))
    NTC = 255 - POT NTC_poort, 255 ;Meet NTC temperatuur (en inverteer het door 255 - POT...)
    PRINT AT 1, 1, "Temperatuur:", DEC NTC, "  " ;Zet actuele temperatuur op display

;*** Thermostaat
    IF NTC < Instelling THEN  ;Als temperatuur lager is dan instelling dan...
      LED_Rood = ON           ;LED aan
    ELSEIF NTC > (Instelling + Hysteresis) THEN ;anders, als temp.hoger is dan instelling
      LED_Rood = OFF          ;LED uit
    ENDIF
  ENDIF

  DELAYMS 100                 ;Anders is 'Tijd' wel heel snel 0
WEND                          ;Terug naar WHILE

END                           ;Einde programma

Er zit een hysteresis in de potmeter ingebouwd.
Dit houdt in dat het verschil in de potmeterwaarde groter moet zijn dan 3 voordat naar de instelweergave van het display wordt gegaan.
Gebeurt dit dan wordt de tijd op MaxTijd gezet (50).
Nu is het mogelijk om de temperatuur in te stellen.
Zolang de tijd loopt zal diezelfde tijd steeds bij de geringste verandering van de potmeter instelling (ook als die verandering nu kleiner is dan 3) opnieuw op MaxTijd (50) worden gezet.
Blijft de potmeter echter de hele lopende tijd hetzelfde (potmeter in rust dus) dan wordt teruggeschakeld naar de NTC temperatuur weergave.
Nu moet de verandering aan de potmeter eerst weer groter zijn dan 3 voordat de instelling weer op het display komt.

De hysteresis van de potmeter is nodig omdat de potmeter tussen 2 waarden kan staan.
Hierdoor staat de potmeter constant te springen tussen bijvoorbeeld 99 en 100.
Als de hysteresis er niet zou zijn dan zou iedere keer de instelling weer op het display verschijnen, terwijl er dus niet aan de potmeter werd gedraaid.
Een hysteresis van 2 zou dus voldoende kunnen zijn, maar voor de zekerheid is die op 3 gezet.

Genoemde hysteresis van de potmeter wordt berekent met de functie ABS.
ABS maakt van een getal een absoluut getal.
Dat betekent dat als een getal onder 0 komt, deze toch positief wordt weergegeven.
Hiervoor is de berekening BD1 = ABS (InstellingPot - Instelling).
'Instelling' bevat de huidige temperatuurinstelling die met de potmeter is ingesteld.
'InstellingPot' bevat continu de actuele potmeter instelling.
Stel dat 'Instelling' is ingesteld op 100.
Als de potmeter nu hoger wordt gedraaid naar bijvoorbeeld 110 dan krijg je 110 − 100 = 10.
Echter, als de potmeter lager wordt gedraaid naar bijvoorbeeld 85, dan krijg je 85 − 100 = −15.
Een negatief getal dus, een BYTE variabele zal de (ogenschijnlijk willekeurige) waarde van 240 krijgen omdat dat de uitkomst van 255 − 15 is.
Door voor de berekening nu ABS te zetten maakt deze instructie er een absoluut getal van, dat wil zeggen, altijd een positief getal.
Dus ABS (110 − 100) = 10 en ABS (85 − 100) = 15.

De uitkomst van deze berekening wordt in een zogenaamde dummy variabele (met de naam BD1) gezet.
Dit is nodig omdat het niet mogelijk is de functie ABS rechtstreeks in de IF...THEN te zetten.
Een dummy is een (gewone) variabele waar je de uitkomst van de ABS berekening even inparkeert, om het de volgende regel er weer uit te halen.

Nu we zeker weten dat BD1 een positief getal is kunnen we schrijven:
IF BD1 > 3 THEN... wat dus betekent, als het verschil tussen 'InstellingPot' en 'Instelling' groter is dan 3, dan...

Omdat een NTC een Negatief Temperatuur Coëfficiënt heeft, daalt de weerstandswaarde als de temperatuur stijgt.
Daarom wordt de gemeten waarde van de NTC eerst geïnverteerd (= omgekeerd).
Dit kun je doen door de gemeten waarde van 255 af te halen.
Hierdoor stijgt de waarde op het display als de temperatuur stijgt, wat veel logischer is natuurlijk.

Ook de thermostaat heeft een hysteresis.
De hysteresis van de thermostaat is hier ingesteld op 5.
Stel dat je de potmeter op 100 hebt ingesteld.
Dat betekent dat de LED (symbool voor de verwarming) aan gaat als de NTC temperatuur onder de 100 komt.
Nu moet de NTC temperatuur eerst 105 (= 100 + 5) zijn, voordat de LED weer uit gaat.
Als er namelijk geen hysteresis is ingebouwd dan staat de LED de hele tijd bij 100 te knipperen als de NTC balanceert tussen 99 en 100, de hysteresis voorkomt dit.

De thermostaat werkt niet als de gebruiker aan de potmeter zit te draaien, maar werkt alleen als de NTC temperatuur op het display wordt weergegeven omdat deze in het blokje ELSE van de displayweergave staat.
Als de LED aan was blijft deze tijdens instellen dus aan en datzelfde geldt voor de LED als deze uit is.
Dit is expres zo gedaan, anders zou je bij het verdraaien van de potmeter ook de thermostaat aan/uit kunnen zetten.
Nu gaat de thermostaat pas werken als de gebruiker klaar is met instellen, oftewel als de potmeter een paar seconden in rust is.

De temperatuur is natuurlijk nog niet weergegeven in graden Celsius, dat gaat te ver voor dit voorbeeld.
De voorbeelden hier gaan immers over de verwerking van een potmeter en een NTC in een programma.
Om de weergave in Celsius te krijgen zul je de gemeten waarden moeten omrekenen naar Celsius via een kleine formule.


Programma's kunnen natuurlijk kleiner zijn voor dit soort schakelingen omdat een display vaak niet nodig is en daardoor de CLS en PRINT instructies ook kunnen vervallen.
Maar voor het opzetten, experimenteren, afregelen en testen van een nieuwe schakeling met potmeter, LDR en/of NTC/PTC is een display eigenlijk onmisbaar.

Voor echt nauwkeurige metingen is een PIC met een ingebouwde ADC (= analoog naar digitaal omzetter) nodig omdat metingen met een condensator niet echt nauwkeurig zijn, door o.a. temperatuurschommelingen.
Helaas zit er geen ADC in een PIC16F628(A).
Het is dus afhankelijk van de toepassing of de functie POT goed genoeg is.
Een functie die stabieler, maar lastiger te programmeren is dan POT is RCIN.

 


RCIN

RCIN (R van Resistor (= weerstand), C van Capacitor (= condensator) IN van input).

De syntaxis
Variabele = RCIN pin, toestand

De functie RCIN meet hoelang de opgegeven pin in de opgegeven toestand (hoog of laag) blijft, meestal is dat het meten van het laden of ontladen van een weerstand/condensator (RC) schakeling.

 
pin - Is een Port.Pin constante die aangeeft op welke poort de variabele weerstand is aangesloten, bijvoorbeeld PORTA.1.
De pin wordt tijdens het uitvoeren van RCIN, automatisch als ingang ingesteld.
toestand - Is een variabele of een constante (0 of 1, LOW of HIGH) die de RCIN meting beëindigd.
Dus stel dat HIGH (= hoog) is opgegeven, dan stopt de meting zodra pin niet meer hoog is en wordt de teller gestopt en de stand van dat moment aan Variabele gegeven.
Variabele - Een variabele waarin de tijdsmeting wordt opgeslagen.
Hierin komt de tellerstand (0 ... 65535), afhankelijk van de gemeten weerstand.
Let er op dat je hiervoor een WORD variabele neemt, want de waarde eindigt niet bij 255, maar kan doortellen t/m 65535.

 
Ten opzichte van de functie POT is de functie RCIN wat lastiger te programmeren, maar dat komt ook omdat je met RCIN meer kunt doen (pulsbreedte meting).
En ook lastig is dat er een extra weerstand nodig is om kortsluiting te voorkomen.
Voordelen zijn de hogere resolutie en dat RCIN stabieler is dan POT.
Dat komt omdat RCIN de oplaadtijd van de condensator meet en POT de ontladingstijd.
Let op, het is met RCIN ook mogelijk om de ontladingstijd te meten.
RCIN kan dus zowel de op- als de ontlaadtijd meten, POT alleen de ontladingstijd.

Het omslagpunt dat een signaal op een ingangspoort van een PIC als laag of hoog wordt gezien ligt rond de 1,5 volt.
Onder de 1,5V wordt een signaal dus als laag gezien, boven de 1,5V als hoog.
Figuur B verdient de voorkeur want bij het starten van een meting is het signaal daar 5V en zakt tot aan 1,5V (een verschil van 3,5V dus) voordat RCIN stopt.
Met het schema uit figuur A start de meting bij 0V en stijgt tot aan 1,5V (een verschil van maar 1,5V) voordat RCIN stopt.
Voor dezelfde weerstand en condensator combinatie zal het schema van figuur B een hogere tellerstand opleveren en dus een hogere resolutie hebben dan figuur A.

Voor schema figuur A moet je in je Basic programma voor toestand een 0 (of LOW) invullen en voor figuur B, die de voorkeur heeft, moet je een 1 (of HIGH) voor toestand invullen, bijvoorbeeld: Variabele = RCIN PORTA.1, 1 (of Variabele = RCIN PORTA.1, HIGH, wat precies hetzelfde doet).
We gaan hier in de voorbeelden steeds van figuur B uit.

Sluit eerst de potmeter en condensator aan volgens bovenstaand schema.
Vergeet de 220Ω (= 220E) weerstand niet!

DEVICE 16F628A                ;Gebruik een 16F628A type
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
ALL_DIGITAL TRUE              ;Alle ingangen digitaal

CLEAR                         ;Wis alle RAM geheugen
DELAYMS 500                   ;LCD stabilisering

CLS                           ;LCD scherm wissen
WHILE 1 = 1                   ;Oneindig door blijven meten
  HIGH PORTA.1                ;Condensator ontladen
  DELAYMS 1                   ;Even wachten zodat condensator helemaal leeg is 
  PRINT AT 1, 1, DEC RCIN PORTA.1, HIGH, " " ;Zet RC oplaadtijd op het display
WEND                          ;Terug naar WHILE

END                           ;Einde programma

Het bovenstaande programma laat op het display een waarde zien van 0 ... max.65535, afhankelijk van de stand van de potmeter.
Als er aan de potmeter wordt gedraaid verandert de waarde mee.
De functie RCIN is hier rechtstreeks in de instructie PRINT geschreven.
Waarschijnlijk zal de maximale waarde met een 25k potmeter rond de 300 ... 400 liggen.

Vanaf zulke waarden moet je eigenlijk een meerslagen (= multiturn) potmeter hebben omdat de resolutie nu zo fijn verdeelt wordt over de potmeter, dat de fijnafregeling een probleem wordt.
Een meerslagen potmeter (bijvoorbeeld een 15-slagen balktrimmer) is een potmeter waarvan je de as meer dan eens kunt verdraaien waardoor de fijnafstelling veel makkelijker gaat.
Het gele blokje (de loper) in de balktrimmer (zie foto) schuift langzaam over een weerstandsbaan als je aan de draadspindel draait.

Bij RCIN moet je zelf zorgen voor het op- of ontladen van de condensator (bij POT gebeurt dit automatisch).
Met de functie RCIN kun je namelijk nog meer doen dan alleen een weerstand meten en dan zou het automatisch laden alleen maar in de weg zitten.
Bovendien kun je zo zelf de op- of ontlaadtijd bepalen, bij POT is dat een vaste tijd van 10 milliseconden.

In bovenstaand programma wordt de condensator eerst volledig ontladen met de instructie HIGH PORTA.1, met daarachter een korte pauze van 1 milliseconde (DELAYMS 1), zodat de condensator zich helemaal kan ontladen.
HIGH maakt de opgegeven poort hoog (+5V) en aangezien de condensator ook aan de +5V hangt, staat er geen spanningsverschil over de condensator.
Normaal moet je de instructie HIGH niet gebruiken (lees hiervoor cursus deel 3), maar komt híer wél van pas.
Voordat RCIN namelijk een meting doet schakelt hij de poort van uitgang naar ingang, om te kunnen meten.
Na de meting wordt de poort als ingang achtergelaten.
HIGH zet de poort weer automatisch van ingang naar uitgang en maakt deze uitgang hoog, zodat de condensator zich ontlaadt.

Het lijkt misschien wat vreemd dat een hoog signaal de condensator ontlaadt.
Een condensator is echter geladen als er een spanningsverschil zit over beide aansluitingen.
Als op beide zijden een +5V spanning staat, is er dus geen spanningsverschil en is de condensator ontladen.

 
De werking van RCIN
Zodra RCIN wordt uitgevoerd wordt de opgegeven poort in inputmode (= als ingang) gezet en begint er een teller te lopen, terwijl RCIN de poort meet.
Omdat de +5V die er met de instructie HIGH was opgezet nu wegvalt, wordt de condensator weer via de potmeter met 0V verbonden en laadt zich hierdoor weer op.
De snelheid van het opladen is afhankelijk van de ingestelde weerstand van die potmeter.
Hoe minder weerstand, des te sneller wordt de condensator opgeladen.

De zojuist gestarte teller stopt zodra de opgegeven pin niet meer in de opgegeven toestand (0 of 1, LOW of HIGH) verkeerd.
Als pin meteen al niet in de opgegeven toestand is zodra RCIN wordt gestart, dan krijgt de Variabele de waarde 1, omdat de RCIN instructie minimaal 1 meting moet doen om dit te weten te komen (= constateren).
Wanneer pin niet van niveau is verandert als de teller de eindstand 65535 heeft bereikt, dan krijgt Variabele de waarde 0.


Het programma hieronder doet eigenlijk precies hetzelfde als het programma hierboven.
Alleen plaatst het nu de waarde eerst in een WORD variabele (met de naam 'Weerstand').
Hierdoor kun je dingen met die variabele gaan doen die afhankelijk zijn van de gemeten potmeterstand, zoals ook in de voorbeeldprogramma's van de functie POT is te zien.

DEVICE 16F628A                ;Gebruik een 16F628A type
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
ALL_DIGITAL TRUE              ;Alle ingangen digitaal

;Variabele declareren
DIM Weerstand AS WORD         ;WORD variabele, bevat straks de stand van de potmeter

CLEAR                         ;Wis alle RAM geheugen
DELAYMS 500                   ;LCD stabilisering


;Hoofdprogramma
CLS                           ;LCD scherm wissen
WHILE 1 = 1                   ;Oneindig door blijven meten
  HIGH PORTA.1                ;Condensator ontladen
  DELAYMS 1                   ;Even wachten zodat condensator helemaal leeg is
  Weerstand = RCIN PORTA.1, HIGH    ;Geef RC oplaadtijd aan WORD variabele 'Weerstand' 
  PRINT AT 1, 1, DEC Weerstand, " " ;Zet waarde van 'Weerstand' op het display
WEND                          ;Terug naar WHILE

END                           ;Einde programma

Denk eraan dat de variabele 'Weerstand' niet als BYTE maar als WORD moet worden gedeclareerd.
RCIN kan immers verder tellen dan 255, namelijk t/m 65535.

Je kunt de resolutie verhogen door een hogere potmeterwaarde (voorkeur) of condensatorwaarde te nemen, hoewel het verhogen van de condensatorwaarde de stabiliteit niet ten goede komt.
Zet over de condensator maar eens die tweede 100n condensator (parallel), zul je zien dat de waarde op het display verdubbelt.


Het volgende voorbeeld kan van pas komen als je te weinig inputpoorten (= ingangen) hebt en je gebruik maakt van pulsschakelaars zoals een toetsenbordje. 


Vergeet niet die 220k weerstand over de condensator van 100n te plaatsen, anders werkt het niet.
 

DEVICE 16F628A                ;Gebruik een 16F628A type
CONFIG INTRC_OSC_NOCLKOUT, WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF
ALL_DIGITAL TRUE              ;Alle ingangen digitaal

;Logische constanten
SYMBOL AAN          = 0       ;Geinverteerd AAN
SYMBOL OFF          = 0       ;UIT
SYMBOL ON           = 1       ;AAN

;Poortnamen
SYMBOL Toets        = PORTA.1 ;Toetsen zitten aan PORTA.1 via een weerstandsnetwerk
SYMBOL LED_Groen    = PORTA.2 ;De groene LED zit op PORTA.2 aangesloten
SYMBOL LED_Rood     = PORTA.3 ;De rode LED zit op PORTA.3 aangesloten

;Variabele declareren
DIM Weerstand AS WORD         ;WORD variabele, bevat straks waarden van de toetsindrukken 

;        76543210
PORTA = %00000000             ;Opstarten met alle PORTA uitgangen uit (laag)
TRISA = %11110011             ;PORTA.3 en PORTA.2 omschakelen als uitgang voor de LED's

CLEAR                         ;Wis alle RAM geheugen
DELAYMS 500                   ;LCD stabilisering


;Hoofdprogramma
CLS                           ;LCD scherm wissen

WHILE 1 = 1                   ;Oneindig door blijven meten
  IF Toets = AAN THEN         ;Als er op een toets wordt gedrukt dan...
    PRINT AT 1, 1, "Toets "   ;Zet het woordje 'Toets' alvast op de eerste display regel

    HIGH Toets                ;Condensator ontladen
    DELAYMS 1                 ;Even wachten zodat condensator helemaal leeg is
    Weerstand = RCIN Toets, HIGH ;Geef RC oplaadtijd aan WORD variabele 'Weerstand'

    IF Weerstand < 31 THEN       ;Toets 1 ingedrukt dan...
      LED_Groen = OFF            ;...beide LED's uit
      LED_Rood  = OFF
      PRINT "1"                  ;Zet het toetsnummer achter 'Toets' op het display
    ELSEIF Weerstand < 94  THEN  ;Toets 2 ingedrukt dan...
      LED_Groen = LED_Groen ^ 1  ;...toggle de groene LED
      PRINT "2"                  ;Zet het toetsnummer achter 'Toets' op het display
    ELSEIF Weerstand < 159 THEN  ;Toets 3 ingedrukt dan...
      LED_Rood  = LED_Rood ^ 1   ;...toggle de rode LED
      PRINT "3"                  ;Zet het toetsnummer achter 'Toets' op het display
    ELSEIF Weerstand < 228 THEN  ;Toets 4 ingedrukt dan...
      LED_Groen = ON             ;...beide LED's aan
      LED_Rood  = ON
      PRINT "4"                  ;Zet het toetsnummer achter 'Toets' op het display
    ELSEIF Weerstand < 300 THEN  ;Toets 5 ingedrukt dan...
      LED_Groen = ON             ;...de groene LED aanzetten
      PRINT "5"                  ;Zet het toetsnummer achter 'Toets' op het display
    ELSEIF Weerstand < 999 THEN  ;Toets 6 ingedrukt dan...
      LED_Rood  = ON             ;...de rode LED aanzetten
      PRINT "6"                  ;Zet het toetsnummer achter 'Toets' op het display
    ENDIF

    PRINT AT 2, 1, DEC5 Weerstand;Zet waarde van 'Weerstand' op regel 2 van het display

    WHILE Toets = AAN : WEND  ;Wacht hier tot toets(en) wordt losgelaten
  ENDIF
WEND                          ;Terug naar WHILE

Alle toetsen worden via 4k7 weerstanden (SIL-netwerk of SMD?) aangesloten op maar één poort (PORTA.1, met de naam 'Toets' in dit geval).
Met de functie RCIN is nu te meten welke toets is ingedrukt omdat elke toets zijn eigen weerstandswaarde heeft.
Het bovenstaand voorbeeldprogramma doet het volgende:

Toets 1: Beide LED's uitzetten.
Toets 2: Toggle de groene LED.
Toets 3: Toggle de rode LED.
Toets 4: Beide LED's aanzetten.
Toets 5: De groene LED aanzetten.
Toets 6: De rode LED aanzetten.
SIL weerstands netwerk

Het werkt als volgt:
De IF Toets = AAN THEN... zorgt ervoor dat de RCIN functie pas wordt uitgevoerd zodra één van de toetsen wordt ingedrukt.
Dit werkt alleen goed als er een (pull-up) weerstand (220k) over de condensator wordt geplaatst, zodat de poort hoog is als er geen toets is ingedrukt.
Elke toets levert z'n eigen weerstandswaarde op, wat wordt gemeten met de functie RCIN.
De waarde die RCIN aan de WORD variabele met de naam 'Weerstand' geeft gaan we daarna filteren met IF...THEN...ELSEIF.

De eerste IF kijkt of de gemeten waarde in 'Weerstand' kleiner is dan 31, zo ja, dan is toets 1 ingedrukt en worden de instructies die daarbij horen uitgevoerd (LED's uitzetten en een "1" achter het woordje "Toets" op het display zetten).
Als 'Weerstand' dus 31 of groter is, loopt het programma verder vanaf de daaropvolgende ELSEIF, en die bekijkt of 'Weerstand' misschien kleiner is dan 94, zo ja, dan is toets 2 ingedrukt en voert dan de instructies van toets 2 uit.
Zo nee, dan naar de daaropvolgende ELSEIF, enzovoort.

In mijn test opstelling gaf het display de volgende waarden aan, die bij jouw iets anders zullen zijn:

Toets 1 Toets 2 Toets 3 Toets 4 Toets 5 Toets 6
00001 00061 00125 00192 00263 00336

Op regel 1 van het display staat welke toets (Toets 1 ... 6) is ingedrukt.
Mocht het zo zijn dat het display een andere toets aangeeft dan die wordt ingedrukt, dan moet je de waarden in het programma aanpassen:

Op regel 2 van het display is te zien welke waarde aan de variabele 'Weerstand' wordt gegeven bij een toetsindruk.
Kijk welke waarde elke toetsindruk oplevert en ga precies tussen de waarden van 2 toetsen zitten.

Voorbeeld voor toets 4
Neem het gemiddelde tussen toets 4 en toets 5.
Toets 4 levert (bij mij) 192 op en toets 5 levert 263 op.
Dan krijg je dus 192 + 263 gedeeld door 2 is 227,5 (afgerond 228).
Die 228 invullen in de regel voor toets 4: ELSEIF Weerstand < 228 THEN...
Deze regel zegt: als de waarde van 'Weerstand' kleiner is dan 228, dan ... met daarachter de instructies die uitgevoerd moeten worden als toets 4 is ingedrukt.

De boven- en ondergrens moeten wel ruim worden aangehouden in verband met toleranties van de componenten.
Anders zou de schakeling misschien niet werken als er bijvoorbeeld een condensator, weerstand (of PIC!) van een ander bouwjaar (of merk) aangesloten wordt, omdat de waarden dan buiten de ingeprogrammeerde waarden kan vallen.
Daarom wordt het afgeraden om een kleinere waarde voor de weerstanden dan die 4k7 te nemen, omdat de gemeten waarden dan te dicht bij elkaar komen te liggen.

Omdat er na iedere toetsindruk wordt gewacht tot de toets weer wordt losgelaten is meteen de mogelijkheid uitgesloten dat de gebruiker meerdere toetsen tegelijk indrukt (= idiot proof).

Let op: Deze truc werkt natuurlijk alleen met pulsschakelaars (zoals een numeriek toetsenbordje of allemaal maakcontacten met functies als Start, Stop, Play, Wind, Rewind enzovoort).
Vaste "aan/uit" schakelaars zoals dipswitches zijn hiervoor ongeschikt, omdat er altijd maar 1 schakelaar tegelijk een signaal mag geven, tenzij het programma zo van opzet is dat altijd maar 1 dipswitch tegelijk is ingesteld.

Je kunt zo nog wel met een paar toetsen meer uitbouwen, 12 toetsen op 1 poort (een numeriek toetsenbordje) is zeker mogelijk.

Overigens wordt in het volgende deel van de cursus een mooiere manier beschreven om de waarde van 'Weerstand' uit te filteren, zonder al die ELSEIF commando's.


Het laatste voorbeeld stelt niet veel voor en is er alleen om aan te tonen dat de resolutie van RCIN ook afhankelijk is van de oscillatorfrequentie van de PIC.
Hiervoor heb je een kristal van 20MHz nodig.
Plaats het kristal zo dicht mogelijk bij de PIC en ook de 2 condensatoren van 22pF (zie schema).

Als een 4MHz oscillator wordt gebruikt dan wordt er om de 10 µs (= microseconden) een meting gedaan.
Is de oscillatorfrequentie 20MHz dan is de resolutie 2 µs, wat neerkomt op 500.000 metingen per seconde.
Aangezien de teller van RCIN tot maximaal 65.535 kan tellen, duurt de meting op z'n langst 132 milliseconden.
Bij een 4MHz oscillator kan de meting 5 keer zo lang duren (= 660 ms).
Het keyword XTAL heeft geen effect op RCIN, de resolutie is rechtstreeks afhankelijk van de oscillatorfrequentie.
Overigens heeft de interne oscillator van de 16F628(A) een vaste frequentie van 4MHz.
Wil je sneller meten dan moet je dus een externe oscillator nemen, bijvoorbeeld die 20MHz kristal.

Meer info over het kristal zie cursus deel 3.

Het programma is verder precies hetzelfde als het tweede voorbeeldprogramma van RCIN alleen werkt het nu niet op de interne (4MHz) oscillator, maar met een externe 20MHz oscillator (en heeft PORTA.1 nu ook de naam 'Potmeter' gekregen).
Hierdoor zul je zien dat de potmeter resolutie nu ineens 5 keer hoger is.
Was de maximale waarde eerst rond de 300, dan is nu de maximale potmeterstand rond de 1500 !
Een meerslagen potmeter is nu zeker nodig.

DEVICE 16F628A                ;Gebruik een 16F628A type
CONFIG WDT_OFF, PWRTE_ON, LVP_OFF, MCLRE_OFF, HS_OSC ;INTRC_OSC_NOCLKOUT verwijderd 
XTAL 20                       ;Kristal van 20MHz
ALL_DIGITAL TRUE              ;Alle ingangen digitaal

;Poortnamen
SYMBOL Potmeter     = PORTA.1 ;PORTA.1 heet vanaf nu 'Potmeter'

;Variabele declareren
DIM Weerstand AS WORD         ;WORD variabele, bevat straks de stand van de potmeter  

CLEAR                         ;Wis alle RAM geheugen
DELAYMS 500                   ;LCD stabilisering


;Hoofdprogramma
CLS                           ;LCD scherm wissen
WHILE 1 = 1                   ;Oneindig door blijven meten
  HIGH Potmeter               ;Condensator die aan de potmeterpoort zit ontladen
  DELAYMS 1                   ;Even wachten zodat condensator helemaal leeg is 
  Weerstand = RCIN Potmeter, HIGH   ;Geef RC oplaadtijd aan variabele 'Weerstand'
  PRINT AT 1, 1, DEC Weerstand, " " ;Zet waarde van 'Weerstand' op het display
WEND                          ;Terug naar WHILE

END                           ;Einde programma

Let op dat in de CONFIG hiervoor INTRC_OSC_NOCLKOUT is vervangen door HS_OSC.
Bovendien moet je XTAL 20 bovenin het programma zetten, anders zou de DELAYMS 500 nu ineens maar 100 milliseconden duren.
Voor de RCIN instructie zelf heeft het keyword XTAL dus geen invloed.


Als je nog meer met RCIN wilt proberen, kun je de voorbeelden van POT gebruiken.
Alleen moet je dan zelf POT vervangen voor RCIN met daarbij natuurlijk het ontladen van de condensator.
 

Tot slot
Misschien vraag je je af waarom die 220Ω weerstand ertussen zit.
Stel je voor dat de potmeter op het minimum is ingesteld (0Ω dus), dan zit die poort dus vrijwel rechtstreeks met GND verbonden.
Als je nu de condensator gaat ontladen maak je met HIGH de poort hoog (+5V), als die weerstand er niet zit dan heb je een kortsluiting!
Bovendien zorgt deze weerstand voor een lichte demping bij het ontladen van de condensator.
Altijd plaatsen dus, deze weerstand.


Voor echt nauwkeurige metingen is een PIC met een ingebouwde ADC (= analoog naar digitaal omzetter) nodig omdat metingen met een condensator niet echt nauwkeurig zijn, door o.a. temperatuurschommelingen.
Helaas zit er geen ADC in een PIC16F628(A).

 


In cursus deel 6 worden weer een paar instructies behandeld die het programmaverloop kunnen bepalen.