Close

Arduino Due reads encoder

A project log for Load Frame Update

Add digital output to a mechanical testing load frame using arduino.

mark-bradshawMark Bradshaw 10/27/2016 at 15:210 Comments

In the last post I described how the Instron 1000 main board is taking the two encoder signals and their inverted twins and mixing and buffering them to reduce noise. The resulting two signals have a normal two wire rotary encoder pattern and can be measured like any other encoder but first they need to be shifted from 12V logic at the Instron to 3V for the Arduino Due.

To shift the signals I am using a Sparkfun BOB-12009 logic level converter. It's overkill for this maybe but it is easy to use, the 12V logic and 12V power are connected on one side and 3V from the Arduino supply is connected to the other side with connections to the Arduino digital input pins.

The Arduino code was a little trickier. At first I tried using the Encoder library by Paul Stoffregen which can be accessed through the Arduinoo IDE library manager. The library looks great but I found I was losing steps even at low speeds no matter what optimizations I flipped on or off. The encoder on this machine really hums along, I measure about 162500 steps / Inch, with crosshead travel able to go up to about 20 inch / min thats about 55,000 steps per second. As I searched for some more options I happened to find that the Arduino Due actually has a hardware encoder! This thread on the Arduino forum was really helpful [1] with a few examples. I mashed those a bit and wound up with this minimal code:

void setup() {
  // Setup the quadrature encoder
  // For more information see http://forum.arduino.cc/index.php?topic=140205.30
  REG_PMC_PCER0 = PMC_PCER0_PID27;   // activate clock for TC0
  REG_TC0_CMR0 = TC_CMR_TCCLKS_XC0;  // select XC0 as clock source

  // activate quadrature encoder and position measure mode, no filters
  REG_TC0_BMR = TC_BMR_QDEN
              | TC_BMR_POSEN
              | TC_BMR_EDGPHA;

  // enable the clock (CLKEN=1) and reset the counter (SWTRG=1)
  REG_TC0_CCR0 = TC_CCR_CLKEN | TC_CCR_SWTRG;
}

// The encoder position is then accessed from
void loop() {
  int newPosition = REG_TC0_CV0; // Read the encoder position from register
}
and this has been totally solid. I put this value out over the serial connection periodically where the computer can read it.

[1] http://forum.arduino.cc/index.php?topic=140205.30

Discussions