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!