The shield uses a ACS712-05B current sense chip, which has a gain of 185 mV/A documented in its datasheet, when powered with 5V. The ESP32s3 uses 3.3v, but I’m not sure what the gain would be if I underpower the ACS712 at 3.3v.
So, my plan is power the ACS712 at 5V. I don’t expect currents higher than 0.5A, so following @Antun_Skuric’s advice here, my expected output voltage range would be:
However, one issue is that this is outside of the default measureable voltage range of the ESP32s3, which maxes out at 0.95V. The ESP has attenuation settings that can be used to increase this range, but the SimpleFOC library doesn’t appear to use these in its hardware specific ADC driver for ESP32.
Another issue is do we need to account for ADC conversion when setting the current sense gain? Or does the SimpleFOC library do this for us, automatically? I’m trying to find the code that does this, but haven’t seen it yet.
However, this doesn’t seem to be working very well… the following screenshot is with SimpleFOC in torque voltage mode, with the target voltage set to zero. Vq and Vd are both zero in the graph. However, the current is all over the place, with noise up to 100mA! It appears that I have a major current noise issue.
The ESP32s3’s ADC has 12 bits or 4095 levels of resolution. Over 3.1V that’s 0.76mV per level. Using the current sense gain mentioned above, that’s a theoretical accuracy limit of about 4mA per level from the ADC.
However it’s a very different story with the ACS712 current sense chip:
Immediately after making this post, I discovered the relevant code
The attenuation and resolution are both being set here, and the 11db attenuation is being used which gives a maximum input voltage of 3.1V.
Then, my understanding is that the simpleFOCLibrary automatically finds the zero current point during the initFOC routine. So I don’t need to worry that my range is not centered.
So if I’m correct, then I can just initialise the current sense exactly as shown in the example:
I’ve never really benchmarked the ina240 vs acs712 noise. I have only qualitatively verified that they output the same things and the only real difference I’ve seen is a bit of lag on acs712 (resulting in a bit more resistance backdriving the motor at 0 torque command).
Seeing the 50mA+ noise really surprised me as I know I was able to control the motor with 0.05 target torques and less. So I just kinda assumed that the noise is much lower.
Today I checked with my stm32 nucleo and I’ve got similar results to yours @Jeremiah_Rose. Thank you for pointing this out.
This much noise is still very much usable for gimbal motors, but I would have preferred to have much less and might consider pivoting from them in the future.
I do not have a v2.0.3 shield on my hands at the moment to compare. As soon as I get one I’ll do a more in depth testing and try to get some more results.
I’ve done some more experiments (created a new simplefocshield version that uses ina240a2 + shunt resistor) and the noise difference is huge!
I’m gonna go back to the amp+shunt for all the next iterations of the simplefoc borads.
I had no idea the ACS712 was so noisy. Thanks for pointing this out. How does it even produce useable current readings for SimpleFOC if it’s that noisy? Basically it has +/-56mA accuracy which is fine if your motor peaks at 5A where that would just be 1% of peak current but I guess your motor has too high resistance windings.
FWIW the 185mv/A works even when the ACS712 is powered at 3.3v, even though officially this is out of spec. I asked on a different thread about this.
The question is: what is the sampling frequency of the ACS712 in SimpleFOC?
There is a 1nF filter capacitor used on the latest SimpleFOC Shield so increasing that would certainly reduce noise.
I think you ended up measuring 21mV noise by chance because the stated figure in the datasheet is for very specific conditions (filter capacitor = 47nF) - I think the graphs I posted above are more applicable.
So the new current measuring chip is basically a sensitive voltmeter whereas the old one was a hall sensor. Are you using the sensors to sample at the same rate in both cases?
My main concern would be bandwidth which looking at the datasheets briefly I can’t easily deduce.
10mR is a 0.03v drop at the DRV8313 “rated”* current of 3A, so basically negligible. I like the fact the datasheet says it will officially work at 3.3v.
I see noise is about 0.3mV pk-pk on input and you chose the chip with gain of 50 so that is 0.015V pk-pk noise in output readings so about 10x less than the poor old ACS712.
Edit: I just worked out that by using a 5pF filter cap on the ACS712 you can reduce noise by a factor of 3 and still have a rise time of 20ns which is well within the 23kHz sampling rate of SimpleFOC (43ns).
*not really as the datasheet is unclear but this is the minimum overcurrent value
Wonderful, that’s great news! I’d love to try one of your new boards if possible. I also made a sensor using the INA240 plus a dedicated MCP3462R ADC so it would be very interesting to compare to yours and see how much noise/inaccuracy is being caused by the internal ADC in the ESP32s3.
Very nice! And this is still inline, correct? The accuracy of inline sensors can be greatly improved with oversampling, whereas lowside can generally only take one sample per PWM cycle due to the timing requirements. My testing on GooserCS showed best results with at least 30 microseconds of sampling time. I’m taking 32 samples per sensor during that period, and the resulting noise level is about the same as the lowside sensing on B-G431B-ESC1, 5 or 6 ADC units (out of 4096). My ACS711 sensors are very noisy without oversampling (24 ADC units typical variation, with occasional spikes far beyond that range), so with INA240 being so much better to begin with, it may be possible to get almost to sub-milliamp accuracy.
It would be nice to add oversampling to the library for inline sensors, but my code is specific to my setup, and I hate the STM32 HAL code with a passion so I certainly won’t be the one to implement it. The general approach I use is to set up the ADC to continuously cycle through the channels, sampling into a circular buffer with DMA. When it’s time to read the sensors, add up everything in the buffer, which contains the most up-to-date readings (it’s circular, so it doesn’t matter which entry was most recently written to). Compared to hardware oversampling, this allows all sensors to be sampled during a long time window rather than taking turns in shorter time windows. The number of samples per sensor is the same either way, but this gives lower latency, and better noise reduction for my sensors. You can use some hardware oversampling to reduce the size of the buffer (less CPU time to add them up), but I recommend no more than 8x.