IP5306_I2C和NU1680使用手记

本文介绍了如何在Robomaster项目中使用ESP32C3控制IP5306进行锂电池充电管理和NU1680无线充电,通过I2C接口实现远程开关功能,以及解决IP5306常见问题和NU1680的使用注意事项。
摘要由CSDN通过智能技术生成

引言

本文仅提供方案的关键点,有人需要的话再写详细的操作指南和源代码。

本人近日在Robomaster中需要做一个飞镖内部的小型的供电模块,由一个电池驱动,通过有线或无线方式充电,由ESP32C3提供远程开关功能,供飞镖头运作。

方案中采用ESP32C3挂载I2C总线,总线挂载IP5306_I2C和NU1680。IP5306用于锂电池线性充电、5V Boost和开关使能,NU1680用于无线充电RX。

IP5306使用手记

由于IP5306这个芯片是出了名的有各种bug的芯片,故提供我队的驱动思路。

IP5306白片存在两大问题:

  1. 仅支持按键操作,单击开启Boost,双击关闭Boost;
  2. 开启Boost后在轻载条件下会不定时关断。
  3. 关闭Boost后会有2V左右的浮动电压。

所以我们使用了IP5306_I2C版本,这个版本的IP5306可以通过I2C寄存器进行开关/常开/屏蔽按键操作,通过一些内部寄存器还可以获得电池电量(0-25-50-75-100)的信息,大大便利了单片机进行远程开关的操作。

长期调试后我们这样实现该芯片的开关控制:

  1. 系统上电(电池上电/5V上电)后通过KEY引脚发送一个单脉冲,强制启动5V Boost输出,否则IP5306不会自动识别负载,所有I2C寄存器都处于浮空状态,读取出来的数据可以说是随机的。
  2. 上电初始化I2C寄存器完成之后就可以直接操作0x00(Sys_Ctrl0)寄存器的Boost_Enable位进行开断使能操作,Key引脚只需要上拉,不需要任何操作。
  3. 通过读取IP5306的INT引脚判断是否成功开断。INT为高时认为BOOST已开启,为低时认为BOOST已关断。

关键驱动代码片段:

// GPIO for charging status
gpio_config_t io_conf;
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pull_down_en = 0;
io_conf.pull_up_en = 1;
io_conf.pin_bit_mask = (1ULL << POWER_KEY);
gpio_config(&io_conf);
// Set default level
gpio_set_level(POWER_KEY, 1);

// INT_5306
io_conf.mode = GPIO_MODE_INPUT;
io_conf.pin_bit_mask = (1ULL << INT_5306);
gpio_config(&io_conf);

// IP5306
ESP_LOGI(TAG, "Powering on");
gpio_set_level(POWER_KEY, 1);
gpio_set_level(POWER_KEY, 0);
// wait for 50ms
vTaskDelay(50);
gpio_set_level(POWER_KEY, 1);
vTaskDelay(2000);

gpio_reset_pin(POWER_KEY);

IP5306_setup();

其他驱动代码参考: 

// ================ Power IC IP5306 ===================
#define IP5306_ADDR (0x75)
#define IP5306_REG_SYS_CTL0 (0x00)
#define IP5306_REG_SYS_CTL1 (0x01)
#define IP5306_REG_SYS_CTL2 (0x02)
#define IP5306_REG_Charger_CTL0 (0x20)
#define IP5306_REG_Charger_CTL1 (0x21)
#define IP5306_REG_Charger_CTL2 (0x22)
#define IP5306_REG_Charger_CTL3 (0x23)
#define IP5306_REG_CHG_DIG_CTL0 (0x24)
#define IP5306_REG_READ0 (0x70)
#define IP5306_REG_READ1 (0x71)
#define IP5306_REG_READ2 (0x72)
#define IP5306_REG_READ3 (0x77)

// REG_CTL0
#define BOOST_ENABLE_BIT (0x20)
#define CHARGE_OUT_BIT (0x10)
#define BOOT_ON_LOAD_BIT (0x04)
#define BOOST_OUT_BIT (0x02)
#define BOOST_BUTTON_EN_BIT (0x01)

//- REG_CTL1
#define BOOST_SET_BIT (0x80)
#define WLED_SET_BIT (0x40)
#define SHORT_BOOST_BIT (0x20)
#define VIN_ENABLE_BIT (0x04)
#define LOWPOWER_SHUTDOWN_BIT (0x01)

//- REG_CTL2
#define SHUTDOWNTIME_MASK (0x0c)
#define SHUTDOWNTIME_64S (0x0c)
#define SHUTDOWNTIME_32S (0x04)
#define SHUTDOWNTIME_16S (0x08)
#define SHUTDOWNTIME_8S (0x00)

//- REG_READ0
#define CHARGE_ENABLE_BIT (0x08)

//- REG_READ1
#define CHARGE_FULL_BIT (0x08)

//- REG_READ2
#define LIGHT_LOAD_BIT (0x20)
#define LOWPOWER_SHUTDOWN_BIT (0x01)

//- CHG
#define CURRENT_100MA (0x01 << 0)
#define CURRENT_200MA (0x01 << 1)
#define CURRENT_400MA (0x01 << 2)
#define CURRENT_800MA (0x01 << 3)
#define CURRENT_1600MA (0x01 << 4)

#define BAT_4_2V (0x00)
#define BAT_4_3V (0x01)
#define BAT_4_3_5V (0x02)
#define BAT_4_4V (0x03)

#define CHG_CC_BIT (0x20)

#define LIGHT_LOAD_BIT (0x20)

// Add voltage marcros
#define ADD_VOLTAGE_0MV (0x00)
#define ADD_VOLTAGE_14MV (0x01)
#define ADD_VOLTAGE_28MV (0x02)
#define ADD_VOLTAGE_42MV (0x03)

/**
 * @brief Read a byte from a IP5306 register
 */
static esp_err_t ip5306_register_read(uint8_t reg_addr, uint8_t *data)
{
    i2c_master_write_read_device(I2C_MASTER_NUM, IP5306_ADDR, &reg_addr, 1, data, 1, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
    ESP_LOGI(TAG, "Read from register 0x%02x: 0x%02x", reg_addr, *data);
    return ESP_OK;
}

/**
 * @brief Write a byte to a IP5306 register
 */
static esp_err_t ip5306_ADDR_register_write_byte(uint8_t reg_addr, uint8_t data)
{
    uint8_t write_buf[2] = {reg_addr, data};
    return i2c_master_write_to_device(I2C_MASTER_NUM, IP5306_ADDR, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
}

int8_t getBatteryLevel()
{
    uint8_t data;
    ip5306_register_read(IP5306_REG_READ3, &data);
    switch (data & 0xf0)
    {
    case 0x00:
        return 100;
    case 0x80:
        return 75;
    case 0xC0:
        return 50;
    case 0xE0:
        return 25;
    default:
        return 0;
    }
}

esp_err_t setBatteryVoltage(uint8_t voltage_marco, uint8_t add_voltage_marco)
{
    uint8_t data;
    ip5306_register_read(IP5306_REG_Charger_CTL2, &data);
    ESP_LOGI(TAG, "1BatteryVoltage Read from register 0x%02x: 0x%02x", IP5306_REG_Charger_CTL2, data);
    data = (data & 0xf0) | (voltage_marco) | (add_voltage_marco);
    ip5306_ADDR_register_write_byte(IP5306_REG_Charger_CTL2, data);
    return ESP_OK;
}

esp_err_t setVinMaxCurrent(uint8_t current_marco)
{
    uint8_t data;
    ip5306_register_read(IP5306_REG_CHG_DIG_CTL0, &data);
    ip5306_ADDR_register_write_byte(IP5306_REG_CHG_DIG_CTL0, (data & 0xe0) | current_marco);
    return ESP_OK;
}

esp_err_t IP5306_setup()
{
    uint8_t data;
    ip5306_register_read(IP5306_REG_SYS_CTL0, &data);
    ip5306_ADDR_register_write_byte(IP5306_REG_SYS_CTL0, (data & 0x50) | BOOST_ENABLE_BIT);
    ip5306_register_read(IP5306_REG_SYS_CTL1, &data);
    ip5306_ADDR_register_write_byte(IP5306_REG_SYS_CTL1, (data & 0x1D));
    setBatteryVoltage(BAT_4_2V, ADD_VOLTAGE_28MV);
    setVinMaxCurrent(CURRENT_800MA | CURRENT_200MA);
    return ESP_OK;
}

void switch_power(bool on)
{
    ESP_LOGI(TAG, "Switching power %s", on ? "on" : "off");
    uint8_t data;
    if (on)
    {
        ip5306_register_read(IP5306_REG_SYS_CTL0, &data);
        ip5306_ADDR_register_write_byte(IP5306_REG_SYS_CTL0, (data & 0xD0) | BOOST_ENABLE_BIT);
    }
    else
    {
        ip5306_register_read(IP5306_REG_SYS_CTL0, &data);
        ip5306_ADDR_register_write_byte(IP5306_REG_SYS_CTL0, (data & 0xD0));
    }
}

NU1680使用手记

使用NU1680需要注意的点有散热、EN使能脚、谐振电容选取和线圈选取。

散热条件不好的板子可以通过VOUT端的电容值修改系统功率。5V1A会比较容易发热,5V0.7A较理想。

EN使能脚不使用可以悬空或接地。如果需要电源选择电路,绘制电路的时候注意MOS管体二极管的方向、GDS三极的电压,如果MOS管偏置不当,可能会导致EN脚异常拉高,导致无法供电。

我们在使用NU1680时遇到的最大问题就是线圈的选型。

经询问代理商和我们自己进行的测试,我们发现NU1680可以用10-16uH的线圈,如果遇到无法供电的情况,可能是TX线圈和RX线圈的耦合系数过低,导致TX线圈不能足功率发射。可以通过更换TX线圈、添加隔磁片、提高线圈中心重合度来保证供电。

为提高系统效率,最好自行计算谐振电容。计算选取的频率是110kHz,电容的封装可以按推荐选择0402,也可以自行选择0603等封装。

f=\frac{1}{2\pi \sqrt{LC}}

选取线圈最好使用品质因数高、内阻小的线圈,以进一步提高输电效率,减少发热。

  • 25
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值