Med støjproblemer, ved du om der da menes 'prel' ?
Hvis det er prel, er det ikke noget problem, for det kan løses med programmering.
Der er to forskellige modeller.
1: Et program, der ikke bruger interrupts. Dette program er lettest at forstå, men er ikke så godt til høje hastigheder.
2: Et interrupt-drevet program. Dette er som indirekte nævnt lidt sværere at forstå/overskue, da det er mere avanceret, men til gengæld er det mere robust.
Jeg kan kun fortælle om principperne, for jeg selv bruger AVR. Men det kan være at Kenn kan give nogle bedre tips, da han er PIC specialist.
Program-type 1:
1: Vent på at signalet fra encoderen ændrer tilstand (dvs. går fra høj til lav eller fra lav til høj).
2: Vent et forudbestemt antal millisekunder. Her bør vi have fat i noget lignende 5 millisekunder hvis encoderen drejer langsomt, men hvis encoderen giver mere end 200 pulser i sekundet, så bør du sætte tallet ned. Dette tal kan beregnes.
3: Se om tilstanden er den samme som i punkt 1. Ér den det, har vi fat i en gyldig værdi; altså en værdi vi stoler på, ellers er der tale om prel.
Ventetiden kan beregnes på denne måde:
ventetid = rund op((1000000 / (Maksimale antal pulser per sekund)) / 2) mikrosekunder
Fx. Hvis du har maks 3000 pulser per sekund: 1000000 / 3000 / 2 = 167 mikrosekunder
Et program-eksempel i C kunne være...
uint8_t oldState;
uint8_t newState;
newState = 0;
oldState = newState;
while(1)
{
while(newState == oldState)
{
newState = PORT_BITS & (1 << PIN_NUMBER); /* read port value */
}
oldState = newState;
wait_us(500); /* max. 1000 pulses per second */
newState = PORT_BITS & (1 << PIN_NUMBER); /* read port value */
if(newState == oldState)
{
/* we have a new valid pin value, take appropriate action here */
}
}
Interrupt-udgaven kan jeg ikke give et uddybende kode-eksempel på, for dér er PIC og AVR nok lidt for forskellige.
Men det går ud på at man kan sætte PIC'en op til at køre en interrupt-rutine, hver gang dit i/o-ben ændrer værdi.
I interruptet starter du så en timer, som tæller ned, og når den rammer 0, udføres et andet interrupt; et timer-interrupt..
Du sætter dette interrupt til kun at køre én gang, dvs. det må ikke repetere.
Når du kommer ind i timer-interruptet, har værdien af i/o-benet været den samme i hele den tid vi har ventet på at timer-interruptet udføres. Man behøver ikke at sammenligne værdier, fordi hvis ben-værdien havde ændret sig, ville timer-interruptet's nedtælling have startet forfra.
I timer-interruptet kan du derfor kopiere den nye i/o-ben værdi over i en variabel, så du kan undersøge værdien nærmere; du bør ikke aflæse i/o-benet direkte, men i stedet bør du kopiere den værdi du gemte fra det andet interrupt.
void pinChanged() /* this is an interrupt-routine, which should be invoked when the i/o-pin changes */
{
newState = PORT_BITS & (1 << PIN_NUMBER); /* there might be an even better way to read this value */
/* set up oneShotTimer() to be invoked N microseconds from now, but only once. */
}
void oneShotTimer() /* this is a timer interrupt-routine, that pinChange() sets up to be invoked when time runs out */
{
pinState = newState;
pulses++; /* count the number of pulses total. */
if(pinState)
{
/* pin went from low to high */
}
else
{
/* pin went from high to low */
}
}
Bemærk: De viste kode-stumper er ikke udtømmende, for du har nemlig brug for to signaler (2 i/o-ben) til en encoder.
Har du 2 signaler, kan du se på mønstret, hvilken vej encoderen kører; om den kører forlæns eller baglæns.
Desuden kan jeg ikke afprøve om der er fejl i de nævnte kodstumper; så regn dem kun for at være forklarende skitser.