Skip to content
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

Battery updates #292

Merged
merged 4 commits into from
Feb 14, 2025
Merged

Battery updates #292

merged 4 commits into from
Feb 14, 2025

Conversation

laurensvalk
Copy link
Member

@laurensvalk laurensvalk commented Feb 11, 2025

This takes initial steps towards resolving https://github.com/orgs/pybricks/discussions/1872.

This follows the observed pattern in the official firmware (MINDSTORMS and SPIKE V3) where charging is briefly disabled for some time after about half an hour of charging. This ensures that the charging chip does not time out and disables charging.


To try it out, please download the firmware file in the post below and install it using these instructions.


Some considerations: Is this really optimal? We could consider doing this only if the timeout error is really reached. This would reduce charge cycles.

@dlech wrote:

I wouldn't make it conditional. Even when it manages to charge full without error, it enters a discharge phase that drains the battery to 8V. Having this timer would help keep the battery topped off at a higher level.

If I understand the comments here correctly, several people have independently confirmed that the official firmware stops charging briefly if still charging after after about half an hour. If so then following this pattern seems acceptable indeed.

Do we know how long it takes for the actual timeout error to be reached? Maybe we can make the software timeout a bit closer to that so we don't introduce more cycles than necessary.

I am currently running some experiments, but it is a slow process. I currently have a robot running around the room to simulate normal use. Then I'll try charging it to see if I can reproduce the issue.

Todo:

  • This also removed the workaround for Technic Hub so we probably need to put that back.

The charger module should be in charge of charging, not the battery module.

This ensures that the battery status getter is synchronized with the actual battery state. Before this commit, the battery could be charging before it was reflected in the charging state.

This will also give us more control to disable charging under certain charger error state conditions in the next commit.
@laurensvalk
Copy link
Member Author

@MrGibbage, @FLL-Team-24277, @BertLindeman: I would be most grateful if you want to give this a try. No need to do anything special. Just install the firmware as instructed above and use it like you normally do. Thank you!

@laurensvalk laurensvalk requested a review from dlech February 11, 2025 15:01
@BertLindeman
Copy link
Contributor

Sure Laurens,

Just to be sure:
This PR has nothing to do with the charger status.

  1. Not charging (light is off).
  2. Charging (light is red).
  3. Charging is complete (light is green).
  4. There is a problem with the charger (light is yellow)

The led is green before the status changes to 2.
IIRC David stated that that is on purpose.

(testing)

Bert

@laurensvalk
Copy link
Member Author

The status indications have (almost) not changed. (We did fix the light and battery thresholds not actually 100% corresponding when close to the 8300 "full" threshold.)

I don't know about the order of lights. I haven't been able to reproduce the problem at all yet. I am currently running tests with old firmware. Otherwise I can't test that it has been fixed.

But ideally you would find that the error condition no longer reproduces without me telling exactly what changed 😉

@BertLindeman
Copy link
Contributor

BertLindeman commented Feb 11, 2025

An example of what I try to say:
Robot inventor at this firmware (as it previously also was):

 0:00:00.001 -  primehub     voltage:  8.368 V current:  0.064 A | Charger:  2   237 mA Charging (light red)
 0:00:30.001 -  primehub     voltage:  8.364 V current:  0.058 A | Charger:  2   228 mA Charging (light red)
 0:01:00.001 -  primehub     voltage:  8.364 V current:  0.057 A | Charger:  2   230 mA Charging (light red)
 0:01:30.001 -  primehub     voltage:  8.363 V current:  0.057 A | Charger:  2   229 mA Charging (light red)
 0:02:00.001 -  primehub     voltage:  8.363 V current:  0.057 A | Charger:  2   230 mA Charging (light red)
 0:02:30.001 -  primehub     voltage:  8.363 V current:  0.057 A | Charger:  2   230 mA Charging (light red)
 0:03:00.001 -  primehub     voltage:  8.363 V current:  0.057 A | Charger:  2   230 mA Charging (light red)
 0:03:30.001 -  primehub     voltage:  8.364 V current:  0.057 A | Charger:  2   226 mA Charging (light red)
 0:04:00.001 -  primehub     voltage:  8.363 V current:  0.057 A | Charger:  2   227 mA Charging (light red)
 0:04:30.001 -  primehub     voltage:  8.364 V current:  0.057 A | Charger:  2   230 mA Charging (light red)
 0:05:00.001 -  primehub     voltage:  8.364 V current:  0.057 A | Charger:  2   226 mA Charging (light red)
 0:05:30.001 -  primehub     voltage:  8.364 V current:  0.057 A | Charger:  2   227 mA Charging (light red)

The charging light is green
Will let it charge further...

My show_version_battery.py program
""" program to show the battery voltage and current consumed over time
    Simplified arithmetic so this can also run on the movehub """

from pybricks import version
from pybricks.tools import wait
from pybricks.tools import StopWatch
from pybricks.parameters import Color

print(f'version {version}')

hw_type = version[0]

# import and define the hub object
from pybricks.hubs import ThisHub
hub = ThisHub()

if hw_type in ["cityhub", "essentialhub", "movehub", "technichub"]:
    pass
elif hw_type in ["inventorhub", "primehub"]:  # aliases == the same firmware
    hub.display.off()
else:
    raise RuntimeException("Unknown hub " + hw_type)  # pylint: disable=E0602  # Undefined variable
print(hw_type, "loaded\n\tBattery voltage:", hub.battery.voltage(), "mV")

DEBUG = False
# DEBUG = True
INTERVAL_MS = 30 * 1000  # 30 seconds in mSec

if hw_type in ["technichub", "cityhub", "movehub"]:
    # max 6 * 1.2 Volt?
    BAT_HI = 8000  # mVolt
    BAT_MED = 7000  # mVolt
    BAT_LOW = 6000  # mVolt
    BAT_OUT = 5500  # mVolt
else:
    # Prime hub complains sooner?
    BAT_HI = 8400  # mVolt
    BAT_MED = 8000  # mVolt
    BAT_LOW = 7000  # mVolt
    BAT_OUT = 6250  # mVolt

HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKCYAN = '\033[96m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'

# Movehub does not have math functions, so no float() just shift the decimal point in
def format_ms_to_time(ms):
    # Constants representing the number of milliseconds in one second, minute, and hour
    ms_per_second = 1000
    ms_per_minute = 60 * ms_per_second
    ms_per_hour = 60 * ms_per_minute

    # Calculate the hours, minutes, and seconds
    hours = ms // ms_per_hour
    ms %= ms_per_hour

    minutes = ms // ms_per_minute
    ms %= ms_per_minute

    seconds = ms // ms_per_second
    ms %= ms_per_second
    return hours, minutes, seconds, ms


def format_msec_as_time(clock):
    # use decimal math not float, so movehub can do it too.
    hour, minute, sec, ms = format_ms_to_time(clock)
    return f'{hour:>2}:{minute:>02}:{sec:02}.{ms:03} - '


def set_voltage_color(volt):
    if volt >= BAT_MED:
        textcolor = OKGREEN + BOLD
        light_color = Color.GREEN
    elif volt >= BAT_LOW:
        textcolor = WARNING + BOLD
        light_color = Color.YELLOW
    else:
        textcolor = FAIL + BOLD
        light_color = Color.RED

    # if DEBUG:
    #     print(f"{hw_type:<12} {textcolor}voltage: {volt:>6} V{ENDC}")

    return textcolor, light_color


def print_time_and_voltage():
    voltage_ma = hub.battery.voltage()
    textcolor, light_color = set_voltage_color(voltage_ma)
    cur_voltage = format_like_decimal(voltage_ma)
    hub.light.on(light_color)
    print(format_msec_as_time(watch.time()), end=" ")
    print(f"{hw_type:<12} {textcolor}voltage: {cur_voltage:>6} V{ENDC}", end=" ")


def print_amperes():
    # print(f"{hw_type:<12} current: {format_like_decimal(hub.battery.current()):>6} A", end=" ")
    print(f"current: {format_like_decimal(hub.battery.current()):>6} A", end=" ")
    # print(f'Charger: {hub.charger.connected():>2}', end=" ")

    # 0. Not charging (light is off).
    # 1. Charging (light is red).
    # 2. Charging is complete (light is green).
    # 3. There is a problem with the charger (light is yellow).

    try:
        charger = hub.charger
    except:  # noqa
        charger = None
    if charger:
        print(f'| Charger: {hub.charger.connected():>2} {hub.charger.current():>5} mA', end=" ")
        charger_status = hub.charger.status()
        if charger_status == 0:
            charge_text = f'{OKCYAN}Not charging (light off){ENDC}'
        elif charger_status == 1:
            charge_text = f'{OKGREEN + BOLD}Charging {ENDC}{FAIL}(light red){ENDC}'
            hub.light.on(Color.RED)
        elif charger_status == 2:
            charge_text = f'{OKGREEN}Complete (light {BOLD}green{ENDC}{OKGREEN}){ENDC}'
        else:
            charge_text = f'{WARNING + BOLD}Problem (light yellow){ENDC}'
        print(charge_text)
    else:
        print()


def format_like_decimal(mynum):
    sign = '-' if mynum < 0 else ''
    num_str = str(abs(mynum))
    num_len = len(num_str)
    result = ''
    if num_len == 1:
        result = sign + '0.00' + num_str
    elif num_len == 2:
        result = sign + '0.0' + num_str
    elif num_len == 3:
        result = sign + '0.' + num_str
    else:
        for i in range(num_len):
            if i == num_len - 3:  # was 4
                result += '.'
            result += num_str[i]
    return result


# tests
if DEBUG:
    print(format_like_decimal(-1000))
    print(format_like_decimal(-100))
    print(format_like_decimal(-10))
    print(format_like_decimal(-1))
    print(format_like_decimal(0))
    print(format_like_decimal(1))
    print(format_like_decimal(10))
    print(format_like_decimal(999))
    print(format_like_decimal(1000))
    print(format_like_decimal(10000))
    print(format_like_decimal(100000))


watch = StopWatch()
watch.reset()
while True:
    # determine the time it took to deliver our payload and subtract that from waittime
    start_time = watch.time()  # get the current time
    print_time_and_voltage()
    print_amperes()
    end_time = watch.time()  # get the time after the action

    processing_time = end_time - start_time  # calculate the time taken for the action
    # wait for the remaining time
    wait(max(INTERVAL_MS - processing_time, 0))

[EDIT]
I have a primehub that "went" into blinking yellow on charge.
Will charge that hub later..

@BertLindeman
Copy link
Contributor

charger-led goes green on 8300 mV and status still charging on my primehub with charger_status == 1

@laurensvalk
Copy link
Member Author

laurensvalk commented Feb 11, 2025

If I understand correctly, this issue occurs when it doesn't complete charging within some time limit. So it is more likely to occur if you start with a low battery voltage.


I made a build/program that uses about as much power as it charges with, and it has already been charging in this state for 5 hours with the old firmware. Still no yellow light. I'll wait some more.

@BertLindeman
Copy link
Contributor

A small change in the charging of the primehub:

 1:28:30.002 -  primehub     voltage:  8.370 V current:  0.042 A | Charger:  2   232 mA Charging (light red)
 1:29:00.002 -  primehub     voltage:  8.369 V current:  0.042 A | Charger:  2   232 mA Charging (light red)
 1:29:30.002 -  primehub     voltage:  8.370 V current:  0.042 A | Charger:  2   231 mA Charging (light red)
 1:30:00.002 -  primehub     voltage:  8.370 V current:  0.042 A | Charger:  2   229 mA Charging (light red)
 1:30:30.002 -  primehub     voltage:  8.354 V current:  0.044 A | Charger:  2   142 mA Not charging (light off)
 1:31:00.002 -  primehub     voltage:  8.367 V current:  0.033 A | Charger:  2   230 mA Charging (light red)
 1:31:30.002 -  primehub     voltage:  8.369 V current:  0.040 A | Charger:  2   231 mA Charging (light red)

waiting for a timeout.

@laurensvalk
Copy link
Member Author

laurensvalk commented Feb 11, 2025

1:30:00.002 - primehub voltage: 8.370 V current: 0.042 A | Charger: 2 229 mA Charging (light red)
1:30:30.002 - primehub voltage: 8.354 V current: 0.044 A | Charger: 2 142 mA Not charging (light off)
1:31:00.002 - primehub voltage: 8.367 V current: 0.033 A | Charger: 2 230 mA Charging (light red)

Every half hour, this new firmware version turns off charging for 20 seconds, so that small change is intentional 😉

(Although the light would be expected to be green above 8.3V, even if it is still charging.)

That half hour timeout was inspired by the LEGO firmware.

@MrGibbage
Copy link

Happy to help with the testing, but right now is "off-season" for us, and we aren't running any robots. Maybe in another month. Anyway, I am going to install it and do some testing, but it won't be super-thorough or intense.

@BertLindeman
Copy link
Contributor

(Although the light would be expected to be green above 8.3V, even if it is still charging.)

The charger light does go to green at 8.3V, just the charger.status does not reflect that, so my program still reports as documented Charging (light red)

That half hour timeout was inspired by the LEGO firmware. But on our old firmware I still haven't triggered the error state after almost 6 hours of charging. I was hoping not to leave it overnight with motors running 🤐

Mine is running without active motors, so this one will run all night.

@laurensvalk
Copy link
Member Author

Happy to help with the testing, but right now is "off-season" for us, and we aren't running any robots. Maybe in another month. Anyway, I am going to install it and do some testing, but it won't be super-thorough or intense.

Thank you! No need to do anything intense.

Perhaps before you install, try to see if you can get it to the bad state (blink yellow) overnight. And then the next time with the new firmware, to see if it doesn't happen this time.

@laurensvalk
Copy link
Member Author

laurensvalk commented Feb 11, 2025

I was able to force the issue artificially but in a reproducible way on our current/old firmware: By drawing just enough current with 6 motors so that an old 5V 500 mA charger would just not charge it.

After 7 hours and 15 minutes it changed to the yellow blink state.

07:14:45 Bat mv 6943 Bat mA 0477 Ch mA 0626 Ch stat 1
07:14:50 Bat mv 6943 Bat mA 0477 Ch mA 0628 Ch stat 1
07:14:55 Bat mv 6943 Bat mA 0477 Ch mA 0627 Ch stat 1
07:15:00 Bat mv 6943 Bat mA 0475 Ch mA 0629 Ch stat 1
07:15:05 Bat mv 6943 Bat mA 0481 Ch mA 0630 Ch stat 1
07:15:10 Bat mv 6945 Bat mA 0477 Ch mA 0634 Ch stat 1
07:15:15 Bat mv 6945 Bat mA 0477 Ch mA 0633 Ch stat 1
07:15:20 Bat mv 6946 Bat mA 0481 Ch mA 0633 Ch stat 1
07:15:25 Bat mv 6945 Bat mA 0477 Ch mA 0631 Ch stat 1
07:15:30 Bat mv 6823 Bat mA 0475 Ch mA 0051 Ch stat 3
07:15:35 Bat mv 6827 Bat mA 0475 Ch mA 0052 Ch stat 3
07:15:40 Bat mv 6828 Bat mA 0481 Ch mA 0050 Ch stat 3
07:15:45 Bat mv 6825 Bat mA 0475 Ch mA 0052 Ch stat 3
07:15:50 Bat mv 6823 Bat mA 0479 Ch mA 0050 Ch stat 3
07:15:55 Bat mv 6820 Bat mA 0475 Ch mA 0051 Ch stat 3
07:16:00 Bat mv 6820 Bat mA 0477 Ch mA 0051 Ch stat 3
07:16:05 Bat mv 6818 Bat mA 0475 Ch mA 0052 Ch stat 3
07:16:10 Bat mv 6818 Bat mA 0475 Ch mA 0051 Ch stat 3

Recreating the situation this way is perhaps not fully representative of the normal case (certain hub-battery pairs not reaching the full state), but the end result is similar.

Reading through some of the notes in https://github.com/orgs/pybricks/discussions/1872, I think I see one instance of @BertLindeman hitting this state after 5 hours and @dlech overnight also in the range of at least several up to 14 hours on return.

So instead of having a 30 minute timeout, a timeout of 60 or 120 minutes may be reasonable. I'll update the PR tomorrow.

@dlech
Copy link
Member

dlech commented Feb 11, 2025

Some considerations: Is this really optimal? We could consider doing this only if the timeout error is really reached. This would reduce charge cycles.

To keep the battery as full as possible, I think it is best to restart the charger more often. The reset actually serves two purposes. On hubs that can't charge fully, it prevents the timeout error. On hubs that can charge fully, it prevents the battery from discharging too much before starting to charge again. If we restart the charger before the battery has had a chance to drop in voltage more than 0.1V, then it will immediately go into constant voltage mode and drop the charging current. This seems like it would be better for the battery to me than fewer but deeper cycles. And having the "good" hubs not be allowed to discharge for too long prevents the chance of someone unplugging the charger near the end of the discharge and not ending up with a full battery.

@BertLindeman
Copy link
Contributor

Status here this morning:
no message(s) about a charger error status.
But I have not seen messages between 5 and a half hour to 6 hours in the charging.

Last part of the measurements (will leave it on today): 14:00:00.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 198 mA Charging (light red) 14:00:30.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 199 mA Charging (light red) 14:01:00.013 - primehub voltage: 8.373 V current: 0.042 A | Charger: 2 205 mA Charging (light red) 14:01:30.013 - primehub voltage: 8.373 V current: 0.042 A | Charger: 2 199 mA Charging (light red) 14:02:00.013 - primehub voltage: 8.373 V current: 0.042 A | Charger: 2 199 mA Charging (light red) 14:02:30.013 - primehub voltage: 8.373 V current: 0.042 A | Charger: 2 199 mA Charging (light red) 14:03:00.013 - primehub voltage: 8.374 V current: 0.042 A | Charger: 2 195 mA Charging (light red) 14:03:30.013 - primehub voltage: 8.373 V current: 0.042 A | Charger: 2 196 mA Charging (light red) 14:04:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 198 mA Charging (light red) 14:04:30.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 196 mA Charging (light red) 14:05:00.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 197 mA Charging (light red) 14:05:30.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 197 mA Charging (light red) 14:06:00.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 200 mA Charging (light red) 14:06:30.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 198 mA Charging (light red) 14:07:00.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 199 mA Charging (light red) 14:07:30.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 197 mA Charging (light red) 14:08:00.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 195 mA Charging (light red) 14:08:30.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 197 mA Charging (light red) 14:09:00.013 - primehub voltage: 8.356 V current: 0.042 A | Charger: 2 134 mA Not charging (light off) 14:09:30.013 - primehub voltage: 8.371 V current: 0.033 A | Charger: 2 197 mA Charging (light red) 14:10:00.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 199 mA Charging (light red) 14:10:30.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 199 mA Charging (light red) 14:11:00.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 201 mA Charging (light red) 14:11:30.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 199 mA Charging (light red) 14:12:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 200 mA Charging (light red) 14:12:30.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 197 mA Charging (light red) 14:13:00.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 198 mA Charging (light red) 14:13:30.013 - primehub voltage: 8.372 V current: 0.040 A | Charger: 2 199 mA Charging (light red) 14:14:00.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 199 mA Charging (light red) 14:14:30.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 195 mA Charging (light red) 14:15:00.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 198 mA Charging (light red) 14:15:30.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 198 mA Charging (light red) 14:16:00.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 202 mA Charging (light red) 14:16:30.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 198 mA Charging (light red) 14:17:00.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 197 mA Charging (light red) 14:17:30.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 199 mA Charging (light red) 14:18:00.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 196 mA Charging (light red) 14:18:30.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 198 mA Charging (light red) 14:19:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 198 mA Charging (light red) 14:19:30.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 197 mA Charging (light red) 14:20:00.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 198 mA Charging (light red) 14:20:30.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 199 mA Charging (light red) 14:21:00.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 196 mA Charging (light red) 14:21:30.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 198 mA Charging (light red) 14:22:00.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 198 mA Charging (light red) 14:22:30.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 197 mA Charging (light red) 14:23:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 199 mA Charging (light red) 14:23:30.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 197 mA Charging (light red) 14:24:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 198 mA Charging (light red) 14:24:30.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 197 mA Charging (light red) 14:25:00.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 196 mA Charging (light red) 14:25:30.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 199 mA Charging (light red) 14:26:00.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 196 mA Charging (light red) 14:26:30.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 197 mA Charging (light red) 14:27:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 200 mA Charging (light red) 14:27:30.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 197 mA Charging (light red) 14:28:00.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 197 mA Charging (light red) 14:28:30.013 - primehub voltage: 8.373 V current: 0.037 A | Charger: 2 198 mA Charging (light red) 14:29:00.013 - primehub voltage: 8.373 V current: 0.035 A | Charger: 2 197 mA Charging (light red) 14:29:30.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 199 mA Charging (light red) 14:30:00.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 199 mA Charging (light red) 14:30:30.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 198 mA Charging (light red) 14:31:00.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 197 mA Charging (light red) 14:31:30.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 197 mA Charging (light red) 14:32:00.013 - primehub voltage: 8.374 V current: 0.042 A | Charger: 2 198 mA Charging (light red) 14:32:30.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 211 mA Charging (light red) 14:33:00.013 - primehub voltage: 8.373 V current: 0.044 A | Charger: 2 197 mA Charging (light red) 14:33:30.013 - primehub voltage: 8.374 V current: 0.042 A | Charger: 2 199 mA Charging (light red) 14:34:00.013 - primehub voltage: 8.372 V current: 0.040 A | Charger: 2 198 mA Charging (light red) 14:34:30.013 - primehub voltage: 8.374 V current: 0.042 A | Charger: 2 197 mA Charging (light red) 14:35:00.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 197 mA Charging (light red) 14:35:30.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 197 mA Charging (light red) 14:36:00.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 201 mA Charging (light red) 14:36:30.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 197 mA Charging (light red) 14:37:00.013 - primehub voltage: 8.372 V current: 0.039 A | Charger: 2 197 mA Charging (light red) 14:37:30.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 196 mA Charging (light red) 14:38:00.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 197 mA Charging (light red) 14:38:30.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 197 mA Charging (light red) 14:39:00.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 197 mA Charging (light red) 14:39:30.013 - primehub voltage: 8.372 V current: 0.040 A | Charger: 2 203 mA Charging (light red) 14:40:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 197 mA Charging (light red) 14:40:30.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 199 mA Charging (light red) 14:41:00.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 201 mA Charging (light red) 14:41:30.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 195 mA Charging (light red) 14:42:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 198 mA Charging (light red) 14:42:30.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 199 mA Charging (light red) 14:43:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 199 mA Charging (light red) 14:43:30.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 199 mA Charging (light red) 14:44:00.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 198 mA Charging (light red) 14:44:30.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 199 mA Charging (light red) 14:45:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 197 mA Charging (light red) 14:45:30.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 200 mA Charging (light red) 14:46:00.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 198 mA Charging (light red) 14:46:30.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 199 mA Charging (light red) 14:47:00.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 197 mA Charging (light red) 14:47:30.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 198 mA Charging (light red) 14:48:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 199 mA Charging (light red) 14:48:30.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 198 mA Charging (light red) 14:49:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 198 mA Charging (light red) 14:49:30.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 198 mA Charging (light red) 14:50:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 200 mA Charging (light red) 14:50:30.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 198 mA Charging (light red) 14:51:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 200 mA Charging (light red) 14:51:30.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 197 mA Charging (light red) 14:52:00.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 195 mA Charging (light red) 14:52:30.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 199 mA Charging (light red) 14:53:00.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 197 mA Charging (light red) 14:53:30.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 199 mA Charging (light red) 14:54:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 199 mA Charging (light red) 14:54:30.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 201 mA Charging (light red) 14:55:00.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 198 mA Charging (light red) 14:55:30.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 199 mA Charging (light red) 14:56:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 199 mA Charging (light red) 14:56:30.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 200 mA Charging (light red) 14:57:00.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 198 mA Charging (light red) 14:57:30.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 197 mA Charging (light red) 14:58:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 201 mA Charging (light red) 14:58:30.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 200 mA Charging (light red) 14:59:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 198 mA Charging (light red) 14:59:30.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 198 mA Charging (light red) 15:00:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 198 mA Charging (light red) 15:00:30.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 198 mA Charging (light red) 15:01:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 200 mA Charging (light red) 15:01:30.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 200 mA Charging (light red) 15:02:00.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 197 mA Charging (light red) 15:02:30.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 199 mA Charging (light red) 15:03:00.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 199 mA Charging (light red) 15:03:30.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 196 mA Charging (light red) 15:04:00.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 200 mA Charging (light red) 15:04:30.013 - primehub voltage: 8.374 V current: 0.042 A | Charger: 2 197 mA Charging (light red) 15:05:00.013 - primehub voltage: 8.374 V current: 0.042 A | Charger: 2 199 mA Charging (light red) 15:05:30.013 - primehub voltage: 8.373 V current: 0.042 A | Charger: 2 197 mA Charging (light red) 15:06:00.013 - primehub voltage: 8.374 V current: 0.042 A | Charger: 2 199 mA Charging (light red) 15:06:30.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 199 mA Charging (light red) 15:07:00.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 199 mA Charging (light red) 15:07:30.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 197 mA Charging (light red) 15:08:00.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 199 mA Charging (light red) 15:08:30.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 195 mA Charging (light red) 15:09:00.013 - primehub voltage: 8.373 V current: 0.042 A | Charger: 2 197 mA Charging (light red) 15:09:30.013 - primehub voltage: 8.357 V current: 0.042 A | Charger: 2 136 mA Not charging (light off) 15:10:00.013 - primehub voltage: 8.371 V current: 0.035 A | Charger: 2 195 mA Charging (light red) 15:10:30.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 200 mA Charging (light red) 15:11:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 199 mA Charging (light red) 15:11:30.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 199 mA Charging (light red) 15:12:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 201 mA Charging (light red) 15:12:30.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 199 mA Charging (light red) 15:13:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 196 mA Charging (light red) 15:13:30.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 198 mA Charging (light red) 15:14:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 198 mA Charging (light red) 15:14:30.013 - primehub voltage: 8.374 V current: 0.040 A | Charger: 2 197 mA Charging (light red) 15:15:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 201 mA Charging (light red) 15:15:30.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 197 mA Charging (light red) 15:16:00.013 - primehub voltage: 8.373 V current: 0.040 A | Charger: 2 197 mA Charging (light red) 15:16:30.013 - primehub voltage: 8.374 V current: 0.039 A | Charger: 2 200 mA Charging (light red) 15:17:00.013 - primehub voltage: 8.372 V current: 0.039 A | Charger: 2 198 mA Charging (light red) 15:17:30.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 198 mA Charging (light red) 15:18:00.013 - primehub voltage: 8.373 V current: 0.039 A | Charger: 2 198 mA Charging (light red)

@laurensvalk
Copy link
Member Author

Thank you @BertLindeman .

@dlech -- agreed. Any thoughts on the exact duration of the timeout? It seems that the voltage drops only slowly and the error state isn't reached until 4 or more hours, so setting it at 1 hours seems reasonable.

If the code change looks OK to you, I'll go ahead and merge.

I am now starting tests with the new firmware with the same discharge method to reproduce a never-completing charge.

After charging for a long time, we disable charging for some time. This
matches observed behavior with the LEGO Education SPIKE V3.x firmware.
The one in pbsys did not converge and we should do this only once to reduce code size.

Fixes pybricks/support#2055
@BertLindeman
Copy link
Contributor

Kept the test running on the primehub and got an error situation.
firmware primehub with git hash '99e4d056 on 2025-02-11' from CI-build 3720
Kept it running to see if the half-hourly stop helps to recover.
Expected the half-hourly stop abotu run time 19:12.

Last messages up to error situation
18:41:00.015 -  primehub     voltage:  8.374 V current:  0.039 A | Charger:  2   201 mA Charging (light red)
18:41:30.015 -  primehub     voltage:  8.374 V current:  0.035 A | Charger:  2   201 mA Charging (light red)
18:42:00.015 -  primehub     voltage:  8.328 V current:  0.042 A | Charger:  2   163 mA Not charging (light off)
18:42:30.015 -  primehub     voltage:  8.371 V current:  0.033 A | Charger:  2   193 mA Charging (light red)
18:43:00.015 -  primehub     voltage:  8.373 V current:  0.040 A | Charger:  2   197 mA Charging (light red)
18:43:30.015 -  primehub     voltage:  8.373 V current:  0.040 A | Charger:  2   199 mA Charging (light red)
18:44:00.015 -  primehub     voltage:  8.373 V current:  0.040 A | Charger:  2   197 mA Charging (light red)
18:44:30.015 -  primehub     voltage:  8.374 V current:  0.040 A | Charger:  2   200 mA Charging (light red)
18:45:00.015 -  primehub     voltage:  8.374 V current:  0.040 A | Charger:  2   199 mA Charging (light red)
18:45:30.015 -  primehub     voltage:  8.373 V current:  0.040 A | Charger:  2   204 mA Charging (light red)
18:46:00.015 -  primehub     voltage:  8.374 V current:  0.040 A | Charger:  2   198 mA Charging (light red)
18:46:30.016 -  primehub     voltage:  8.373 V current:  0.042 A | Charger:  2   225 mA Charging (light red)
18:47:00.015 -  primehub     voltage:  8.309 V current:  0.042 A | Charger:  2    59 mA Problem (light yellow)
18:47:30.015 -  primehub     voltage:  8.315 V current:  0.037 A | Charger:  2    58 mA Problem (light yellow)
18:48:00.015 -  primehub     voltage:  8.316 V current:  0.037 A | Charger:  2    60 mA Problem (light yellow)
18:48:30.015 -  primehub     voltage:  8.313 V current:  0.037 A | Charger:  2    61 mA Problem (light yellow)
18:49:00.015 -  primehub     voltage:  8.314 V current:  0.035 A | Charger:  2    59 mA Problem (light yellow)
18:49:30.015 -  primehub     voltage:  8.313 V current:  0.035 A | Charger:  2    58 mA Problem (light yellow)
18:50:00.015 -  primehub     voltage:  8.312 V current:  0.035 A | Charger:  2    59 mA Problem (light yellow)
18:50:30.015 -  primehub     voltage:  8.312 V current:  0.035 A | Charger:  2    60 mA Problem (light yellow)
18:51:00.015 -  primehub     voltage:  8.312 V current:  0.035 A | Charger:  2    59 mA Problem (light yellow)
18:51:30.015 -  primehub     voltage:  8.310 V current:  0.035 A | Charger:  2    59 mA Problem (light yellow)
18:52:00.015 -  primehub     voltage:  8.311 V current:  0.035 A | Charger:  2    60 mA Problem (light yellow)
18:52:30.015 -  primehub     voltage:  8.309 V current:  0.035 A | Charger:  2    60 mA Problem (light yellow)
18:53:00.015 -  primehub     voltage:  8.310 V current:  0.035 A | Charger:  2    59 mA Problem (light yellow)
18:53:30.015 -  primehub     voltage:  8.309 V current:  0.035 A | Charger:  2    61 mA Problem (light yellow)
18:54:00.015 -  primehub     voltage:  8.308 V current:  0.035 A | Charger:  2    61 mA Problem (light yellow)
18:54:30.015 -  primehub     voltage:  8.307 V current:  0.035 A | Charger:  2    60 mA Problem (light yellow)
18:55:00.015 -  primehub     voltage:  8.307 V current:  0.035 A | Charger:  2    60 mA Problem (light yellow)
18:55:30.015 -  primehub     voltage:  8.306 V current:  0.035 A | Charger:  2    61 mA Problem (light yellow)

No change until:


19:25:30.016 -  primehub     voltage:  8.278 V current:  0.035 A | Charger:  2    60 mA Problem (light yellow)
19:26:00.016 -  primehub     voltage:  8.279 V current:  0.037 A | Charger:  2    62 mA Problem (light yellow)
19:26:30.016 -  primehub     voltage:  8.278 V current:  0.035 A | Charger:  2    62 mA Problem (light yellow)

Will keep running for an hour or so to see if there is a change.

@laurensvalk
Copy link
Member Author

Expected the half-hourly stop abotu run time 19:12. (...) Last messages up to error situation

The results for 19:12 seem to be missing from your log. Also, the pause is 20 seconds, so your 30 second sample window might just miss them, right?


But it is certainly possible that a soft reset like we are doing here does not prevent the error from triggering. This is puzzling but good to know. My tests results should be ready in a few hours...

@BertLindeman
Copy link
Contributor

BertLindeman commented Feb 12, 2025

The results for 19:12 seem to be missing from your log. Also, the pause is 20 seconds, so your 30 second sample window might just miss them, right?

I would have expected the error situation elevated by the half-hourly stop of the charger.
So I was not too interested in the messages itself.
But, in the meantime I picked up such a stop message.
Proves the stops are done also in the error status, but it does not alleviate (I think) the problem.

19:42:00.016 -  primehub     voltage:  8.263 V current:  0.035 A | Charger:  2    61 mA Problem (light yellow)
19:42:30.016 -  primehub     voltage:  8.262 V current:  0.039 A | Charger:  2    62 mA Not charging (light off)
19:43:00.016 -  primehub     voltage:  8.262 V current:  0.035 A | Charger:  2    62 mA Problem (light yellow)
19:43:30.016 -  primehub     voltage:  8.261 V current:  0.037 A | Charger:  2    61 mA Problem (light yellow)

@laurensvalk
Copy link
Member Author

Thanks! I'll keep monitoring my local test but it looks like we need another approach.

@laurensvalk
Copy link
Member Author

laurensvalk commented Feb 12, 2025

@BertLindeman: are you certain that this does not happen with the SPIKEV3 firmware? Browsing through the tests in https://github.com/orgs/pybricks/discussions/1872, there doesn't seem to be any test where that firmware is given 6+ hours to charge from empty to full. Time to let this robot discharge itself again so we can try that overnight...

EDIT: My sincere apologies to the other Bert that I just accidentally tagged.

@BertLindeman
Copy link
Contributor

BertLindeman commented Feb 12, 2025

@BertLindeman: are you certain that this does not happen with the SPIKEV3 firmware? Browsing through the tests in https://github.com/orgs/pybricks/discussions/1872, there doesn't seem to be any test where that firmware is given 6+ hours to charge from empty to full. Time to let this robot discharge itself again so we can try that overnight...

With my memory, no i'm not sure. Wanted to run the test 24 hours, but to no real solution, so I did the hard "charger stop" - unplug USB - wait 20 seconds - plug in again.
Short result:


22:34:00.018 -  primehub     voltage:  8.119 V current:  0.040 A | Charger:  2    61 mA Problem (light yellow)
22:34:30.018 -  primehub     voltage:  8.120 V current:  0.039 A | Charger:  2    61 mA Problem (light yellow)
22:35:00.018 -  primehub     voltage:  8.118 V current:  0.037 A | Charger:  2    61 mA Problem (light yellow)
22:35:30.018 -  primehub     voltage:  8.117 V current:  0.042 A | Charger:  0    62 mA Not charging (light off)
22:36:00.018 -  primehub     voltage:  8.245 V current:  0.039 A | Charger:  2   526 mA Charging (light red)
22:36:30.018 -  primehub     voltage:  8.250 V current:  0.044 A | Charger:  2   522 mA Charging (light red)
22:37:00.018 -  primehub     voltage:  8.255 V current:  0.044 A | Charger:  2   524 mA Charging (light red)
22:37:30.018 -  primehub     voltage:  8.259 V current:  0.046 A | Charger:  2   524 mA Charging (light red)

Will connect a bunch of motors and later today use SpikeV3 to charge tonight.
(I really like to fiddle like this.)
Do we have a Spike (python?) program to measure the charge?
Your memory is better than mine 😉

EDIT: My sincere apologies to the other Bert that I just accidentally tagged.

No problem by me 😄

@laurensvalk
Copy link
Member Author

Indeed, unplugging will restart charging, but I'm not convinced we can trigger it from software.

Do we have a Spike (python?) program to measure the charge?

https://github.com/orgs/pybricks/discussions/1872#discussioncomment-11419066

@BertLindeman
Copy link
Contributor

Loose observation: On startup the center button blinks a few times (two?) orange like it is battery-low.
Not on the cityhub, not on the movehub.
It does on the TechnicHub, RobotInventor and Spike primehub.

@laurensvalk
Copy link
Member Author

Yeah, there is an open todo for that in the opening post.

@laurensvalk
Copy link
Member Author

I'm glad to hear that though. I was briefly very worried. Mystery solved!

Just tell me what you need tested.

While we don't need any logs at this point, just general day to day use (or mimicking that) of a full discharge and charge would be great. As long as the battery is mostly full at the very end without yellow blinking lights, we should be good.

In fact, it would be good to do that without being connected at all, just to get that case covered.

So no laptops or automation involved: Just the hub turned off and charging, starting red and hopefully green in the end 😄

We've got a few more minor battery updates coming, so if you don't mind starting it later today or tomorrow when those are done, that would be even beter.

Thanks @MrGibbage for initially reporting this and persevering with additional feedback. It is much appreciated.

@laurensvalk
Copy link
Member Author

Everything is now released as part of the new beta. So open https://beta.pybricks.com/, wait a few minutes for it to inform you about a new version. Load it, and then install the firmware as usual. You can tell you have the latest if the about menu gives you:

image

The firmware version will then be as follows:

image

@BertLindeman
Copy link
Contributor

It took me to almost 20 hours testing to err on the copy (CTRL-C) in the console.
Last message:


19:26:00.055 - e876c5933 Hub:  8372 mV   33 mA | Ch conn:2 stat:1   196 mA Charging (light red) 

Have to report no anomalies occurred on the primehub test. (Sigh)

Starting to test primehub on SPIKEV3 to see the interval / timeout after the speed skating.

@laurensvalk
Copy link
Member Author

Thanks! No anomalies is good, right?

@MrGibbage
Copy link

My hub had been charging "offline" all day and the charging light is still red. At least it isn't flashing yellow. I don't know what the current charge is, and I think I am just going to keep it going like this for the rest of the day. I am currently using the 16c8 build.

What is the expected behavior now?

@dlech
Copy link
Member

dlech commented Feb 14, 2025

It depends on the type of charger you have, how much current it can put out, and if the hub is "off" or not.

If you have an underpowered charger and/or there are a bunch of lights turned on, the load might be greater than the charging current and so it never changes up fully. If you have a decent charger that can put out ~1A and the hub is off (all lights are off except for the battery light), then it should charge up in a few hours.

If you still have trouble, try a different hub and a different battery to rule out hardware issues.

@MrGibbage
Copy link

I've been charging it since 0600 this morning, and it is now 2330, so 17.5 hours. Previously when charging it, I frequently saw 500+ mA, so I have no reason to think it is any different now. Anyway, I am still charging and it's a red light. The hub is off, other than the charging light. I'll see what it is doing tomorrow morning. I do have a USB power monitoring device that I could hook up tomorrow to try and get a feel for what it is doing.

Would you expect a green light at some point? Even on a "bad" hub?

@dlech
Copy link
Member

dlech commented Feb 15, 2025

Did the battery voltage on the one that won't charge reach a steady state or is it going up and down? And what is the actual voltage?

@laurensvalk
Copy link
Member Author

@MrGibbage - 500mA charge current is quite low. With a dedicated charger it could typically reach 1200 MA, which helps reaching the top voltage.

@dlech, could we perhaps reconsider the 8300 threshold for green since we've set it ourselves? If it is somewhat arbitrary, maybe we can set a slightly lower level like 8200.

Alternatively, maybe we could set it green if >8100 && steady state or something like that.

@MrGibbage
Copy link

This is the charging hub I am using.
https://www.amazon.com/gp/product/B00SCX6I8A

Left it charging overnight and the light was still red. I turned it on and ran the battery monitor code and have this:
version ('primehub', '3.6.0b2', 'ci-build-3726-v3.6.0b2-54-gb8a516c8 on 2025-02-13')
primehub loaded
Battery voltage: 8298 mV
primehub with git hash 'b8a516c8 on 2025-02-13' from CI-build 3726
0:00:30.001 - b8a516c Hub: 8292 mV 73 mA | Ch conn:2 stat:1 232 mA Charging (light red)

@MrGibbage
Copy link

Looks like that is as full as it will get

version ('primehub', '3.6.0b2', 'ci-build-3726-v3.6.0b2-54-gb8a516c8 on 2025-02-13')
primehub loaded
Battery voltage: 8298 mV
primehub with git hash 'b8a516c8 on 2025-02-13' from CI-build 3726
0:00:30.001 - b8a516c Hub: 8292 mV 73 mA | Ch conn:2 stat:1 232 mA Charging (light red)
0:01:00.002 - b8a516c Hub: 8292 mV 65 mA | Ch conn:2 stat:1 229 mA Charging (light red)
0:01:30.002 - b8a516c Hub: 8292 mV 65 mA | Ch conn:2 stat:1 232 mA Charging (light red)
0:02:00.002 - b8a516c Hub: 8292 mV 65 mA | Ch conn:2 stat:1 229 mA Charging (light red)
0:02:30.002 - b8a516c Hub: 8292 mV 65 mA | Ch conn:2 stat:1 230 mA Charging (light red)
0:03:00.002 - b8a516c Hub: 8293 mV 65 mA | Ch conn:2 stat:1 229 mA Charging (light red)
0:03:30.002 - b8a516c Hub: 8293 mV 73 mA | Ch conn:2 stat:1 231 mA Charging (light red)
0:04:00.002 - b8a516c Hub: 8292 mV 73 mA | Ch conn:2 stat:1 244 mA Charging (light red)
0:04:30.002 - b8a516c Hub: 8293 mV 67 mA | Ch conn:2 stat:1 245 mA Charging (light red)
0:05:00.002 - b8a516c Hub: 8292 mV 62 mA | Ch conn:2 stat:1 234 mA Charging (light red)
0:05:30.002 - b8a516c Hub: 8292 mV 69 mA | Ch conn:2 stat:1 234 mA Charging (light red)
0:06:00.002 - b8a516c Hub: 8292 mV 71 mA | Ch conn:2 stat:1 244 mA Charging (light red)
0:06:30.002 - b8a516c Hub: 8292 mV 62 mA | Ch conn:2 stat:1 244 mA Charging (light red)
0:07:00.002 - b8a516c Hub: 8292 mV 65 mA | Ch conn:2 stat:1 234 mA Charging (light red)
0:07:30.002 - b8a516c Hub: 8292 mV 71 mA | Ch conn:2 stat:1 246 mA Charging (light red)
0:08:00.002 - b8a516c Hub: 8293 mV 65 mA | Ch conn:2 stat:1 231 mA Charging (light red)
0:08:30.002 - b8a516c Hub: 8292 mV 71 mA | Ch conn:2 stat:1 245 mA Charging (light red)
0:09:00.002 - b8a516c Hub: 8292 mV 64 mA | Ch conn:2 stat:1 232 mA Charging (light red)
0:09:30.002 - b8a516c Hub: 8292 mV 65 mA | Ch conn:2 stat:1 246 mA Charging (light red)
0:10:00.002 - b8a516c Hub: 8292 mV 74 mA | Ch conn:2 stat:1 245 mA Charging (light red)
0:10:30.002 - b8a516c Hub: 8292 mV 65 mA | Ch conn:2 stat:1 238 mA Charging (light red)
0:11:00.002 - b8a516c Hub: 8292 mV 67 mA | Ch conn:2 stat:1 248 mA Charging (light red)
0:11:30.002 - b8a516c Hub: 8292 mV 74 mA | Ch conn:2 stat:1 247 mA Charging (light red)
0:12:00.002 - b8a516c Hub: 8292 mV 65 mA | Ch conn:2 stat:1 232 mA Charging (light red)
0:12:30.002 - b8a516c Hub: 8293 mV 64 mA | Ch conn:2 stat:1 247 mA Charging (light red)
0:13:00.002 - b8a516c Hub: 8291 mV 71 mA | Ch conn:2 stat:1 245 mA Charging (light red)
0:13:30.002 - b8a516c Hub: 8291 mV 74 mA | Ch conn:2 stat:1 236 mA Charging (light red)

@laurensvalk
Copy link
Member Author

laurensvalk commented Feb 15, 2025

Thanks!

8298 is practically green if you squint 😄

It turns green at 8300 in our firmware but since this is just a value we picked it seems like it make sense to pick a slightly lower value - then your light would have turned green a long time ago.

And a bit of hysteris should help prevent it toggling for hubs that happen to stabilize precisely around the threshold.

@dlech
Copy link
Member

dlech commented Feb 15, 2025

If it is somewhat arbitrary, maybe we can set a slightly lower level like 8200.

I actually have one hub here that would benefit from a 8.2 V threshold as well. (It's actually hub C that I traded from Skip). I know it gets quite close to the threshold, but I would still use 8.2 V for now unless we actually find a hub that measures lower.

image

Also, interestingly it looks like the ADC is measurably affected by temperature. We let our house get quite cold at night during the winter, then you can clearly see when we turned the heater back on in the morning. Off topic, but I wonder if people reporting gyro performance being affected by temperature are actually experiencing battery voltage feedback in the motor control being affected by temperature.

@dlech
Copy link
Member

dlech commented Feb 15, 2025

Alternatively, maybe we could set it green if >8100 && steady state or something like that.

Thinking about this a bit more, an easy way to determine "steady state" could be to just look at the charge current. If it is < 400 mA, then we know we have reached the constant voltage charge state and the voltage isn't going to go up much more and the charging rate will be much slower, so the battery is reasonably close to as full as it can get.

Another thing we could do is that if the voltage is less that 8.2 V and the charge current is < 400 mA, we could make the light yellow to let users know that the hub probably isn't going to charge all of the way, likely due to an underpowered USB port.

@BertLindeman
Copy link
Contributor

Had a long test with my primehub on SPIKEV3.

A plot of the charging might help in the design. Hope it's readible.

image

Status as usual: my primehub with two medium angular motors attached, on USB-c of my laptop.
To ease copy / paste only write one line per minute with 12 observations over 5 seconds.
In an excel spreadsheet make a list of all observations.

Conclusion:
I see the charger stop each 16:45. Might it be some 1000 internal seconds?
And from time to time there is another stop after 10 seconds. Strange.

Could not pinpoint the voltage of the red to green change.
Btw the red no SPIKEV3 is more orangy red.
I saw the red-green switch at 7871 mV but could be well before that. (I had no direct vision)

SPIKEV3 measure battery each 5 seconds python program
import motor
from hub import port
# import runloop
import time
from hub import light, light_matrix, battery_voltage, battery_current, usb_charge_current, battery_temperature
import color

# Initialize a list to store data
data_buffer = []

def interval_header():
    return format_msec_as_time(time.ticks_ms() - PROGRAM_START_MS) + " " + str(battery_temperature())

def get_one_interval():
    return "{};{};{}".format(battery_voltage(),battery_current(),usb_charge_current())

SEP = "|"
CRLF = "\x0d\x0a"

# Print the header
print("-|+0;sec;=|+5;sec;=|+10;sec;=|+15;sec;=|+20;sec;=|+25;sec;=|+30;sec;=|+35;sec;=|+40;sec;=|+45;sec;=|+50;sec;=|+55;sec;=", end=CRLF)
print("hhmmss dTmp" + SEP + "bat mV;bat mA;ch mA" + SEP + "bat mV;bat mA;ch mA" + SEP + "bat mV;bat mA;ch mA" + SEP + "bat mV;bat mA;ch mA" + SEP + "bat mV;bat mA;ch mA" + SEP + "bat mV;bat mA;ch mA" + SEP +
        "bat mV;bat mA;ch mA" + SEP + "bat mV;bat mA;ch mA" + SEP + "bat mV;bat mA;ch mA" + SEP + "bat mV;bat mA;ch mA" + SEP + "bat mV;bat mA;ch mA" + SEP + "bat mV;bat mA;ch mA", end=CRLF)

INTERVAL_MS = 5000  # 5 seconds in milliseconds
DRAIN = False  # chose what kind of measurement you want 

PROGRAM_START_MS = time.ticks_ms()

hw_type = "LEGO HUB"

if hw_type in ["technichub", "cityhub", "movehub"]:
    # max 6 * 1.0 Volt
    BAT_HI = 8000# mVolt
    BAT_MED = 6000# was 7000# mVolt
    BAT_LOW = 5400# was 6000# mVolt
    BAT_OUT = 4800# was 5500# mVolt
else:
    # Prime hub complains sooner?
    BAT_HI = 8400# mVolt /BL keep it up to 8400 as it **can** reach this high
    BAT_MED = 7200# 8000# mVolt
    BAT_LOW = 6800# 7000# mVolt
    BAT_OUT = 6000# 6250# mVolt

if hw_type in ["technichub", "cityhub", "movehub"]:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKCYAN = '\033[96m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    ENDC = '\033[0m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'
else:# LEGO does not support ANSI colors
    HEADER = ''
    OKBLUE = ''
    OKCYAN = ''
    OKGREEN = ''
    WARNING = ''
    FAIL = ''
    ENDC = ''
    BOLD = ''
    UNDERLINE = ''


def format_ms_to_time(ms):
    ms_per_second = 1000
    ms_per_minute = 60_000
    ms_per_hour = 3_600_000
    hours, ms = divmod(ms, ms_per_hour)
    minutes, ms = divmod(ms, ms_per_minute)
    seconds, ms = divmod(ms, ms_per_second)
    return hours, minutes, seconds, ms


def format_msec_as_time(clock):
    hour, minute, sec, ms = format_ms_to_time(clock)
    return '{:02}{:02}{:02}'.format(hour, minute, sec)


if DRAIN:
    motor.run(port.A, 720)
    motor.run(port.B, 720)
    motor.run(port.C, 720)
    motor.run(port.D, 720)
    motor.run(port.E, 720)
    motor.run(port.F, 720)

while True:
    # Collect data for 60 seconds (12 intervals of 5 seconds)
    data_buffer.append(interval_header())  # leading timestamp
    for _ in range(12):
        start_time = time.ticks_ms()
        data_buffer.append(get_one_interval())
        # wait the interval minus the processing time
        time.sleep_ms(max(INTERVAL_MS - time.ticks_diff(time.ticks_ms(), start_time), 0))

    # Print the collected data as a single line, separated by tabs
    print(SEP.join(data_buffer), end=CRLF)

    # Clear the data buffer for the next minute
    data_buffer.clear()
Log of "Charge dips only"
hhmmss bat temp bat mV bat mA charge mA Charging Time Since Last Charging Dip Time of previous dip last minute average of of Battery mV last minute average of Charger mA
0:03:05 35,7 C 7170 52 2 Not charging 0:01:45 0:01:20 7200 340
0:19:50 32,5 C 7213 53 3 Not charging 0:16:45 0:03:05 7270 334
0:36:35 30,2 C 7256 50 3 Not charging 0:16:45 0:19:50 7298 331
0:36:45 30,2 C 7254 52 2 Not charging 0:00:10 0:36:35 7299 332
0:53:30 28,9 C 7274 52 2 Not charging 0:16:45 0:36:45 7326 331
1:10:15 28,2 C 7297 52 3 Not charging 0:16:45 0:53:30 7345 329
1:27:10 27,8 C 7322 50 3 Not charging 0:16:55 1:10:15 7372 328
1:43:55 27,6 C 7347 50 2 Not charging 0:16:45 1:27:10 7399 329
2:00:40 27,8 C 7381 52 4 Not charging 0:16:45 1:43:55 7432 329
2:17:35 27,6 C 7438 50 3 Not charging 0:16:55 2:00:40 7478 328
2:34:20 27,6 C 7509 50 3 Not charging 0:16:45 2:17:35 7508 327
2:51:05 27,3 C 7589 50 3 Not charging 0:16:45 2:34:20 7628 327
2:51:15 27,3 C 7586 48 3 Not charging 0:00:10 2:51:05 7628 327
3:08:00 26,8 C 7641 55 2 Not charging 0:16:45 2:51:15 7689 327
3:24:45 27,6 C 7714 48 3 Not charging 0:16:45 3:08:00 7758 327
3:41:40 27,4 C 7775 48 3 Not charging 0:16:55 3:24:45 7827 327
3:58:25 27,6 C 7855 44 3 Not charging 0:16:45 3:41:40 7900 327
4:15:20 27,7 C 7935 44 3 Not charging 0:16:55 3:58:25 7975 326
4:32:05 27,9 C 8008 44 3 Not charging 0:16:45 4:15:20 8057 327
4:48:50 28,0 C 8094 44 2 Not charging 0:16:45 4:32:05 8137 328
5:22:30 28,0 C 8254 43 3 Not charging 0:33:40 4:48:50 8293 279
5:39:15 28,1 C 8308 43 3 Not charging 0:16:45 5:22:30 8328 206
5:39:25 28,1 C 8297 43 3 Not charging 0:00:10 5:39:15 8328 205
5:56:10 27,8 C 8327 43 3 Not charging 0:16:45 5:39:25 8346 159
6:12:55 27,2 C 8336 44 3 Not charging 0:16:45 5:56:10 8347 133
6:29:50 26,9 C 8340 44 3 Not charging 0:16:55 6:12:55 8352 116
6:46:35 26,5 C 8343 44 3 Not charging 0:16:45 6:29:50 8352 106
7:20:15 26,0 C 8338 43 3 Not charging 0:33:40 6:46:35 8351 98
7:24:55 25,9 C 8354 0 0 Not charging 0:04:40 7:20:15  8354 96
7:37:00 25,8 C 8349 48 3 Not charging 0:12:05 7:24:55 8355 96
7:53:45 26,0 C 8347 43 3 Not charging 0:16:45 7:37:00 8354 95
7:53:55 26,0 C 8349 44 3 Not charging 0:00:10 7:53:45 8355 95
8:10:40 26,0 C 8345 43 4 Not charging 0:16:45 7:53:55   8354 95

@laurensvalk
Copy link
Member Author

Amazing, thanks @BertLindeman!

@laurensvalk
Copy link
Member Author

The charge current in that firmware still looks suspicious, as reported earlier. If it charges in about the same time as our firmware but with half the current, then one of them is not right.

@BertLindeman
Copy link
Contributor

The charge current in that firmware still looks suspicious, as reported earlier. If it charges in about the same time as our firmware but with half the current, then one of them is not right.

The hub switches from bluetooth connection to usb connection even if it already was BT connected.
I cannot explain that difference by it, though.

@BertLindeman
Copy link
Contributor

BertLindeman commented Feb 17, 2025

To close this for me, a graph with the "same" program as the charging via SPIKEV3.
Measure with a 5 second interval via excel to scatterplot.
[EDIT]
Same hub / battery, same motors attached, same usb cable to same port on same laptop.
python program a bit different due to pybricks / SPIKEV3 differences.

A strange peak in the battery voltage at 2:09 to 7445 mV I cannot explain.

convert_pybricks_into_log_graph2

@laurensvalk
Copy link
Member Author

Excellent. This is useful to have for future reference. I noticed the charging current is a bit higher this time as well.

@laurensvalk
Copy link
Member Author

Alternatively, maybe we could set it green if >8100 && steady state or something like that.

Thinking about this a bit more, an easy way to determine "steady state" could be to just look at the charge current. If it is < 400 mA, then we know we have reached the constant voltage charge state and the voltage isn't going to go up much more and the charging rate will be much slower, so the battery is reasonably close to as full as it can get.

Another thing we could do is that if the voltage is less that 8.2 V and the charge current is < 400 mA, we could make the light yellow to let users know that the hub probably isn't going to charge all of the way, likely due to an underpowered USB port.

Just to complete the brainstorming topic on colors: we could use a blue light to indicate "fast" charging such as >1A as opposed to "slow" charging. Power teams might find this quite helpful, as they'd know their robot will be ready for use more quickly. But it might confuse newcomers. Opinions?

@BertLindeman
Copy link
Contributor

Excellent. This is useful to have for future reference. I noticed the charging current is a bit higher this time as well.

Could be in one of the previous tests on pybricks I had an USB cable on a USB-A to USB-C adapter.
Now on SPIKEV3 and pybricks tests an USB-C straight to USB-micro cable.

@BertLindeman
Copy link
Contributor

BertLindeman commented Feb 17, 2025

How about Cyan:

  • Red → Charging
  • Green → Charged or nearly charged
  • Blinking Yellow → Error
  • Cyan → Speed charging

Blue might be (wrongly) related to Bluetooth by novice users?

[EDIT] Or fade-in/out red for slow charge (also maybe at the end of the real charge?)
and solid red for fast charge?

No idea if it is doable the fade-in/out on this led.

@MrGibbage
Copy link

Are there any other charging tests I can be doing right now?

@laurensvalk
Copy link
Member Author

laurensvalk commented Feb 17, 2025

@BertLindeman -- Blue is loosely associated with USB3.0 which usually (but not always) support higher currents than older ports and devices, hence thinking of blue. I would rather not introduce any new blink patterns. I think cyan could be perceived as green.

@MrGibbage. I think no further tests are needed for now. Thanks for offering! The yellow blink error does not seem to have happened for anyone in any condition after the patch was applied. If you want to help further, just keep using https://beta.pybricks.com/ for day to day use and report issues as they occur. In a week or so, this should automatically get the update that will turn the light green a little bit sooner, so that your hub will turn green too.

@MrGibbage
Copy link

I got the green light on my hub. Charged "offline", just like I would at practice (hub was off, not running any monitoring program). I found a higher amperage charger and got it to green. Very promising.

I ran the monitor one more time now that it is charged so we can see the results:

version ('primehub', '3.6.0b2', 'ci-build-3726-v3.6.0b2-54-gb8a516c8 on 2025-02-13')
primehub loaded
Battery voltage: 8202 mV
primehub with git hash 'b8a516c8 on 2025-02-13' from CI-build 3726
0:00:30.000 - b8a516c Hub: 8195 mV 74 mA | Ch conn:0 stat:0 66 mA Not charging (light off)
0:00:50.001 - b8a516c Hub: 8290 mV 67 mA | Ch conn:4 stat:1 711 mA Charging (light red)
0:01:00.001 - b8a516c Hub: 8288 mV 67 mA | Ch conn:4 stat:1 663 mA Charging (light red)
0:01:30.001 - b8a516c Hub: 8289 mV 74 mA | Ch conn:4 stat:1 590 mA Charging (light red)
0:02:00.001 - b8a516c Hub: 8290 mV 71 mA | Ch conn:4 stat:1 525 mA Charging (light red)
0:02:30.001 - b8a516c Hub: 8291 mV 71 mA | Ch conn:4 stat:1 513 mA Charging (light red)
0:03:00.001 - b8a516c Hub: 8291 mV 76 mA | Ch conn:4 stat:1 522 mA Charging (light red)
0:03:30.001 - b8a516c Hub: 8292 mV 65 mA | Ch conn:4 stat:1 507 mA Charging (light red)
0:04:00.001 - b8a516c Hub: 8292 mV 67 mA | Ch conn:4 stat:1 470 mA Charging (light red)
0:04:30.001 - b8a516c Hub: 8292 mV 73 mA | Ch conn:4 stat:1 472 mA Charging (light red)
0:05:00.001 - b8a516c Hub: 8293 mV 62 mA | Ch conn:4 stat:1 451 mA Charging (light red)
0:05:30.001 - b8a516c Hub: 8293 mV 71 mA | Ch conn:4 stat:1 454 mA Charging (light red)
0:06:00.001 - b8a516c Hub: 8294 mV 67 mA | Ch conn:4 stat:1 418 mA Charging (light red)
0:06:30.001 - b8a516c Hub: 8293 mV 69 mA | Ch conn:4 stat:1 441 mA Charging (light red)
0:07:00.001 - b8a516c Hub: 8294 mV 74 mA | Ch conn:4 stat:1 431 mA Charging (light red)
0:07:30.001 - b8a516c Hub: 8293 mV 73 mA | Ch conn:4 stat:1 392 mA Charging (light red)
0:07:40.001 - b8a516c Hub: 8247 mV 69 mA | Ch conn:4 stat:2 69 mA Complete (light green)

@MrGibbage
Copy link

Interesting. I still have it on the charger and I actually have a blinking green light. Blinks every three seconds. No idea what that means, but I have never seen it before. The hub is off.

@laurensvalk
Copy link
Member Author

That means you got it to be properly full, even according to the chip's standard rather than some arbitrary threshold. We made it blink green in this state to indicate that you might as well unplug now.

But now that we know that many people never reach this state, I suppose we might want to drop this pattern to avoid confusion.

@MrGibbage
Copy link

Thanks. I am trying to decide if I should upgrade all of our chargers to 2.4A. I'll need ten of them. Or should I just stick with "regular" chargers, which seem to get around 550mA.

I like the blinking green light, and I also like the idea about the blue light. I do pretty much all of my charging offline. At the end of practice, we put all of the robots on the chargers, and leave the classroom. I do have my charging bricks on a mechanical wall outlet timer where it runs for about an hour after practice and turns on again about an hour or two before practice.

One other thing to think about. Not sure if anything can even be done about this. But frequently the kids will put the robot on the charger with a program running. Our master program runs all the time, even if the robot isn't moving/doing stuff. But it does keep the light sensor on. That way it is ready to launch with a button press. How will that affect the charging? I haven't tested it yet, but it would be nice to know what to expect. If someone does leave a master program running, when my mechanical timer shuts the charger down, that robot is probably going to drain completely until it dies, right? Probably the best thing I can do is add "Make sure robots are all charging AND shut down" to our end-of-practice checklist (also includes pushing code to GitHub and picking up legos off the floor).

@BertLindeman
Copy link
Contributor

Hi Skip, not really an answer to your question, but the graph above had the monitoring program running and I forgot to stop the display.
Charges OK I think.

Bert

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.

6 participants