Measure battery state, PicoW + Pico Amigo Pro

I have a Pico W with a Pico Amigo Pro wired up. The + Device Wire to VSYS and Ground to ground on the Pico. Running the following code, it never shows Charging, and the battery state stays at ~ 50%. Power supply is plugged into the Amiga Pro USC C.
MPY: soft reboot
3.54
53%
3.54
52%
3.55
52%
3.54
52%
3.55
53%
3.53
52%

from machine import ADC, Pin
import time
import network

def get_vsys():
    # Pico W voltage read function by darconeous on reddit: 
    # https://www.reddit.com/r/raspberrypipico/comments/xalach/comment/ipigfzu/
    conversion_factor = 3 * 3.3 / 65535
    wlan = network.WLAN(network.STA_IF)
    wlan_active = wlan.active()

    try:
        # Don't use the WLAN chip for a moment.
        wlan.active(False)

        # Make sure pin 25 is high.
        Pin(25, mode=Pin.OUT, pull=Pin.PULL_DOWN).high()
        
        # Reconfigure pin 29 as an input.
        Pin(29, Pin.IN)
        
        vsys = ADC(29)
        return vsys.read_u16() * conversion_factor

    finally:
        # Restore the pin state and possibly reactivate WLAN
        Pin(29, Pin.ALT, pull=Pin.PULL_DOWN, alt=7)
        wlan.active(wlan_active)


charging = Pin('WL_GPIO2', Pin.IN)  # reading this pin tells us whether or not USB power is connected

full_battery = 4.2                  # these are our reference voltages for a full/empty battery, in volts
empty_battery = 2.8                 # the values could vary by battery size/manufacturer so you might need to adjust them

while True:
    # convert the raw ADC read into a voltage, and then a percentage
    percentage = 100 * ((get_vsys() - empty_battery) / (full_battery - empty_battery))
    if percentage > 100:
        percentage = 100.00
    

    if charging.value() == True:         # if it's plugged into USB power...
        print ("Charging!")
    else:                             # if not, display the battery stats
        print('{:.2f}'.format(get_vsys()))
        print('{:.0f}%'.format(percentage))
    
    
    time.sleep(2.0)

charging.value() returns a number, which is only equal to True if it happens to be 1. Which you wont see in your case (you will have 0 or something around 5).

You should code instead:

if charging.value():
  print("Charging!")

Another hint for more pythonic code:

print(f"{get_vsys():0.2f}")

The f"..." are called format-strings and are really cool, since you can put any expression into the braces. And it is much easier to read, especially if you have multiple values within a single string. F-strings also support a special format that is helpful for debugging:

print(f"{percentage=}")

You will also have to wire the VBUS to the Lipo Amigo 5V. And I would use the pin labeled “CH” to check for charging (you only check for VBUS). This pin is connected to the STATE-pin of the charging chip. But you need a voltage-divider for this. So it might be simpler to just assume “charging” when VBUS is present.

Another thing: the Lipo Amigo has a battery protection chip which will shutdown at 2.8V. But many LiPos have their own integrated chip that shutsdown earlier. And I would actually recommend to stop using the LiPo already latest at 3V. It is not good for them if you decharge below that threshold. And this is not a design flaw of the Lipo Amigo: I have been looking hard for a protection chip myself that has a higher threshold, but without success.

I did that, and my code works that way. It does introduce another issue though. The on off circuit on the Amigo Pro gets messed up. On battery power only all is good. It toggles on and off, and the Pico turns off etc. Plug power into the USB Jack and it no longer functions, sort of. It still toggles, but the Pico just continues to run on the +5V. If the AC fails and the its in an off state, so is the Pico. No running on battery. If it’s on all Ok, runs on battery. No way to tell as the power LED is always on when+5V is present.

I have the protection bypassed, and fast charge enabled. Going to have a good look at the schematic and how the Power LED works.

Correct: once you connect Pico-VBUS to LiPo-Amigo 5V (which is connected to a different VBUS on the USB-C connector) the on-off circuit wont work. Simply because there is an internal connection within the Pico from VBUS to VSYS.

When using the LiPo-Amigo you should actually use the USB-C plug of the Amigo and not the micro USB-plug of the Pico (except for programming of course).

The On Off circuit is still working, it toggles VBAT on and off. The Power LED is wired to VSYS which explains why its always on if +5V is present on VBUS.
I’ll just have to toggle it on with no +5V present, “then” plug in my USB C Power. Then if the AC mains fail it will run on Battery.
I’ll also have to unplug +5V, and then toggle (Battery) Power Off. Or unplug the Battery.
I have a custom Micro USB cable for programing. D+, D-, and GND, no +5V. No way for the +5V from the Pico / Amigo backfeeding into my programing PC. ;)

Added a jumper from GP22 to the CH pin on the Amiga Pro.
And did up this test code. With no USB power its showing the Battery State. Plugged in USB power and its showing Charging (charge LED is on). Charging LED went out while I was typing this and now its showing USB Powered. Just have to transfer this into my main file. =)

import time, math, os
import network
from machine import ADC, Pin, PWM
#from pimoroni import Analog

def get_vsys():
    # Pico W voltage read function by darconeous on reddit: 
    # https://www.reddit.com/r/raspberrypipico/comments/xalach/comment/ipigfzu/
    conversion_factor = 3 * 3.3 / 65535
    wlan = network.WLAN(network.STA_IF)
    wlan_active = wlan.active()

    try:
        # Don't use the WLAN chip for a moment.
        wlan.active(False)

        # Make sure pin 25 is high.
        Pin(25, mode=Pin.OUT, pull=Pin.PULL_DOWN).high()
        
        # Reconfigure pin 29 as an input.
        Pin(29, Pin.IN)
        
        vsys = ADC(29)
        return vsys.read_u16() * conversion_factor

    finally:
        # Restore the pin state and possibly reactivate WLAN
        Pin(29, Pin.ALT, pull=Pin.PULL_DOWN, alt=7)
        wlan.active(wlan_active)

power = Pin('WL_GPIO2', Pin.IN)  # reading this pin tells us whether or not USB power is connected
charging = Pin(22, mode=Pin.IN, pull=Pin.PULL_UP) #pin29 GP22
full_battery = 4.2                  # these are our reference voltages for a full/empty battery, in volts
empty_battery = 2.8                 # the values could vary by battery size/manufacturer so you might need to adjust them


while True:
        
    percentage = 100 * ((get_vsys() - empty_battery) / (full_battery - empty_battery))
    if percentage > 100:
        percentage = 100.00
        
    if power.value() == True:# if it's plugged into USB power...
        
        if charging.value() == 0:
            print ("Charging!")
        else:
            print ("USB Powered")    
    else:# if not, display the battery stats
        print('{:.2f}V'.format(get_vsys()))
        print('{:.0f}%'.format(percentage))    
    #print(reading)
        
    time.sleep(10.0)

I never did a direct connection. You should measure the voltage on the CH-pin. The Pico is not 5V safe and according to the datasheet the voltage at the STATE-pin is at least VBUS-0.4. This would be something like 4.6V.

1 Like

Thanks for the heads up. With the charge LED on, it measure 0.25V. Charge LED off, it measures 4.96V. Time for a rethink. I saw the 2K resistor in there and thought it would drop the voltage enough to be safe. There is little to no current flow though so it’s not doing much. I may be able to wire in another resistor for a voltage divider and get it safe to use. I should have measured it but got carried away going to fast. :(

I wired in a 3.3K from CH to Ground. I now get get 3.19 V when not charging and essentially 0 V when charging. All is good now. @bablokb I owe you one. You likely saved me from frying that input and a head scratcher after it happened some time down the road.

I also had to rethink about that, but in fact current is one thing and voltage another. In this post microcontroller - Using single resistor to receive 5v signal on the 3.3v rated pin - Electrical Engineering Stack Exchange there is an answer (I think it is the third) that elaborates on that.

1 Like