Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] [Moved] Rotary Encoder interfacing with ATmega32

Status
Not open for further replies.

ismbn

Full Member level 3
Joined
Feb 11, 2012
Messages
160
Helped
4
Reputation
8
Reaction score
4
Trophy points
1,308
Location
Mumbai. india
Activity points
2,444
hello.
I working on a motor in which there is a rotary encoder is connected, with 2 output channels i.e. A & B. this output channels are giving the square wave with 90° Phase shift.
In my application i have to detect the direction of the motor and count the pulses done, & send to PC via UART.
The codding till now i have done is here. but the thing is its working fine in proteus. but when i am connecting the hardware... its not responding properly.
some time its giving "clock wise" and "anti clock " correctly, but most of the time it doesn't sending anything.
the UART communication header is working OK.. its tested...
Code:
/*
/*
 * Motor_incoder2_test.c
 *
 * Created: 11/29/2012 12:43:17 PM
 *  Author: Ismail
 */ 


#include <avr/io.h>
#include <avr/interrupt.h>
#include <dbits/usart32.h>
#include <util/delay.h>

volatile unsigned long x=1000;
char z=0;

void go_intr()
{
	MCUCR=1;
	GICR |=(1<<INT0);//|(1<<INT0);
	_delay_ms(10);
	sei();
}

int main(void)
{
	uart_init(103,0);
	sbit (DDRD,7);
	go_intr();
	sei();
	print('a');
	while(1)
	{
		if (z==1)
		{
			x++;
			print(x);
		}
		if(z==2)
		{
			x--;
			print(x);
		}
		if(z==1)
		{
			print_str(" clock wise ");
		}
		if(z==2)
		{
			print_str(" anti clock wise ");
		}
	}
}

ISR(INT0_vect)
{
while(bit_is_clear(PIND,2) && bit_is_clear(PIND,3));;;

//	if(bit_is_set(PINB,0) && bit_is_clear(PINB,1) && z==0)
	if(bit_is_clear(PIND,2)  && (z==0))
	{
		if (bit_is_set(PIND,3))
		{
			z=1;
		}			
	}
	if(bit_is_clear(PIND,3) && (z==0))
	{
		if (bit_is_set(PIND,2))
		{
			z=2;
		}			
	}
}

What do you think where is the problem... I think there is some problem in the coding...
i think i am not nicely checking the direction on the motor...
Please guide me.

Thanks Regards
Ismail
 

alexan_e

Administrator
Joined
Mar 16, 2008
Messages
11,895
Helped
2,021
Reputation
4,158
Reaction score
2,031
Trophy points
1,393
Location
Greece
Activity points
64,377
The problem is probably related to the bounce of the switch contacts (which doesn't exist in proteus).

In the past I have used https://arduino.cc/forum/index.php?topic=40382.0;wap2 (the one at the end)
The function gets called from a timer using the polling method.

Or add your own debounce method in your code
 
  • Like
Reactions: ismbn

    ismbn

    Points: 2
    Helpful Answer Positive Rating

ismbn

Full Member level 3
Joined
Feb 11, 2012
Messages
160
Helped
4
Reputation
8
Reaction score
4
Trophy points
1,308
Location
Mumbai. india
Activity points
2,444
this is my project file...

- - - Updated - - -

and for the hardware testing i am using a 89S51 which is giving same output as encoder does with 2 pins...
and i have connected that 2 pins to the external interrupt INT0 and INT1. of At mega 32.
Ismail

- - - Updated - - -

i have removed the switch to toggle the channels, now the weir is directly connected to the avr.

i am connecting the channel A to interrupt 0 and Channel B to interrupt 1, switching on the the circuit.
for clock wise
and
i am connecting the channel A to interrupt 1 and Channel B to interrupt 0, switching on the the circuit.
for anti clock wise...
Sir is there any ready made library is there for encoder.. witch i can use in AVR studio... for Audrino its there but i dont have any idea of Library for this which can be use in AVR studio.
 

Attachments

  • encoder.rar
    16.4 KB · Views: 39

alexan_e

Administrator
Joined
Mar 16, 2008
Messages
11,895
Helped
2,021
Reputation
4,158
Reaction score
2,031
Trophy points
1,393
Location
Greece
Activity points
64,377
I don't use arduino either, the code needs just a couple of modifications

Code:
#define encoder0PinA  2
#define encoder0PinB  4

volatile int encoder0Pos = 0;

// Service routine called by a timer interrupt
void DebounceSwitch()
{
  static unsigned char rawEncoder0A = 1;
  static unsigned char rawEncoder0B = 1;
  static unsigned char debouncedEncoder0A = 1;  // debounced state of encoder0PinA
  static unsigned char debouncedEncoder0B = 1;  // debounced state of encoder0PinB
  static uint16_t State[] = { 0, 0  }; // Current debounce status of encoder pins { A, B }

[COLOR="#FF0000"]  rawEncoder0A = (0 || encoder0PinA);	// rawEncoder0A = digitalRead(encoder0PinA);
  rawEncoder0B = (0 || encoder0PinB);	// rawEncoder0B = digitalRead(encoder0PinB);[/COLOR]

  // Encoder Pin A
  State[0]=(State[0]<<1) | rawEncoder0A | 0xe000;
  if(State[0]==0xf000) { // High --> Low Transition
    if (!debouncedEncoder0B) {   // check channel B to see which way
      // encoder is turning  
      encoder0Pos = encoder0Pos + 1;          // CW
    }
    else {
      encoder0Pos = encoder0Pos - 1;          // CCW
    }
    debouncedEncoder0A = 0;
  }
  if(State[0]==0xefff) { // Low --> High Transition
    //if (!debouncedEncoder0B) {  // check channel B to see which way
    //  // encoder is turning
    //  encoder0Pos = encoder0Pos - 1;         // CCW
    //}
    //else {
    //  encoder0Pos = encoder0Pos + 1;         // CW
    //}
    debouncedEncoder0A = 1;
  }

  // Encoder Pin B
  State[1]=(State[1]<<1) | rawEncoder0B | 0xe000;
  if(State[1]==0xf000) { // High --> Low Transition
    //if (debouncedEncoder0A == HIGH) {   // check channel A to see which way
    //  // encoder is turning  
    //  encoder0Pos = encoder0Pos + 1;          // CW
    //}
    //else {
    //  encoder0Pos = encoder0Pos - 1;          // CCW
    //}
    debouncedEncoder0B = 0;
  }
  if(State[1]==0xefff) { // Low --> High Transition
    //if (debouncedEncoder0A == HIGH) {  // check channel A to see which way
    //  // encoder is turning
    //  encoder0Pos = encoder0Pos - 1;         // CCW
    //}
    //else {
    //  encoder0Pos = encoder0Pos + 1;         // CW
    //}
    debouncedEncoder0B = 1;
  }

  // Clamp
  if (encoder0Pos < 0) encoder0Pos = 0;
  if (encoder0Pos > 32) encoder0Pos = 32;

}

The code changes encoder0Pos depending on the rotation , you can modify the code to do something different or return a result from the function etc.
 

ismbn

Full Member level 3
Joined
Feb 11, 2012
Messages
160
Helped
4
Reputation
8
Reaction score
4
Trophy points
1,308
Location
Mumbai. india
Activity points
2,444
Hello sir...
Please Check this code out, if there any thing that is not required please point me out.
this code is working good in proteus as well as in hardware...
Code:
#include <avr/io.h>
#include <util/delay.h>
#include <dbits/usart32.h>
int x=0,y=0,z1=0,z2,a=0;
long ctr=1000,ctr1=1000;
#define state1 0
#define state2 1
#define state3 3
#define state4 2
 

void go_encoder(char x, char y)
{
	if(x==state1 && y==state2 ){ctr++;print_str(" clock ");}
	else if(x==state4 && y==state3) {ctr--;print_str(" anti ");}
	else if(x==state2 && y==state3) {ctr++;print_str(" clock ");}
	else if(x==state3 && y==state2) {ctr--;print_str(" anti ");}

	else if(x==state3 && y==state4) {ctr++;print_str(" clock ");}
	else if(x==state2 && y==state1) {ctr--;print_str(" anti ");}
	else if(x==state4 && y==state1) {ctr++;print_str(" clock ");}
 	else if(x==state1 && y==state4) {ctr--;print_str(" anti ");}
	
// 	if(ctr1>ctr) print_str(" Clock ");
// 	else print_str(" Anti clock ");

 }

int main (void)
{
// 	DDRB=0xff;
//	DDRC=0xff;
	uart_init(103,0);
	while(1)
	{
		if(bit_is_set(PINA,2)) x=1;else x=0;
		if(bit_is_set(PINA,3)) y=2;else y=0;
		z1=x+y;
[COLOR="#FF0000"]
 more:          if(bit_is_set(PINA,2)) x=1;else x=0;
		if(bit_is_set(PINA,3)) y=2;else y=0;
		z2=x+y;
		if(z1==z2) goto more;
[/COLOR]	go_encoder(z1,z2);
		print(ctr);
	}
	
}
for now i have not connected it to interrupt.
but using pooling method.
if i just call it in ISR will it work?
also i am little worried about goto: command i have used.
it ok to use it????
Please Guide me...

Ismail
 

alexan_e

Administrator
Joined
Mar 16, 2008
Messages
11,895
Helped
2,021
Reputation
4,158
Reaction score
2,031
Trophy points
1,393
Location
Greece
Activity points
64,377
A goto usually is avoided although it can be used if you are careful.

You can replace it with

Code:
do {
    if(bit_is_set(PINA,2))
        x=1;
    else
        x=0;

    if(bit_is_set(PINA,3))
        y=2;
    else
        y=0;

    z2=x+y;
	
} while(z1==z2);
 
  • Like
Reactions: ismbn

    ismbn

    Points: 2
    Helpful Answer Positive Rating

ismbn

Full Member level 3
Joined
Feb 11, 2012
Messages
160
Helped
4
Reputation
8
Reaction score
4
Trophy points
1,308
Location
Mumbai. india
Activity points
2,444
actually i have to drive 3 motors, and have to take care of all. so i thinking to make the library of encoder.
how can i do this. i just want to pass minimum things, and get the result??? i have defined some micro and did some thing but its not working. i made it to work but i don't actually like the way i did.
how to make that. here it is
Code:
#define ENCA(add,bit) bit_is_set(add,bit)
#define ENCB(add,bit) bit_is_set(add,bit)

#define state1 0
#define state2 1
#define state3 3
#define state4 2
long ctr;
unsigned char clockx,clocky,clockz1,clockz2;
void go_count(char bit1, char bit2);

void encoder(){
		if(ENCA(PINA,2))	clockx=1;	else clockx=0;
		if(ENCB(PINA,3))	clocky=2;	else clocky=0;
		clockz1=clockx+clocky;
		
do {
    if(bit_is_set(PINA,2)) clockx=1; else  clockx=0;

    if(bit_is_set(PINA,3)) clocky=2; else  clocky=0;
     clockz2=clockx+clocky;
    } while(clockz1==clockz2);

     go_count(clockz1,clockz2);
}

void go_count(char bit1, char bit2)
{
	if(bit1==state1 && bit2==state2 )	  {ctr++;print_str(" clock ");}
	else if(bit1==state4 && bit2==state3) {ctr--;print_str(" anti ");}
	else if(bit1==state2 && bit2==state3) {ctr++;print_str(" clock ");}
	else if(bit1==state3 && bit2==state2) {ctr--;print_str(" anti ");}

	else if(bit1==state3 && bit2==state4) {ctr++;print_str(" clock ");}
	else if(bit1==state2 && bit2==state1) {ctr--;print_str(" anti ");}
	else if(bit1==state4 && bit2==state1) {ctr++;print_str(" clock ");}
 	else if(bit1==state1 && bit2==state4) {ctr--;print_str(" anti ");}

}

this is in .h fine that i am including. and here .c file
Code:
#include<avr/io.h>
#include<dbits/usart32.h>
#include<dbits/encoder.h>
long ctr;

int main (void){
uart_init(103,0);
while(1)
{

ctr = 1000;
encoder();
}
}

thanks
Ismail
 

alexan_e

Administrator
Joined
Mar 16, 2008
Messages
11,895
Helped
2,021
Reputation
4,158
Reaction score
2,031
Trophy points
1,393
Location
Greece
Activity points
64,377

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Top