Rotary Encoder Value only Increasing, Not able to Decrease

Go To Last Post
9 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

I am trying to use rotary encoder in my project so was testing with initial test setup, Code works but it only increases value in either direction either clockwise or CCW.

 

Below is the code please if anyone help me to analyse.

 

void encoder_ID()
{	
	n = PINC & _BV(PC0);
	if((alaststate == 0) && (n == 1))
	{
		if((PINC & _BV(PC1)) == 0)
		{
			encoder--;
		}
		else
		{
			encoder++;
		}
	//	_delay_ms(200);
	
	}
	alaststate = n;
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

asking wrote:
Below is the code please if anyone help me to analyse.

What happens when you run in the simulator, or work through on paper?

 

It looks to me as though your previous-state check is forcing uni-directional.

 

In my quadrature encoder work, I assume that I am getting clean edges and will be able to service all the edges.  But I do it interrupt-driven.  You have not given us enough context, nor told us max edge rate, nor quadrature "flavor":

 

x1 -- 1 signal; 1 edge

x2 -- 1 signal; both edges

x4 -- both signals; both edges

 

http://www.avrfreaks.net/comment...

http://www.avrfreaks.net/comment...

http://www.avrfreaks.net/comment... and links therein

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Sat. Aug 12, 2017 - 08:24 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Check your wiring.

I once had a similar situation where I switched one of the data signals with the common pin of the encoder.

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks will take a look at wires and will get back.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

theusch

 

Actually there's no speed matter in my case. I am using it for Changing Menu in 16x2 LCD or Changing PWM Rates. So i would say polling should work. But if anyone has working Polling code, please share. 

Last Edited: Mon. Aug 14, 2017 - 04:53 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I just tried simulating your code and it does seem to work. Some issues I spotted:

  • there is no protection against wrap-around of the variable "encoder"
  • I had to guess the declarations of "n", "alaststate" and "encoder" - it would be better if you provided the declarations
  • you have not shown how the variable "encoder" is actually used

 

I suggest you make a small example code that exhibits the encoder problem, then provide all the code for that case.

/Jakob Selbing

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Even if your signal is slow I would suggest you used an interrupt to handle that. Pin Change interrupt is sufficient. Trigger on one signal and in ISR handler check the state of the other input. if it's low - decrease, if high - increase. Easy as that. Just don't forget to declare the value volatile.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
volatile uint8_t alaststate = 0,astate = 0,n = 0, n1 = 0,encoder = 0;

void encoder_ID()
{	

	if(bit_is_clear(PIND, 6))
	n = 0;
	else if(bit_is_set(PIND, 6))
	n = 1;

	if(bit_is_clear(PIND, 7))
	n1 = 0;
	if(bit_is_set(PIND, 7))
	n1 = 1;

//	astate = PINC & _BV(PC0);
	astate = n;
	if(n != alaststate)
	{
		if(n1 != astate)
		{
			encoder++;
		}
		else
		{
			encoder--;
        }

	}
	alaststate = astate;
}

int main(void)
{
	DDRB = 0XFF; // ALL OUTPUT
	DDRC = 0X00; // ALL INPUT ADC
	DDRD = 0X3F;// ALL OUTPUT // 6 7 INPUT
//	PORTC = 0X03; // PULL UP ENABLE EFOR PC1,PC0
	PORTD = 0X00;//

	while(1)
	{
		encoder_ID();

    }
}

 

This is my code. Please can you suggest how to use interrupt provide me editing in my code to use interrupt on Atmega8A. i think polling should work... but i wonder why its not working this code i adapted from Arduino.

 

 

Last Edited: Tue. Aug 15, 2017 - 06:20 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I took the following from an Arduino example and modified it as a simple c program, try it and see if it works for you.

 

/* Read Quadrature Encoder
  Connect Encoder to Pins encoder0PinA, encoder0PinB, and +5V.
*/
#define HIGH 1
#define LOW  0

int val;
//int encoder0PinA = 3;  PIND 6
//int encoder0PinB = 4;  PIND 7
int encoder0Pos = 0;
int encoder0PinALast = LOW;
int n = LOW;

void setup()
{
    DDRD = 0x3f; //pinMode (encoder0PinA, INPUT);
    //pinMode (encoder0PinB, INPUT);
    //Serial.begin (9600);
}

void main()
{
    setup();  //init encoder pins

    While(1) {
        n = PIND & (1 << pd6); 			 	//digitalRead(encoder0PinA);
        if ((encoder0PinALast == LOW) && (n == HIGH)) {
            if ((PIND & (1 << pd7) == LOW)) {	//(digitalRead(encoder0PinB) == LOW) {
                encoder0Pos--;
            }

            else {
                encoder0Pos++;
            }
            //Serial.print (encoder0Pos);
            //Serial.print ("/");
        }
        encoder0PinALast = n;
    }
}

If it works, compare to your code.

 

Jim