Skip to content

Commit

Permalink
Don't reset the MAX17043 battery fuel gauge after waking from Deep Sl…
Browse files Browse the repository at this point in the history
…eep (#19412)

* fix: don't reset the device when coming out of deep sleep

* fix: move debug log message to inside the device validation

* Update xsns_110_max17043.ino

* add: update global battery percentage when max17043 reports new value
  • Loading branch information
blacknell authored Sep 9, 2023
1 parent 7726f1e commit 4cc81f0
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 14 deletions.
4 changes: 2 additions & 2 deletions tasmota/include/tasmota.h
Original file line number Diff line number Diff line change
Expand Up @@ -515,10 +515,10 @@ enum DevGroupShareItem { DGR_SHARE_POWER = 1, DGR_SHARE_LIGHT_BRI = 2, DGR_SHARE

enum CommandSource { SRC_IGNORE, SRC_MQTT, SRC_RESTART, SRC_BUTTON, SRC_SWITCH, SRC_BACKLOG, SRC_SERIAL, SRC_WEBGUI, SRC_WEBCOMMAND, SRC_WEBCONSOLE, SRC_PULSETIMER,
SRC_TIMER, SRC_RULE, SRC_MAXPOWER, SRC_MAXENERGY, SRC_OVERTEMP, SRC_LIGHT, SRC_KNX, SRC_DISPLAY, SRC_WEMO, SRC_HUE, SRC_RETRY, SRC_REMOTE, SRC_SHUTTER,
SRC_THERMOSTAT, SRC_CHAT, SRC_TCL, SRC_BERRY, SRC_FILE, SRC_SSERIAL, SRC_USBCONSOLE, SRC_SO47, SRC_MAX };
SRC_THERMOSTAT, SRC_CHAT, SRC_TCL, SRC_BERRY, SRC_FILE, SRC_SSERIAL, SRC_USBCONSOLE, SRC_SO47, SRC_SENSOR, SRC_MAX };
const char kCommandSource[] PROGMEM = "I|MQTT|Restart|Button|Switch|Backlog|Serial|WebGui|WebCommand|WebConsole|PulseTimer|"
"Timer|Rule|MaxPower|MaxEnergy|Overtemp|Light|Knx|Display|Wemo|Hue|Retry|Remote|Shutter|"
"Thermostat|Chat|TCL|Berry|File|SSerial|UsbConsole|SO47";
"Thermostat|Chat|TCL|Berry|File|SSerial|UsbConsole|SO47|Sensor";

const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 };

Expand Down
62 changes: 50 additions & 12 deletions tasmota/tasmota_xsns_sensor/xsns_110_max17043.ino
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/*
xsns_110_max17043.ino - Support for MAX17043 fuel-gauge systems Lipo batteries for Tasmota
Copyright (C) 2023 Vincent de Groot
Copyright (c) 2023 Vincent de Groot
Copyright (c) 2023 Paul Blacknell
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -40,6 +41,8 @@
#define XSNS_110 110
#define XI2C_83 83 // See I2CDEVICES.md

#define MAX17043_NAME "MAX17043"

#define MAX17043_ADDRESS 0x36
#define MAX17043_VCELL 0x02
#define MAX17043_SOC 0x04
Expand All @@ -48,39 +51,74 @@
#define MAX17043_CONFIG 0x0c
#define MAX17043_COMMAND 0xfe

#define MAX17043_MODE_COMMAND_POWERONRESET 0x5400
#define MAX17043_MODE_COMMAND_QUICKSTART 0x4000
#define MAX17043_CONFIG_POWER_UP_DEFAULT 0x971c
#define MAX17043_CONFIG_NO_COMPENSATION 0x9700

bool max17043 = false;
int battery_latest = 101;

/*********************************************************************************************/

void Max17043Init(void) {
if (I2cSetDevice(MAX17043_ADDRESS)) {
I2cWrite16(MAX17043_ADDRESS, MAX17043_COMMAND, 0x5400); // Power on reset
delay(10);
if (I2cRead16(MAX17043_ADDRESS, MAX17043_CONFIG) == 0x971c) { // Default 0x971c
I2cWrite16(MAX17043_ADDRESS, MAX17043_MODE, 0x4000); // Quick start
I2cWrite16(MAX17043_ADDRESS, MAX17043_CONFIG, 0x9700);
if (REASON_DEEP_SLEEP_AWAKE == ESP_ResetInfoReason()) {
// if waking from deep sleep we assume the hardware design maintained power to the MAX17043
// retaining its model of the internal dynamics the battery
// if the hardware design doesn't (to conserve battery) then we lose some of
// the benefits of the device anyway as it'll be re-learning from scratch every DeepSleepTime seconds.

// to confirm this is a MAX17043 - check for both the default (if the MAX17043 did lose it's power)
// or our setting if power was maintained
if (I2cRead16(MAX17043_ADDRESS, MAX17043_CONFIG) == MAX17043_CONFIG_NO_COMPENSATION
|| I2cRead16(MAX17043_ADDRESS, MAX17043_CONFIG) == MAX17043_CONFIG_POWER_UP_DEFAULT) {
max17043 = true;
I2cSetActiveFound(MAX17043_ADDRESS, MAX17043_NAME);
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("SNS: Waking from deep sleep - skipping " MAX17043_NAME " Power on Reset & Quick Start"));
}
} else {
// otherwise perform a full Power on Reset (which is the same as disconnecting power)
// and a Quick Start which essentially does the same but handles a noisy power up sequence

I2cWrite16(MAX17043_ADDRESS, MAX17043_COMMAND, MAX17043_MODE_COMMAND_POWERONRESET);
delay(10);
max17043 = true;
I2cSetActiveFound(MAX17043_ADDRESS, "MAX17043");
if (I2cRead16(MAX17043_ADDRESS, MAX17043_CONFIG) == MAX17043_CONFIG_POWER_UP_DEFAULT) { // Read the default to confirm this is a MAX17043
I2cWrite16(MAX17043_ADDRESS, MAX17043_MODE, MAX17043_MODE_COMMAND_QUICKSTART);
I2cWrite16(MAX17043_ADDRESS, MAX17043_CONFIG, MAX17043_CONFIG_NO_COMPENSATION);
delay(10);
max17043 = true;
I2cSetActiveFound(MAX17043_ADDRESS, MAX17043_NAME);
}
}
}
}


void Max17043Show(bool json) {
float voltage = (1.25f * (float)(I2cRead16(MAX17043_ADDRESS, MAX17043_VCELL) >> 4)) / 1000.0; // Battery voltage in Volt
uint16_t per = I2cRead16(MAX17043_ADDRESS, MAX17043_SOC);
float percentage = (float)((per >> 8) + 0.003906f * (per & 0x00ff)); // Battery remaining charge in percent
int battery_current;

// During charging the percentage might be (slightly) above 100%. To avoid strange numbers
// in the statistics the percentage provided by this driver will not go above 100%
if (percentage > 100.0) { percentage = 100.0; }

// only update the system percentage if it's changed
battery_current = int(round(percentage));
if (battery_latest != battery_current) {
char cmnd[30];
sprintf(cmnd, "%s %d", D_CMND_ZIGBEE_BATTPERCENT, battery_current);
ExecuteCommand(cmnd, SRC_SENSOR);
battery_latest = battery_current;
}
if (json) {
ResponseAppend_P(PSTR(",\"MAX17043\":{\"" D_JSON_VOLTAGE "\":%3_f,\"" D_JSON_BATTPERCENT "\":%2_f}"), &voltage, &percentage );
ResponseAppend_P(PSTR(",\"" MAX17043_NAME "\":{\"" D_JSON_VOLTAGE "\":%3_f,\"" D_JSON_BATTPERCENT "\":%2_f}"), &voltage, &percentage );
#ifdef USE_WEBSERVER
} else {
// WSContentSend_Voltage("MAX17043", voltage);
WSContentSend_PD(PSTR("{s}MAX17043 " D_VOLTAGE "{m}%1_f" D_UNIT_VOLT "{e}"), &voltage);
WSContentSend_PD(PSTR("{s}MAX17043 " D_BATTERY_CHARGE "{m}%1_f %% {e}"), &percentage);
WSContentSend_PD(PSTR("{s}" MAX17043_NAME " " D_VOLTAGE "{m}%1_f" D_UNIT_VOLT "{e}"), &voltage);
WSContentSend_PD(PSTR("{s}" MAX17043_NAME " " D_BATTERY_CHARGE "{m}%1_f " D_UNIT_PERCENT " {e}"), &percentage);
#endif
}
}
Expand Down

0 comments on commit 4cc81f0

Please sign in to comment.