Measure battery state, Plus 2W + Amigo Pro

This is a bit of a continuation of this thread.
Measure battery state, PicoW + Pico Amigo Pro - Support - Pimoroni Buccaneers
I have an Pimoroni Amiga Pro wired up to a Pimoroni Pico Plus 2W.

Grd-----Grd
5V ----- VBUS
CH -----GP 22 Pin 29
ON
Grd
Vdev – VSYS
Vbat
Grd

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(3)
        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

The above gets me
MPY: soft reboot
1.28V
-108%

I’ve been at this all day and I’m struggling trying to figure out how to edit it for the Pico Plus 2 W?

I have no knowledge of this exact circuit schematic but it looks to me like you are reading the voltage from a potential divider circuit as 4.2v would be too much for an analogue input with 3.3v max to measure.
If the divider is 50:50 then you would need to double the 3.3/65535 - so use 6.6/65535 as the conversion factor (or use whatever the exact ratio of the potential divider is).

My code is based on this,

And these

It gets trickier when you do it on a Pico W though, as per that other thread. I also had that working just fine.
Things are different with the Pico Plus 2 W as it uses the RP2350 and different internal wiring. I don’t think I have to mess with turning the WIFI off? Going to have another go tonight some time after having a good look at the schematic.
@hel

Regarding VSYS, the Pico-W and Pico2-W are identical (no different wiring). GPIO29 measures VSYS/3, so your conversion-factor is still correct.

I think the problem is different: if I look at C-code doing VSYS measurement, then I always see disabled interrupts during VSYS measurements using GPIO29. Just turning off wifi does not do the trick. The fact that this works with the RP2040 but not with the RP2350 might be due to the higher speed of the RP2350.

What you could do (trying some voodoo): add a small delay before actually reading vsys.

1 Like

Tanks bablokb, I was Hoping you would chime in. I’ll give that a try in a bit.

If I put in a Pico 2 W it works just fine.

MPY: soft reboot
4.12V
94%
4.13V
95%

If I put the Pico Plus 2W in, its a no go, even with some delay added.

Time to get ready for my morning walk with my Dog Missy. I should be back at this shortly after 8AM local time. It’s 6 AM as I post this.

Oh yes, sorry. I did check the schematic of the Pico Plus 2W, but not good enough. It has a similar voltage divider as the Pico2-W, but it turns out that ADC3 is connected to GPIO43, so there is no dual use. This should simplify things, since it does not interfere with WLAN and it does not need GPIO25 (the WL chip-select) to be driven high.

The trick is that Pimoroni uses the RP2350B which has more GPIOs.

So please give it a try…

I just did up a separate test setup with a spare Amigo Pro I had on hand.
With the Pico 2 W, I get good values.

MPY: soft reboot
USB Powered
USB Powered
4.10V
93%
Charging!
Charging!
Charging!
Charging!

Now I’m going to swap in the Pico Plus 2W and have another go. I saw the same thing in the schematic. Which is why I was thinking I don’t have to mess with turning the WIFI off. With the Pico Plus 2W you have to use vsys = ADC(3). If you use Pin you get a this Pin does not support something something, even if you put 43 in.

Getting there, very slowly, so confused now by Pin versus GP, lol.
This

def get_vsys():
    conversion_factor = 3 * 3.3 / 65535
    Pin(43, Pin.IN)
    vsys = ADC(3)
    return vsys.read_u16() * conversion_factor
    Pin(43, Pin.ALT, pull=Pin.PULL_DOWN, alt=7)

gets me this.

MPY: soft reboot
3.95V
81%
3.96V
81%
3.96V
82%
3.96V
82%
3.95V
81%

My USB powered / charging isn’t working though.

If I plug my power cable into the Amiga Pro I get a charging indication, but the voltage reading goes way high when i unplug it?

MPY: soft reboot
4.12V
94%
4.11V
94%
Charging!
Charging!
6.72V
100%

Is this correct, for the Pico Plus 2W?
power = Pin('WL_GPIO2', Pin.IN) # reading this pin tells us whether or not USB power is connected

EDIT: Here is my current file.

import time
import network

from pimoroni import Analog
from machine import ADC, Pin

def get_vsys():
    conversion_factor = 3 * 3.3 / 65535
    Pin(43, Pin.IN)
    vsys = ADC(3)
    return vsys.read_u16() * conversion_factor
    Pin(43, Pin.ALT, pull=Pin.PULL_DOWN, alt=7)
    

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)

What ever is happening sticks until I reset the Pico Plus 2. I started my code then plugged in my power supply. It then shows charging and the 6.72 volts. Unplug the power supply from the Amigo Pro and I still get the 6.72 volts reading.

MPY: soft reboot
4.14V
93%
Charging!
6.78V
100%
Charging!
6.78V
100%
6.72V
100%
6.72V
100%

If stop my code and unplug power supply, I get the 6.72 volt reading.

MPY: soft reboot
6.73V
100%

If I press the reset button and then click run I get this.

MPY: soft reboot
4.13V
92%

It does the same thing when charged and indicates USB Powered. Anytime the power supply is plugged in it shows 6+ volts. I checked the voltage at VSYS while this is happening and get 4.9 volts. VDEV shows the same thing. The +5V pin on the Amiga Pro shows 5.1V Something in my code must not be right?

I did try another Raspberry Pi USB C supply and got the same thing

MPY: soft reboot
4.13V
93%
Charging!
6.79V
100%
6.72V
100%

@hel Hel are you out there? Could you please take a look see?

Does it stay high, or is it temporarily high? ADC readings do have some noise, especially when the reference voltage is not good. In our case it is the 3V3 voltage generated by the LDO and this voltage also drives everything else so don’t expect it to be stable.

You could work around the noise by reading multiple times and averaging (or maybe use the median instead of the average). It really depends on how exact you need to know.

Otherwise, your data seems ok as far as I can see. A minor thing to note: Pin(43, Pin.ALT, pull=Pin.PULL_DOWN, alt=7) in get_vsys() is never executed.

I can’t quite picture how you’ve got your Pico Plus hooked up to your LiPo Amigo Pro I’m afraid, please can you post a photo showing your wiring?

It stays high. Once I plug the power supply into the Amiga Pro the reading goes high and stays high after I unplug the power supply. It also stays high if I do a Stop, and then Run. I have to do a reset or click the power button the Amiga Pro to get back to normal readings. My cable to the Pico Plus 2W is Data only, the +5V wire is cut.
As per the other thread I linked too, I have a 3.3K resistor wired from the Amiga Pro On pin to ground. And another 3.3K resistor wired from CH pin to ground. The CH pin is wired to GP 22 Pin 29 on the Pico Plus 2W.

If the input pin is latching high, could you be running into the errata 9 issue with the pull downs on RP2350?

Which Pin? Pin 43?
I do believe this mitigates that as far as Pin 29 / GP22 goes.
charging = Pin(22, mode=Pin.IN, pull=Pin.PULL_UP) #pin29 GP22

I don’t understand why you are pulling CH low with a 3.3K resistor and then pulling GP22 high with an internal pullup. That does not make sense at all. CH is pulled low by the STAT pin of the MCP73831T-2ACI/OT during charging.

I don’t think E9 is relevant in your case. The real question is why the ADC(3) readings are so high. Can you output the raw values?

It might be because you configure GPIO43 as an input-type GPIO: Pin(43, Pin.IN). Either remove this line or replace it with Pin(43, Pin.ANALOG).

Sorry, yes, I was looking at the lines that referenced GP43 - E9 likely not to blame on this occasion :)

@hel: On a second thought: you might be right that we see E9 here, because the pin is first setup as input and then as an ADC. One of the very first reports that led to the discovery of the problem was a user that was switching a pin from digital to analog, exactly what we see here.

The errata states that the level is about 2.1-2.2V. As we measure VSYS/3 this would translate to something like 6.6V, and this is very near to what @alphanumeric has as a reading.

AttributeError: type object 'Pin' has no attribute 'ANALOG'

+5V is wired to VBUS
VDEV is wired to VSYS
CH is wired to GP 22 Pin 29

With no 3.3K resistor, with the charge LED on, CH measures 0.25V and with the Charge LED off, CH measures 4.96V. With the resistor added it drops to a safe 3.19V. We talked about this in the other thread.