Skip to content

Hardware (timer-based) encoder handling for STM32 #114

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed

Conversation

conroy-cheers
Copy link

This implements quadrature encoder tracking using the STM32's built in timer hardware.
Main advantage over the interrupt-based Encoder is that performance is very consistent, and it doesn't bog down the CPU at higher shaft speeds. Demo and performance measurements here.
Timer rollover is handled nicely, and should work up to an int32-sized number of shaft rotations.

Probably not ready to merge yet, but I'd appreciate any design insights.

Remaining features to add include:

  • Selectable encoder A/B pins (right now, it's only for B-G431B-ESC1, and maybe some other STM32G4-based boards)
  • Selectable timer instance (as above, it uses TIM4, because that's the only timer available on both of those input pins)
  • Option to disable quadrature (not sure why this is useful, but Encoder.h provides it)
  • Index pin support (my hardware doesn't have index pin, so I can't easily test this)

I created a HardwareEncoder class separate to Encoder, as they're quite different implementation-wise. Would it be worth factoring out a common Encoder interface, from which both classes inherit?

As for making input pins and timer instance selectable, I'd appreciate any recommendations.
STM32G4 doesn't allow arbitrary pins to be connected to arbitrary inputs of an arbitrary timer, so it'd be a pain to try and validate inputs. Perhaps best to just leave this up to the end user? I'm also not sure how portable this is across different STM32 cores.

There's also a possibility that this could be supported for other MCUs in future, if their timers support a similar "encoder mode". Is this worth thinking about now, or should it just be refactored later if needed?

Thanks for reading, would love to hear any feedback.

@askuric
Copy link
Member

askuric commented Sep 16, 2021

Hey @conroy-cheers
Thanks for the proposed implementation, I like it a lot and I'd like to help you to extend it a bit further to the wider range of use cases and mcus. 😄

@runger1101001
Copy link
Member

Hey,

I have been meaning to write... looks like awesome work!

I have a small ESC board I've designed and am now testing lying on my desk. And by pure chance, it has a STM32 MCU and a magnetic encoder with ABI outputs, which I hooked up to timer inputs, just in case I ever had a chance to try out the encoder mode... and now you've provided the solution! How cool!

I'm going to try it out as soon as I can, I'm really short on time these days :-( I'll definately let you know when I do.

In the meantime, @askuric what do you think about taking the code as is into the drivers repository? It is very hardware-specific, which is what the drivers repo is for... I would give it an interface allowing you to specify the pins, but otherwise it looks good as it is?

@askuric
Copy link
Member

askuric commented Sep 16, 2021

That's sounds great @runger1101001!

Even though I think we'll try to support this type of sensor for more mcus than just stm32 so we will need to figure how to structure this better.
But in general the soon er the people can use it with the library the better in my opinion 😄

@conroy-cheers
Copy link
Author

Sounds good. When I have time, I'll add a basic pin assignment interface and open a pull request in the drivers repo.

I think this timer-based approach can potentially work on many MCUs (STM32 timers, SAM QDEC, maybe even with AVR T0/T1); the implementation here can probably be used on most STM32s with minimal changes.

I'm happy to refactor this for multiple MCU support, just let me know what you'd like there.

@askuric
Copy link
Member

askuric commented Sep 18, 2021

Something to consider https://github.com/mjs513/Teensy-4.x-Quad-Encoder-Library

@askuric
Copy link
Member

askuric commented Sep 20, 2021

esp32 version
https://github.com/madhephaestus/ESP32Encoder

@askuric
Copy link
Member

askuric commented Sep 20, 2021

a bit more comprehensive stm32 verison of the hardware encoder:
https://github.com/bubulindo/STM32Encoder

But it seems to work only with bluepill and stm32f1 boards...

@ithinkido
Copy link

@runger1101001
Copy link
Member

I've merged this code into the SimpleFOC drivers repository, where we keep the more hardware specific code.

You can find it here: https://github.com/simplefoc/Arduino-FOC-drivers/tree/master/src/encoders/stm32hwencoder

I modified it to make the pins settable, but as luck would have it my test setup uses exactly the same pins on TIM4 that yours does, and so I guess it should be tested to make sure it works with other timers/stm32s as well.

Regarding the libraries, I think it is a good idea to subclass the SimpleFOC Sensor class to make a wrapper for an existing library. But I think I would prefer to keep code that links simplefoc to another library to the examples folder - otherwise you'd be pulling in a 3rd party library dependency that most users would not need.

If it is ok I will close this pull request.

@runger1101001
Copy link
Member

This has been merged to the drivers repo as described above... Thanks a lot @conroy-cheers !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants