Skip to content

Instantly share code, notes, and snippets.

@rlightner

rlightner/battery.cpp Secret

Created Jul 17, 2019
Embed
What would you like to do?
Keep Power Boost On
#include <esp32-hal-log.h>
#include <Arduino.h>
#include "battery.h"
// Local logging tag
static const char TAG[] = "main";
esp_adc_cal_characteristics_t *adc_characs = (esp_adc_cal_characteristics_t *)calloc(1, sizeof(esp_adc_cal_characteristics_t));
static adc1_channel_t adc_channel = ADC1_GPIO36_CHANNEL;
static const adc_atten_t atten = ADC_ATTEN_DB_11;
static const adc_unit_t unit = ADC_UNIT_1;
void calibrate_voltage(adc1_channel_t channel) {
adc_channel = channel;
// configure ADC
ESP_ERROR_CHECK(adc1_config_width(ADC_WIDTH_BIT_12));
ESP_ERROR_CHECK(adc1_config_channel_atten(adc_channel, atten));
// calibrate ADC
esp_adc_cal_value_t val_type = esp_adc_cal_characterize(
unit, atten, ADC_WIDTH_BIT_12, DEFAULT_VREF, adc_characs);
// show ADC characterization base
if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
ESP_LOGI(TAG,
"ADC characterization based on Two Point values stored in eFuse");
} else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
ESP_LOGI(TAG,
"ADC characterization based on reference voltage stored in eFuse");
} else {
ESP_LOGI(TAG, "ADC characterization based on default reference voltage");
}
}
uint16_t read_voltage() {
// multisample ADC
uint32_t adc_reading = 0;
for (int i = 0; i < NO_OF_SAMPLES; i++) {
adc_reading += adc1_get_raw(adc_channel);
yield();
}
adc_reading /= NO_OF_SAMPLES;
// Convert ADC reading to voltage in mV
uint16_t voltage = (uint16_t)esp_adc_cal_raw_to_voltage(adc_reading, adc_characs);
#ifdef BATT_FACTOR
voltage *= BATT_FACTOR;
#endif
ESP_LOGD(TAG, "Raw: %d / Voltage: %dmV", adc_reading, voltage);
return voltage;
}
#ifndef _BATTERY_H
#define _BATTERY_H
#include <driver/adc.h>
#include <esp_adc_cal.h>
#define DEFAULT_VREF 1100 // tbd: use adc2_vref_to_gpio() for better estimate
#define NO_OF_SAMPLES 32 // we do some multisampling to get better values
uint16_t read_voltage(void);
void calibrate_voltage(adc1_channel_t);
#endif
#include <SPI.h>
#include <Wire.h>
#include <GxEPD2_BW.h>
#include <GxEPD2_3C.h>
#include <Fonts/FreeMonoBold9pt7b.h>
#define xstr(a) str(a)
#define str(a) #a
#define ENABLE_GxEPD2_GFX 0
GxEPD2_BW<GxEPD2_270, GxEPD2_270::HEIGHT> display(GxEPD2_270(/*CS=5*/ 5, /*DC=*/17, /*RST=*/16, /*BUSY=*/4));
#define uS_TO_S_FACTOR 1000000
#define IP5306_ADDR 0X75
#define IP5306_REG_SYS_CTL0 0x00
#define BOOST_OUT_BIT 0x02
#define CHARGE_FULL_BIT (0x08)
#define IP5306_REG_READ0 (0x70)
bool canControl() {
uint8_t data;
Wire.beginTransmission(IP5306_ADDR);
Wire.write(IP5306_REG_READ0);
return (Wire.endTransmission() == 0);
}
bool setPowerBoostKeepOn(bool en) {
uint8_t data;
Wire.beginTransmission(IP5306_ADDR);
Wire.write(IP5306_REG_SYS_CTL0);
Wire.endTransmission();
if (Wire.requestFrom(IP5306_ADDR, 1))
{
data = Wire.read();
Wire.beginTransmission(IP5306_ADDR);
Wire.write(IP5306_REG_SYS_CTL0);
if (en) Wire.write(data | BOOST_OUT_BIT);
else Wire.write(data & (~BOOST_OUT_BIT));
Wire.endTransmission();
return true;
}
return false;
}
bool isCharging() {
uint8_t data;
Wire.beginTransmission(IP5306_ADDR);
Wire.write(IP5306_REG_READ0);
Wire.endTransmission(false);
if (Wire.requestFrom(IP5306_ADDR, 1))
{
data = Wire.read();
if (data & (1 << CHARGE_FULL_BIT)) return true;
else return false;
}
return false;
}
int8_t getBatteryLevel()
{
Wire.beginTransmission(0x75);
Wire.write(0x78);
if (Wire.endTransmission(false) == 0
&& Wire.requestFrom(0x75, 1)) {
switch (Wire.read() & 0xF0) {
case 0xE0: return 25;
case 0xC0: return 50;
case 0x80: return 75;
case 0x00: return 100;
default: return 0;
}
}
return -1;
}
RTC_DATA_ATTR int bootCount = 0;
void setup()
{
delay(200);
Serial.begin(115200);
++bootCount;
SPI.begin(18, 2, 23, 13);
delay(1000);
calibrate_voltage(ADC1_GPIO35_CHANNEL);
//begin i2c bus
Wire.begin(21, 22);
if (setPowerBoostKeepOn(true)) {
Serial.println("5306 begin pass");
} else {
Serial.println("5306 begin fail");
}
Serial.println("setup");
display.init();
display.setRotation(2);
display.setFullWindow();
display.setTextColor(GxEPD_BLACK);
display.setFont(&FreeMonoBold9pt7b);
display.setTextSize(0);
display.fillScreen(GxEPD_WHITE);
Serial.println("Waking Up");
display.setCursor(0, display.height() / 2);
display.println("Boot Count: " + String(bootCount));
display.display(true);
delay(200);
bool cc = canControl();
display.println("Can Control: " + String(cc));
display.display(true);
delay(200);
bool c = isCharging();
display.println("is charging: " + String(c));
display.display(true);
uint8_t percentage = 100;
calibrate_voltage(ADC1_GPIO35_CHANNEL);
delay(200);
float voltage = 2.0 * (((float) read_voltage()) * 0.001);
delay(200);
if (voltage > 4.2) percentage = 100;
else if (voltage < 3.2) percentage = 0;
else percentage = (voltage - 3.2) * 100 / (4.2 - 3.2);
display.println("Voltage: " + String(voltage));
display.println("Percentage: " + String(percentage));
display.display(true);
uint64_t sleeptime = UINT64_C((60 * 30) * uS_TO_S_FACTOR);
esp_sleep_enable_timer_wakeup(sleeptime);
display.println("sleeping for: " + String(60 * 30));
display.display(true);
delay(200);
display.powerOff();
delay(200);
esp_deep_sleep_start();
}
void loop()
{
// put your main code here, to run repeatedly:
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.