Go Down

Topic: Using the Hardware Quadrature Encoder Channel on the DUE (Read 17 times) previous topic - next topic

pingflip

I'm currently working my self through the datasheet and the Timer/Counter relating header and source files and I think I'm almost there :)
But: which T/C channel should I use to not generate conflicts with a PWM output or any other peripheral.

Does any one know which channels are already in use by the PWM and / or other functions?

schwingkopf

I got the hardware quadrature encoder running partially...

Using the following code and a motor with a 2 trace quadrature encoder I manage to make the REG_TC0_CV0 register measure the position of the motor. To use the hardware quadrature encoder the two traces need to be connected to digital pins 2 and 13 which correspond to the TIOA0 and TIOB0 peripheral pin function of the SAM3x8e. I didn't test using the Index pin for revolution counting yet...

Code: [Select]

const int quad_A = 2;
const int quad_B = 13;
const unsigned int mask_quad_A = digitalPinToBitMask(quad_A);
const unsigned int mask_quad_B = digitalPinToBitMask(quad_B); 

void setup() {
    Serial.begin(115200); 
    delay(100);
   
    // activate peripheral functions for quad pins
    REG_PIOB_PDR = mask_quad_A;     // activate peripheral function (disables all PIO functionality)
    REG_PIOB_ABSR |= mask_quad_A;   // choose peripheral option B   
    REG_PIOB_PDR = mask_quad_B;     // activate peripheral function (disables all PIO functionality)
    REG_PIOB_ABSR |= mask_quad_B;   // choose peripheral option B
   
    // activate clock for TC0
    REG_PMC_PCER0 = (1<<27);
    // select XC0 as clock source and set capture mode
    REG_TC0_CMR0 = 5;
    // activate quadrature encoder and position measure mode, no filters
    REG_TC0_BMR = (1<<9)|(1<<8);
    // enable the clock (CLKEN=1) and reset the counter (SWTRG=1)
    // SWTRG = 1 necessary to start the clock!!
    REG_TC0_CCR0 = 5;   
   
void loop() {
  Serial.println(REG_TC0_CV0,DEC);
  delay(500);
}


The problem I encountered is that the TC0_CV0 register only counts half of the position steps that could actually be measured when evaluating all slopes on quad_A and quad_B. I investigated further and the problem seems to be that the slope detection on the digital pin 13 doesn't work. The position value is changed only when a slope on the digital pin 2 is send. A slope on pin 13 changes nothing.
However the level detection on pin 13 seems to work fine because otherwise the quadrature encoder wouldn't count all the way up when turning the motor in one direction. If the level at pin 13 was fixed, the counter would count one up at a positive slope on pin 2 and then down on the following negative slope, so the position value would alternate between two values...

anyone ideas that could explain this behaviour? maybe the quadrature encoder is not build to evaluate all slopes (which would be kinda stupid)?

Matthias

retrolefty

Quote
anyone ideas that could explain this behaviour? maybe the quadrature encoder is not build to evaluate all slopes (which would be kinda stupid)?


But possible until proven otherwise I guess? Shouldn't the datasheet shed light on how it responds to the four transitions of each encoder step is handled?

Lefty

schwingkopf

#8
Feb 13, 2013, 09:15 pm Last Edit: Feb 13, 2013, 11:08 pm by schwingkopf Reason: 1
I checked, but I couldn't find a clear statement. In Figure 37-15 the wire going out the Quadrature Decoder block is labeled "PHEdges" (and not particularly PHAEdges or PHBedges, they name the quadrature signals PHA and PHB in the datasheet), which kind of makes me think there should be edges on both detected.

update: from the datasheet:
" Position channel 0 accumulates the edges of PHA, PHB input signals giving a high accuracy on motor position..."
and
"After filtering, the quadrature signals are analyzed to extract the rotation direction and edges of
the 2 quadrature signals detected in order to be counted by timer/counter logic downstream."

sounds like edges should be detected on both signals.. will run some more tests tomorrow..

schwingkopf

just solved the problem.. the EDGPHA bit in the TC_BMR register controls whether the edges are detected on both PHA and PHB or just on PHA. I had this bit set to 0 before which according to the datasheet was the good choice.

("0: edges are detected on both PHA and PHB. 1: edges are detected on PHA only.")

BUT!! the description in the datasheet is WRONG!! its inverted!

so the code that works fine is the following:
Code: [Select]

const int quad_A = 2;
const int quad_B = 13;
const unsigned int mask_quad_A = digitalPinToBitMask(quad_A);
const unsigned int mask_quad_B = digitalPinToBitMask(quad_B); 

void setup() {
    Serial.begin(115200); 
    delay(100);
   
    // activate peripheral functions for quad pins
    REG_PIOB_PDR = mask_quad_A;     // activate peripheral function (disables all PIO functionality)
    REG_PIOB_ABSR |= mask_quad_A;   // choose peripheral option B   
    REG_PIOB_PDR = mask_quad_B;     // activate peripheral function (disables all PIO functionality)
    REG_PIOB_ABSR |= mask_quad_B;   // choose peripheral option B
   
    // activate clock for TC0
    REG_PMC_PCER0 = (1<<27);
    // select XC0 as clock source and set capture mode
    REG_TC0_CMR0 = 5;
    // activate quadrature encoder and position measure mode, no filters
    REG_TC0_BMR = (1<<9)|(1<<8)|(1<<12);
    // enable the clock (CLKEN=1) and reset the counter (SWTRG=1)
    // SWTRG = 1 necessary to start the clock!!
    REG_TC0_CCR0 = 5;   
   
void loop() {
  Serial.println(REG_TC0_CV0,DEC);
  delay(500);
}

Go Up