lolwheel / Owie

MIT License
145 stars 43 forks source link

converting voltage to % remaining #1

Closed biell closed 2 years ago

biell commented 2 years ago

The following formula can be used to convert voltage into % remaining on an idle XR. It works with a CBXR, and so would work with a JWXR. I don't know how it would work with VNR.

         99.9
-----------------------   -  10
0.8 + 1.29^(54-voltage)

Also, I updated pOnewheel and Onewave for my Two-X to do a pretty good job showing the % remaining while moving at about 10 MPH. Maybe, we could try a new way to do that here, so you don't have to stop riding to check your % remaining? In those apps, I had access to a lot of variables, we may not be able to do this with just the variables output by the BMS.

I think JW just drops the amp usage statistics because FM combines them with other variables to stop the board. However, I think it would be worth manipulating them to cause the main app to actually report correctly. For example, we could divide them by 10 maybe, then apps like OWCE could have an option to multiply by 10, and then report some of these statistics to the user in a reconstructed fashion.

The solution should always pass through the individual cell voltages also, because these are important for troubleshooting when they are available.

thibauddavid commented 2 years ago

Voltage to battery percentage is not linear so you can't just use a formula for this if you want something accurate.

On my OnewheelEnhancer tweak, I've integrated ChiBattery's voltage-to-percent lookup table, by linearizing voltage between two values which gives a much accurate result.

But I think a better way to do this on a chip would be to leverage used amps once the chip knows how much total amps the battery has, which is easily deductible from approximating remaining battery percent from voltage.

So on the first charge of a newly chip'd board, display an approximated voltage based on value, then once this percent drops to 80% (and then recalibrated at 50%), we'll know what the total amperage of the battery based on nearest known value.

biell commented 2 years ago

I totally agree that voltage -> percent remaining is non-linear, which is why I had to use a non-linear equation to fit the data. I included a graph below comparing my line to Chi and JW. I have also received feedback from others that Chi's bottom end (below 45 volts) is not available in practice. My equation is much more accurate than any interpolation between Chi's table data points, and I recommend you switch to it for your OnewheelEnhancer tweak for CBXRs. I can't speak to its accuracy on a Quart. However, a very similar non-linear equation would exist, and it would just be a minor tweak of the one I have for a CBXR.

However, you bring up a good point. When I was adding support for my Two-X to pOnewheel and Onewave, I used amp draw down as my primary method with wild success. I can ride that board down to 1% very consistently before it would shut off. For me, the catch was that I can only use that method from an app when the board starts fully charged; if you stop and start the board, the app looses track because it is disconnected and can't know what happened when it wasn't connected to the board. For those cases, I implemented both an amps used and a voltage calculation, and prefer one over the other based on the state of the board when I turn it on.

However, this chip will always be connected, and so we can use non-volatile memory to keep an accurate state of how many amp hours are left and produce a number using the same method the BMS uses to send its %remaining. The great advantage to this method is that is is just as accurate when not on the board as it is when you are riding at 15MPH. As long as there is a way for people to configure their amp hours, this should also work for VNR setups. I am very much in favor of making this the primary method for sending a %remaining statistic to the controller.

I do think that implementing routines to perform a voltage -> %remaining calculation either as an option, backup, or sanity check is probably a good idea.

CBXR Voltage to Percent

lolwheel commented 2 years ago

Good convo everyone. I'm planning on starting with Coulomb counting just like @biell suggested. If I or anyone else feels getting fancier later, an extended Kalman filter can be used to make this work better, i.e. keep track of battery degradation due to aging, taking in account temperature etc.

lolwheel commented 2 years ago

Closing the issue for now.

lolwheel commented 2 years ago

@biell Hey William, I ended up using the function you provided here instead of coulomb counting (for now).

Q: Did you fit the curve yourself? The numbers are a little off so I was wondering if it's possible to refit the curve?

In particular, the voltage I have access to is just the sum of voltages of individual cells. This number is consistently 0.7 volts lower than what the official app reports. The highest voltage we can ever see is 4.2 * 15 = 63.0v which with your formula gives around 96% or so. Close enough but I'm being a little OCD here, might as well do better.

biell commented 2 years ago

@lolwheel I fit the curve myself and the data that comes from what is reported to the app over bluetooth on a CBXR. If you can get me data, I can refit a new line based on the data supplied by the BMS. It would be cool if you could download this data in CSV from the module via bluetooth anyway. Alternatively, you can just add 0.7 volts to whatever is reported by the BMS (assuming that really is consistent). Or, you can change the formula to use 53.3 instead of 54 and it will shift the curve for you.

All that being said, you must be doing something wrong if you have 63->96%, because the formula should calculate 63v to 100.87%. What kind of floating point precision do you have? Even single precision should be able to handle this no problem. If your FP is total crap, I can look into alternatives.

julia> 99.9/(0.8+1.29^(54-63))-10
100.86617573243242
Volts| Calculation
63.0 | 100.9
62.5 | 99.2
62.0 | 97.4
61.5 | 95.4
61.0 | 93.2
60.5 | 90.8
60.0 | 88.2
59.5 | 85.5
59.0 | 82.5
58.5 | 79.4
58.0 | 76.0
57.5 | 72.6
57.0 | 68.9
56.5 | 65.2
56.0 | 61.3
55.5 | 57.4
55.0 | 53.4
54.5 | 49.4
54.0 | 45.5
53.5 | 41.6
53.0 | 37.8
52.5 | 34.1
52.0 | 30.5
51.5 | 27.1
51.0 | 23.9
50.5 | 20.9
50.0 | 18.0
49.5 | 15.3
49.0 | 12.8
48.5 | 10.6
48.0 | 8.5
47.5 | 6.6
47.0 | 4.8
46.5 | 3.2
46.0 | 1.8
45.5 | 0.5
45.0 | -0.7
biell commented 2 years ago

@lolwheel I also remembered that, for my Plus, I had different equations for the total voltage output and the sum of cells. Specifically, the Plus version of 1.29 had to be different for the two. That being said, you have to be way more accurate on LiFePO4 batteries because the curve is so dramatic, NMC's are much easier, with a shallow curve. I actually like sum of cells better to estimate capacity while riding because it is more stable. If my Plus Two-X isn't fully charged, so I can use the amp counting method, my cell summation method is what I fall back on for that board.

We can start with changing the median value to something like 53.3 and that should take you far. My issue with gathering data on my CBXR to refine this is that, even though I have a 4209, if I keep the app connected while I ride, then my board will shut off prematurely after the controller thinks I am at 0%. To periodically stop and get a voltage number is easy, but all 15 would be a lot. Also, pOnewheel's logging feature doesn't seem to work well on my new phone.

If you were able to write a log of voltages, amp usage, etc (all the variables you have access to) along with timestamps and pull that back via wifi or bluetooth after your rides, we could use that data to figure out if my original equation needs to be changed.

lolwheel commented 2 years ago

Eek I cannot read apparently, I used 1.24^(...) instead of 1.29 https://github.com/lolwheel/Owie/blob/main/lib/bms/packet_parsers.cpp#L17

Logging is absolutely possible but I'm not sure about its usefullness as we won't have access to the open circuit voltage in runtime.

biell commented 2 years ago

It's amazing what 0.05 can do! It is possible that a Pint and XR have the same curve, but it might be different. So, that might need to be accounted for. The curve is different for the Plus for sure, and the GT will also have a different curve, too.

I mention this because, even after you get coulomb counting working, it might be good to keep this method around as a reference to compare that your internal state is correct. I would think a quick comparison whenever the current draw drops near 0 for more than a few seconds. If we disagree by more than some threshold (5% maybe), then something is probably off.

lolwheel commented 2 years ago

This seems to be working great so far to the point where I'm hesitant to switch to Coulomb counting, especially given the cross-product space of possible stock battery capacity, extended battery capacity and VnR hookup method(pre/post BMS) which will make the Owie initial configuration much more error prone.

Closing the issue. Thanks again @biell for hooking us up with the nicely fitted curve.

Some closing remarks for further development in this space, if anyone is interested. Theoretically we can further fit the curve so it drops off even more drastically at the bottom, here's the motivation: Assuming(bold one on my side, I haven't compared the current curve to any voltage curves out there) that the curve we have right now is close to being linear based on Ah used, it still doesn't reflect available range linearly as the range is linearly related to the energy left in the pack, which is V A h. Example - 1 Ah at the full battery voltage - 60v - corresponds to 20% more energy and range compared to the same 1 Ah at the bottom of the battery, around 50 v.

This is all super fine tuning though, I wouldn't bother too much here.