Go Down

Topic: Using Motor Encoder with Arduino? (Read 1 time) previous topic - next topic

rwgast

Awesome thank you very much, do you happen to have any code using PID that keeps the wheels the same speed?

MarkT


Ive obviously got the wrong idea about something here.. This is how im thinking about Encoders

In order to keep track of pulses you need to count them obviously so for every hi pulse you would increment a variable. You would need to monitor two channels for each encoder, so overall to read a quad encoder you need two pins and two variables. This is just a simplification of things, ignoring overflow.


Two pins and one variable. You only need interrupt handler on only one of the pins (in CHANGE mode) if you're
prepared to reduce precision by a factor of two.  On the pin change XOR the two pins together - result is direction.

digitalRead() is quite slow, so direct port manipulation can really speed up such interrupt processing.
[ I won't respond to messages, use the forum please ]

WizenedEE


Awesome thank you very much, do you happen to have any code using PID that keeps the wheels the same speed?


haha no, that's quite a bit way down the road. First I'm working on tracking where the robot is based on the encoder values (differentiate to find speeds, rotate vector depending on angle, integrate to get new distance).

dreschel

If you want to measure velocity profiles with your encoder, then you definitely need to use a timer/counter. I have used the Mega to do this a few times. You put the 2 quadrature encoder channels to the INT0 and INT1 pins 20 and 21 of the MEGA. You set up the interrupt vectors for either transition:
         EICRA = B00000101; //EITHER EDGE FOR THE INTERRUPT
         EIMSK = B00000011; //INT0 and INT1 ENABLED

You have two interrupt routines ISR(INT0_vect) and ISR(INT1_vect). Both basically do the same thing. In those routines, you grab the two bits from the encoder channels and determine the way the encoder is turning. (I do it by using two arrays CW and CCW.) You also grab the count from the interval timer, reset it and start it running again. The ISRs store the encoder position in one unsigned integer array, the position in the first position, the timer interval in the second position. The MEGA has 8K of SRAM so you can store about 2000 samples without resorting to external RAM.

byte CW[4] = {0x01,0x03,0x00,0x02};
byte CCW[4] = {0x02,0x00,0x03,0x01};

//BOTH ISRs do the same thing

ISR(INT0_vect){
  byte encoded = PIND & 0x03; //converting the 2 lower bit value to single number

  last_e_direction = e_direction;
  if (CW[encoded] == lastEncoded) {encoderValue ++; e_direction = 1;}
  else if (CCW[encoded] == lastEncoded) {encoderValue --; e_direction = 0;}

lastEncoded = encoded;

//count is an unsigned integer that keeps track of the number of positions and timer intervals stored
  count+=2;
// ptr points to the array I am saving values in
  *ptr++ = (unsigned int) encoderValue;
// we use 16 bit timer 3 of the MEGA
  TCCR3B=0x00; //stop timer
//saving counter (time) value to the array
  *ptr++ = (unsigned int) TCNT3;
  TCNT3=0x00; // counter reset to zero;

  //enable overflow and input capture interrupts

  /* start timer, without prescaler, rising edge*/

  TCCR3B=0x41;
//Collect data untill you have filled the array

  if (count >= HIGHEST_COUNT) EIMSK = B00000000; //INT0 and INT1 DISABLED; //stop the interrupts when we have collected the full number
}
 

Go Up