Accelerometer
Et accelerometer måler den acceleration modulet er påvirket af, også tyngdeaccelerationen.
Modulet måler i 3 akser i forhold til dens eget koordinatsystem, i en X-, Y- og Z-akse. Modulet kan således bestemme i hvilken position det ligger, hvis det ligger stille i et tyngdefelt (hvilket er normalt her på jorden), og det kan ligeledes bestemme hvorledes det accelererer i en given retning.
Princip-diagram for Accelerometer print
Modulet er baseret på en accelerometer-chip kaldet MMA7361L, der f.x. anvendes i bevægelsesfølsomme controllere som Wii samt i smartphones. Chippen arbejder på 3,3V, så der er også indbygget en 3,3V regulator på printet, der skal forsynes med 5V. De 3,3V kan hentes på en ben på printet. Man kan på benet G-select vælge om området skal være på 0-1,5g (benet sættes lavt) eller om det skal være 0-6g (benet sættes højt). De 3 accelerometersignaler for X-, Y- og Z-akse kommer ud på hvert sit ben og har i 0-1,5g området følgende typiske specifikationer: Dette er dog kun typiske værdier, og det er testet at specielt nulpunktet varierer en del. Der er yderligere 2 input, som blot skal tilsluttes høj eller lav. Sleep skal være høj for at modulet fungerer og Self-Test skal være lav. Sleep er lavet til strømbesparelse, men det giver ingen mening at anvende det, da der sidder en lysdiode på modulet. Self-Test har ikke rigtigt nogen funktion. Sidste ben er et 0-g detekterings output, der aktiveres når alle 3 akser ligger omkring 0, hvilket betyder at den befinder sig i frit fald. Outputtet anvendes til enheder man kan risikere at tabe, og hvor man kan lukke f.x. en harddisk ned, inden den rammer jorden. |
Print Accelerometer
Modulet er købt ved hjemmesiden miniinthebox.com [1]
Andre versioner af Accelerometer
Der findes flere forskellige hardware versioner, hvor nogle ikke har 3,3V regulator indbygget, hvilket kan gøre det mere besværligt at anvende modulet i forbindelse med de PIC-kredse vi anvender.
Opkobling af accelerometer
I testen er accelerometeret koblet op på følgende måde:
Forbindelse fra Port A stikket på PIC udviklingsboard til accelerometer modulet
De 3 udgange X, Y og Z forbindes til pin A0, A2 og A4.
Pin A0 er lidt problematisk på udviklingsboardet, da der sidder en modstand på 4,7 k i serie med signalet, og der belastes med 100 k til GND efter det, så der kommer ikke så meget signal ind til PIC-benet, men det viser sig at den stadig måler rimeligt lineært.
Dette er dog kun når PICkit 2 ikke er tilsluttet, for så sidder der en 4,7 k internt i PIC-brænderen, der belaser signalet langt mere. Det er i en grad så det ikke fungerer, ligeledes på grund af referencen.
Det optimale ville være at bygge et specielt board hvor der ikke var disse ekstra komponenter.
3,3 V forsyningsspændingen anvendes som reference ved at koble den til pin A1. Dette kræver også at PICkit 2 ikke er tilsluttet, da der en 4,7 k i serie med signalet og 4,7 k inde i PICkit2.
+5V og GND tuilsluttes de respektive ben.
Sleep tilsluttes +5V.
Gain-Select og Self-Test tilsluttes GND.
Det sidste ben 0-g skal svæve, da det er en udgang fra accelerometeret, med mindre man ønsker at aflæse signaler, hvor det så kan kobles til en indgang på PIC'en.
Software modulet accelero.jal
Modulet kan læse de 3 akser og returnere dem samt håndtere omregning til g-kræfter ud fra et sæt målinger på accelerometeret
Anvendelse af Accelerometeret
Når man vil anvende accelero modulet, så skal man include accelero.jal som følger:
include accelero.jal
Hvis accelero.jal ligger i \lib inde i c:\jalpack så kan compileren finde modulet.
accelero.jal anvender adc_holst.jal, så det skal også ligge i \lib.
JAL-filen ligger sammen med et par eksempler inde i Fil:Modul accelero jal.zip
accelero er testet på følgende kombinationer:
PIC | pin |
---|---|
PIC16F684 | a0, a2, a4 (a1 som reference) |
PIC16F690 | a0, a2, a4 (a1 som reference) |
Til softwaremodulet er der udviklet 3 demo-programmer: accelerometer_demo.jal, accelerometer_demo2.jal og accelerometer_demo3.jal. Alle 3 har samme pin-opsætning og anvender ALCD til visning af resultater, men accelerometer_demo3.jal kræver en PIC16F690 på grund af brugen af intern hukommelse.
accelerometer_demo.jal viser de rå X-, Y- og Z-værdier.
accelerometer_demo2.jal viser de midlede X-, Y- og Z-værdier. Der kan nulstilles med acc_calibrate ved at trykke på A3 (knap på udviklingsboard).
accelerometer_demo3.jal viser X-, Y- og Z-værdier udtrykt som g-størrelser. Der kan calibreres og nulstilles med acc_calibrate_inv ved at trykke på A3 (knap på udviklingsboard).
Interface fil til accelero
I interface-filen indstilles hvilke AD-kanaler og hvilke ben der anvendes.
Der angives antallet af værdier i midlingsarrayet, så man kan lave større eller minde antal i gennemsnitsberegningen af g-værdierne. Ved anvendelsen af acc_get_avg er der ikke noget problem med størrelsen, andet end PIC'ens hukommelse, hvilket hurtigt kan blive et problem med PIC16F684. Ved anvendelsen af acc_get_g der regner om til g-værdier, der kommer problemer når midlingsarrayet kommer over 8, da der sker et overflow i beregningen.
Der er desuden angivet standard-værdierne for nulpunkt og området.
I accelero_def.jal defineres det ved:
-- Accelerometer definitions - accelero_def.JAL
-- The AD-channels used for measyring X, Y and Z
const byte acc_X_channel = 0
const byte acc_Y_channel = 2
const byte acc_Z_channel = 3
-- And the corresponding pins
alias acc_X_dir is pin_A0_direction
alias acc_Y_dir is pin_A2_direction
alias acc_Z_dir is pin_A4_direction
-- Input to initiate a calibration
alias acc_cal_pin is pin_A3
alias acc_cal_dir is pin_A3_direction
-- Number of values in the averaging array - takes a lot of memory
-- Using values above 8 will require larger variables for g-calculation
const byte acc_arr_size = 5
-- The value for zero G - differs from each unit
var sword acc_X_zero = 452
var sword acc_Y_zero = 573
var sword acc_Z_zero = 492
var sword acc_X_range = sword (acc_arr_size) * 18
var sword acc_Y_range = sword (acc_arr_size) * 26
var sword acc_Z_range = sword (acc_arr_size) * 26
Anvendelsen af accelero.jal
Modulet til accelerometeret anvendes ved at include accelero.jal og indstille i accelero_def.jal hvilke indgange man har sluttet modulet til.
I den anvendte version bruges de 3,3V fra modulet som reference-spænding, ved at koble den spænding ind på pin A1 (RA1)
include accelero.jal
forever loop
acc_get_avg -- Aflæser X-, Y- og Z-værdier der midles ved at kalde flere gange
X = acc_X -- Anvend værdierne
Y = acc_Y -- Anvend værdierne
Z = acc_Z -- Anvend værdierne
--
-- Her kan placeres anden kode i loopet, der skal lave andre ting
--
end loop
Der ligger 3 aflæsnings-rutiner i modulet:
acc_get_raw Aflæser de 3 aktuelle læsninger og placerer dem i acc_X, acc_Y og acc_Z. Værdierne er korrigeret med nulpunktet fra definitionsfilen.
acc_get_avg Aflæser de 3 læsninger med en midling over arrayets størrelse og placerer dem i acc_X, acc_Y og acc_Z. Værdierne er korrigeret med nulpunktet fra definitionsfilen. Der lægges kun et nyt sæt aflæsninger i midlingsarrayet for hvert kald af acc_get_avg.
acc_get_g laver samme aflæsning som acc_get_avg, men den tilpasser målingerne til visning i g, ved både at korrigere nulpunktet og området ved hjælp af variablerne i accelero_def. Tallet er et heltal med en opløsning på 10mg så det er tilpasset visning med 2 decimaler.
Der ligger 2 calibrerings-rutiner i modulet:
acc_calibrate og acc_calibrate_inv virker ens, men er lavet til hhv. en knap der giver høj og en der giver lav når der trykkes på den.
Begge rutiner kræver et ALCD display for at virke.
Princippet i calibreringen er at man måler +/- 1g for alle 3 akser individuelt. Det forløber som følger:
Når man kommer ind i rutinen ventes lige på at knappen slippes, og så skriver den X-MAX og den rå AD-værdi for X-kanalen.
Man placerer så modulet i den position hvor X er på 1g, holder den stille og trykker på knappen.
Herefter skriver den X-MIN og den rå værdi for X-kanalen
Man vender så modulet om, så det er i den position hvor X er på -1g, holder den stille og trykker på knappen.
På denne måde kan modulet beregne nulpunktet som midte mellem de to aflæsninger, og range-variablen kan ligeledes beregnes, således at acc_get_g beregner den korrekte værdi ud fra målingerne.
Calibreringen fortsætter på samme måde for Y- og Z-kanalerne, så der er de korrekte værdier at beregne efter.
Forklaring af accelero software
Modulet indeholde 3 aflæsningsrutiner og 2 stort set identiske kalibreringsrutiner
Initialisering af softwaren
Initialiseringen kan i Pseudokode udtrykkes som følger:
sæt anslåede nulpunkter op sæt anslåede range-værdier op sæt indgangene op
Funktionen acc_get_raw
Funktionen aflæser de rå X-, Y- og Z-værdier korrigeret med nulpunktet.
Koden ser ud som følger:
procedure acc_get_raw is
acc_X = (sword(adc_read(acc_X_channel))) - acc_X_zero
acc_Y = (sword(adc_read(acc_Y_channel))) - acc_Y_zero
acc_Z = (sword(adc_read(acc_Z_channel))) - acc_Z_zero
end procedure
Funktionen acc_get_avg
Funktionen aflæser midlede X-, Y- og Z-værdier korrigeret med nulpunktet.
Koden ser ud som følger:
procedure acc_sum_up is
var byte n
acc_X_arr[acc_ptr] = (sword(adc_read(acc_X_channel))) - acc_X_zero
acc_Y_arr[acc_ptr] = (sword(adc_read(acc_Y_channel))) - acc_Y_zero
acc_Z_arr[acc_ptr] = (sword(adc_read(acc_Z_channel))) - acc_Z_zero
acc_ptr = (acc_ptr + 1) % acc_arr_size
acc_X = 0
acc_Y = 0
acc_Z = 0
for acc_arr_size using n loop
acc_X = acc_X + acc_X_arr[n]
acc_Y = acc_Y + acc_Y_arr[n]
acc_Z = acc_Z + acc_Z_arr[n]
end loop
end procedure
procedure acc_get_avg is
acc_sum_up
acc_X = acc_X / acc_arr_size
acc_Y = acc_Y / acc_arr_size
acc_Z = acc_Z / acc_arr_size
end procedure
Den første procedure er skilt ud, for at kunne opsummere indholdet i arrayene til videre beregning. Proceduren starter med at aflæse 3 nye værdier, og overskriver dem ind i de 3 respektive arrays. Efter den er gennemløbet deles værdierne med størrelsen på arrayet, så det stadig er samme talstørrelse.
Funktionen acc_get_g
Funktionen aflæser midlede X-, Y- og Z-værdier korrigeret med nulpunktet og tilpasset til visning med 2 decimaler.
Koden ser ud som følger:
procedure acc_get_g is
acc_sum_up
acc_X = (acc_X * 10) / acc_X_range
acc_Y = (acc_Y * 10) / acc_Y_range
acc_Z = (acc_Z * 10) / acc_Z_range
end procedure
Denne funktion anvender samme procedure til at aflæse kanalerne og opsummere de 3 arrays, hvorefter der beregnes værdien med en opløsning på 10 mg. Årsagen til at der ganges med 10 inden værdierne deles ned er, at range variablerne skal have en rimelig størrelse (ca. 100) for ikke at give for stor hældningsfejl, da de er heltal. Dette betyder samtidigt at de summerede værdier i acc_X, acc_Y og acc_Z variablerne ikke må blive for store, da det ellers kan give overflow - det betyder som rutinen er lavet, at der ikke må summeres mere end 8 værdier (array-størrelsen). Skulle det ændres skal der anvendes en sdword variabel til at indeholde de 10 gange den summerede aflæsning, inden der deles ned til den skalerede værdi.
Funktionen acc_calibrate
Beder om 6 aflæsninger for at kalibrere X-, Y- og Z-parametrene, både for nulpunkt og området til omregning i g.
En del af koden ser ud som følger:
ALCD_clear_screen()
repeat
delay_1ms(20)
until ! acc_cal_pin
acc_X_zero = 0
while ! acc_cal_pin loop
acc_get_avg()
ALCD_cursor_position(0,0) -- start of first line
ALCD_write_char("X")
ALCD_write_char("-")
ALCD_write_char("M")
ALCD_write_char("A")
ALCD_write_char("X")
ALCD_write_char(" ")
ALCD_write_char("P")
ALCD_write_char("O")
ALCD_write_char("S")
ALCD_write_char(" ")
ALCD_swDec(acc_X, 4) -- Skriv X-aflæsning
delay_100ms(1)
end loop
acc_X_range = acc_X
repeat
delay_1ms(20)
until ! acc_cal_pin
while ! acc_cal_pin loop
acc_get_avg()
ALCD_cursor_position(0,0) -- start of first line
ALCD_write_char("X")
ALCD_write_char("-")
ALCD_write_char("M")
ALCD_write_char("I")
ALCD_write_char("N")
ALCD_write_char(" ")
ALCD_write_char("P")
ALCD_write_char("O")
ALCD_write_char("S")
ALCD_write_char(" ")
ALCD_swDec(acc_X, 4) -- Skriv X-aflæsning
delay_100ms(1)
end loop
acc_X_zero = (acc_X_range + acc_X) / 2
acc_X_range = (acc_X_range - acc_X) * acc_arr_size / 20
Der startes med at slette skærmen, og vente på knappen bliver sluppet.
Nulpunktskorrektionen nulstilles, så det er de rå værdier der aflæses, herefter loopes der mens der vises X-MAX POS og den aktuelle aflæsning af X-værdien. Her skal brugeren placere modulet så der aflæses værdien for 1g. Når brugeren trykker på knappen gemmes den aflæste værdi midlertidigt.
Der ventes igen på at knappen slippes, hvorefter der laves en ny aflæsning med teksten X-MIN POS, hvor det er værdien for -1g der aflæses.
Ud fra de to aflæsninger beregnes nulpunktet som værende midt mellem aflæsningerne, og range-variablen som det aflæste område tilpasset efter summeringen af arrayet og det at det skal give 2 decimaler. Variablen bliver omkring 100 ved en arraystørrelse på 5, hvilket er en passende nøjagtigehed til 1 g med 2 decimaler.
Herefter foretages præcist det samme for Y- og Z-kanalen, så alle 3 kanaler bliver kalibreret.
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