EmbeddedRelated.com
Forums
Memfault Beyond the Launch

Atmel AVR, too slow encoder tics counting

Started by Umpa May 6, 2004
On Fri, May 07, 2004 at 12:54:16AM +0200, Umpa wrote:

> Below, I present my program.
> long int licz = 0;
The above most definitely needs to be 'volatile' to keep the optimizer from caching the value in registers since it has no idea it might be updated out of band in the interrupt routine.
> int flagaA = 0, flagaB = 0;
Hmmm ... these are probably OK as is. -Brian --- Brian Dean http://www.bdmicro.com/
Alexander Peter wrote:
>>But, above two people have said that >>my ATmega16 works with 1MHz >>frequency, and I need to attach >>cristal. I think, it solves my problem. > > > You can set up your internal RC to 8 or 16MHz by progamming the corrseponding fuses. Look at the datasheet!
The device is shipped with 1MHZ internal RC clock. Internal RC clock can be set to 1,2,4,8 Mhz, NOT 16Mhz. Using an simple external 16Mhz crystal gives 16Mhz clock rate. best regards, -- Bernhard Roessmann
"Umpa" <&#4294967295;&#4294967295;&#4294967295;&#4294967295;@umpaumpalala.com> schreef in bericht
news:c7ffsi$hj2$1@atlantis.news.tpi.pl...
> > The second thing is, when I change type of "licz" to > int (not long int), it can count ticks faster.
32 bits integers are very time consuming on 8 bit uP's. Perhaps you can use an 8 bit, and use that to adjust a 32 bit value in your main code. main() { while(1) { cli() 32bitlicz += 8bitlicz; 8bitlicz = 0; sei() .......... } } Well, something like that. I'm not in favor of using interrupts for encoder inputs. There are dedicated encoder frontend chips, such as HCTL2000 etcetera, which would be my preference for reading encoders at this speed. For reading hand turned encoders, such as digital pots, a timer interrupt does pretty well. The risk with this all-software method, and the speeds you have, is loosing/gaining a few steps perhaps. Imagine the encoder/shaft is stopped, but vibrates. You can get nasty bursts of pulses in such situations, as the encoder is actually going back and forth. Of course, in many systems it may not matter much if a few steps are missed. -- Thanks, Frank. (remove 'x' and 'invalid' when replying by email)
> The risk with this all-software method, and the speeds you have, > is loosing/gaining a few steps perhaps. Imagine the encoder/shaft is > stopped, > but vibrates. You can get nasty bursts of pulses in such situations, > as the encoder is actually going back and forth. Of course, in > many systems it may not matter much if a few steps are missed. >
Hello, My code (I posted above) counts correctly -- I know about problem of "vibrating encoder shaft", and prepared correct code. Umpa.
Tim Mitchell <timng@sabretechnology.co.uk> wrote in message news:<LCLrZHMFc2mAFAbe@tega.co.uk>...
> In article <c7fobq$os$1@atlantis.news.tpi.pl>, Umpa > <?@umpaumpalala.com.invalid> writes > > > >> 16Mhz is the max frequency it will go at when using a crystal. > >> -- > >Hurrayy !!! > >Maybe it is a cause !! > >Tell me please, what cristal shall I attach, where, and what > >to set up in my program ? > >Or provide me with any document. > > > If you don't have the Mega16 data sheet you can download it from > www.atmel.com, it contains all the information you need to either attach > a crystal or change the internal RC oscillator speed.
I have published an article that may be of some revelance on this topic. http://www.embedded-designer.com/articles/c1201lt.pdf Hope this helps George
In article <e9d879fa.0405100615.388dd51c@posting.google.com>,
George <george.martin@att.net> wrote:

[snip]

>I have published an article that may be of some revelance on this topic. > >http://www.embedded-designer.com/articles/c1201lt.pdf
I couldn't read it (Acrobat 5.0 under Linux) -frank --
Umpa wrote:
> Hello, > > I have problem with counting ticks of an encoder. > I can achieve about 5 kHz without errors. > Above this frequency, I loose ticks. > > I use second AVR processor as the generator of > two signals -- I just test my device, without real encoder. > > What to do to improve frequency ? > > Below, I present my program. > Processor: AVR ATmega16 > You should connect an Encoder in the way: > Canal A : PD2 i PD3 > Canal B: PD4 > > #include <stdio.h> > #include <avr/io.h> > #include <avr/interrupt.h> > #include <avr/signal.h> > #include "lcd.h" > > long int licz = 0; > int flagaA = 0, flagaB = 0; > > > SIGNAL (SIG_INTERRUPT0) > { > if (!(inb(PIND) & 16)) /* if 0 on canal B */ > flagaA = 1; > else /* otherwise, (1 on canal B) */ > flagaB = 1; > } > > > SIGNAL (SIG_INTERRUPT1) > { > if (inb(PIND) & 16) { /* if 1 on canal B */ > if (flagaA) /* if flagaA is set */ > licz++, flagaA = 0; > } else if (flagaB) /* if flagaB is set */ > licz--, flagaB = 0; > } > > > int main(void) > { > char s[16]; > > outp(0, DDRD); > > /* Setting interrupts INT 0 i INT1 -- rising, falling edge > */ > outp((1<<INT0)|(1<<INT1), GIMSK); > outp((1<<ISC01)|(1<<ISC00) | (1<<ISC11), MCUCR); > > > initLCD(); > > sei(); /* star interrupts */ > > for (;;) { > cursorHome(); > sprintf(s, "%ld ", licz); > showStringOnLCD(s); > } > > return 0; > } > >
In my opinion, your programm waste time in cursorHome() function because 1 or 2ms is needed by lcd controller to achieve this operation, but it depend of how this function is implented. Possibly you may invoke cursorHome when you really need to showString... something on LCD Cheers,
> In my opinion, your programm waste time in cursorHome() function because > 1 or 2ms is needed by lcd controller to achieve this operation, but it > depend of how this function is implented. Possibly you may invoke > cursorHome when you really need to showString... something on LCD >
You are right. cursorHome() isn`t the fastest function in the world ;) But, counting encoder`s ticks are realized by interrupt-driven function. So, cursorHome() can be interrupted when system calls SIG_INTERRUPT0 or 1. Umpa.
Umpa wrote:
>>In my opinion, your programm waste time in cursorHome() function because >>1 or 2ms is needed by lcd controller to achieve this operation, but it >>depend of how this function is implented. Possibly you may invoke >>cursorHome when you really need to showString... something on LCD >> > > You are right. cursorHome() isn`t the fastest function in the world ;) > But, counting encoder`s ticks are realized by interrupt-driven > function. So, cursorHome() can be interrupted when > system calls SIG_INTERRUPT0 or 1. > > Umpa. > >
Okay that's right Umpa, ticks increment or decrement prior to normal AVR code execution in that case. I thought about licr overflow or underflow, in fact time waisted in cursorHome() before showString() anything on LCD that might be misinterpret the results on LCD ... but i realized that licr variable is long int (32 bits !!!) so no problem ! Tell me how you fixed that bug (hard or soft prob ?) Habib.
> Tell me how you fixed that bug (hard or soft prob ?) >
I did two things: -- now my program uses only one interrupt - it made my program faster, but only a little bit, -- I changed internal frequency rate - default it is 1MHz, I changed it to 8MHz and my program runs 8 times faster ;) Umpa.

Memfault Beyond the Launch