Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't reset the MAX17043 battery fuel gauge after waking from Deep Sleep #19412

Merged
merged 4 commits into from
Sep 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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