PIC 16F684 van knipperlicht naar... (pagina 5)

Terug analoog

Schema      JAL code


Tot nu toe heeft de controller enkel met digitale waarden gewerkt. Zoals vele PIC's beschikt de 16F684 ook over analoge ingangen en natuurlijk een analoog-digitaal converter (ADC).

De schakeling is uitgebreid met een potentiometer aangesloten als spanningsdeler op pen 12 (RA1/AN1)

De instellingen zijn grotendeels gelijkgebleven als bij het vorig voorbeeld, alleen zijn er enkele variabelen bijgekomen bij de instellingen voor Timer2. Deze uitbreidingen zijn er omdat we een waarschuwing willen krijgen elke 20 ms (om de ADC te lezen) en elke 400 ms (om het display te laten knipperen).

De instellingen voor de analoog-digitaal converter.
Met const bit ADC_HIGH_RESOLUTION = true geven we aan dat we de ADC in hoge resolutie willen gebruiken (10 bits dus waarden tussen 0 en 1023).
ADC_NVREF = 0 is de instelling om geen referentiespanning te gebruiken (we meten van 0 tot 5 volt).
Na het laden van de bibliotheek met de ADC instellingen/functies/procedures gaan we de ADC initialiseren en geven we aan dat we analoge ingang 1 (RA1/AN1) effectief als analoge ingang gaan gebruiken (in het begin van het programma hebben we met enable_digital_io() alle ingangen als digitaal gezet).

We declareren een variabele om de gemeten waarde op te slaan en verder te bewerken (var dword dwValue).
Die variabele vraagt wel een woordje uitleg. Tot nu toe hebben we variabelen altijd al als byte gedeclareerd. Een bytevariabele kan waarden van 0 tot 255 verwerken (8 bits - 1 byte). De ADC geeft echter een waarde tot 10 bits als resultaat en daarom hebben we een grotere variabele nodig. Een variabele van het type word zou volstaan, maar de ADC waarde willen we verder bewerken. Wanneer we bijvoorbeeld de gelezen waarde willen omzetten naar een getal tussen 0 tot 99 gebruiken we volgend trukje: (gelezen waarde * 100)/ 1024. Door in eerste instantie de gelezen waarde te vermenigvuldigen met 100 komen we tot een waarde van maximum 102300 en dat is een waarde die niet meer in een 16 bits (2 bytes) variabele past (0 tot 65535). Door gebruik te maken van een dword variabele (32 bits) kunnen we die waarde wel huisvesten.
Door de naam van de variable (Value) te laten voorafgaan door 'dw' zien we overal in het programma dat dit een dword variabele is ('w' gebruiken bij een word variabele is ook aan te raden).

  ;-------------------------------------------------------------------------------
;ADC instellingen
;-------------------------------------------------------------------------------
const bit ADC_HIGH_RESOLUTION = true
const byte ADC_NVREF = 0
;de bibliotheek laden
include adc
;De ADC initialiseren
adc_init()
;en maak pen 12 (RA1/AN1) analoge ingang
set_analog_pin(1)

var dword dwValue
 

De interruptprocedure is uitgebreid om verschillende tijdstippen door te geven aan de mainloop (20 ms -> variabele Ms20, 1 seconde -> variabele TimePassed en 400 ms -> variabele Blink).

  ;-------------------------------------------------------------------------------
;INTERRUPT PROCEDURE
;-------------------------------------------------------------------------------
procedure TimerInterrupt is
  
pragma interrupt
  
if(PIR1_TMR2IF)then
    
PIR1_TMR2IF = low
    
;20ms
    
Ms20 = 1
    
;laat dit 50 keer gebeuren voor 1 seconde
    
TimerCounter = TimerCounter - 1
    
if(TimerCounter == 0)then
      
TimerCounter = TimerCounterReload ;herlaad de teller
      
TimePassed = 1 ;tijd is verstreken
    
end if
    
;laat dit 20 keer gebeuren om te knipperen (400ms)
    
BlinkTimer = BlinkTimer - 1
    
if(BlinkTimer == 0)then
      
BlinkTimer = BlinkTimerReload
      Blink
= 1
    
end if
  end if
end procedure
 

De MainLoop is opgebouwd uit drie delen.

Deel één laat de led elke seconde knipperen.

  ;-------------------------------------------------------------------------------
forever loop
  if
(TimePassed > 0)then
    
;1 seconde is verstreken
    
TimePassed = 0 ;wis de vlag
    
Led = !Led ;zet de led aan of uit
  
end if
 

In deel twee laten we 'Hello World' knipperen.
Een ganse tekst laten knipperen wordt standaard door de LCD module niet voorzien. Software in de PIC lost dit op.
Telkens als de vlag Blink geset is (elke 400 ms) wordt er tekst op de eerste regel van het display geschreven. De ene keer is dat 'Hello World', de andere keer is dat een string gevuld met spaties die daardoor 'Hello World' overschrijft.

    ;Knipper 'Hello World'
  
if(Blink > 0)then
  
Blink = 0
  
lcd_cursor_position(0,0)
    if(TextOn > 0)then
      
TextOn = 0
      
print_string(lcd, World)
    else
      
TextOn = 1
      
print_string(lcd, ClearText)
    end if
  end if
 

De ADC wordt elke 20 ms gelezen (om een de stand van een potmeter te lezen is een leesfrequentie van 50 Hz ruim voldoende en blijft er nog ruim tijd over voor de processor om andere zaken uit te voeren).
De waarde van de ADC wordt in een variabele gelezen en omgerekend naar een waarde tussen 0 en 59. Die waarde wordt op de tweede regel van het display geschreven.
Om de waarde 'rechts uitgelijnd' op het display te krijgen, wordt een trukje toegepast: wanneer de waarde slechts 1 digit is (0-9), wordt voor de waarde een spatie geschreven. Op die manier staan de eenheden steeds op dezelfde plaats (de procedure print_ houdt geen rekening met uitlijning).

    ;we lezen de ADC niet continu, slechts om de 20 ms
  
if(Ms20 > 0)then
    
Ms20 = 0
    
dwValue = adc_read(1)
    ;De gelezen waarde is tussen 0 en 1023.
    ;We maken er een waarde tussen 0 en 59 van
    
dwValue = (dwValue * 60) / 1024
    
;en zetten het resultaat op het scherm (op de juiste positie)
    
lcd_cursor_position(1,0)
    if(dwValue < 10)then
      
lcd_write_char("0")
    end if
    
print_dword_dec(lcd, dwValue)
  end if
end loop
 

 


(pagina 4) ...PIC 16F684 van knipperlicht naar... (pagina 6)


Links

JALEdit de editor om JAL code te schrijven
JALlib de bibliotheken (en voorbeelden) en de compiler
MPLab IDE de ontwikkel- en PicProgrammeromgeving
Microchip de site van de PIC's
JalList Hulp en hopen voorbeelden