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?
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.
I forked the Arduino_STM32 and uploaded the changes to my Git.
https://github.com/bubulindo/Arduino_STM32.git
I’ll work a bit more on the example sketch to include it with a simulation program.
Also, having an example sketch that other people can run to demonstrate the new code, would speed up testing on various versions of STM32F103
Thanks
I’m just finishing the example as I’m still a bit unclear about the edge counting (not matching what is on the manual).
I’m just finishing the example as I’m still a bit unclear about the edge counting (not matching what is on the manual).
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.
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;
Direct access is done with RTC_BASE->CNTH
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?
Thanks
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:
https://github.com/bubulindo/STM32Encoder/tree/master
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.
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.
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.
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.
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.
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.
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.