PB0A I2C Test Setup

Accessing PB0A I2C Interface For Testing

To test-drive the I2C interface on the PB0A board, you just need a microcontroller, and a few wires and resistors.

Overview

For communication, both PB0A and the microcontroller must either run from the same power source, or use a special level shifter.

Since PB0A is powered from the battery input (range 3.0-4.2V), normally it is not possible to run your microcontroller from this same voltage source. Most microcontrollers are not compatible with this voltage range and would be damaged.

Before we look at the requirements for a suitable level shifter that would allow your microcontroller to be run from a different voltage source, there is one simple way for a microcontroller to communicate with the PB0A:

Just power PB0A from the 3.3V pin of your microcontroller, simulating a battery at this level.

Ensuring Compatible Battery Voltage

Simply connect 3.3V of your microcontroller to BAT+ on PB0A, and connect GND of both devices.

This is a test setup simply to test-drive and experiment with the I2C interface. Obviously, the 3.3V output of your microcontroller is not strong enough to drive external loads. So make sure there are no external loads connected to your PB0A’s 5V+ and 5V- while powering it from your microcontroller pin.

I2C Interface Pins

Here is how PB0A exposes its I2C interface:

Pin Pin on PCB Description
SDA DATA I2C data line
SCL/SCK unmarked surface pad I2C clock
VDD BAT+ I2C is using battery voltage level
GND GND I2C and external microcontroller must share GND
IRQ unmarked surface pad high when IP5306 power output is active

Wiring

Three resistors are required:

  • Pull-Up:
    Both SDA and SCL must be pulled up by a strong external pull-up resistor (2.2KOhm or lower). It is not sufficient to use internal pull-up resistors of your microcontroller.
  • Pull-Down:
    IRQ must be pulled down by a typical 10KOhm resistor if you need the IRQ line. This line is high when the PB0A power output is active, else low.

Source Code

In my test setup I used a ESP32S DevKit V4, and I used this platform.ini:

[env:esp32dev]
  platform = espressif32
  board = esp32doit-devkit-v1
  framework = arduino
  board_upload.flash_size = 4MB
  monitor_speed = 115200
  upload_speed = 921600
  build_flags =
     #-DBOARD_HAS_PSRAM
     # -mfix-esp32-psram-cache-issue
     -DARDUINO_ESP32_DEV

Any microcontroller will do. If you decide to use a different one, adjust GPIO numbers in wiring and source code as appropriate.

Main Program

The main program uses the wire library to establish the I2C communication:

#include <Arduino.h>
#include <Wire.h>
#include <ip5306.h>

#define IRQ1 23      // GPIO for IRQ input
#define I2C = 117    // IP5306 I2C address

void setup()
{
  pinMode(IRQ1, INPUT); 
  Wire.begin();
  Serial.begin(115200);
  delay(1000); 
}

void loop()
{
  bool active;
  byte error, address;
  Serial.print("0x75: ");
  bool active = digitalRead(IRQ1);
  bool i2c_ready = false;
  if (active)
{
    Wire.beginTransmission(I2C);
    error = Wire.endTransmission();
    i2c_ready = (error == 0);
}
    if (i2c_ready) {
      Serial.println("OK");

      bool lpt = IP5306_GetLongPressTime();
      Serial.print("Long Press Time: ");
      Serial.println(lpt);
      bool pws = IP5306_GetPowerSource();
      Serial.print("Power Source: ");
      Serial.println(pws);
      bool lld = IP5306_GetOutputLoad();
      Serial.print("Light Load: ");
      Serial.println(lld);
      int llst = IP5306_GetOutputLoad();
      Serial.print("Light Load shutdown time: ");
      Serial.println(llst);
      int vin = IP5306_GetVinCurrent();
      Serial.print("Vin Current: ");
      Serial.println(vin);
    }  else  {
      Serial.println("---");
    }
    delay(500);           // wait 5 seconds for next scan
}

It uses a special IP5306 library to handle the specific I2C registers and interpret the meaning of register bits.

IP5306 Library

Either use one of the many available IP5306 libraries, or add the library to your project yourself:

  1. In platform.io, in your project, create a new folder named IP5306 in the existing subfolder lib.
  2. In the folder IP5306, create two files: ip5306.h and ip5306.cpp.

Source code for ip5306.h

Here is the source code for ip5306.h:

/*
  IP5306.h - Library for IP5306_I2C Power controller.
  Created by Sebastian Haap, December 3, 2019.
  Based on https://gist.github.com/me-no-dev/7702f08dd578de5efa47caf322250b57
*/

#ifndef IP5306_h
#define IP5306_h

#include "Wire.h"

#define IP5306_REG_SYS_0    0x00
#define IP5306_REG_SYS_1    0x01
#define IP5306_REG_SYS_2    0x02
#define IP5306_REG_CHG_0    0x20
#define IP5306_REG_CHG_1    0x21
#define IP5306_REG_CHG_2    0x22
#define IP5306_REG_CHG_3    0x23
#define IP5306_REG_CHG_4    0x24
#define IP5306_REG_READ_0   0x70
#define IP5306_REG_READ_1   0x71
#define IP5306_REG_READ_2   0x72
#define IP5306_REG_READ_3   0x77
#define IP5306_REG_READ_4   0x78

#define IP5306_GetKeyOffEnabled()               ip5306_get_bits(IP5306_REG_SYS_0, 0, 1)
#define IP5306_SetKeyOffEnabled(v)              ip5306_set_bits(IP5306_REG_SYS_0, 0, 1, v)
//0:dis,*1:en

#define IP5306_GetBoostOutputEnabled()          ip5306_get_bits(IP5306_REG_SYS_0, 1, 1)
#define IP5306_SetBoostOutputEnabled(v)         ip5306_set_bits(IP5306_REG_SYS_0, 1, 1, v)
//*0:dis,1:en

#define IP5306_GetPowerOnLoadEnabled()          ip5306_get_bits(IP5306_REG_SYS_0, 2, 1)
#define IP5306_SetPowerOnLoadEnabled(v)         ip5306_set_bits(IP5306_REG_SYS_0, 2, 1, v)
//0:dis,*1:en

#define IP5306_GetChargerEnabled()              ip5306_get_bits(IP5306_REG_SYS_0, 4, 1)
#define IP5306_SetChargerEnabled(v)             ip5306_set_bits(IP5306_REG_SYS_0, 4, 1, v)
//0:dis,*1:en

#define IP5306_GetBoostEnabled()                ip5306_get_bits(IP5306_REG_SYS_0, 5, 1)
#define IP5306_SetBoostEnabled(v)               ip5306_set_bits(IP5306_REG_SYS_0, 5, 1, v)
//0:dis,*1:en

#define IP5306_GetLowBatShutdownEnable()        ip5306_get_bits(IP5306_REG_SYS_1, 0, 1)
#define IP5306_SetLowBatShutdownEnable(v)       ip5306_set_bits(IP5306_REG_SYS_1, 0, 1, v)
//0:dis,*1:en

#define IP5306_GetBoostAfterVin()               ip5306_get_bits(IP5306_REG_SYS_1, 2, 1)
#define IP5306_SetBoostAfterVin(v)              ip5306_set_bits(IP5306_REG_SYS_1, 2, 1, v)
//0:Closed, *1:Open

#define IP5306_GetShortPressBoostSwitchEnable() ip5306_get_bits(IP5306_REG_SYS_1, 5, 1)
#define IP5306_SetShortPressBoostSwitchEnable(v) ip5306_set_bits(IP5306_REG_SYS_1, 5, 1, v)
//*0:disabled, 1:enabled

#define IP5306_GetFlashlightClicks()            ip5306_get_bits(IP5306_REG_SYS_1, 6, 1)
#define IP5306_SetFlashlightClicks(v)           ip5306_set_bits(IP5306_REG_SYS_1, 6, 1, v)
//*0:short press twice, 1:long press

#define IP5306_GetBoostOffClicks()              ip5306_get_bits(IP5306_REG_SYS_1, 7, 1)
#define IP5306_SetBoostOffClicks(v)             ip5306_set_bits(IP5306_REG_SYS_1, 7, 1, v)
//*0:long press, 1:short press twice

#define IP5306_GetLightLoadShutdownTime()       ip5306_get_bits(IP5306_REG_SYS_2, 2, 2)
#define IP5306_SetLightLoadShutdownTime(v)      ip5306_set_bits(IP5306_REG_SYS_2, 2, 2, v)
//0:8s, *1:32s, 2:16s, 3:64s

#define IP5306_GetLongPressTime()               ip5306_get_bits(IP5306_REG_SYS_2, 4, 1)
#define IP5306_SetLongPressTime(v)              ip5306_set_bits(IP5306_REG_SYS_2, 4, 1, v)
//*0:2s, 1:3s

#define IP5306_GetChargingFullStopVoltage()     ip5306_get_bits(IP5306_REG_CHG_0, 0, 2)
#define IP5306_SetChargingFullStopVoltage(v)    ip5306_set_bits(IP5306_REG_CHG_0, 0, 2, v)
//0:4.14V, *1:4.17V, 2:4.185V, 3:4.2V (values are for charge cutoff voltage 4.2V, 0 or 1 is recommended)

#define IP5306_GetChargeUnderVoltageLoop()      ip5306_get_bits(IP5306_REG_CHG_1, 2, 3)   
//Automatically adjust the charging current when the voltage of VOUT is greater than the set value
#define IP5306_SetChargeUnderVoltageLoop(v)     ip5306_set_bits(IP5306_REG_CHG_1, 2, 3, v)//Vout=4.45V + (v * 0.05V) (default 4.55V) 
// //When charging at the maximum current, the charge is less than the set value. Slowly reducing the charging current to maintain this voltage

#define IP5306_GetEndChargeCurrentDetection()   ip5306_get_bits(IP5306_REG_CHG_1, 6, 2)
#define IP5306_SetEndChargeCurrentDetection(v)  ip5306_set_bits(IP5306_REG_CHG_1, 6, 2, v)
//0:200mA, 1:400mA, *2:500mA, 3:600mA

#define IP5306_GetVoltagePressure()             ip5306_get_bits(IP5306_REG_CHG_2, 0, 2)
#define IP5306_SetVoltagePressure(v)            ip5306_set_bits(IP5306_REG_CHG_2, 0, 2, v)
//0:none, 1:14mV, *2:28mV, 3:42mV (28mV recommended for 4.2V)

#define IP5306_GetChargeCutoffVoltage()         ip5306_get_bits(IP5306_REG_CHG_2, 2, 2)
#define IP5306_SetChargeCutoffVoltage(v)        ip5306_set_bits(IP5306_REG_CHG_2, 2, 2, v)
//*0:4.2V, 1:4.3V, 2:4.35V, 3:4.4V

#define IP5306_GetChargeCCLoop()                ip5306_get_bits(IP5306_REG_CHG_3, 5, 1)
#define IP5306_SetChargeCCLoop(v)               ip5306_set_bits(IP5306_REG_CHG_3, 5, 1, v)
//0:BAT, *1:VIN

#define IP5306_GetVinCurrent()                  ip5306_get_bits(IP5306_REG_CHG_4, 0, 5)
#define IP5306_SetVinCurrent(v)                 ip5306_set_bits(IP5306_REG_CHG_4, 0, 5, v)
// Charging current: I=0.05 + 00.1 + 10.2 + 20.4 + 30.8 + 4*1.6A

#define IP5306_GetShortPressDetected()          ip5306_get_bits(IP5306_REG_READ_3, 0, 1)
#define IP5306_ClearShortPressDetected()        ip5306_set_bits(IP5306_REG_READ_3, 0, 1, 1)

#define IP5306_GetLongPressDetected()           ip5306_get_bits(IP5306_REG_READ_3, 1, 1)
#define IP5306_ClearLongPressDetected()         ip5306_set_bits(IP5306_REG_READ_3, 1, 1, 1)

#define IP5306_GetDoubleClickDetected()         ip5306_get_bits(IP5306_REG_READ_3, 2, 1)
#define IP5306_ClearDoubleClickDetected()       ip5306_set_bits(IP5306_REG_READ_3, 2, 1, 1)

#define IP5306_GetPowerSource()                 ip5306_get_bits(IP5306_REG_READ_0, 3, 1)
//0:BAT, 1:VIN
#define IP5306_GetBatteryFull()                 ip5306_get_bits(IP5306_REG_READ_1, 3, 1)
//0:CHG/DIS, 1:FULL
#define IP5306_GetLevelLeds()                ((~ip5306_get_bits(IP5306_REG_READ_4, 4, 4)) & 0x0F)
//LED[0-4] State (inverted)
#define IP5306_GetOutputLoad()                  ip5306_get_bits(IP5306_REG_READ_2, 2, 1)
//0:heavy, 1:light

#define IP5306_LEDS2PCT(byte)  \
  ((byte & 0x01 ? 25 : 0) + \
  (byte & 0x02 ? 25 : 0) + \
  (byte & 0x04 ? 25 : 0) + \
  (byte & 0x08 ? 25 : 0))

int ip5306_get_reg(uint8_t reg);
int ip5306_set_reg(uint8_t reg, uint8_t value);
uint8_t ip5306_get_bits(uint8_t reg, uint8_t index, uint8_t bits);
void ip5306_set_bits(uint8_t reg, uint8_t index, uint8_t bits, uint8_t value);


#endif

Source Code for ip5306.cpp

And here is the source code for ip5306.cpp:

/*
  IP5306.cpp - Library for IP5306_I2C Power controller.
  Created by Sebastian Haap, December 3, 2019.
  Based on https://gist.github.com/me-no-dev/7702f08dd578de5efa47caf322250b57
*/

#include "Wire.h"
#include "ip5306.h"

int ip5306_get_reg(uint8_t reg){
    Wire.beginTransmission(0x75);
    Wire.write(reg);
    if(Wire.endTransmission(false) == 0 && Wire.requestFrom(0x75, 1)){
        return Wire.read();
    }
    return -1;
}

int ip5306_set_reg(uint8_t reg, uint8_t value){
    Wire.beginTransmission(0x75);
    Wire.write(reg);
    Wire.write(value);
    if(Wire.endTransmission(true) == 0){
        return 0;
    }
    return -1;
}

uint8_t ip5306_get_bits(uint8_t reg, uint8_t index, uint8_t bits){
    int value = ip5306_get_reg(reg);
    if(value < 0){
        //Serial.printf("ip5306_get_bits fail: 0x%02x\n", reg);
        return 0;
    }
    return (value >> index) & ((1 << bits)-1);
}

void ip5306_set_bits(uint8_t reg, uint8_t index, uint8_t bits, uint8_t value){
    uint8_t mask = (1 << bits) - 1;
    int v = ip5306_get_reg(reg);
    if(v < 0){
        //Serial.printf("ip5306_get_reg fail: 0x%02x\n", reg);
        return;
    }
    v &= ~(mask << index);
    v |= ((value & mask) << index);
    if(ip5306_set_reg(reg, v)){
        //Serial.printf("ip5306_set_bits fail: 0x%02x\n", reg);
    }
}

Running the Code

Once you uploaded the source code to your microcontroller, and then did the wiring, once the microcontroller is powered on (i.e. powered by its USB connector), PB0A also receives power.

The firmware establishes the I2C connection and dumps a selected number of information to the serial monitor.

Once I2C communication works, you can easily take a closer look at the ip5306 library and its methods. You’ll quickly realize which information now can be read and set by your microcontroller.

Keep in mind that IP5306/PB0A has no internal memory, and you cannot permanently change the settings. Whenever the PB0A enables its power output, the microcontroller must (re)configure PB0A via I2C.

Slow Website?

This website is very fast, and pages should appear instantly. If this site is slow for you, then your routing may be messed up, and this issue does not only affect done.land, but potentially a few other websites and downloads as well. Here are simple steps to speed up your Internet experience and fix issues with slow websites and downloads..

Comments

Please do leave comments below. I am using utteran.ce, an open-source and ad-free light-weight commenting system.

Here is how your comments are stored

Whenever you leave a comment, a new github issue is created on your behalf.

  • All comments become trackable issues in the Github Issues section, and I (and you) can follow up on them.

  • There is no third-party provider, no disrupting ads, and everything remains transparent inside github.

Github Users Yes, Spammers No

To keep spammers out and comments attributable, all you do is log in using your (free) github account and grant utteranc.es the permission to submit issues on your behalf.

If you don’t have a github account yet, go get yourself one - it’s free and simple.

If for any reason you do not feel comfortable with letting the commenting system submit issues for you, then visit Github Issues directly, i.e. by clicking the red button Submit Issue at the bottom of each page, and submit your issue manually. You control everything.

Discussions

For chit-chat and quick questions, feel free to visit and participate in Discussions. They work much like classic forums or bulletin boards. Just keep in mind: your valued input isn’t equally well trackable there.

  Show on Github    Submit Issue

(content created Jul 12, 2025)