Optical encoder questions

I just got about 4 millions optical encoders for christmas, and I want to know what the programming is like for them.

There digital input right? If so, how does that work out??

Also, I got a girl sitting next to me correct my grammar… ANNOYING!!!

well, they are not digital input, they run out of interrupts ports. im sure you know they have 90 clicks per revolution, so setting up a distance is really easy. i have used them to make a robot move 9 ft very accurately.

Here’s the download to some simple test code for all vex sensors including shaft encoders http://www.vexlabs.com/vex-robotics-downloads.shtml

This should get you started. The encoders use interupts because they are sending data faster than the programming loop can log it.

Can’t help you with the girl problems man - but VEX stuff - maybe.:slight_smile:

The optical encoders can be used in either interrupt or digital I/O ports. The speed at which you want to read them is another matter. I have several posts on this topic but don’t remember the subject lines.

Nevertheless, if you are going to use them in applications that are faster than say 10 rpm, you will need to use user_routines_fast.c (MPLAB) to capture each pulse. Interrupt routines can be used, but they come at the expense of overhead and details of PIC operations. On the other hand, for my applications, I just write a chunk of code in the “fast” section (not the interrupt section) and that is more than fast enough for any optical sensor applications.

Here is the latest chunk of code for my bot - it is raw and not fancied up at all. (I use limit switches to indicate extreme lifter positions).



#define MAIN_OPTICAL_ENCODER rc_dig_int1
#define SECONDARY_OPTICAL_ENCODER rc_dig_int2
#define LIFT_HIGH_SWITCH      rc_dig_int3 
#define LIFTER_FLOOR_SWITCH   rc_dig_in08

/*** DEFINE USER VARIABLES AND INITIALIZE THEM HERE ***/

int lifter_position = 0;
int temp_counter=0;
int lifter_lo_res = 0;
extern unsigned char lift_reset_flag;
  //0=ready for use, 1=reset enabled, 2=reset completed, 3 = force immediate reset
unsigned char current_state = 0; // holds the current state of the encoders.
unsigned char last_state = 0; // holds the previous state of the encoders.

#ifdef nobuild
unsigned int count=0, state=0;
#endif

.
.
.
.

void Process_Data_From_Local_IO(void)
{
  /* Add code here that you want to be executed every program loop. */
#ifdef nobuild

  // the following works with or without the receiver on.

  if (rc_dig_in05  && state)
  {
    state = 0;
    count++;
  }
  if (!rc_dig_in05) state=1;
  if (!rc_dig_in06) count=0;

#endif

// the following manages the lifter_position number

// Hold count on reset until first rising edge of limit switches
  if(((LIFT_HIGH_SWITCH == 0) || (LIFTER_FLOOR_SWITCH == 0)) && (lift_reset_flag == 1)) 
  {
    // limit switch closed, hold counters at zero
    lifter_position = 0;
    temp_counter = 0;
    lifter_lo_res = 0;
  }
  // If both limit switches are open and lift reset flag is 1, move it to a 2.
  // This is to ensure that the counters stay at reset until the switch opens.
  if(!((LIFT_HIGH_SWITCH == 0) || (LIFTER_FLOOR_SWITCH == 0)) && (lift_reset_flag == 1)) lift_reset_flag = 2;

  if(lift_reset_flag == 3)
  {
    // Immediate reset!
    lifter_position = 0;
    temp_counter = 0;
    lifter_lo_res = 0;
    lift_reset_flag = 2; // reset only one time
  }

// Get current State
  current_state = MAIN_OPTICAL_ENCODER ? 1 : 0;
  current_state = SECONDARY_OPTICAL_ENCODER ? (current_state+2) : current_state;

// process for raising arm (decreasing lifter_position)
// main - sec. - state
//  0      0       0  
//  1      0       1  
//  1      1       3  
//  0      1       2
//  repeat
//  last - new - action
//    2     0     decrement
//    1     0     increment
//    0     1     decrement
//    3     1     increment
//    1     3     decrement
//    2     3     increment
//    3     2     decrement
//    0     2     increment
// Reverse ports or actual sensor plugs to get proper phasing for up/down

  switch (current_state)
    {
    case 0:
      if (last_state == 2) lifter_position--; // decrease
      if (last_state == 1) lifter_position++; // increase
      break;
    case 1:
      if (last_state == 0) lifter_position--; // decrease
      if (last_state == 3) lifter_position++; // increase
      break;
    case 3:
      if (last_state == 1) lifter_position--; // decrease
      if (last_state == 2) lifter_position++; // increase
      break;
    case 2:
      if (last_state == 3) lifter_position--; // decrease
      if (last_state == 0) lifter_position++; // increase
      break;
    }
  //last_state = current_state; // post-update last state so counters only
                              // change by one

  // the following is for the low resolution counter
  switch (current_state)
    {
    case 0:
    case 2:
      if ((last_state == 3) || (last_state == 1))
      {
        //for the low resolution counter, direction is not determined
        //by the other optical counter.
        temp_counter++; // for low resolution counter
        last_state = current_state;
      }
      break;
    case 1:
    case 3:
      if ((last_state == 0) || (last_state == 2))
      {
        //for the low resolution counter, direction is not determined
        //by the other optical counter.
        temp_counter++; // for low resolution counter
        last_state = current_state;
      }
      break;
    }
  lifter_lo_res = temp_counter / 8;
        // since temp_counter changes on every edge of one encoder, there
        // are 180 counts per revolution.  180/8 gives 22.5 counts per rev.
        // Division done for noise immunity.

}

This lives in the user_routines_fast.c. I had real crummy luck with my quadrature effort, so I slapped in a lower resolution version instead.

Anyway, it is 11:30pm on a Saturday, and I better get back to my other life.

EJ

I’m having problems getting my program to read my encoder fast enough to be acurate (trying to get a shaft to turn 90 degrees). Unfortunately, Easy-C is as far as my skills and resources go, and the deadline for our class competition is fast approaching. Any Insight would be great.

Are you able to slow down the shaft’s rotation enough to solve your problem that way?

Here’s some more of the facts: I tested my custom encoder with the encoder test program and it read and displayed every single notch without skipping any numbers. This tells me the encoder works fine.
I have tried slowing the motor down, but it is doing a lot of work. So when I slow it down to where the program will read every notch, the motor won’t turn.

Try gearing down the shaft that has the wheel on it, so that the motor turns at its normal rate, but the shaft will be slowed down.

You night want to ut the encoder on the motor shaft and not an axle that has been geard up or down.