1. This forum section is a read-only archive which contains old newsgroup posts. If you wish to post a query, please do so in one of our main forum sections (here). This way you will get a faster, better response from the members on Motherboard Point.

Atmel AVR, too slow encoder tics counting

Discussion in 'Embedded' started by Umpa, May 6, 2004.

  1. Umpa

    Umpa Guest

    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;
    }
     
    Umpa, May 6, 2004
    #1
    1. Advertising

  2. 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 ?


    If you want a lot faster, use hardware, like a CPLD.
    If the AVR has an Up/Dn counter mode a la 89C52, the PLD
    needs only do the conditioning to Dirn and Count signals.

    If you only have UP counters, you can allocate two, and
    internally take the difference. PLD then generates Clk_UP,
    and Clk_DN pulse trains.

    5KHz sounds about right for LONGINT SW -
    To speed SW further, try assembler and do cascaded or queued BYTE
    increments, rather than a full long int INC. Latter is simpler
    to write, but every INC handles all bytes.

    In the AVR, register access is much better than DATA access,
    so either move all the counter to regs, or if that chews too much
    REG resource, move the LSB byte to one reg, and cascade into
    pointer/data access only on overflow.
    For that, you will need to use assembler....

    -jg
     
    Jim Granville, May 7, 2004
    #2
    1. Advertising

  3. Umpa

    Phil W Guest

    How fast are you running the clock on your CPU?
    What is your clock src?

    Phil W



    "Umpa" <¹¿æó@umpaumpalala.com> wrote in message
    news:c7efnb$qna$...
    > 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;
    > }
    >
    >
     
    Phil W, May 7, 2004
    #3
  4. Umpa

    Rob Turk Guest

    "Umpa" <¹¿æó@umpaumpalala.com> wrote in message
    news:c7efnb$qna$...
    > 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 ?


    Your interrupt service routines will translate to only a few assembler
    instructions. There's plenty processing power in the AVR to cope with this
    at 5 kHz and higher.

    You may want to check your LCD output routines. Check if it's disabling
    interrupts somewhere.

    How do you determine that you loose ticks, not by reading the the LCD I
    suppose?

    Rob
     
    Rob Turk, May 7, 2004
    #4
  5. Umpa

    Umpa Guest


    > How do you determine that you loose ticks, not by reading the the LCD I
    > suppose?
    >

    My generator generates known numer of ticks on both chanels with
    different phase.
    Yea, I read LCD -- it shows smaller numer at higher frequencies.

    When I add "cli" at begining of interrupt function and "sei" at the end
    -- LCD shows "0" at higher frequencies. And it works correctly at
    smaller frequencies.
    So, I think, that processor tries to run interrupt function when
    previous hasn`t finished yet.
    I think, I must optimalize my code and write it in assembler.

    The second thing is, when I change type of "licz" to
    int (not long int), it can count ticks faster.

    So, I`m almost sure, my code is too slow.

    Now, I use only INT0 in my program, and I can
    count ticks with a little bit more frequency -- but
    not enough still.
    I need about 10 kHz.

    unsigned long int licz = 0;
    unsigned char flagaA = 0, flagaB = 0;

    SIGNAL (SIG_INTERRUPT0)
    {
    // cli();
    if (PIND & 4) {
    (!(PIND & 16)) ? (flagaA = 1) : (flagaB = 1);
    } else {
    if (PIND & 16) {
    flagaA && (licz++, flagaA = 0);
    } else {
    flagaB && (licz--, flagaB = 0);
    }
    }
    // sei();
    }

    int main(void)
    {
    char s[16];
    outp(0, DDRD);
    outp((1<<INT0), GIMSK);
    outp((1<<ISC00), MCUCR);
    sei();
    .....
    }
     
    Umpa, May 7, 2004
    #5
  6. Umpa

    Umpa Guest

    > How fast are you running the clock on your CPU?
    > What is your clock src?
    >

    I have ATmega16 -- 16 MHz.
    Clock source is internal I think, I didn`t connect any quartz.

    Did I do something wrong?

    Umpa.
     
    Umpa, May 7, 2004
    #6
  7. Umpa

    Umpa Guest

    Thanks for smart advices.

    > 5KHz sounds about right for LONGINT SW -


    My processor has 16 MHz.
    Even if execution of interrupt procedure lasts 1000 cycles
    (I don`t think so it lasts as long), we should have
    16000000 / 1000 = 16 kHz.
    I think, my program should be able to count with
    higher frequencies according to high processor
    speed, and not so slow (I think not slower than e.g. 1000 cycles)
    interrupt procedure.

    Umpa.
     
    Umpa, May 7, 2004
    #7
  8. Umpa

    Umpa Guest

    This code:

    #include <stdio.h>
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/signal.h>

    unsigned long int licz = 0;
    unsigned char flagaA = 0, flagaB = 0;


    SIGNAL (SIG_INTERRUPT0)
    {
    // cli();
    if (PIND & 4) {
    (!(PIND & 16)) ? (flagaA = 1) : (flagaB = 1);
    } else {
    if (PIND & 16) {
    if (flagaA)
    licz++, flagaA = 0;
    } else {
    if (flagaB)
    licz--, flagaB = 0;
    }
    }
    // sei();
    }

    int main(void)
    {
    outp(0, DDRD);

    outp((1<<INT0), GIMSK);
    outp((1<<ISC00), MCUCR);

    sei();

    for (;;)
    ;

    return 0;
    }




    Looks that in assembler:


    encoder.elf: file format elf32-avr

    Sections:
    Idx Name Size VMA LMA File off Algn
    0 .text 0000014a 00000000 00000000 00000094 2**0
    CONTENTS, ALLOC, LOAD, READONLY, CODE
    1 .data 00000000 00800060 0000014a 000001de 2**0
    CONTENTS, ALLOC, LOAD, DATA
    2 .bss 00000006 00800060 00800060 000001de 2**0
    ALLOC
    3 .noinit 00000000 00800066 00800066 000001de 2**0
    CONTENTS
    4 .eeprom 00000000 00810000 00810000 000001de 2**0
    CONTENTS
    Disassembly of section .text:

    00000000 <.text>:
    0: 0c 94 2a 00 jmp 0x54
    4: 0c 94 47 00 jmp 0x8e
    8: 0c 94 45 00 jmp 0x8a
    c: 0c 94 45 00 jmp 0x8a
    10: 0c 94 45 00 jmp 0x8a
    14: 0c 94 45 00 jmp 0x8a
    18: 0c 94 45 00 jmp 0x8a
    1c: 0c 94 45 00 jmp 0x8a
    20: 0c 94 45 00 jmp 0x8a
    24: 0c 94 45 00 jmp 0x8a
    28: 0c 94 45 00 jmp 0x8a
    2c: 0c 94 45 00 jmp 0x8a
    30: 0c 94 45 00 jmp 0x8a
    34: 0c 94 45 00 jmp 0x8a
    38: 0c 94 45 00 jmp 0x8a
    3c: 0c 94 45 00 jmp 0x8a
    40: 0c 94 45 00 jmp 0x8a
    44: 0c 94 45 00 jmp 0x8a
    48: 0c 94 45 00 jmp 0x8a
    4c: 0c 94 45 00 jmp 0x8a
    50: 0c 94 45 00 jmp 0x8a
    54: 11 24 eor r1, r1
    56: 1f be out 0x3f, r1 ; 63
    58: cf e5 ldi r28, 0x5F ; 95
    5a: d4 e0 ldi r29, 0x04 ; 4
    5c: de bf out 0x3e, r29 ; 62
    5e: cd bf out 0x3d, r28 ; 61
    60: 10 e0 ldi r17, 0x00 ; 0
    62: a0 e6 ldi r26, 0x60 ; 96
    64: b0 e0 ldi r27, 0x00 ; 0
    66: ea e4 ldi r30, 0x4A ; 74
    68: f1 e0 ldi r31, 0x01 ; 1
    6a: 02 c0 rjmp .+4 ; 0x70
    6c: 05 90 lpm r0, Z+
    6e: 0d 92 st X+, r0
    70: a0 36 cpi r26, 0x60 ; 96
    72: b1 07 cpc r27, r17
    74: d9 f7 brne .-10 ; 0x6c
    76: 10 e0 ldi r17, 0x00 ; 0
    78: a0 e6 ldi r26, 0x60 ; 96
    7a: b0 e0 ldi r27, 0x00 ; 0
    7c: 01 c0 rjmp .+2 ; 0x80
    7e: 1d 92 st X+, r1
    80: a6 36 cpi r26, 0x66 ; 102
    82: b1 07 cpc r27, r17
    84: e1 f7 brne .-8 ; 0x7e
    86: 0c 94 9a 00 jmp 0x134
    8a: 0c 94 00 00 jmp 0x0
    8e: 1f 92 push r1
    90: 0f 92 push r0
    92: 0f b6 in r0, 0x3f ; 63
    94: 0f 92 push r0
    96: 11 24 eor r1, r1
    98: 8f 93 push r24
    9a: 9f 93 push r25
    9c: af 93 push r26
    9e: bf 93 push r27
    a0: 82 9b sbis 0x10, 2 ; 16
    a2: 0a c0 rjmp .+20 ; 0xb8
    a4: 84 99 sbic 0x10, 4 ; 16
    a6: 04 c0 rjmp .+8 ; 0xb0
    a8: 81 e0 ldi r24, 0x01 ; 1
    aa: 80 93 64 00 sts 0x0064, r24
    ae: 39 c0 rjmp .+114 ; 0x122
    b0: 81 e0 ldi r24, 0x01 ; 1
    b2: 80 93 65 00 sts 0x0065, r24
    b6: 35 c0 rjmp .+106 ; 0x122
    b8: 84 9b sbis 0x10, 4 ; 16
    ba: 1a c0 rjmp .+52 ; 0xf0
    bc: 80 91 64 00 lds r24, 0x0064
    c0: 88 23 and r24, r24
    c2: 79 f1 breq .+94 ; 0x122
    c4: 80 91 60 00 lds r24, 0x0060
    c8: 90 91 61 00 lds r25, 0x0061
    cc: a0 91 62 00 lds r26, 0x0062
    d0: b0 91 63 00 lds r27, 0x0063
    d4: 01 96 adiw r24, 0x01 ; 1
    d6: a1 1d adc r26, r1
    d8: b1 1d adc r27, r1
    da: 80 93 60 00 sts 0x0060, r24
    de: 90 93 61 00 sts 0x0061, r25
    e2: a0 93 62 00 sts 0x0062, r26
    e6: b0 93 63 00 sts 0x0063, r27
    ea: 10 92 64 00 sts 0x0064, r1
    ee: 19 c0 rjmp .+50 ; 0x122
    f0: 80 91 65 00 lds r24, 0x0065
    f4: 88 23 and r24, r24
    f6: a9 f0 breq .+42 ; 0x122
    f8: 80 91 60 00 lds r24, 0x0060
    fc: 90 91 61 00 lds r25, 0x0061
    100: a0 91 62 00 lds r26, 0x0062
    104: b0 91 63 00 lds r27, 0x0063
    108: 01 97 sbiw r24, 0x01 ; 1
    10a: a1 09 sbc r26, r1
    10c: b1 09 sbc r27, r1
    10e: 80 93 60 00 sts 0x0060, r24
    112: 90 93 61 00 sts 0x0061, r25
    116: a0 93 62 00 sts 0x0062, r26
    11a: b0 93 63 00 sts 0x0063, r27
    11e: 10 92 65 00 sts 0x0065, r1
    122: bf 91 pop r27
    124: af 91 pop r26
    126: 9f 91 pop r25
    128: 8f 91 pop r24
    12a: 0f 90 pop r0
    12c: 0f be out 0x3f, r0 ; 63
    12e: 0f 90 pop r0
    130: 1f 90 pop r1
    132: 18 95 reti
    134: cf e5 ldi r28, 0x5F ; 95
    136: d4 e0 ldi r29, 0x04 ; 4
    138: de bf out 0x3e, r29 ; 62
    13a: cd bf out 0x3d, r28 ; 61
    13c: 11 ba out 0x11, r1 ; 17
    13e: 80 e4 ldi r24, 0x40 ; 64
    140: 8b bf out 0x3b, r24 ; 59
    142: 81 e0 ldi r24, 0x01 ; 1
    144: 85 bf out 0x35, r24 ; 53
    146: 78 94 sei
    148: ff cf rjmp .-2 ; 0x148
     
    Umpa, May 7, 2004
    #8
  9. Umpa

    Umpa Guest

    > You may want to check your LCD output routines. Check if it's disabling
    > interrupts somewhere.
    >

    I didn`t disable interrupts myself in any code.
    But, after translating code to assembler, I can see many "cli"
    instructions in my source code.
    When I cut LCD library and left pure interrupt function and
    main(), there were no "cli" instructions in source code.

    Umpa.
     
    Umpa, May 7, 2004
    #9
  10. Umpa

    Umpa Guest

    Now, I did loops at the begining
    of main():

    for(i=0;i<10000;i++)
    for(j=0;j<10000;j++)
    ;

    after that I initialize LCD and
    display counter -- to avoid "cli"
    instructions (there are no such instructions
    in C code, but they apear in assembler code
    generated by winavr) which could be in
    LCD library.
    It improved situation (I can count with a little
    bit more frequencies), but not as much I would like.

    Umpa.
     
    Umpa, May 7, 2004
    #10
  11. Umpa

    Tim Mitchell Guest

    In article <c7fg8j$a1c$>, Umpa
    <?@umpaumpalala.com.invalid> writes
    >> How fast are you running the clock on your CPU?
    >> What is your clock src?
    >>

    >I have ATmega16 -- 16 MHz.
    >Clock source is internal I think, I didn`t connect any quartz.
    >
    >Did I do something wrong?
    >

    An ATMega16 on internal oscillator runs by default at 1MHz not 16MHz. So
    that will make quite a difference.

    16Mhz is the max frequency it will go at when using a crystal.
    --
    Tim Mitchell
     
    Tim Mitchell, May 7, 2004
    #11
  12. Umpa

    jetmarc Guest

    > What to do to improve frequency ?

    Re-write the interrupt code in assembler. Make sure that your LCD output
    function does not disable interrupts.

    How fast do you want to go?
     
    jetmarc, May 7, 2004
    #12
  13. Umpa

    jetmarc Guest

    > long int licz = 0;

    That needs a "volatile".
     
    jetmarc, May 7, 2004
    #13
  14. Umpa schrieb:
    >> How fast are you running the clock on your CPU?
    >> What is your clock src?
    >>

    > I have ATmega16 -- 16 MHz.
    > Clock source is internal I think, I didn`t connect any quartz.
    >
    > Did I do something wrong?
    >

    Have you checked the correct setup for the internal oscillator?
    The ATmegas are shipped with internal RC @ 1MHz...

    Alexander
     
    Alexander Peter, May 7, 2004
    #14
  15. Umpa

    Umpa Guest


    > 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.

    Umpa.
     
    Umpa, May 7, 2004
    #15
  16. Umpa

    Umpa Guest

    > How fast do you want to go?

    10 kHz would be enough.
    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.

    Umpa.
     
    Umpa, May 7, 2004
    #16
  17. Umpa

    Tim Mitchell Guest

    In article <c7fobq$os$>, 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.
    --
    Tim Mitchell
     
    Tim Mitchell, May 7, 2004
    #17
  18. Umpa

    Umpa Guest

    One more thing.
    I need to use UART transmision.
    I bought 11,059 MHz cristal.
    If I attach this cristal, will processor
    run with 11,059 MHz frequency ?

    Umpa.
     
    Umpa, May 7, 2004
    #18
  19. Umpa schrieb:
    >> How fast do you want to go?

    >
    > 10 kHz would be enough.
    > 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!

    Alexander
     
    Alexander Peter, May 7, 2004
    #19
  20. Umpa

    jetmarc Guest

    > The second thing is, when I change type of "licz" to
    > int (not long int), it can count ticks faster.


    Well, you also have to protect the reading of "licz" by a pair
    of CLI/SEI (in the main code). Don't protect the whole LCD call,
    but rather copy it to a local autovar in protected fashion, and
    then use the copy in the printf/LCD calls.
     
    jetmarc, May 7, 2004
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Rich Webb

    Re: Atmel Avr, n-coder`s ticks counting

    Rich Webb, Aug 23, 2003, in forum: Embedded
    Replies:
    0
    Views:
    345
    Rich Webb
    Aug 23, 2003
  2. Jan-Hinnerk Reichert
    Replies:
    0
    Views:
    731
    Jan-Hinnerk Reichert
    Aug 23, 2003
  3. Rikko
    Replies:
    0
    Views:
    303
    Rikko
    Aug 22, 2003
  4. Erwin Rensink
    Replies:
    5
    Views:
    451
    eddumweer
    Feb 19, 2004
  5. Stef
    Replies:
    8
    Views:
    764
    Chris Hills
    Aug 14, 2006
Loading...

Share This Page