Suggestions for new sensor implementations

Hey guys,
I imagine this thread to be a place to discuss new sensor implementations for the simple FOC library, as it is one of the most often asked question so far.
There is so many position sensors out there and all of them have their own use cases so I would like to you to help me decide which ones make the most sense to implement in the next version of the SimpleFOClibrary.

So far I have decided to implement Hall sensors, but there have been some requests for magnetic sensors with I2C and SSI communications which I’m still not sure that a lot of people uses.

Let me know what do you think, and feel free to add more sensors to my list!

magnetic sensors!

Its price is getting cheaper and its performance is quite good. Although the stability of this kind of sensor does have problems, it does not affect the application. (by the way, using the current “simplefoc” and using the magnetic sensors to obtain the motor speed is extremely unstable! Even if the motor doesn’t move, there will be a jump in the speed value. For example, from 0.01, 0.02 to 2.1 or higher… So I don’t think it’s good enough to get the function of the speed in simplefoc.)

On the other hand, don’t you think this kind of sensor is the easiest to refit a sensorless motor?

Hey Jack, thanks for the post. Could you please explain a bit better what kind of magnetic sensors are you talking about.

And also it would be great if you could start a new topic regarding the velocity meausurement being “extremely unstable”. I did not have this problem so far so it would help me a lot if you could better explain it. You can also do a GitHub issue.

A post was merged into an existing topic: Velocity measurement problem, magnetic sensor

I’ve been spending a bit of time with getting the AS5600 up and running because I thought it could be a cost effective solution for the hundreds of encoders I will need for our robots. I have run into some issues generally speaking with having multiple magnetic encoders. Firstly I am using the STM32 blue pill as the hardware PWM is fantastic. The issue is having 3 I2C devices run at the same(AS5600s all use the same address)…unless this is software it seems that at least the STM32Duino doesnt support more than 2 i2c channels so that could be a dead end. The AS5600 also has analog out and encoded PWM but the analog is not very helpful because it has a dead band programmed into he output. Im thinking to give the encoded PWM a try but the update rate isnt that fast @ PWM Frequency
00 = 115 Hz; 01 = 230 Hz; 10 = 460 Hz; 11 = 920 Hz
If there was another magnetic encoder IC closer to the 2Euro cost the AS5600 with A B and index output Id be happy to go with that. I know the AS5047 has that but at 7 euros an IC its not so suitable for swarm robotics as the cost is too high at around 2000 Euro mark for the number I would need. Ive also got an i2c multiplexer arriving today to test but I dont have a good feeling with adding some junk to our robot design.


Seems to me the low power options of the 5200l could still be a good choice for some applications. The AS5200l has 2 I2c addresses so 3 gimbal motor control would work on a blue pill. Apart from that I am interested to know your thoughts on the analog output of these devices, either analog or the encoded PWM.

I2C, which can be simulated by software.
“Arduino_STM32-master”—Already contains available “SoftWire.h”…


  • @file SoftWire.h
  • @author Trystan Jones
  • @brief Wire library, uses the WireBase to create the primary interface
  •    while keeping low level interactions invisible to the user.


1 Like

I have i2c working now. have not tried software i2c but if it works then yay and no more multiplexer needed I hope. I currently use normal mode i2c not fast mode as that seemed to break the bootloader on the stm32. I drive quite small gimbal motors and they sound a bit crunchy with the stm32 at the moment. Ive checked the output from pb1 pb0 nd pa7 on my scope and seems like the normal pwm I would expect at least on channel 1 pb1. Generally speaking the arduino nano i was using with an as5040 worked quite smooth. Perhaps Ill try the as5040 with the blue pill to see if I can narrow it down to either the stm32 or the as5600 interaction.

also I am using the stm32duino and not Roger Clarks version. I see the stm32 example here uses analogwrite but I will not try and set it up with a hardware pwm pin.

Hey @Adam_Donovan and @blackblue007 I am not sure what is the best solution in your situation.

So in my opinion I would start with the i2c multiplexer and see how easy/complicated it is. It should work reliably enough in my opinion. I am not really sure how well do they perform from the price standpoint.
But I would certainly recommend SPI is possible, as discussed in previous posts about the I2C sensors.

Regarding the analog output, I have gone through the datasheet and you are right is has a dead-band making it unusable.

The PWM output however is maybe a better solution. From what I was able to see it uses a pretty simple protocol. The thing I am concerned about is reading the PWM signals. The reading is very time sensitive and there we would need to be very careful. Also most of the Arduino built in functions dealing with PWM reading use the blocking functions that would produce a lot of problems in execution. Functions like pulseIn. Especially with the PWM frequency of <1Khz.
If it would be implemented in the interrupt manner that would maybe work, it would depend on time measurement function, i am not sure that micros() would be precise enough. I have not spent too much time passing through the datasheet but that is something you can try to see. If we can precisely measure time in between two interrupts then it would probably work.

@Adam_Donovan, regarding the crunchiness of the motor movements, can you tell me what is the your average loop time and which control loop do you use?
If it is longer than 2 ms that would maybe be too much (depends of application).
Have you tried to change filtering values LPF_velocity?

SimpleFOClibrary is intended to be run in stm32duino not the Roger Clarks version. But the conversion should not be too complicated. On the other hand, in terms of the communication interface support I am not really sure which one is “better”.

Good question with the loop time I will check that presently. I tried tuning those values including the LPF for hours to try and get it just right but still feels like it vibrates a lot when you hold it. As for my experience just direct driving these motors with a huge 12bit table array for esp32 and an 8bit. nothing seems as bad yet as the blue pills handling with the as5600…

As for the PWM mode for the stm32, im having a hard time to figure out the correct way to use the hardware PWM instead of analogwrite…at least it my understanding that it should take no CPU time to do it. perhaps like in this example but at the arduino level

I do think that if the i2c willw ork then i can still sue the as5200l…it has 2 seperate i2c address that can be selected and with 2 channels of i2c then it shouldnt be a problem to address 3 at the same time. Any suggestions on the harware PWM or perhaps the table array? Id consider using a slightly larger array size for 10bit values. Im not sure exactly how you did with your method?

I am really not sure why do you have problems. I would say it is either sample time (both too short and too long) or maybe that the position values are just too noisy. I have filtered the velocity value but I did not really filter the position.
Could you try to see how noisy the measurement is?
The other thing you can try is to leave loopFOC() in the Arduino loop directly and execute motor.move() every few loop iterations.
Also make sure you are not filtering too much. Don’t put the LPF_vrlocity.Tf too high >0.1s.

I2C communication can be pretty bad in terms of EMF. Can you also check the I2C bus signals to see if there are noisy.

Overall I would not say it is a problem of PWM and I would not say that you will gain much with faster pwm execution. And you will get a lot of complexity.
I mean, Arduino IDE offers just a niche of the Stm32 features. So if you don’t have many Arduino libraries needed for your project you could look into how to use Keil and Stm32CubeMX to write your project. The end solution would much better use the resources. But it is much more complex.
On the other hand working with DMA from Arduino IDE I am not really sure how to do and how to setup.
But I am still pretty sure that in terms of PWM you cannot gain much. Communication part maybe.

Regarding the sine waves. The open loop sines are not really a good comparison because there is no control part of the problem. And in your case we are still not sure if it is the controller, measurement or the pwm(sine wave) the problem.
FOC algorithm basically sets the same sine waves you set in the open-loop control you did before, just it uses the measurement to determine where is it in the table.
I am using a table for the sine waves too. You can find the implementation of the sine and cos functions using tables in the FOCUtis.h/cpp files.
I’m using 200 elements for 90 degrees so overall it should be 800 elements. I have calculated the max sine error of 0.005, I think.
These functions are used in file BLDCMotor.cpp in function setPhaseVoltage if you want to try you can change the _sin and _cos to sin and cos for real sin and cos calculation.

You can also try to change the modulation type to see if it will be better:

motor.for_modulation = FOCModulationType::SinePWM; // or FOCModulationType:: SpaceVectorPWM

For me the steps would be:

  1. loop time check
    • if longer then 2ms - probably a problem
      • check the I2C read time
  2. sensor noise check
    • velocity and position (especially) values
  3. if 1 and 2 are fine then it is a control problem
    • spend some more time tuning the controller
  4. if you tried everything else and it still doesn’t work then maybe it is a pwm problem
    • change pwm pins combinations
    • try changing the Pwm frequency in the FOCUtils.cpp in setHighFrequencyPwm at the moment it is set to 50kHz.

Keep me updated,

Hey @Adam_Donovan,

@Owen_Williams has created few very cool pull requests and has implemented the magnetic sensor communication interface using the analog output. I am pretty impressed by it and you should definitely it.
There is a lot of room to improvement but even this relatively basic version it works very well.

The code is currently in the dev branch:

1 Like