Determining charged and charging on custom board with nrf5340

I'm still new to this but particularly in regards to battery. I have a custom board with a nrf5340 and have been working on reading the voltage. I used the battery sample for testing, which seems to be working, though I'm not sure I have it configured correctly and need to determine if the readings are what I should expect I wanted to understand how to deal with the other two pins for charging and charged as I don't see reference to them in the battery sample. Here are the pins:

  • P0.04 - BatADC - Battery Voltage divided to 7.666
  • P0.05 - ChargingADC - to see if charging while 5V connected
  • P0.06 - ChargedADC - to see if charger standby while 5V connected

I am using a voltage divider, btw.

How do I determine if the battery is charged or charging? Do I use ADC or GPIO?

I'm using 2.9.1 at the moment.

Parents
  • Your application can measure the battery voltage on P0.04 using the SAADC exactly as in the Zephyr battery sample. Your external divider scales the pack voltage down into the ADC range; after sampling, we multiply by 7.666 to recover the real battery voltage in millivolts.

    For charging status your application can tread the charger IC’s two pins, CHG and STAT as digital signals rather than analog inputs.The CHG pin lights up whenever your charger is actually pumping current into the battery. The STAT pin becomes on once the battery is full or the charger has gone idle. You just need to connect CHG to P0.05 and STAT to P0.06 on the nRF5340, add a pull-up to 3.3 V and set them up as normal digital inputs.

    In firmware, every sampling loop (e.g. once per 5 s):

    Read the SAADC channel on P0.04, convert the raw sample to millivolts (applying the divider ratio), and report “Battery: X mV.”
    Read P0.05 and P0.06 as digital inputs:

    If CHG is asserted, print “Charger: CHARGING.” Else if STAT is asserted, print “Charger: FULL/STANDBY.” Otherwise, print “Charger: NO POWER.”

    This way you keep your SAADC pipeline focused on the analog battery voltage.
    Use straightforward HIGH/LOW GPIO reads (and interrupts, if you like) for charger events.
    Avoid extra dividers or calibration on the CHG/STAT lines, since they’re inherently digital.
    You’ll need only minimal Zephyr DT overlays (to bind the two GPIOs) and standard gpio_pin_get() calls alongside your existing ADC setup.

  • Whoa. Ok. Maybe a little over my head. Let me see if we can breatk it down. I got reading working in an example with this in the dts:


    &adc {
        status = "okay"; // Ensure the ADC controller is enabled
    
        #address-cells = <1>; // Required for defining child nodes
        #size-cells = <0>;    // Required for defining child nodes
    
        channel@0 { // Defines the hardware properties for ADC channel 0
            reg = <0>;
            // CRITICAL: Verify this matches the physical pin your battery divider is on
            // AIN0 typically maps to P0.04 on nRF52/nRF53
            zephyr,input-positive = <NRF_SAADC_AIN0>;
            zephyr,gain = "ADC_GAIN_1_6";       // Adjust gain based on your voltage range
            zephyr,reference = "ADC_REF_INTERNAL"; // Or "ADC_REF_VDD_1_4" if your sample uses that
            zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
            zephyr,resolution = <12>; // 12-bit resolution for nRF SAADC
        };
    
         
        // Use this for ADC testing and set CONFIG_DJ_TEST_CHARGING_ADC=y in the prj.conf
        channel@1 { // For Charged ADC -> Configure for P0.05
            reg = <1>;
            zephyr,input-positive = <NRF_SAADC_AIN1>; // Alternative syntax
            zephyr,gain = "ADC_GAIN_1_6";
            zephyr,reference = "ADC_REF_INTERNAL";
            zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
            zephyr,resolution = <12>;
        };
        
    
        channel@2 {
            reg = <2>;
            zephyr,input-positive = <NRF_SAADC_AIN2>; // Alternative syntax
            zephyr,gain = "ADC_GAIN_1_6";
            zephyr,reference = "ADC_REF_INTERNAL";
            zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
            zephyr,resolution = <12>;
        };
    };


    I would send out the readings for charged and charging and adc_raw_to_millivolts_dt I would get the following readings. The first one is charging_val and the second is charged_val.

    When connected to power the readings would be:

    14,2284
    10,2293
    9,2284

    When not connected:

    0,2
    0,0
    0,0
    0,0
    0,0
    0,5
    7,0

    Is it best to do these another way? I was going to try GPIO but seem to be having problems getting it to work. I tried testing by commenting out the channel 1 & 2 and putting this in the overlay:

    &gpio0 {
        status = "okay";
    
        chargerstatus: charger_status {
            compatible = "gpio-battery-charger-status"; // Add this line
            gpio-hog;
            gpios = <6 GPIO_ACTIVE_LOW>;
        };
    };

    but getting device is not ready when doing:

    #define CHARGER_STATUS_NODE DT_NODELABEL(chargerstatus)
    static const struct gpio_dt_spec charger_gpio = GPIO_DT_SPEC_GET_OR(CHARGER_STATUS_NODE, gpios, {0});
    static bool charger_gpio_initialized = false;	
    	
    	
    	
    int test_init() {
    	
    	if (!gpio_is_ready_dt(&charger_gpio)) {
    		LOG_ERR("Error: charger GPIO device is not ready");
    		return -1;
    	} else {
    		LOG_DBG("Charger GPIO device is ready");
    	}
    
    	int ret = gpio_pin_configure_dt(&charger_gpio, GPIO_INPUT);
    	if (ret != 0) {
    		LOG_ERR("Error %d: failed to configure charger GPIO pin", ret);
    		return -1;
    	} else {
    		LOG_DBG("Charger GPIO pin configured successfully");
    	}
    	
    	return 0;
    	
    )

    I tried using this:

    #define CHARGING_STATUS_NODE DT_NODELABEL(charging_status)
    static const struct gpio_dt_spec charger_gpio = GPIO_DT_SPEC_GET(CHARGING_STATUS_NODE, gpios);

    But am geting the same sort of error this person is getting in the post GPIO pin configuration using Devicetree. I would think there is a common configuration for P0.05 and P0.06 on a nrf5340.

  • Do you have any code to show how to:


    Use straightforward HIGH/LOW GPIO reads (and interrupts, if you like) for charger events.

    Do I need to do what the other article recommends with the 'compatible' property and:


    add CONFIG_REGULATOR=y

    I see it needs a regulator-name based on the build error I'm getting. Will that change the behavior?

    / {
        gpio_power_pin: gpio-power-pin {
            compatible = "regulator-fixed";
            regulator-name = "gpio_pwr";
            enable-gpios = <&gpio0 10 GPIO_ACTIVE_HIGH>;
            regulator-boot-on;
        };
    
    };

    How do I set up the overlay/dts   with pins P0.04 and P0.05 to accomplish what you said:


    For charging status your application can tread the charger IC’s two pins, CHG and STAT as digital signals rather than analog inputs.The CHG pin lights up whenever your charger is actually pumping current into the battery. The STAT pin becomes on once the battery is full or the charger has gone idle. You just need to connect CHG to P0.05 and STAT to P0.06 on the nRF5340, add a pull-up to 3.3 V and set them up as normal digital inputs.

  • It seems strange I need to create a custom binding for something which is probably very common, right?

  • Hi lcj,

    Our apologies for the late follow-up.

    I am a little unclear about the physical setup here.

    It seems that previously, Susheel assumed that the Charging and Charged signal on P0.05 and P0.06 are digital. Are they digital? Or are they analog signals?

    What charger are you working with? Do you have a schematic?

    lcj said:

    add CONFIG_REGULATOR=y

    I see it needs a regulator-name based on the build error I'm getting. Will that change the behavior?

    What build error are you having? Could you share the full build log, and the relevant source file or snippet?

    Hieu

Reply
  • Hi lcj,

    Our apologies for the late follow-up.

    I am a little unclear about the physical setup here.

    It seems that previously, Susheel assumed that the Charging and Charged signal on P0.05 and P0.06 are digital. Are they digital? Or are they analog signals?

    What charger are you working with? Do you have a schematic?

    lcj said:

    add CONFIG_REGULATOR=y

    I see it needs a regulator-name based on the build error I'm getting. Will that change the behavior?

    What build error are you having? Could you share the full build log, and the relevant source file or snippet?

    Hieu

Children
No Data
Related