[SNIPPET] Optical Incremental Encoder Using Timer Counter

jdenis
Wed Aug 22, 2018 7:28 am
So I needed an incremental encoder for my project, I bought some cheap ones from china, something around 10usd each…

After that I looked at the datasheet from the stm32f1 and found out that they have a builtin incremental encoder counter, so my mission was to make it to work!

Here’s the video working:

Now first the code:

First set the pins to input (in this case PB6 and PB7)

on the setup:


HardwareTimer timer4(4);
timer4.pause();
TIMER4->regs.adv->CCMR1 |= 0x0101;
TIMER4->regs.adv->CCER |= 0x0000;
TIMER4->regs.adv->SMCR |= 0x0303; (reads 8 clock cycles to make sure)
TIMER4->regs.adv->CR1 |= 0x0001;
timer4.refresh();
timer4.resume();


jdenis
Sat Sep 01, 2018 11:43 pm
On youtube I received a question:

GnuReligion

This is pretty slick! Can you feel any bumps, like a rotary encoder, or does it roll smooth?
Here from http://www.stm32duino.com.

The answer is absolutely NO bumps, it’s like a ball bearing rolling! (probably because it is :lol: )

Cheers!


stevestrong
Fri Sep 07, 2018 8:42 am
Can you maybe post a link where did you get it from? Which type is it?

flyboy74
Fri Sep 07, 2018 9:40 am
This maybe of some interest to people on this thread.

I brought 1 of these rotary encoders https://www.aliexpress.com/item/Rotatin … 39904.html for 1 of my projects but in the end didn’t end up using it.

I brought this particular 1 as it has a builtin debounce on the encoder and is suppose to give very good clear signals without switch bounce. Although I haven’t used it the person that recommended it to me said it fixed the problems he had with other encoders.


rgd
Mon Sep 10, 2018 2:43 pm
Hi jdenis

that looks very interesting but i have three more questions:

does this code count more then 16 bit or > 65536 counts?

and should it not be 2400 count’s with a 600 ppr encoder? Maybe one have to change counting mode for using falling and rising edge?

where can i find informations about the Timer configuration bits that are used in your code?


jansun
Sun Nov 04, 2018 9:42 am
[rgd – Mon Sep 10, 2018 2:43 pm] –

does this code count more then 16 bit or > 65536 counts?

Did you find an answer to this? I need a 32bit value


jansun
Sun Jan 13, 2019 8:33 pm
[jdenis – Wed Aug 22, 2018 7:28 am] –

That’s it, works awesomely perfect!!!!

I did some tests with the code, and it works, but not perfect. When you disconnect 1line (a or b, doesnt matter) it stays counting up (or down, depending on the channel you disconnect). So this is actually the same if you toggle one pulse up and down again. Your actually moving forward and backwards to the same value, but the counter counts up. I think the code should look like this:

HardwareTimer timer4(4);
timer4.pause();
TIMER4->regs.adv->CCMR1 = 0xf1f1; //Capture compare mode register, now CC1S AND CC2S
TIMER4->regs.adv->CCER = 0x0000; // Capture/compare enable register
TIMER4->regs.adv->SMCR = 0x0003; //(reads 8 clock cycles to make sure) // slave mode control registe
TIMER4->regs.adv->CR1 = 0x0001;
TIMER4->regs.adv->PSC = 0x0000;
TIMER4->regs.adv->ARR = 0xffffffff;
timer4.refresh();
timer4.resume();


jansun
Sun Jan 13, 2019 8:37 pm
for the 16 to 32bit timer i have a sollution, but its not verry elegant

/*

pins to input in this case PB6 and PB7

*/
unsigned int count = 0;
unsigned int prevCount = 0;
int overFlowCnt = 0;
long encCnt = 0;
char userInput = 0;

void tim3Handler(void) {

count = TIMER4->regs.adv->CNT;

if ( prevCount > 40000 && prevCount <= 65535 && count < 20000) { //overflow ++
overFlowCnt ++;
}
if (prevCount >= 0 && prevCount < 20000 && count >= 40000) { //overflow ++
overFlowCnt --;
}
encCnt = (65535 * overFlowCnt) + count;
prevCount = count;

}//end tim3handler

void setup() {

HardwareTimer timer4(4);
timer4.pause();
TIMER4->regs.adv->CCMR1 = 0xf1f1; //Capture compare mode register, now CC1S AND CC2S
TIMER4->regs.adv->CCER = 0x0000; // Capture/compare enable register
TIMER4->regs.adv->SMCR = 0x0003; //(reads 8 clock cycles to make sure) // slave mode control registe
TIMER4->regs.adv->CR1 = 0x0001;
TIMER4->regs.adv->PSC = 0x0000;
TIMER4->regs.adv->ARR = 0xffffffff;
timer4.refresh();
timer4.resume();

Serial.begin(9600);
}

void loop() {

Serial.print("now: ");
Serial.print(count);
Serial.print(" flow Count: ");
Serial.print(overFlowCnt);
Serial.print(" Enc count: ");
Serial.println(encCnt);

delay(300);
}


mausi_mick
Mon Jan 28, 2019 2:49 am
one question:

can I use it for two incremental encoders ?


RogerClark
Mon Jan 28, 2019 4:38 am
I’m pretty sure you’d need to use a different timer for the other encoder.

You’d need to double check which counters are available and which pins they are connected to. e.g. possibly use Timer3 (though I could be wrong and you’d need to check this yourself)


jansun
Thu Feb 14, 2019 9:57 am
Timer4 uses PB6/PB7 and Timer3 uses PA6/PA7. I didn’t checked if you can use multiple encoders at once.

If you install cube MX you can easily see what pins you need and i guess also if you can use multiple encoders at once.


Leave a Reply

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