AD-tast

Fra Holstebro HTX Wiki
Skift til: navigering, søgning

Modulet AD-tast er lavet til at fungere i en software, hvor der konstant loopes i en menu (princippet hedder polling), hvor man venter på en tasteværdi. Den returnerede tasteværdi går fra 0 til antal taster - 1.

Hardwaren er baseret på spændingsdeling af en række ens modstande, der giver en række spændinger med lige stort interval. Når der ikke er trykket på en tast, så skal en relativ stor modstand holde spændingen nede på 0V.

Tastaturet kan laves med et frit antal taster, men får på et tidspunkt en begrænsning præcisionen af modstandene og belastningen af den store modstand der skal trække til 0.

Princip-diagram for AD-tastaturet

Som det kan se her, så er tastaturet baseret på en række ens modstande der sidder i serie, således at forsyningsspændingen opdeles i en række lige store dele. Antallet af ens modstande er det samme som antallet af taster.

Hvis der ikke er trykket på nogen tast, så vil R1 sørge for at der kommer 0V ind til PIC-benet, så AD'en kan se at der ikke er trykket på noget. Denne modstand skal være så stor, at den ikke belaster spændingsdelingen, så den bliver skæv (det er værst midt i modstandsrækken). Den skal heller ikke være så stor at der kommer problemer med læk-strømmen ud af indgangsbenet på PIC'en.

Hvis der trykkes på en tast, så kommer der en spænding ind der enten er en del af forsyningsspændingen eller selve forsyningsspændingen. Ud fra at der i definitions-filen til softwaremodulet er angivet hvor mange taster der er på tastaturet, og da modstandene i spændingsdeleren er ens, så ved softwaren hvilken spænding den skal forvente.

Med 3 taster, så vil softwaren registrere følgende niveauer:

  • fra 0V til 1/6 af forsyningen betyder at der ikke er nogen tast trykket.
  • fra 1/6 til 3/6 af forsyningen betyder det at 0-tasten er trykket ned.
  • fra 3/6 til 5/6 af forsyningen betyder det at 1-tasten er trykket ned.
  • fra 5/6 og op til forsyningen betyder det at 2-tasten er trykket ned.
Den spænding som en tast giver ud er givet ved den viste formel. Hvor Vtast er spændingen når der er trykket på tasten og N er det tal tasten giver i softwaren. Tast-formel.png
De spændinger som softwaren skelner imellem, for at se hvilken tast der er trykket på er givet ved den viste formel. Hvor Vtast-min er det laveste niveau for spændingen når der er trykket på tasten og Vtast-max er det højeste niveau for spændingen når der er trykket på tasten. N er det tal tasten giver i softwaren. Tast-l-formel.png Tast-h-formel.png


Principskitse af AD-tastaturet

Print med 12 taster

Som vist til højre, så kan diagrammet opbygges af en række ens modstande placeret i serie (R2 til R13) fra forsyningen til stel, så der kommer til at ligge lige stor spænding over alle 12 modstande.

Tasterne i diagrammet er placeret på samme måde som på printet, så de sidder som et numerisk tastatur f.x. på en telefon med 1 2 3 øverst og 0 nederst i midten, hvor 10 og 11 er placeret uden om, som så kan anvendes som en slags funktionstaster.

R1 fungerer som en pull-down modstand, og er valgt så stor, at den ikke trækker spændingsdelingen skæv.

R14 og LED1 er blot for at indikere, at der er forsyningsspænding til printet, og for at hjælpe med at vende printet rigtigt.

SV2 ligner et fladkabel-stik, men er lavet til en jumper, så printet kan anvendes universelt på 5 forskellige ben (port-pin 0 til 4), så det er fleksibelt hvilket ben i porten man vil anvende.

Tastatur Layout

Layoutet på det viste tastatur.

Board og Schematich ligger i en ZIP-fil.

Diagram over Tastatur til AD-aflæsning

Diagrammet med 12 taster, der giver fra 0 til 11

Størrelserne af modstandene er ikke så kritiske. R1 skal være meget (helst mere end 1000 gange) større end de ens modstande, og helst ikke så stor at det giver fejl med læk-strømme fra PIC'en. De ens modstande (R2 - R13) skal helst ikke over 2k2, og ikke være for små (under 100 ohm ved 12 stk), da de så trækker for meget strøm. R14 er dimensioneret til at give 5 mA i LED1, så den giver et fornuftigt lys.

Tastaturer med andre antal taster

Der er ikke umiddelbart lagt print ud til tastaturer med andre antal taster end 12 og 16, men kan i princippet lægge ud til hvilket som helst antal man ønsker. Hvis man vil bidrage til wikien, så kan man lægge sine tastaturer her, med en kort beskrivelse:

  • Print med 12 taster hvor de sidder som illustreret oven for, altså som på en telefon med # og *.
  • Print med 16 taster hvor de 12 sidder som på det 12 tasters, og de sidste 4 sidder i højre side, som på en regnemaskine.
  • Print med 30 taster hvor de sidder i en 6x5 matrix startende med 0 og op til 29.

Software modulet AD-tast.jal

Strukturen i softwaremodulet AD_tast følger den generelle struktur på software-moduler til PIC'en, der er en interface-fil med de definitioner man kan rette på, som man placerer sammen med sin egen kode, og en biblioteksfil, som man ikke behøver at rette i, men som indeholder hele funktionen (placeres i lib). I filen med softwaren er der også et simpelt testprogram, der viser anvendelsen af modulet.

Modulet anvendes efter polling princippet, der betyder at AD_tast skal kaldes ofte i softwaren (gerne mere en 50 gange i sekundet).

Normalt vil AD_tast returnere værdien AD_tast_antal, som viser at der ikke er tastet på noget.

Når der trykkes en tast ned, så vil software modulet sikre siga at det er en gyldig tast, ved at den skal læse den samme tast et antal gange, og først når det er gjort, så returnerer AD_tast værdien for tasten. Den bliver kun returneret en gang, selvom man holder tasten nede.

Anvendelse af AD-tast

Når man vil anvende AD_tast modulet, så skal man include AD-tast.jal som følger:

   include AD_tast

Hvis AD-tast.jal ligger i \lib inde i c:\jalpack så kan compileren finde modulet.

AD_tast anvender ADC_holst.jal, så den skal også ligge i \lib.

JAL-filen ligger sammen med et par eksempler inde i Fil:AD tast jal.zip

AD_tast er testet på følgende kombinationer:

PIC pin
PIC16F684 a2, a4
PIC16F690 a0[1], a1[1], a2, a4, c0, c1, c2, c3, c6[2], c7[2], b4, b5[2]

Interface fil til AD-tast

Ud over de andre filer skal der lægges en AD-tast-def.jal i den mappe hvor man har sine egne filer liggende. Denne fil definerer hvordan ens tastatur ser ud, så AD-tast er et generelt modul, der kan anvendes til mange forskellige tastaturer.

I AD-tast-def.jal angives hvor mange taster der er på tastaturet ved:

   AD_tast_antal = 12

I AD-tast-def.jal angives hvilken AD kanal der anvendes til aflæsningen:

   AD_tast_analog_kanal = 3

AD-tast modulet finder selv ud af hvilken pin der svarer til den analoge kanal, så den bliver sat op som analogt input. Man skal altså ikke sætte andet op, men man skal selvfølgelig sørge for at forbinde AD-tastaturet til den rigtige port og vælge det rigtige bennummer.

Man skal være opmærksom på at den analoge kanal ikke er det samme som ben-nummeret. På de testede PIC-kredse er sammenhængen som følger:

Pin Stik-ben Jumper-nr Analog kanal
PIC16F684
Analog kanal
PIC16F690
pin_a0 1 0 0 note[1] 0 note[1]
pin_a1 2 1 1 note[1] 1 note[1]
pin_a2 3 2 2 2
pin_a4 5 4 3 3
pin_c0 1 0 4 4
pin_c1 2 1 5 5
pin_c2 3 2 6 6
pin_c3 4 3 7 7
pin_c6 7 note[2] note[3] 8
pin_c7 8 note[2] note[3] 9
pin_b4 5 4 note[3] 10
pin_b5 6 note[2] note[3] 11
  1. 1,0 1,1 1,2 1,3 1,4 1,5 Tastaturet giver fejl på udviklingsboardet, da der er koblet ekstra modstande ind til ICSP-beskyttelse og til lysdioder. Fejlen er ikke stor ved ekstern forsyning, men den er helt gal når PICkit 2 er koblet på.
  2. 2,0 2,1 2,2 2,3 2,4 2,5 Dette ben er ikke lagt ud på det 12 tasters AD-tastatur
  3. 3,0 3,1 3,2 3,3 Denne AD-kanal eksisterer ikke på denne PIC-type

Endelig kan man indstille hvor mange ens aflæsninger i træk der skal til, for at AD-tast sender den valgte tast. Det gør man ved:

   AD_tast_ens_antal = 5

Anvendelsen af AD-tast modulet

Man skal kalde AD-tast mange gange for at få en godkendt aflæsning fra tastaturet, så det gør man i sit forever loop, hvor man sørger for at der ikke er andet der tager væsentlig tid.

Når den ikke finder en godkendt tast, så returneres der antallet af taster, så man kan se at det ikke er en godkendt tast. Hvis en tast er holdt nede, så AD-tast kan læse den det valgte antal gange, så returneres tasten EN gang med et tal der ligger fra 0 til antal taster - 1.

Et simpelt demo-eksempel kunne se ud som følger:

 portC_direction = all_output
 include AD-tast
 var tast = AD_tast_antal
 
 forever loop
   tast = AD_tast
   IF (tast < AD_tast_antal) THEN
     port_C = tast
   END IF
   --
   -- Her kan placeres anden kode i loopet, der skal lave andre ting
   --
 end loop

Programmet vil med det viste tastatur fungere sådan at det binære tal der læses ud på port C vil være den tast der er trykket på, og den vil først skifte når der trykkes på en ny tast. Tallet der læses ud vil være 0 - 11 (binært fra 0000 til 1011).

Forklaring af AD-tast software

Funktionen af softwaren går i alt sin enkelhed ud på, at angive en tasteværdi ud fra den AD-værdi der kommer fra AD-tastaturet.

Man sætter op hvilket ben tastaturet læses ind på, hvor mange taster der er og hvor mange ens læsninger der skal til før den godkender tasten.

Man kalder AD_tast mange gange, og får tasteværdien retur når den er godkendt. alle andre gange får man antallet af taster retur.

Initialisering af softwaren

I starten af modulet includes modulet ADC_holst, for at kunne anvende den indbyggede AD-konverter i PIC'en, og der includes interfacefilen med definitionerne til AD_tast, og der foretages en initialisering for at få beregnet værdierne som funktionen skal bruge.

Initialiseringen kan i Pseudokode udtrykkes som følger:

   Læs opsætningen i AD_tast_def.jal
   Konfigurer AD-referencen
   Indlæs ADC_holst, der sætter op til den rigtige PIC-type
   Opsæt variabler der gør det simpelt at udregne taste-værdien ud fra AD-tallet

Det at AD-tast anvender ADC_holst som bibliotek gør at modulet ikke umiddelbart kan anvendes på en PIC16F877,da den anvender et andet AD-converter modul adc.jal.

Funktionen AD_tast

Selve funktionen AD_tast har ingen Parametre, men den returnerer en byte, som svarer til den tast man har trykket på.

Når man skal anvende funktionen, så skal man aflæse AD_tast over i en variabel en gang i hver omgang man kører i sit hoved-loop, og så kan man teste på variablen hvad man skal gøre med sin indtastning. På den måde kan man fange alle taster, filtrere på dem med IF eller CASE strukturer, og man kan regne på dem, hvis det f.x. er tal der indtastes.

Internt i funktionen foretager den sig følgende, udtrykt som Pseudokode, hvor det er vigtigt at huske, at koden kaldes mange gange i sekundet:

   Aflæs AD-tallet
   Hvis aflæsningen er under tast 0 så
      nulstil og returner "ingen tast"
   Udregn tasteværdien ud fra AD-tallet
   Hvis det er samme tast som sidst så
      Hvis samme tast er set et bestemt antal gange så
         returner tasteværdien
      ellers 
         returner ingen tast
   ellers
      nustil
   returner ingen tast

Princippet i koden er at den bliver ved med at aflæse AD-værdien, og hvis den har beregnet den samme tast 5 gange i træk, så godkender den det som en gyldig indtastning. Alt andet vil returnere at der ikke er aflæst en tast.

Koden er lavet universel, så den kan fungere til alle forskellige antal taster fra 3 og op til 255, og det gør at den kan være lidt svær at afkode, specielt delen der bestemmer hvilken tast det er der er trykket på aktuelt.

Konstanterne i interface-filen

De to af konstanterne der ligger defineret i interface-filen er dels hardware-opsætningen, nemlig hvilken AD-kannal (og dermed hvilket ben modulet skal læse på), og dels hvor mange gange der skal læses samme værdi for at modulet returnerer tasteværdien. Disse væredier kan være defineret som:

  const byte AD_tast_analog_kanal = 2
  const byte AD_tast_ens_antal = 5

Den sidste konstant der er defineret i interfacefilen er som sådan også enkel nok:

  const byte AD_tast_antal = 12

Beregning af værdier ud fra antallet af taster

Det komplicerede ved AD_tast_antal er alle de ting der beregnes ud fra den, for at gøre beregningen af tasteværdien rimelig hurtig. Inde i modulet startes der med at definere en opløsningen på AD-konverteren til 1024, og ud fra disse to kan der beregnes hvor mange trin der er mellem hver tast:

  const word AD_tast_resolution = 1024
  const word AD_tast_step = AD_tast_resolution / AD_tast_antal

Med 12 taster bliver det til 85 i afrundet værdi (egentlig 85,33).

  elsif AD_tast_antal < 16 then
    AD_tast_start_punkt = 8 * AD_tast_resolution / AD_tast_antal
    AD_tast_start_tast = 8

Med 12 taster bliver AD_tast_start_punkt til 682, og AD_tast_start_tast sættes til 8 (de 682 er den forventede AD-afløsning på den 8. tast, der gerne skal give 7).

Disse ting skal kun beregnes en gang, altså i initialiseringen af modulet.

Koden inde i funktionen AD_tast

Det første der sker i funktionen er at AD-converteren aflæses på den fastsatte kanal, og der testes om taller er under det halve af ad-tallet for et trin (42 ved 12 taster), hvilket tolkes som at der ikke er trykket på en tast.

Herefter sættes en række variabler op til at udføre beregningen af tastens værdi, hvilket sker i en repeat-sløjfe, hvor der hele tiden halveres det område der betragtes, indtil tastens værdi er fundet. Fordelen ved denne metode er at man med op til 16 taster vil kunne finde tastens værdi på 4 gennemløb, og det vil altid tage 4 gennemløb at finde værdien.

De variabler der sættes op er følgende:

  var word AD_tast_punkt = AD_tast_start_punkt + AD_tast_step / 2
  var word AD_tast_weight = AD_tast_start_punkt
  var byte AD_tast_resultat = 0                
  var byte AD_tast_res_weight = AD_tast_start_tast

Disse variabler får værdier, der meget er baseret på den afstand der er mellem to taster, i AD-trin (85,33 ved 12 taster). AD_tast_punkt sættes til en halv tasteafstand over den 8. tast, altså 724. AD_tast_weight sættes til afstanden mellem 8 taster, altså 682. AD_tast_resultat stilles på 0, og AD_tast_res_weight sættes til 8, hvilket forholder sig til værdien i AD_tast_weight.

Det første der sker inde i repeat-sløjfen er en sammenligning mellem den aflæste AD-værdi og AD_tast_punkt som vist her:

    if AD_tast_conv > AD_tast_punkt then
      AD_tast_resultat = AD_tast_resultat + AD_tast_res_weight
    else
      AD_tast_punkt = AD_tast_punkt - AD_tast_weight
    end if

Hvis den aflæste værdi er størst, så lægger man AD_tast_res_weight til AD_tast_result (i første gennemløb ville den lægge 0 til 8).

Hvis den aflæse værdi ikke er størst, så gøres der ikke noget ved AD_tast_result, men i stedet trækkes AD_tast_weight fra AD_tast_punkt (i første gennemløb ville det blive til 724 - 682 = 42).

Efter sammenligningen beregnes det næste grundlag for sammenligningen. Det sker søm følger:

    AD_tast_res_weight = AD_tast_res_weight / 2
    AD_tast_weight = AD_tast_weight / 2 
    AD_tast_punkt = AD_tast_punkt + AD_tast_weight

I det første gennemløb bliver AD_tast_res_weight til 4 og AD_tast_weight til 341, og AD_tast_punkt afhænger af hvordan den første sammenligning gik. Hvis den aflæste AD-værdi var over, så bliver AD_tast_punkt til 1065, hvilket er et halvt taste-trin over den 12. tast, og hvis den aflæste AD-værdi var under, så bliver AD_tast_punkt til 383, hvilket er hvilket er et halvt taste-trin over den 4. tast.

Sådan fortsættes indtil løkken er løbet 4 gange igennem, og ad_tast_result har fået den korrekte værdi.

Følgende eksempel illustrerer værdiernes forløb, hvis det er den 6. taste der er trykket ned, hvilket gerne skulle give en AD-værdi på 511:

Forløbet i en løkke, hvor AD-værdien er 511
Gennemløb AD_tast_punkt AD_tast_weight AD_tast_result AD_tast_res_weight
Før 1. 724 682 0 8
Efter 1. 383 341 4 4
Efter 2. 553 170 4 2
Efter 3. 468 85 5 1
Efter 4. 510 42 5 0

Som det kan ses i forløbet, så tilnærmer AD_tast_punkt sig gradvist den aflæste AD-værdi, hvilket også har givet navn til den metode der har inspireret koden, nemlig successiv approksimation

Moduler på Holstebro HTX
Tastaturer Displays AD-konvertering I/O-ekspander Serielt Interface Færdige Andre
RC-tast - AD-tast - M_tast ALCD - LCD ADC_holst - ADC
mcp3201 - mcp3208
input - output Seriel_holst - Serial hardware
Serial hw int cts - Serial software
Stepmotor - RFID
RGB - RF-link - Afstand
Humidity - Analog temp - Dig temp
Accelerometer
Rotary Encoder

Oversigt over Hardware Moduler på Holstebro HTX