#include #include // To get access to various commands, for example sei() #include // To get access to interrupt handling unsigned char portVal; // Nuvarande status på porten med lysdioderna. void setlightled(char nr,char on); // Ändrar status på lysdiod nr, lys när on==1 void init_avr(); // Startar timer, sätter portar till input osv. int getwidth(int pin,int value); // Retunerar beredden på pulsen, pin= X el Y led, value = hög(1)/låg(0) på signalen. #define true 1 // Definera true som en 1:a #define false 0 // Definera false som en 0:a char doCalibrate; // ==true när det skall kalibreras. void sdelay(); // Väntar ett litet tag. volatile uint8_t tick; // Global variabel för sdelay(). Om den inte är volatile kan kompilatorn optimera bort den. float calibratex=1.0f; // Sätta default värde för kalibreringen. Efter kalibrering är dessa värderna (kankse) annorlunda. float calibratey=1.0f; // Sätta default värde för kalibreringen. Efter kalibrering är dessa värderna (kankse) annorlunda. int main(void) { DDRA = 0xff; // PortA skall vara out för lysdioderna PORTA= 0x00; // Släcka allt. int counter=0; // Kalibrering sker inte direkt när avr startar utan lite senare, counter är räknar uppåt tills det är dags att kalibrera doCalibrate=false; // Inte kalibrera i början utan vänta tills counter har nått ett visst värde. init_avr(); // Initera avr. sei(); // Set enable interupts, behövs för timern. setlightled(0,false); // Släcker ut diod 1 sdelay(); setlightled(1,false); // Släcker ut diod 2 sdelay(); setlightled(2,false); // Släcker ut diod 3 sdelay(); setlightled(3,false); // Släcker ut diod 4 sdelay(); int c=0; // När c är jämnt mäts X, när c är udda mäts y. while(1) // Starta en oändligt loop. { long t1; // t1 är antalet samplingar som är den höga delen long t2; // t2 är antalet samplingar som är den låga delen float ratio; // Skillnaden mellan hög och låg del av signalen. (t1/t2). c++; // Öka våran jämt/udda variabel med 1 if(counter<20) // Vi har redan kalibrerat, ingen anledning att fortsätta räkna. counter++; if(c % 2==0) { // Börja med att läsa X axeln. while(PIND & (1<<5)); // Vänta till att signalen går högt. t1=getwidth(5,0); // Nu är perioden hög börja läsa på pinne 5 tills peridoen är låg. t2=getwidth(5,1); // Nu är perioden låg börja läsa på pinne 5 tills peridoen är hög. if(t2==0) // Ifall det blir något fel vill vi inte riskera en "divide by zero" t2=1; ratio= (float) t1 / (float) t2; // Räkna ut skillnaden mellan vågorna if(counter==10) // Test ifall counter har nått tillräckligt högt för att kalibrera. { calibratex=1/ratio; // Räkna ut kalibrerings faktorn. setlightled(0,true); // Nedan stående blinkar dioderna för att visa att vi kalibrerar setlightled(1,true); setlightled(2,true); setlightled(3,true); for(int i=0;i<200;i++) sdelay(); setlightled(0,false); setlightled(1,false); setlightled(2,false); setlightled(3,false); } else { ratio*=calibratex; // Kalibrera det inmätna värdet. if(ratio < 0.9f) // Avgöra ifall vi lutar bakåt setlightled(3,true); // Lutar åt bakåt, tänd den dioden. else setlightled(3,false); // Om inte, så skall den vara släkt. if(ratio > 1.1f) // Avgöra ifall vi lutar framåt setlightled(0,true); // Lutar framåt, tänd den dioden else setlightled(0,false); // Om inte, släck den. } } while(PIND & (1<<4)); // Vänta tills signalen går hög på y pinnen. t1=getwidth(4,0); // Nu är perioden hög börja läsa tills peridoen är låg. t2=getwidth(4,1); // Nu är perioden låg börja läsa tills peridoen är hög. if(t2==0) // Ifall det blir något fel vill vi inte riskera en "divide by zero" t2++; ratio= (float) t1 / (float) t2; // Räkna ut skillnaden mellan vågorna if(counter==11) // Test ifall counter har nått tillräckligt högt för att kalibrera. { calibratey=1/ratio; // Räkna ut kalibrerings faktorn. setlightled(0,true); // Nedan stående blinkar dioderna för att visa att vi kalibrerar. setlightled(1,true); setlightled(2,true); setlightled(3,true); for(int i=0;i<100;i++) sdelay(); setlightled(0,false); setlightled(1,false); setlightled(2,false); setlightled(3,false); } else { ratio*=calibratey; // Kalibera det inmätna värdet if(ratio < 0.9f) // Avgöra ifall vi lutar åt vänster setlightled(1,true); // Lutar vänster, tänd dioden else setlightled(1,false); // Om inte, släck den. if(ratio > 1.1f) // Avgöra ifall vi lutar åt höger setlightled(2,true); // Lutar höger, tänd dioden. else setlightled(2,false); // Om inte, släck den. } } return; } void sdelay() { tick=1; // Sätta delay tiden, ju högre desto längre vänte tid. while (tick); // Vänta tills tick==0, tick ändras av timer interupten - det är därför den är volatile. } int getwidth(int pin,int high) { long pulsecount=0; // Har inte räknat några pulser i början. while((PIND & (1<