zhanghaijason
Posts: 81
Joined: Tue Sep 29, 2015 9:23 pm

About encoder output "jump"

Fri Nov 06, 2015 12:32 am

Hello everyone,
Currently I am using raspi to make a closed loop speed control of the motor. When read the output of the encoder. I use the code below:\

Code: Select all

#include "stdio.h"
#include "rotaryencoder.h"
int main()
{
	printf("Hello!\n");
	wiringPiSetup();
	/*using pins 23/24*/
	struct encoder *encoder = setupencoder(4, 5);
	long cri;
	while (1)
	{
		updateEncoders();
		long l = encoder->value;
		if (l != cri)
		{
			printf("value: %d\n", (void *)l);
			value = l;
		}
	}
	return(0);
}

Code: Select all

#include <wiringPi.h>

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#include "rotaryencoder.h"

int numberofencoders = 0;

void updateEncoders()
{
    struct encoder *encoder = encoders;
    for (; encoder < encoders + numberofencoders; encoder++)
    {
        int MSB = digitalRead(encoder->pin_a);	  // -> an element in the struct
        int LSB = digitalRead(encoder->pin_b);

        int encoded = (MSB << 1) | LSB;			  //first left shift MSB and then 'or' it in byte with LSB	 The aim is to get output of AB '00' '01'......   or in byte!!!
        int sum = (encoder->lastEncoded << 2) | encoded;	// record the value of 

        if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoder->value++;		//Actually 1101 means 11-01, 0100 means 01-00.....   All these are colckwise
        if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoder->value--;	    // All these are counterclockwise

        encoder->lastEncoded = encoded;	  // save the current state of AB into encoder-
    }
}

struct encoder *setupencoder(int pin_a, int pin_b)
{
    if (numberofencoders > max_encoders)
    {
        printf("Maximum number of encodered exceded: %i\n", max_encoders);
        return NULL;
    }

    struct encoder *newencoder = encoders + numberofencoders++;
    newencoder->pin_a = pin_a;
    newencoder->pin_b = pin_b;
    newencoder->value = 0;
    newencoder->lastEncoded = 0;

    pinMode(pin_a, INPUT);
    pinMode(pin_b, INPUT);
    pullUpDnControl(pin_a, PUD_UP);
    pullUpDnControl(pin_b, PUD_UP);
    wiringPiISR(pin_a,INT_EDGE_BOTH, updateEncoders);
    wiringPiISR(pin_b,INT_EDGE_BOTH, updateEncoders);

    return newencoder;
}
The output of is like value:1 value:2 value:3....... (the number of the pulse generated by encoder) . But after some time, the output may jump, like value:733 value: 2000. Could anyone who has the experience about encoder help me?
Thanks and best regards.

User avatar
AndyD
Posts: 2326
Joined: Sat Jan 21, 2012 8:13 am
Location: Melbourne, Australia
Contact: Website

Re: About encoder output "jump"

Fri Nov 06, 2015 12:40 am

zhanghaijason wrote:

Code: Select all

			printf("value: %d\n", (void *)l);
Why are you casting the long value l to a void * pointer? Try printing like this.
zhanghaijason wrote:

Code: Select all

			printf("value: %ld\n", l);

zhanghaijason
Posts: 81
Joined: Tue Sep 29, 2015 9:23 pm

Re: About encoder output "jump"

Fri Nov 06, 2015 12:45 am

AndyD wrote:
zhanghaijason wrote:

Code: Select all

			printf("value: %d\n", (void *)l);
Why are you casting the long value l to a void * pointer? Try printing like this.
zhanghaijason wrote:

Code: Select all

			printf("value: %ld\n", l);
Thanks for your reply first, AndyD. I tried but it still jump. Sometimes even jump from 2000 to -200

davenull
Posts: 1162
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

Re: About encoder output "jump"

Fri Nov 06, 2015 3:44 pm

are your pins 4+5 according to wiringPi counting system?

struct encoder *setupencoder(4, 5);

what is cri?

if (l != cri)
{
printf("value: %ld\n", l);
value = l;
}

ps,
will test this in a couple of hours at home by myself!
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

davenull
Posts: 1162
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

Re: About encoder output "jump"

Fri Nov 06, 2015 6:34 pm

ok, I start trying.

1st, how can I download and install the rotary encoder libs on my SD card?
1 step after the other

they must be available system-wide from either working directory
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

davenull
Posts: 1162
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

Re: About encoder output "jump"

Fri Nov 06, 2015 8:21 pm

nobody got any quick guide availble ?
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

zhanghaijason
Posts: 81
Joined: Tue Sep 29, 2015 9:23 pm

Re: About encoder output "jump"

Fri Nov 06, 2015 10:04 pm

davenull wrote:ok, I start trying.

1st, how can I download and install the rotary encoder libs on my SD card?
1 step after the other

they must be available system-wide from either working directory
Sorry Davenull, I didn't check the forum in time. The codes can be downloaded here:https://github.com/astine/rotaryencoder And http://planb.nicecupoftea.org/2013/06/3 ... pberry-pi/

The cri in the code is just used to prevent from printing the same output of the encoder->value. If cri==l, then it will not print the value of encoder->value
Thanks

davenull
Posts: 1162
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

Re: About encoder output "jump"

Sat Nov 07, 2015 7:47 am

how exactly are the download and install commands?
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

davenull
Posts: 1162
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

Re: About encoder output "jump"

Sat Nov 07, 2015 12:27 pm

I cant make this lib working.

but I tried my own code which is working fine on Arduino Mega (by AVR timer IRQs) and on Arduino DUE (by quick DueTimer Loops of 100µs)..

The good news: for extremely slow rotations (<100 encoder ticks / sec) it works by the Raspi.

The bad news:
for normal rotation speed (2000 encoder ticks/sec) the values are jerking and are counting to wrong directions.
when plugged back to Arduinos again, everything is fine nevertheless !!!!

I think, the Raspi is simply far too slow for pin reading and quick reliable encoder value processing!!!
We needed to have hardware-Interrupts on processor level, not in user space !!


Code: Select all

// 
// rotary encoder test

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <stdint.h>
#include <errno.h>

#include <termios.h>

#include "VG/openvg.h"
#include "VG/vgu.h"
#include "fontinfo.h"
#include "shapes.h"

#include <wiringPi.h>
#include <wiringSerial.h>

#define  byte  uint8_t;
#define  MAXMOTORS           2 // max number of encoder motors at Arduino Uno=2 // Due=6 // Mega=8


// motor 0
#define pinenc0A   4  // enc0A yellow
#define pinenc0B   5  // enc0B blue
#define pinmot0d1  14  // dir0-1   <<
#define pinmot0d2  15  // dir0-2
#define pinmot0pwm 16  // pwm enable0   

// motor 1
#define pinenc1A   6  // enc1A yellow
#define pinenc1B   7  // enc1B blue
#define pinmot1d1  17 // dir1-1   <<
#define pinmot1d2  18  // dir1-2
#define pinmot1pwm  19  // pwm enable1   



volatile long   motenc[MAXMOTORS], 
                oldenc[MAXMOTORS] ;
               
int pinmotdir[MAXMOTORS][ 2] = {
  {pinmot0d1, pinmot0d2} ,  // motor direction pin array
  {pinmot1d1, pinmot1d2}
};

int  pinmotpwm[MAXMOTORS] =      {pinmot0pwm, pinmot1pwm };

volatile int8_t ISRab[MAXMOTORS];

// 1/2 Auflösung
int8_t encTab[16] = {0, 0,0,0,1,0,0,-1, 0,0,0,1,0,0,-1,0};

                              
                                 
/*************************************************************
* Interrupt Handler Routine
*************************************************************/


void setup() {
  // motor pin settings
  // setup for L293D motor driver 
  // pullUpDnControl (butpin, PUD_UP);

     // motor 0
     pinMode(pinenc0A, INPUT);          // enc0A    yellow
     pullUpDnControl(pinenc0A, PUD_UP);    
     pinMode(pinenc0B, INPUT);          // enc0B    blue
     pullUpDnControl(pinenc0B, PUD_UP); 
     pinMode(pinmot0d1, OUTPUT);        // dir0-1   
     pinMode(pinmot0d2, OUTPUT);        // dir0-2   
     pinMode(pinmot0pwm ,OUTPUT);       // enable0 
       
     // motor 1
     pinMode(pinenc1A, INPUT);          // enc0A    yellow
     pullUpDnControl(pinenc1A, PUD_UP);    
     pinMode(pinenc1B, INPUT);          // enc0B    blue
     pullUpDnControl(pinenc1B, PUD_UP); 
     pinMode(pinmot1d1, OUTPUT);        // dir1-1   
     pinMode(pinmot1d2, OUTPUT);        // dir1-2 
     pinMode(pinmot1pwm, OUTPUT);       // enable1   

}


void loop() {
  char sbuf[128];	 
	 
  while(true) {  
	 
    ISRab [ 0] <<= 2;
    ISRab [ 0] &=  0b00001100;
    ISRab [ 0] |= (digitalRead(pinenc0A) << 1) | digitalRead(pinenc0B);
    motenc[ 0] += encTab[ISRab[0]];           //

    ISRab [ 1] <<= 2;
    ISRab [ 1] &= 0b00001100;
    ISRab [ 1] |= (digitalRead(pinenc1A) << 1) | digitalRead(pinenc1B);
    motenc[ 1] += encTab[ISRab[1]];           //


	  
     sprintf(sbuf, " 0=%6d, \n ",  motenc[ 0]);
     printf(sbuf);
     delay(5);
  }
}


int main() {
    char  sbuf[128];
    
    wiringPiSetup();
    if(wiringPiSetup() == -1) return 1;
     
    setup();
    loop();
    
}
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

User avatar
joan
Posts: 13556
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: About encoder output "jump"

Sat Nov 07, 2015 1:40 pm

The Pi is not an Arduino. It has a multi-tasking, multi-user operating system. You should not expect code which only works on a dedicated CPU without an operating system to work on the Pi.

Why not Google for Pi rotary encoder code? There must be hundreds of working examples.

What do you mean by 2000 encoder ticks a second? Is that 8000 switch contact state changes per seconds?

davenull
Posts: 1162
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

Re: About encoder output "jump"

Sat Nov 07, 2015 1:44 pm

Also the DUE (and even the Mega optionally) is running by multitasking plus Hardware and Timer Interrupts, but I agree: bare metal, not Linux.

I googled and read a lot in the web but all the RASPI libs are either confusing or don't work at all or don't work reliably (like my own approach and the one of the TO).
My own code runs perfectly and absolutely accurately both on my Mega and on my Due.

http://www.mindstormsforum.de/viewtopic ... 624#p67235

I dont know how many switch contacts state changes.
I get a 0.5° or optionally a 1° resolution of the encoder readings (1-2 "ticks" per axle rotation degree),
so 360-720 "ticks" per 1 revolution,
the motors are rotating by about 1000-1500(-2000) degrees per second = about 2- 5 revolutions per second.
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

User avatar
joan
Posts: 13556
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: About encoder output "jump"

Sat Nov 07, 2015 2:04 pm

The code you have will work at higher rates if you change delay(5) to delay(1). That delay is in units of milliseconds so a delay 5 imposes a limit of 200 changes per second.

I suspect you will have to use pigpio if you want reliable results, especially if the encoder is purely mechanical and has no debounce hardware.

davenull
Posts: 1162
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

Re: About encoder output "jump"

Sat Nov 07, 2015 2:08 pm

we had this discusion before, but even if I get quicker pin readings, nevertheless the encoder value computation is done exactly quite as slow as before (CMIIW)

is the loop cycle perhaps slowed down by terminal output?

I also assumed that delay is a non-busy wait... :-/
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

User avatar
joan
Posts: 13556
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: About encoder output "jump"

Sat Nov 07, 2015 2:10 pm

davenull wrote:we had this discusion before, but even if I get quicker pin readings, nevertheless the encoder value computation is done exactly quite as slow as before (CMIIW)

is the loop cycle perhaps slowed down by terminal output?

I also assumed that delay is a non-busy wait... :-/
Did you try? What code did you use?

davenull
Posts: 1162
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

Re: About encoder output "jump"

Sat Nov 07, 2015 2:11 pm

delay(1) is also faulty. now I try no delay at all.....
Last edited by davenull on Sat Nov 07, 2015 2:12 pm, edited 1 time in total.
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

davenull
Posts: 1162
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

Re: About encoder output "jump"

Sat Nov 07, 2015 2:12 pm

no delay even worse!, almost hangs up completely
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

davenull
Posts: 1162
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

Re: About encoder output "jump"

Sat Nov 07, 2015 2:16 pm

I need 2 tasks
1 high priority for encoder pins and computation

1 normal priority for screen output.

perhaps additionally 1 mutex then for the high pri task.

how to do it?
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

davenull
Posts: 1162
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

Re: About encoder output "jump"

Sat Nov 07, 2015 5:09 pm

now this code seperating the pin reading task from the values screen-writing task is still too slow.
When 360° should have been read, it's just < 300.

using usleep(20) instead of 50 doesn't make it better.

Code: Select all

// encoder test
//

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <stdint.h>
#include <errno.h>
#include <pthread.h>
#include <termios.h>

#include "VG/openvg.h"
#include "VG/vgu.h"
#include "fontinfo.h"
#include "shapes.h"

#include <wiringPi.h>
#include <wiringSerial.h>



#define  byte  uint8_t;

#define  MAXMOTORS           2 // max number of encoder motors at Arduino Uno=2 // Due=6 // Mega=8


// motor 0
#define pinenc0A   4  // enc0A yellow
#define pinenc0B   5  // enc0B blue
#define pinmot0d1  14  // dir0-1   <<
#define pinmot0d2  15  // dir0-2
#define pinmot0pwm 16  // pwm enable0   

// motor 1
#define pinenc1A   6  // enc1A yellow
#define pinenc1B   7  // enc1B blue
#define pinmot1d1  17  // dir1-1   <<
#define pinmot1d2  18  // dir1-2 
#define pinmot1pwm 19  // pwm enable1   


volatile long   motenc[MAXMOTORS], 
                oldenc[MAXMOTORS] ;
               
int pinmotdir[MAXMOTORS][ 2] = {
  {pinmot0d1, pinmot0d2} ,  // motor direction pin array
  {pinmot1d1, pinmot1d2}
};

int  pinmotpwm[MAXMOTORS] =      {pinmot0pwm, pinmot1pwm };

volatile int8_t ISRab[MAXMOTORS];

// 1/2 Auflösung
int8_t enctab[16] = {0, 0,0,0,1,0,0,-1, 0,0,0,1,0,0,-1,0};
                              
                                 
/*************************************************************
* Interrupt Handler Routine
*************************************************************/


void setup() {
  int i;	
	
  // motor pin settings
  // setup for L293D motor driver 
  // pullUpDnControl (butpin, PUD_UP);
  
  
  // motor 0
     pinMode(pinenc0A, INPUT);          // enc0A    yellow
     pullUpDnControl(pinenc0A, PUD_UP);    
     pinMode(pinenc0B, INPUT);          // enc0B    blue
     pullUpDnControl(pinenc0B, PUD_UP); 
     pinMode(pinmot0d1, OUTPUT);        // dir0-1   
     pinMode(pinmot0d2, OUTPUT);        // dir0-2   
     pinMode(pinmot0pwm ,OUTPUT);       // enable0 
       
  // motor 1
     pinMode(pinenc1A, INPUT);          // enc0A    yellow
     pullUpDnControl(pinenc1A, PUD_UP);    
     pinMode(pinenc1B, INPUT);          // enc0B    blue
     pullUpDnControl(pinenc1B, PUD_UP); 
     pinMode(pinmot1d1, OUTPUT);        // dir1-1   
     pinMode(pinmot1d2, OUTPUT);        // dir1-2 
     pinMode(pinmot1pwm, OUTPUT);       // enable1   

     for( i=0; i< MAXMOTORS; ++i) motenc[i] = 0;
     for( i=0; i< MAXMOTORS; ++i) ISRab[i] = 0; 

}



void* thread3Go(void *)
{
   while(1) {
	   delay(1);
   }			
   return NULL;
}

void* thread2Go(void *)
{
   while(1) {
	   delay(1);
   }			
   return NULL;
}

void* thread1Go(void *)
{
   char  sbuf[128];
   while(1) {
      sprintf(sbuf, " 0=%6ld, \n ",  motenc[ 0]);
      printf(sbuf);
      delay(100);
   }			
   return NULL;
}


void* thread0Go(void *) {
  char sbuf[128];	 
	 
  while(1) {  
	 
    ISRab [ 0] <<= 2;
    ISRab [ 0] &=  0b00001100;
    ISRab [ 0] |= (digitalRead(pinenc0A) << 1) | digitalRead(pinenc0B);
    motenc[ 0] += enctab[ISRab[0]];          

    ISRab [ 1] <<= 2;
    ISRab [ 1] &= 0b00001100;
    ISRab [ 1] |= (digitalRead(pinenc1A) << 1) | digitalRead(pinenc1B);
    motenc[ 1] += enctab[ISRab[1]];           

    usleep(50);  
    
  }
}


int main() {
    char  sbuf[128];
    pthread_t thread0, thread1, thread2, thread3;
    
    wiringPiSetup();
    
    if(wiringPiSetup() == -1) return 1;    
   
    setup();
    
    pthread_create(&thread0, NULL, thread0Go, NULL);
    pthread_create(&thread1, NULL, thread1Go, NULL);
    pthread_create(&thread2, NULL, thread2Go, NULL);
    pthread_create(&thread3, NULL, thread3Go, NULL);
    
     
    pthread_join(thread0, NULL);
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    pthread_join(thread3, NULL);
    
    exit(0);
    
}
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

zhanghaijason
Posts: 81
Joined: Tue Sep 29, 2015 9:23 pm

Re: About encoder output "jump"

Sat Nov 07, 2015 7:05 pm

davenull wrote:how exactly are the download and install commands?
I just download the lib on the two websites above without using command.

User avatar
[email protected]
Posts: 1979
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
Contact: Website

Re: About encoder output "jump"

Sat Nov 07, 2015 7:19 pm

Curiously enough I've just coded up a typical (cheap) rotary encoder into a Pi. It sufers bounce issues, but does work well. It doesn't do that faffing about checking pin states- 00 01 10 11 encoding, but uses an interrupt on line A, then sample on line B. Seems fine and I'll be adding this into wiringPi in due course, but:

Code: Select all

#include <stdio.h>
#include <wiringPi.h>

#define	PIN_A	8
#define	PIN_B	9

#define	DEBOUNCE	5

static volatile int counter ;

void encoder (void)
{
  static unsigned int debounce = 0 ;

// If PIN_A is high then ignore it
//	This may be due to bouncing, or a bug/feature of the edge detect

  if (digitalRead (PIN_A) == HIGH)
    return ;

// Ignore multiple interrupts inside our debounce time

  if (millis () < debounce)
    return ;

  if (digitalRead (PIN_B) == LOW)	// Anti-clockwise
    --counter ;
  else
    ++counter ;

  debounce = millis () + DEBOUNCE ;
}

int main ()
{
  int last ;

  wiringPiSetup () ;

  last = counter = 0 ;

  wiringPiISR (PIN_A, INT_EDGE_FALLING, encoder) ;

  printf ("\nRunning... \n") ;

  for (;;)
  {
    if (counter != last)
    {
      printf ("%5d\n", counter) ;
      last = counter ;
    }
    delay (1) ;
  }

  return 0 ;
}
works well enough for what I need it for for now.
(Using it with a cheap encoder with 20 detents per revolution)

-Gordon
--
Gordons projects: https://projects.drogon.net/

davenull
Posts: 1162
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

Re: About encoder output "jump"

Sun Nov 08, 2015 9:23 am

thank you Gordon, I tried that immediatly, but it's also counting not quick enough.

By your coding, for a whole revolution at 1° resolution instead of 360° now just 220° can be detected, even at a very slow rotation speed (1 revol./sec) , which is even less than by my pthread and bitshifting approach (which counted 300 of 360° at 4 revol./sec which is still faulty, nevertheless).

Just out of curiousity: why do you just monitor the pinchange on pin A (for me it's pin 4 instead of 8), not additionally on pin B (for me, pin 5 instead of 9) ?


NOTE:
BTW, just for your interest, I'm using the Lego Minstorms NXT or EV3 encoder motors. The technical resolution is even 720° per revolution (!!), but I'm using half resolution by my software algorithm because of convenience reasons. This agoithm is working highly accurate on my Arduino AVRs and ARMs.

http://www.philohome.com/nxtmotor/nxtmotor.htm

Image
Last edited by davenull on Sun Nov 08, 2015 9:33 am, edited 1 time in total.
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

User avatar
[email protected]
Posts: 1979
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
Contact: Website

Re: About encoder output "jump"

Sun Nov 08, 2015 9:32 am

davenull wrote:thank you Gordon, I tried that immediatly, but it's also counting not quick enough.

By your coding, for a whole revolution at 1° resolution instead of 360° now just 220° can be detected, even at a very slow rotation speed (1 revol./sec) , which is even less than by my pthread and bitshifting approach (which counted 300 of 360° at 4 revol./sec which is still faulty, nevertheless).
Are you the same person that's been emailling me about this? If-so, I think I gave the answer - it's all to do with latency of getting the interrupt and the debounce. If you're using an optical encoder and not a mechanical one try removing the debounce code...
Just out of curiousity: why do you just monitor the pinchange on pin A (for me it's pin 4 instead of 8), not additionally on pin B (for me, pin 5 instead of 9) ?
Because you don't need to. You wait for Pin A to make a high to low transition, then sample Pin B. If it's high, you turned it one way, if its low, then it's going the other way. Simples.

-Gordon
--
Gordons projects: https://projects.drogon.net/

davenull
Posts: 1162
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

Re: About encoder output "jump"

Sun Nov 08, 2015 9:52 am

(edited:)

yes, I am, and yes, it's an optical encoder.

I removed the debounce and now it's counting about 180° per revolution, not 360°, but even for quicker rotations, mostly accurate, but NOT for higher speed at >=3 rev. /sec.. If so for faster rotations, then again counter ticks are missing.

actually 180° is just 1/4 of the actual encoder counter signal readings, so:
Is it possible to have twice the current sensitivity, i.e. 360°/rev ? (technically even 720° are possible, see my edit above).

- Helmut


ps, edit:
for 2-4 motors simultaneously not tested yet!
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

PiGraham
Posts: 3400
Joined: Fri Jun 07, 2013 12:37 pm
Location: Waterlooville

Re: About encoder output "jump"

Sun Nov 08, 2015 10:07 am

[email protected] wrote:
davenull wrote: Just out of curiousity: why do you just monitor the pinchange on pin A (for me it's pin 4 instead of 8), not additionally on pin B (for me, pin 5 instead of 9) ?
Because you don't need to. You wait for Pin A to make a high to low transition, then sample Pin B. If it's high, you turned it one way, if its low, then it's going the other way. Simples.

-Gordon
Quite right, although that does mean you get 1/4 resolution because you don't count on every transition. There are four - rising and falling on a and B.
If you catch every transition of A and B, sampling the other phase state in the callback, you can count all the increments.

The important thing is to sample the other phase with minimal delay, but the count should be right as long as there is not another edge transition before the first has sampled.

davenull
Posts: 1162
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

Re: About encoder output "jump"

Sun Nov 08, 2015 10:17 am

thanks for your input!

so what would you suggest for 360° (1/2) instead of 180° (1/4) resolution which would work perfectly then (360 counts for 1 rev for calculating is accurate enough and makes calculations easier for odometry as 1 encoder count == 1 dregree, not 2 degrees, and not 0.5 degrees in reality)?

Now what code changes would you suggest in detail:
an extra low/high transition (i.e., pin_change instead of pin_falling) on pinA
or better an extra transition on pin B ?
Last edited by davenull on Sun Nov 08, 2015 10:25 am, edited 1 time in total.
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

Return to “C/C++”

Who is online

Users browsing this forum: No registered users and 6 guests