Skip to content

Conversation

ArcaneNibble
Copy link
Collaborator

This reads the values from the ADC and scales them according to the ideal scaling factors.

Voltage was tested and reads in the correct order of magnitude, slightly lower (~100 mV) when compared against a cheap DMM without traceable calibration.

Current appears reasonable (116 mA) and increases when I squeeze a running motor (up to 500 mA).

Fixes pybricks/support#2311

@coveralls
Copy link

coveralls commented Aug 6, 2025

Coverage Status

coverage: 56.965% (-0.01%) from 56.979%
when pulling a5c354c on ArcaneNibble:ev3-bat
into af9c1f4 on pybricks:master.

This reads the values from the ADC and scales them according to
the ideal scaling factors.
Without this, the hub can falsely detect low battery when booting.
@ArcaneNibble
Copy link
Collaborator Author

Done. Also added a workaround for detecting low battery on bootup (it's added in the ADC driver, unlike the REVISIT in the STM32 implementation).

// Battery current is read across a 0.05 ohm equivalent shunt resistor
// which is then connected to an op-amp configured with a gain of 16
// (non-inverting). This yields 1 A = 0.8 V.
*value = ((uint32_t)(value_raw) * 5000 * 10) / (1023 * 8);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to move scaling to mV to the ADC driver on all platforms. Can be a different PR though. I think David might be working on ADC at the moment.

@dlech
Copy link
Member

dlech commented Aug 8, 2025

I tried this with 3 EV3s so far and the error is kind of all over the place.

image

// Battery voltage is read through a voltage divider consisting of two
// 100 K resistors, which halves the voltage. The ADC returns 10 LSBs,
// where full scale is 5 V.
*value = ((uint32_t)(value_raw) * 2 * 5000) / 1023;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the Linux kernel, for the battery voltage, I also took into account the VCE of Q19B that I somehow figured to be 50 mV (don't remember how I came up with that number). And I also added a bit more to account for the shunt resistor which depends on the current.

@dlech
Copy link
Member

dlech commented Aug 8, 2025

I also think we need to first slow down the SPI on the ADC a bit more to get more accurate readings.

Below are some data points I took (by enabling debug prints in the DCM). As we can see, the {W,C2T,T2C}DELAYs are already helping quite a bit, but the values are still skewed a bit compared to running at a slower SCLK rate.

It looks like 1MHz is the magic value to let us actually read a saturated 5V on the ADC. (Note: the values are what I set ADC_SPI_CLK_SPEED to, not the actual rounded rate).

No *DELAY

56::: p1: 4878mv p2:1 p5:1 p6:0 (254 mv)                                        
56::: p1: 4883mv p2:1 p5:1 p6:0 (249 mv)                                        
56::: p1: 4863mv p2:1 p5:1 p6:0 (229 mv)  

master (~20 MHz)

56::: p1: 4946mv p2:1 p5:1 p6:0 (234 mv)                                        
56::: p1: 4946mv p2:1 p5:1 p6:0 (229 mv)                                        
56::: p1: 4931mv p2:1 p5:1 p6:0 (200 mv)  

10 MHz 

56::: p1: 4951mv p2:1 p5:1 p6:0 (229 mv)                                        
56::: p1: 4956mv p2:1 p5:1 p6:0 (229 mv)                                        
56::: p1: 4941mv p2:1 p5:1 p6:0 (200 mv) 

5 MHz

56::: p1: 4961mv p2:1 p5:1 p6:0 (224 mv)                                        
56::: p1: 4966mv p2:1 p5:1 p6:0 (224 mv)                                        
56::: p1: 4951mv p2:1 p5:1 p6:0 (195 mv)  

1 MHz

56::: p1: 5000mv p2:1 p5:1 p6:0 (190 mv)                                        
56::: p1: 5000mv p2:1 p5:1 p6:0 (190 mv)                                        
56::: p1: 5000mv p2:1 p5:1 p6:0 (171 mv)  

100 kHz

56::: p1: 5000mv p2:1 p5:1 p6:0 (175 mv)                                        
56::: p1: 5000mv p2:1 p5:1 p6:0 (175 mv)                                        
56::: p1: 5000mv p2:1 p5:1 p6:0 (161 mv) 

10 kHz

56::: p1: 5000mv p2:1 p5:1 p6:0 (190 mv)                                        
56::: p1: 5000mv p2:1 p5:1 p6:0 (190 mv)                                        
56::: p1: 5000mv p2:1 p5:1 p6:0 (171 mv) 

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.

[Feature] [EV3] Implement battery voltage sensing
4 participants