Go Down

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


Ah, yes I could just accumulate a counter in a larger integer and do a carry at the overflow.

I just need a delta count though. So reset at plus or minus 32K works great for me.

I admit to using the SAM3S datasheet

which shows the FILTER bit on page 768.

0 = IDX,PHA, PHB input pins are not filtered.
1 = IDX,PHA, PHB input pins are filtered using MAXFILT value.

Looks like SAM3X is different. I suspect that it has no effect (except perhaps to disable), because the SAM3S datasheet also says that the filter is enabled when QDEC is enabled.

Regarding reset to avoid overflow using

It seems that the reset does indeed work, but the counter value of zero is not active until the encoder has been touched again. At least I think that's what is happening.


Looks like SAM3X is different. I suspect that it has no effect (except perhaps to disable), because the SAM3S datasheet also says that the filter is enabled when QDEC is enabled.

If you look at Sam3x, Sam4 or Sam7 datasheets, the quadrature decoders are all the same, FILTER bit is missing in the documentation BUT present in the header files, therefore IMO the right version of TC_BMR register is in Sam3s datasheet and the same for all Sam versions.



To begin, I don't have much knowledge in Aurduino DUE.

I bought an arduino DUE in order to get the speed of 2 RENISHAW Atom quadrature encoders with a Lowest recommended counter input frequency of 25MHz.

First of all, I read the various datasheet and previous post to understand what you did.

However, I wish in my case connect on the same arduino DUE my 2 encoders (without index) to know their speed (negative or positive) and save them or print them on serial port. Is that possible with DUE ?

Thanks in advance


You can use both quadrature decoder QDEC0 and QDEC1 at the same time, for speed or position measurement of rotary quadrature encoders.

Two hardware quadrature decoder QDEC0 and QDEC1:
Timer Counter 0 channel 0 / TIOA and TIOB of channel 0
PHA  TIOA0       =   pin 2
PHB  TIOB0       =   pin 13

Timer Counter 0 channel 1 / TIOB of channel 1
INDEX  TIOB1   =   pin A6

Timer Counter 2 channel 0 / TIOA and TIOB of channel 0
PHA  TIOA6      =   pin 5
PHB  TIOB6       =   pin 4

Timer Counter 2 channel 1 / TIOB of channel 1
INDEX  TIOB7   =   pin 10

A minimal example sketch for speed measurement with QDEC1 (For QDEC0, replace TC2 accordingly):

Code: [Select]

/*                          QDEC Speed mode by polling in loop()                                   */

  In speed mode, the results are accumulated within the time base (100 ms in this example).
  Every 100 ms, we get an edge that is connected internally thru TIOA8 to TC6. Depending on the user
  application and the requirement, the user must modify the time base with respect to their speed range.
  For example, if the application requires low speed measurement, the time base can be increased to get
  the fine results. For higher speed measurement, the user must choose the lesser time base so that the
  number of pulses counted does not overflow beyond the channel 0 counter (32-bit). If this is not taken
  care, the results may be inaccurate.
const uint32_t ENCODER_CPR = 150;                            // Cycles per revolution; this depends on your encoder
const uint32_t ENCODER_SAMPLES_PER_SECOND = 10;              // this will need to be tuned depending on your use case...
const uint32_t LOOP_DELAY_MS = 1 * 100;                     // ... as will this

void setup() {


  PMC->PMC_PCER1 = PMC_PCER1_PID33                  // TC6 power ON ; Timer counter 2 channel 0 is TC6
                   | PMC_PCER1_PID34                // TC7 power ON ; Timer counter 2 channel 1 is TC7
                   | PMC_PCER1_PID35;               // TC8 power ON ; Timer counter 2 channel 2 is TC8

  // TC8 in waveform mode
                              | TC_CMR_WAVE               // Waveform mode
                              | TC_CMR_ACPC_TOGGLE        // Toggle TIOA of TC2 (TIOA8) on RC compare match
                              | TC_CMR_WAVSEL_UP_RC;      // UP mode with automatic trigger on RC Compare match

  // Final TC frequency is 84 MHz/2/TC_RC

  // TC6 in capture mode
  // Timer Counter 2 channel 0 is internally clocked by TIOA8
  TC2->TC_CHANNEL[0].TC_CMR = TC_CMR_ABETRG               // TIOA8 is used as an external trigger.
                              | TC_CMR_TCCLKS_XC0         // External clock selected
                              | TC_CMR_LDRA_EDGE          // RA loading on each edge of TIOA6
                              | TC_CMR_ETRGEDG_RISING     // External TC trigger by edge selection of TIOA8
                              | TC_CMR_CPCTRG;            // RC Compare match resets the counter and starts the counter clock

  TC2->TC_BMR = TC_BMR_QDEN                               // Enable QDEC (filter, edge detection and quadrature decoding)
                | TC_BMR_SPEEDEN                          // Enable the speed measure on channel 0, the time base being provided by channel 2.
                | TC_BMR_EDGPHA                           // Edges are detected on both PHA and PHB
                | TC_BMR_SWAP                             // Swap PHA and PHB if necessary
                | TC_BMR_MAXFILT(1);                      // Pulses with a period shorter than MAXFILT+1 peripheral clock cycles are discarded



void loop() {
  double dSpeedRPS, dSpeedRPM;
  int32_t __dSpeedRPM;
  int32_t iSpeedPPP;

  iSpeedPPP = TC2->TC_CHANNEL[0].TC_RA;

  dSpeedRPM =  dSpeedRPS * 60;
  __dSpeedRPM = (int32_t) dSpeedRPM;

    " Speed rpm: %d \n",

Your encoders doc is unclear to me, Your encoders seem to run either as linear or rotary encoders. If they are used as rotary encoders, the speed measurement code is relevant, providing you know the number of pulses per revolution. For a linear use, search the code for Position measurement (an example in this thread, reply #87).

The DUE is 3.3V compliant, be careful with the voltage of the encoders output signals.

The "Master" clock of the DUE Timer Counters is 42 MHz (84 MHz/2).


Is it possibile to run 3 Encoders on DUE at the same time?
Now I have running 2 Encoders and it works fine.
The speed is very slow, max. 0.2 turns / Sec.
The Encoder sending 2500 Pulses / Revolution, that is 500 Pulses / Sec. maximum.


For the third quadrature encoder, a simple attachInterrupt() should work fine since the speed is low. Attach a pull down resistor to the attachInterrupt pin you will select to avoid EMI.


Sep 23, 2019, 03:24 am Last Edit: Sep 23, 2019, 03:28 am by ASK_ME Reason: More Questions
This is my code for two encoders that works fine (attached File).
How can I configure Timer 1 for the third Encoder wit the corresponding Ports?


I realise that this thread is quite old but in post #55 you posted some code for getting the speed of an encoder. I have been looking at you code for the hardware interrupts and speed calculation for quadrature encoders with a Due and have difficulty getting the RPM to match the values found just using a normal interrupt driven sketch which makes me think that I haven't really understood what is going on here. I have tried finding the referenced PDF document (doc11057.pdf) but can't find it.
I am using the encoder and disc from an old printer as well as a single slit disc with a simple photo interrupter on the same motor shaft and a simple sketch to get the time between breaking of the beam to work out the speed of the motor. Also by counting the quadrature RISING pulses (2 per interruption of the quadrature beam) between photointerrupter signals will give the encoder edges per rotation * 2 (4200 on my version). However I don't seem to be able to get values anything near this with the sketch in post #55. My motor is spinning at 840 rpm (according to my sketch) but yours gives something like 2000. I don't know enough about the inner workings of the SAM3 to get any further. Any suggestions would be helpful. Could you possibly suggest where the PDF is located in case this sheds some light on the problem.




I'm using the encoders for my hobby milling machine, to get the precise position (+/- 0.003mm) of the platform.
X and Y acsis works fine but I need the Z axis to!

The doc11057.pdf you can get here:


Hey Users!

I don't believe it, nobody using Arduino DUE with 3 Axis encoder ???
Ok, I will do it myself, it is a big challenge for me ( mechanical designer) to learn programming, but I'll do it!!!


Thanks for all comments (and helps ???)...

:)  :)  :)  :)

Unable to publish the post. Please notice you can only post once every 5 minutes and only edit posts after 30 seconds. Once you reach 100 published posts this limit will be removed.

Shame on you Arduino Forum !!!

BAD, BAD, BAD, BAD !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


Hello ASK_ME, have try your Rotary_Encoder_3_DUO.ino very nice, I have code for 3 axis with arduino mega2560 and display SSD1963 code working nice with 3 axis but problem is refreshing display nummbers of axis dont turn in real time so I got today ARDUINO DUE SAM3X and try with your code but problem is becouse I have 7" SSD1963 i try repair code for SSD1963  or You have maybe code for rotary encoder with 7" SSD1963?
If can You help I will happy!


The mega 2560 has no Hardware-Quadrature-Encoder!
mega2560 is to slow to handle 3 encoders at the same time but this is dependent of the rotations speed!

For your Display, get this Library: http://www.rinkydinkelectronics.com/download.php?f=UTFT.zip

Best Regards


Code encoder ARDUINO DUE SAM3X for SSD1963 display x and y axis DRO


Feb 27, 2020, 04:41 pm Last Edit: Feb 27, 2020, 04:44 pm by chamarthi
I learned Quadrature decoder usage from the code of ard_newbie, I measured the speed of the shaft by using signals QA and QB only.

what I understood is..................

The rotary encoder will have three signals as per my knowledge, which are named as QA,QB and Index. The signals QA and QB  signals are enough for the measurement of speed. In ATSAM3X8E their is an option of using the hardware Quadrature decoder module.

There are two quadrature decoders modules in the device which are incorporated in Timer/Counter-0 and Timer/Counter-2. Therefore by manipulating the registers of each channel in the timer/counter segment the speed or position of the shaft can be calculated.

steps to measure the speed.
1. Initialize the channel-0 in counter mode. To count the number pulses for a particular time interval.
2. Initialize the channel-2 in timer mode. For generating the triggering pulses for the channel-0, such that counter value will be stored into the register and then reset to zero every time.

The code is available at ard_newbie posts. If anybody wants my code just put a message to me. mine is a bit modified version of ard_newbie code.

If their is any mistake in my analysis, please inform me.

Go Up