Multi encoder sketch with acceleration

madias
Mon Apr 27, 2015 3:51 pm
easy to use sketch for setting up multiple encoders with acceleration (faster movements, more data increase). IRQ driven, HW timer and direct pin access (instead of digitalRead).

mausi_mick
Sat Nov 12, 2016 3:08 am
I think the code in the zip-file is not ok,
I think there should be one more { … } at this lines: <<#######

if ( (gpio_read_bit(PIN_MAP[encoderpinB[counter]].gpio_device, PIN_MAP[encoderpinB[counter]].gpio_bit) ? HIGH : LOW) != B_set[counter] )
{
B_set[counter] = !B_set[counter];
if ( B_set[counter] && !A_set[counter] )
// <###################################### {
if (millis() – encodertimer > 3)
encoderpos[counter] -= 1;
else
encoderpos[counter] -= 5;
// <######################################## }
encodertimer = millis();
}

mausi_mick


RogerClark
Sat Nov 12, 2016 6:18 am
The code compiles OK, so those brackets aren’t essential, but I agree it makes it easier to read and maintain the code if it did have them.

RogerClark
Sat Dec 03, 2016 7:56 am
Matthias

BTW.

I tried you code and it worked fine, but I found I needed to use the hardware timer for another purpose, so I found it doesnt work too bad if you simply turn on the internal pullup resistor and use a 100nF capacitor between the output of the rotary encoder and GND.

I know this isnt as good as the 2 resistors and one capacitor debounce method, but it worked OK for me.

The only drawback with this simple method (using attachinterrupt on input A), is that if you turn really quickly, it looses some steps and you don’t get the 5x acceleration. But I could add acceleration by getting the millis in the interrupt handler and if it was less than some small value, since the last interrupt, then I could add or subtract 5 instead of 1.

But I do like the external analog debounce method.


Pito
Mon Dec 05, 2016 9:40 am
FYI – in very past I worked with http://www.bourns.com/docs/Product-Data … f?sfvrsn=0 encoders (DDS stuff) and there are types with detents and without detents, and also with 1/4 quadrature cycle per detent or a full cycle per detent. So I had to modify the sw based on the encoder I got.. Still a few in my junk box, I will try..

max_sl
Thu Dec 15, 2016 2:51 pm
Hello,
I used your “sketch” with my rotary encoder that named “ROTARY ENCODER TYPE: LPD3806-600BM-G5-24C” and it works fine on the first sight.
But after couple of turns it starts to miss impulses (app. 10 impulses at one turn) When I delete a part of code for the second encoder, it starts work better and it misses only 5 impulses at one turn.
When I used quadrature encoder at the Arduino Due, all was fine. Could you explain, how I can get a valid number of impulses on the STM32duino?
(I have STM32f103c8t6)
Sorry for bad English. I am from Russia)

Pito
Thu Dec 15, 2016 7:02 pm
Your encoder gives
.. 600 pulses/revolution for a single phase.. – when using it as an manual input you can easily do 1-2rev per second. That is 600-1200 pulses/sec single phase (and it gives probably more in the quadrature mode). The routine uses millis() for the measurements – so to overload the sw could be easy then.. Try to use micros() instead. Also you may try to decrease the
#define ENCODER_RATE 1000 // in microseconds;

RogerClark
Thu Dec 15, 2016 7:23 pm
I rewrote to just use interrupt on one of the encoder output, and read the value of the other.

As long as you use hardware debounce, e.g an internal pullup resistor and a small capacitor from the encoder output to gnd, this worked well.

But if you rotate quickly, it still misses steps because of the debounce time.
I tuned the capacitor value for my particular encoder, as it only seemed to need 50nF with the internal 22k pullup.
But even then, I could make it loose steps, so one approach to hiding this, is to increase the amount that you change the position variable if you detect the encoder is being rotated quickly.


Pito
Thu Dec 15, 2016 7:35 pm
With 50nF and 22k you get ~1-2msec tau, so you actually limit the “real pulse rate” to this tau..
The typical bounce of a microswitch takes <1ms, so the RC value seems to be ok.
I think a processing of every pulse should be possible with a 72MHz arm :) provided the encoder’s interrupt priority would be the highest..

RogerClark
Thu Dec 15, 2016 10:05 pm
Pito

I tried a few capacitors starting much higher but I didn’t have anything less than 50nF in my box of spares (well I had some 22pf etc but they were much too low)

I agree perhaps 10nF would be OK.


max_sl
Fri Dec 16, 2016 9:12 am
Thanks for the answers.
My “ENCODER RATE” value changed to 1. Because with the value “1000” it loses very many impulses.
I just want to get direct number of impulses by STM32duino, like in this article (http://blablacode.ru/mikrokontrollery/531) It`s not in English but the code is universal. I want to get result like this:

u16 cnt = TIM3->CNT;
Delay(100);

But there are no available descriptions of translation stm32 functions to stm32duino ( in Internet) :(

P.S.
Transition “millis” to “micros” cannot give an effect for my device.


Pito
Fri Dec 16, 2016 9:52 am
While browsing the Rot Enc debouncing this seems to be the most discussed solution:

Rotary Encoder debounce.JPG
Rotary Encoder debounce.JPG (22.62 KiB) Viewed 717 times

max_sl
Fri Dec 16, 2016 10:27 am
Ok.
I work with Arduino and STM32 for about 3 month so could you explain these strings:

if ( (gpio_read_bit(PIN_MAP[encoderpinA].gpio_device, PIN_MAP[encoderpinA].gpio_bit) ? HIGH : LOW) != A_set )
{
A_set = !A_set;
if ( A_set && !B_set )
{
//if (millis() - encodertimer > 3)
encoderpos += 1;
//else
//encoderpos += 5;
}
encodertimer = micros();
}


Leave a Reply

Your email address will not be published. Required fields are marked *