Timer as Encoder

Fri Sep 11, 2015 10:57 am

It’s my first post here. I’ve played with the Maple boards before for some time (writing one of the RTC libraries on the web) and I decided dusting off my maple boards and picking up where I left off.

The hardware timers can be configured as an encoder reader. Meaning that they can count pulses with a direction bit ( count on one channel and the other channel as a direction bit), or as a normal two channel encoder with up and down counting.

I’ve added support for this functionality on the HardwareTimer class and related timer.c/h files, but am not sure what would be the best way to add these to the official repository for the stm32duino.

Can someone give me an indication, please?

Fri Sep 11, 2015 12:25 pm
I've added support for this functionality on the HardwareTimer class and related timer.c/h files, but am not sure what would be the best way to add these to the official repository for the stm32duino.

Fri Sep 11, 2015 2:27 pm

I forked the Arduino_STM32 and uploaded the changes to my Git.


I’ll work a bit more on the example sketch to include it with a simulation program.

Sat Sep 12, 2015 6:58 pm
Can you create a Pull Request, on GitHub as otherwise its really hard to determine what you changed

Also, having an example sketch that other people can run to demonstrate the new code, would speed up testing on various versions of STM32F103


Sat Sep 12, 2015 8:13 pm
I will.

I’m just finishing the example as I’m still a bit unclear about the edge counting (not matching what is on the manual).

Sat Sep 12, 2015 11:01 pm
bubulindo wrote:I will.

I’m just finishing the example as I’m still a bit unclear about the edge counting (not matching what is on the manual).

Sun Sep 13, 2015 4:50 am
Thanks guys…

Sun Sep 13, 2015 4:42 pm
Hello Gents,

I’ve added an example to the Arduino_STM32\examples\Sensors folder and made a pull request.
The example has a quadrature encoder simulator inside to be able to test the encoder as timer. Only two jumpers needed.

Regarding this mode, I think it will make more sense to eventually create an Encoder class where the Zero pulse is supported. This could be interesting perhaps…

I noticed that there is a bit of functionality missing from the Hardware Timer class, so will look into it and eventually we can document the HardwareTimer class with examples for each function.

Let me know if something is missing.

Fri Feb 12, 2016 12:16 pm
Hi @bubulindo, i read your thread here
and i got the library, it is yours right?
It has been usefull to me to find out how to access timers registers,
reading it i was able to write this
(TIMER1->regs).gen->CR1 = 0x00;

Fri Feb 12, 2016 1:58 pm
I’ve provided the detailed answer in the other thread : viewtopic.php?f=2&p=10619#p10619
Direct access is done with RTC_BASE->CNTH

Tue Feb 16, 2016 9:04 pm
Hi everyone,
I am kind of new here, and I wonder why @bubulindo did not create a pull request for his Encoder code that seems quite interesting.
Is there an issue with it that I should be aware before trying to use it?

Thu Sep 01, 2016 11:24 am

Life kind of got in the way and I suppose I hit a wall with the upgrades on the Arduino probably broke it.

I was looking and I changed the HardwareTimer library to include Encoder code, however, that may not be the best way. Your thoughts on this matter are appreciated.

I’ve refactored it and tested this code as a separate library that is stored in:


Have a look at it and let me know if something is missing. To run the example, wire D4 to D10 and D5 to D11, swapping these connections will change the direction of the encoder count.

Sat Sep 03, 2016 1:23 pm
Oh, it sounds like a good idea to put it into the library.
I will try to test it later with a DC motor and encoder.

At first look, I see that you named it Encoder.h so it may be a bit misleading with PJRC’s Encoder Library: https://www.pjrc.com/teensy/td_libs_Encoder.html and code here: https://github.com/PaulStoffregen/Encoder
Maybe it is a good idea to keep the same name but use the same API so Arduino code that use the PJRC library will be able to run on stm32 (only of the pin used are corresponding to hardware timer).

But after looking at the source code, the library is named STM32Encoder and the file STM32Encoder.h so there must be an error in the example.

Sun Sep 04, 2016 6:33 am

You are right… I also have the PJRC’s encoder library installed and was wondering why mine wouldn’t compile and afterwards ended up renaming it to STM32Encoder.

That should be a pretty unique name and is more or less in line with other libraries.

Do have a go at it with proper hardware. My example simulates encoder steps and not only that it simulates them fairly slow too. If you have a setup with a motor/encoder assembly where you can validate this it would be great. :)

Sun Sep 04, 2016 2:15 pm

I think the name STM32Encoder is OK. But you should make the change in the example (which should be in its own directory with the same name as the sketch), in the library.properties and keywords.txt files.

Also change enc.Direction() to enc.getDirection() in the example.

I have tried it on a Maple Mini, Blue Pill and Olimexino-STM32. Why so many boards? Because I did not managed to make it work at first on the Maple Mini. The Digital Pins are not named the same as the Maple (I am not so used of using STM32duino on these boards) so I had random figures at first.
With the correct pins, it works well (I have only tried to read the value ans revolutions numbers). By the way, you should try to integrate the interrupt callback in the library. I know that is not easy without tricks, I saw you post in another thread about dealing with the instances.

But the remaining issue is that the counting is divided by 2 if I compare with what I get using the ST HAL code.
I do not understand the issue because the COUNT_BOTH_CHANNELS defined is used and it puts 0x3 in the SMCR register which seems OK. So maybe you are more experienced than me to understand the issue.

Sun Sep 04, 2016 6:43 pm
I realize now that I messed up badly on my file management (I can’t get my head around github for some reason).
Either way, I’ve uploaded the corrections that you referred.

When you said that the counts were half, that sounded to me as a prescaler issue. Sure enough, it is.

The manual says that the value of the prescaler can be from 1 to ~65000. However, I missed the actual prescaler description where they add a safety bit.
Further down, the manual states this: fCK_PSC / (PSC[15:0] + 1)
So when you put 1 in the prescaler field you are actually having a prescaler of two. Documentation is scarce to none on the examples, so I might compensate for this by subtracting 1 from the user input in the code.

It pains me that I didn’t find a way to get the interrupts inside the class as that would make it a much cleaner interface. But if doesn’t look like it’s possible, or easily possible. I did go through all the functionality of the timers and usart which are to me the most developed libraries and did not find a way to link it to the private members (number of turns) of the class.
I’m looking into the ADC now as it looks like a nice project (considering very little was brought out to the arduino style interface) for taking the rust out of my C skills and learn a bit more of C++.

If someone knows how to get by it… I would appreciate it. :)

Let me know what else may be missing. :)

Mon Sep 05, 2016 6:15 pm

Thanks for the updates and explanation about the prescaler, but it seems that you did not add the fix yet.
I have tried to put 0 as a prescaler and I get the full resolution. Thanks.

Also, I forgot to mention before, but the first example lacks a Serial.begin() statement in setup().
And there is a remaining “Encoder” in the keywords.txt file.

Anyway, it is good that you add some advanced features in the Arduino like API. I am currently learning how to use these STM32 chips using the HAL library but I realized that I am mostly trying to mimic the Arduino API because it is what I am used to. I have chosen to use the HAL instead of the STM32Duino because I want to use all the hardware features to free the CPU, things that are not possible with the raw Arduino API.
For example I read a bunch of Ultrasonic sensors with Input Capture Interrupts and a dedicated timer to schedule the triggers and avoid the interferences between the sensors. So the CPU is almost doing nothing while with the Arduino API, I would have used the pulseIn() function which do a busy wait.

Mon Sep 05, 2016 6:47 pm

I did now.
To be honest, I started with the HALMX, but do not like it as there is far too much under the hood for my liking.
I was quite happy when I saw that it included FreeRTOS, but then realized that they even added a wrapper around that. Meaning that you need to dig into their files if you want to check something.

Plus, I can’t really get my head around on how to move the code up from there…

Next, I’m looking at the ADC and trying to come with something nice to get the most of it.

Leave a Reply

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