Problem with Rotary Encoder (Atmega168)

Hi there!

I´m currently working on a student project and i recently got stuck. I am a newbie on AVR programming but i think i can understand or atleast try to understand most of the terms used in this forum.

My project is to make a rotary encoder hooked up to a DC motor determine how far a small cart has moved and print the values to the terminal via rs232.

Attached is a picture of the circuit with the rotary encoder terminals connected to PINC 4&5 on the Atmega168

I cannot seem to get the code to work properly. I only get rubbish on TeraTerm which makes it impossible to see if i count pulses the right way. Do you guys think that the code looks alright or what can i improve? Am I reading the encoder pins correctly??!

I got some code examples from different places and put them together and thats why some functions may not be called!

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

//global variables: encoder position and direction of rotation

volatile unsigned int enc_pos;
volatile unsigned char enc_dir;
volatile static unsigned char enc_last,enc_now;

#define FOSC 8000000
#define BAUD 4800
#define MYUBRR FOSC/16/BAUD-1

#define sbi(var, mask)   ((var) |= (uint8_t)(1 << mask))
#define cbi(var, mask)   ((var) &= (uint8_t)~(1 << mask))

void ioinit(void);      // initializes IO
static int uart_putchar(char c, FILE *stream);
uint8_t uart_getchar(void);

static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
_FDEV_SETUP_WRITE);

void delay_ms(uint16_t x); // general purpose delay

ISR (PCINT1_vect) {
   //static unsigned char enc_last,enc_now;
   enc_now = (PINC & (3<<4))>>4;                 //read the port pins and shift result
to bottom bits
   enc_dir = (enc_last & 1)^((enc_now & 2) >> 1);         //determine direction of
rotation
   if(enc_dir==0) enc_pos++; else enc_pos--;         //update encoder position
   enc_last=enc_now;                  //remember last state
}



int main(void)
{
   printf("Position:");
   ioinit(); //Setup IO pins and defaults

   enc_pos=0;               //Initialize encoder position
   int jmfr =0;
//   LCDInit();               //Initialize LCD display
    ;
   DDRC &=~(3<<4);              //Port C pins 4 and 5 as input
   PCMSK1 |= (3<<PCINT12);            //enable interrupt on pin change, bits 4&5 PORTC
   PCICR |= 1<<PCIE1;            //enable interrupt on pin change, PORTC
   sei();                  //enable global interrupts

   while (1){


      if(enc_pos<jmfr)
         {
         //   printf("forward");
            
            jmfr= enc_pos;
            
         }
      if(enc_pos>jmfr)
         {
            printf("backwards");
            jmfr= enc_pos;
            //delay_ms(1);
         }
      
      }
}


void ioinit (void)
{
   //1 = output, 0 = input
   DDRB = 0b11101111; //PB4 = MISO
   DDRC = 0b11111111; //
   DDRD = 0b11111110; //PORTD (RX on PD0)

   //USART Baud rate: 9600
   UBRR0H = MYUBRR >> 8;
   UBRR0L = MYUBRR;
   UCSR0B = (1<<RXEN0)|(1<<TXEN0);

   stdout = &mystdout; //Required for printf init
}

static int uart_putchar(char c, FILE *stream)
{
   if (c == '\n') uart_putchar('\r', stream);

   loop_until_bit_is_set(UCSR0A, UDRE0);
   UDR0 = c;

   return 0;
}

uint8_t uart_getchar(void)
{
   while( !(UCSR0A & (1<<RXC0)) );
   return(UDR0);
}

//General short delays
void delay_ms(uint16_t x)
{
 uint8_t y, z;
 for ( ; x > 0 ; x--){
   for ( y = 0 ; y < 80 ; y++){
     for ( z = 0 ; z < 4 ; z++){
       asm volatile ("nop");
     }
   }
 }
}

Best regards

Phil!

A debugger like the Atmel Dragon would help. Do you have one? Failing that, have you simulated the program?

Leon

Before worrying about the encoder, you need to get serial I/O working so you will have some way to debug this. Getting garbage output sounds like a problem with the fuse settings. Have you set the '168 to use the external crystal or oscillator (whichever you have on your board)? Also,

you are calling printf before ioinit.

What baud rate were you using in TereTerm? In the comments of your initialization code you specify 9800, but the baud rate is defined as 4800. Also, if you don’t aren’t using the 8Mhz crystal, there’s no telling what the baud rate is going to be.

You’re on the right track though, seeing rubbish is the first step!

problem solved! Just a misplaced capacitor on the max232 side…Done a lot of optimization on the code right now and its working like a charm!

thank you for all the help!