diff --git a/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/.gitattributes b/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/.gitattributes
new file mode 100644
index 000000000..dfe077042
--- /dev/null
+++ b/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/.gitattributes
@@ -0,0 +1,2 @@
+# Auto detect text files and perform LF normalization
+* text=auto
diff --git a/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/LICENSE b/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/LICENSE
new file mode 100644
index 000000000..b08933d57
--- /dev/null
+++ b/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 SparkFun Electronics
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/README.md b/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/README.md
new file mode 100644
index 000000000..966e9e608
--- /dev/null
+++ b/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/README.md
@@ -0,0 +1,59 @@
+SparkFun MAX1704x Fuel Gauge Arduino Library
+========================================
+
+
+
+ |
+ |
+
+
+ SparkFun LiPo Fuel Gauge - MAX17043 [TOL-20680] |
+ SparkX Qwiic Fuel Gauge - MAX17048 [SPX-17715] |
+
+
+
+
+The MAX17043/MAX17044 are ultra-compact, low-cost,
+host-side fuel-gauge systems for lithium-ion (Li+) batteries
+in handheld and portable equipment. The MAX17043
+is configured to operate with a single lithium cell and the
+MAX17044 is configured for a dual-cell 2S pack.
+
+The MAX17048/MAX17049 ICs are tiny, micropower current
+fuel gauges for lithium-ion (Li+) batteries in handheld
+and portable equipment. The MAX17048 operates with
+a single lithium cell and the MAX17049 with two lithium
+cells in series.
+
+This Arduino library provides support for all four devices.
+
+## Thanks
+
+Parts of this library were inspired by [Daniel Porrey's max1704x library](https://github.com/porrey/max1704x). Thank you Daniel.
+
+## Repository Contents
+
+- **/examples** - Example sketches for the library (.ino). Run these from the Arduino IDE.
+- **/src** - Source files for the library (.cpp, .h).
+- **keywords.txt** - Keywords from this library that will be highlighted in the Arduino IDE.
+- **library.properties** - General library properties for the Arduino package manager.
+
+## Products That Use This Library
+
+- [Qduino Mini - Arduino Dev Board (DEV-13614)](https://www.sparkfun.com/products/13614) - Built in MAX17048
+- [SparkFun IoT RedBoard - ESP32 Development Board (WRL-19177)](https://www.sparkfun.com/products/19177) - Built in MAX17048
+- [SparkX Qwiic Fuel Gauge - MAX17048 (SPX-17715) ](https://www.sparkfun.com/products/17715)
+- [SparkFun LiPo Fuel Gauge - MAX17043 (TOL-20680)](https://www.sparkfun.com/products/20680)
+- [SparkFun LiPo Fuel Gauge - MAX17043 (TOL-10617)](https://www.sparkfun.com/products/10617)
+
+
+## Documentation
+
+- **[Installing an Arduino Library Guide](https://learn.sparkfun.com/tutorials/installing-an-arduino-library)** - Basic information on how to install an Arduino library.
+- **[LiPo Fuel Gauge (MAX1704X) Hookup Guide](https://learn.sparkfun.com/tutorials/lipo-fuel-gauge-max1704x-hookup-guide)** - Basic hookup guide for the MAX1704X (i.e. MAX1703 and MAX17048).
+
+
+
+## License Information
+
+Please see [LICENSE.md](./LICENSE.md) for the license information.
diff --git a/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/examples/Example1_Simple/Example1_Simple.ino b/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/examples/Example1_Simple/Example1_Simple.ino
new file mode 100644
index 000000000..893479fdd
--- /dev/null
+++ b/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/examples/Example1_Simple/Example1_Simple.ino
@@ -0,0 +1,88 @@
+/******************************************************************************
+Example1_Simple
+By: Paul Clark
+Date: October 23rd 2020
+
+Based extensively on:
+MAX17043_Simple_Serial.cpp
+SparkFun MAX17043 Example Code
+Jim Lindblom @ SparkFun Electronics
+Original Creation Date: June 22, 2015
+
+This file demonstrates the simple API of the SparkFun MAX17043 Arduino library.
+
+This example will print the gauge's voltage and state-of-charge (SOC) readings
+to Serial (115200 baud)
+
+This code is released under the MIT license.
+
+Distributed as-is; no warranty is given.
+******************************************************************************/
+
+#include // Needed for I2C
+
+#include // Click here to get the library: http://librarymanager/All#SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library
+
+SFE_MAX1704X lipo; // Defaults to the MAX17043
+
+//SFE_MAX1704X lipo(MAX1704X_MAX17043); // Create a MAX17043
+//SFE_MAX1704X lipo(MAX1704X_MAX17044); // Create a MAX17044
+//SFE_MAX1704X lipo(MAX1704X_MAX17048); // Create a MAX17048
+//SFE_MAX1704X lipo(MAX1704X_MAX17049); // Create a MAX17049
+
+double voltage = 0; // Variable to keep track of LiPo voltage
+double soc = 0; // Variable to keep track of LiPo state-of-charge (SOC)
+bool alert; // Variable to keep track of whether alert has been triggered
+
+void setup()
+{
+ Serial.begin(115200); // Start serial, to output debug data
+ while (!Serial)
+ ; //Wait for user to open terminal
+ Serial.println(F("MAX17043 Example"));
+
+ Wire.begin();
+
+ lipo.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial
+
+ // Set up the MAX17043 LiPo fuel gauge:
+ if (lipo.begin() == false) // Connect to the MAX17043 using the default wire port
+ {
+ Serial.println(F("MAX17043 not detected. Please check wiring. Freezing."));
+ while (1)
+ ;
+ }
+
+ // Quick start restarts the MAX17043 in hopes of getting a more accurate
+ // guess for the SOC.
+ lipo.quickStart();
+
+ // We can set an interrupt to alert when the battery SoC gets too low.
+ // We can alert at anywhere between 1% - 32%:
+ lipo.setThreshold(20); // Set alert threshold to 20%.
+}
+
+void loop()
+{
+ // lipo.getVoltage() returns a voltage value (e.g. 3.93)
+ voltage = lipo.getVoltage();
+ // lipo.getSOC() returns the estimated state of charge (e.g. 79%)
+ soc = lipo.getSOC();
+ // lipo.getAlert() returns a 0 or 1 (0=alert not triggered)
+ alert = lipo.getAlert();
+
+ // Print the variables:
+ Serial.print("Voltage: ");
+ Serial.print(voltage); // Print the battery voltage
+ Serial.println(" V");
+
+ Serial.print("Percentage: ");
+ Serial.print(soc); // Print the battery state of charge
+ Serial.println(" %");
+
+ Serial.print("Alert: ");
+ Serial.println(alert);
+ Serial.println();
+
+ delay(500);
+}
diff --git a/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/examples/Example2_AlternatePorts/Example2_AlternatePorts.ino b/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/examples/Example2_AlternatePorts/Example2_AlternatePorts.ino
new file mode 100644
index 000000000..7fd651aad
--- /dev/null
+++ b/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/examples/Example2_AlternatePorts/Example2_AlternatePorts.ino
@@ -0,0 +1,92 @@
+/******************************************************************************
+Example2_AlternatePorts
+By: Paul Clark
+Date: October 23rd 2020
+
+Based extensively on:
+MAX17043_Simple_Serial.cpp
+SparkFun MAX17043 Example Code
+Jim Lindblom @ SparkFun Electronics
+Original Creation Date: June 22, 2015
+
+This file demonstrates the simple API of the SparkFun MAX17043 Arduino library using non-standard Wire and Serial ports.
+
+This example will print the gauge's voltage and state-of-charge (SOC) readings
+to serial (115200 baud)
+
+This code is released under the MIT license.
+
+Distributed as-is; no warranty is given.
+******************************************************************************/
+
+#include // Needed for I2C
+
+#include // Click here to get the library: http://librarymanager/All#SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library
+
+SFE_MAX1704X lipo; // Defaults to the MAX17043
+
+//SFE_MAX1704X lipo(MAX1704X_MAX17043); // Create a MAX17043
+//SFE_MAX1704X lipo(MAX1704X_MAX17044); // Create a MAX17044
+//SFE_MAX1704X lipo(MAX1704X_MAX17048); // Create a MAX17048
+//SFE_MAX1704X lipo(MAX1704X_MAX17049); // Create a MAX17049
+
+// Define our non-standard ports:
+#define mySerial Serial1
+TwoWire myWire(0);
+
+double voltage = 0; // Variable to keep track of LiPo voltage
+double soc = 0; // Variable to keep track of LiPo state-of-charge (SOC)
+bool alert; // Variable to keep track of whether alert has been triggered
+
+void setup()
+{
+ mySerial.begin(115200); // Start serial, to output debug data
+ while (!mySerial)
+ ; //Wait for user to open terminal
+ mySerial.println(F("MAX17043 Example"));
+
+ myWire.begin();
+
+ lipo.enableDebugging(mySerial); // Uncomment this line to enable helpful debug messages on non-standard serial
+
+ // Set up the MAX17043 LiPo fuel gauge:
+ if (lipo.begin(myWire) == false) // Connect to the MAX17043 using non-standard wire port
+ {
+ mySerial.println(F("MAX17043 not detected. Please check wiring. Freezing."));
+ while (1)
+ ;
+ }
+
+ // Quick start restarts the MAX17043 in hopes of getting a more accurate
+ // guess for the SOC.
+ lipo.quickStart();
+
+ // We can set an interrupt to alert when the battery SoC gets too low.
+ // We can alert at anywhere between 1% - 32%:
+ lipo.setThreshold(20); // Set alert threshold to 20%.
+}
+
+void loop()
+{
+ // lipo.getVoltage() returns a voltage value (e.g. 3.93)
+ voltage = lipo.getVoltage();
+ // lipo.getSOC() returns the estimated state of charge (e.g. 79%)
+ soc = lipo.getSOC();
+ // lipo.getAlert() returns a 0 or 1 (0=alert not triggered)
+ alert = lipo.getAlert();
+
+ // Print the variables:
+ mySerial.print("Voltage: ");
+ mySerial.print(voltage); // Print the battery voltage
+ mySerial.println(" V");
+
+ mySerial.print("Percentage: ");
+ mySerial.print(soc); // Print the battery state of charge
+ mySerial.println(" %");
+
+ mySerial.print("Alert: ");
+ mySerial.println(alert);
+ mySerial.println();
+
+ delay(500);
+}
diff --git a/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/examples/Example3_MAX17044/Example3_MAX17044.ino b/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/examples/Example3_MAX17044/Example3_MAX17044.ino
new file mode 100644
index 000000000..439f8566a
--- /dev/null
+++ b/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/examples/Example3_MAX17044/Example3_MAX17044.ino
@@ -0,0 +1,87 @@
+/******************************************************************************
+Example3_MAX17044
+By: Paul Clark
+Date: October 23rd 2020
+
+Based extensively on:
+MAX17043_Simple_Serial.cpp
+SparkFun MAX17043 Example Code
+Jim Lindblom @ SparkFun Electronics
+Original Creation Date: June 22, 2015
+
+This file demonstrates how to talk to the MAX17044 using the SparkFun MAX17043 Arduino library.
+
+This example will print the gauge's voltage and state-of-charge (SOC) readings
+to Serial (115200 baud)
+
+This code is released under the MIT license.
+
+Distributed as-is; no warranty is given.
+******************************************************************************/
+
+#include // Needed for I2C
+
+#include // Click here to get the library: http://librarymanager/All#SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library
+
+SFE_MAX1704X lipo(MAX1704X_MAX17044); // Create a MAX17044
+
+//SFE_MAX1704X lipo(MAX1704X_MAX17043); // Create a MAX17043
+//SFE_MAX1704X lipo(MAX1704X_MAX17048); // Create a MAX17048
+//SFE_MAX1704X lipo(MAX1704X_MAX17049); // Create a MAX17049
+
+double voltage = 0; // Variable to keep track of LiPo voltage
+double soc = 0; // Variable to keep track of LiPo state-of-charge (SOC)
+bool alert; // Variable to keep track of whether alert has been triggered
+
+void setup()
+{
+ Serial.begin(115200); // Start serial, to output debug data
+ while (!Serial)
+ ; //Wait for user to open terminal
+ Serial.println(F("MAX17044 Example"));
+
+ Wire.begin();
+
+ lipo.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial
+
+ // Set up the MAX17044 LiPo fuel gauge:
+ if (lipo.begin() == false) // Connect to the MAX17044 using the default wire port
+ {
+ Serial.println(F("MAX17044 not detected. Please check wiring. Freezing."));
+ while (1)
+ ;
+ }
+
+ // Quick start restarts the MAX17044 in hopes of getting a more accurate
+ // guess for the SOC.
+ lipo.quickStart();
+
+ // We can set an interrupt to alert when the battery SoC gets too low.
+ // We can alert at anywhere between 1% - 32%:
+ lipo.setThreshold(20); // Set alert threshold to 20%.
+}
+
+void loop()
+{
+ // lipo.getVoltage() returns a voltage value (e.g. 7.86)
+ voltage = lipo.getVoltage();
+ // lipo.getSOC() returns the estimated state of charge (e.g. 79%)
+ soc = lipo.getSOC();
+ // lipo.getAlert() returns a 0 or 1 (0=alert not triggered)
+ alert = lipo.getAlert();
+
+ // Print the variables:
+ Serial.print("Voltage: ");
+ Serial.print(voltage); // Print the battery voltage
+ Serial.println(" V");
+
+ Serial.print("Percentage: ");
+ Serial.print(soc); // Print the battery state of charge
+ Serial.println(" %");
+
+ Serial.print("Alert: ");
+ Serial.println(alert);
+ Serial.println();
+
+ delay(500);
+}
diff --git a/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/examples/Example4_MAX17048_KitchenSink/Example4_MAX17048_KitchenSink.ino b/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/examples/Example4_MAX17048_KitchenSink/Example4_MAX17048_KitchenSink.ino
new file mode 100644
index 000000000..d04f057ec
--- /dev/null
+++ b/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/examples/Example4_MAX17048_KitchenSink/Example4_MAX17048_KitchenSink.ino
@@ -0,0 +1,181 @@
+/******************************************************************************
+Example4: test all the things on the MAX17048
+By: Paul Clark, SparkFun Electronics
+Date: October 23rd 2020
+
+This example is an everything-but-the-kitchen-sink test of the MAX17048.
+
+This code is released under the MIT license.
+
+Distributed as-is; no warranty is given.
+******************************************************************************/
+
+#include // Needed for I2C
+
+#include // Click here to get the library: http://librarymanager/All#SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library
+
+SFE_MAX1704X lipo(MAX1704X_MAX17048); // Create a MAX17048
+
+void setup()
+{
+ Serial.begin(115200); // Start serial, to output debug data
+ while (!Serial)
+ ; //Wait for user to open terminal
+ Serial.println(F("MAX17048 Example"));
+
+ Wire.begin();
+
+ lipo.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial
+
+ // Set up the MAX17048 LiPo fuel gauge:
+ if (lipo.begin() == false) // Connect to the MAX17048 using the default wire port
+ {
+ Serial.println(F("MAX17048 not detected. Please check wiring. Freezing."));
+ while (1)
+ ;
+ }
+
+ // Just because we can, let's reset the MAX17048
+ Serial.println(F("Resetting the MAX17048..."));
+ delay(1000); // Give it time to get its act back together
+
+ // Read and print the reset indicator
+ Serial.print(F("Reset Indicator was: "));
+ bool RI = lipo.isReset(true); // Read the RI flag and clear it automatically if it is set
+ Serial.println(RI); // Print the RI
+ // If RI was set, check it is now clear
+ if (RI)
+ {
+ Serial.print(F("Reset Indicator is now: "));
+ RI = lipo.isReset(); // Read the RI flag
+ Serial.println(RI); // Print the RI
+ }
+
+ // To quick-start or not to quick-start? That is the question!
+ // Read the following and then decide if you do want to quick-start the fuel gauge.
+ // "Most systems should not use quick-start because the ICs handle most startup problems transparently,
+ // such as intermittent battery-terminal connection during insertion. If battery voltage stabilizes
+ // faster than 17ms then do not use quick-start. The quick-start command restarts fuel-gauge calculations
+ // in the same manner as initial power-up of the IC. If the system power-up sequence is so noisy that the
+ // initial estimate of SOC has unacceptable error, the system microcontroller might be able to reduce the
+ // error by using quick-start."
+ // If you still want to try a quick-start then uncomment the next line:
+ //lipo.quickStart();
+
+ // Read and print the device ID
+ Serial.print(F("Device ID: 0x"));
+ uint8_t id = lipo.getID(); // Read the device ID
+ if (id < 0x10) Serial.print(F("0")); // Print the leading zero if required
+ Serial.println(id, HEX); // Print the ID as hexadecimal
+
+ // Read and print the device version
+ Serial.print(F("Device version: 0x"));
+ uint8_t ver = lipo.getVersion(); // Read the device version
+ if (ver < 0x10) Serial.print(F("0")); // Print the leading zero if required
+ Serial.println(ver, HEX); // Print the version as hexadecimal
+
+ // Read and print the battery threshold
+ Serial.print(F("Battery empty threshold is currently: "));
+ Serial.print(lipo.getThreshold());
+ Serial.println(F("%"));
+
+ // We can set an interrupt to alert when the battery SoC gets too low.
+ // We can alert at anywhere between 1% and 32%:
+ lipo.setThreshold(20); // Set alert threshold to 20%.
+
+ // Read and print the battery empty threshold
+ Serial.print(F("Battery empty threshold is now: "));
+ Serial.print(lipo.getThreshold());
+ Serial.println(F("%"));
+
+ // Read and print the high voltage threshold
+ Serial.print(F("High voltage threshold is currently: "));
+ float highVoltage = ((float)lipo.getVALRTMax()) * 0.02; // 1 LSb is 20mV. Convert to Volts.
+ Serial.print(highVoltage, 2);
+ Serial.println(F("V"));
+
+ // Set the high voltage threshold
+ lipo.setVALRTMax((float)4.1); // Set high voltage threshold (Volts)
+
+ // Read and print the high voltage threshold
+ Serial.print(F("High voltage threshold is now: "));
+ highVoltage = ((float)lipo.getVALRTMax()) * 0.02; // 1 LSb is 20mV. Convert to Volts.
+ Serial.print(highVoltage, 2);
+ Serial.println(F("V"));
+
+ // Read and print the low voltage threshold
+ Serial.print(F("Low voltage threshold is currently: "));
+ float lowVoltage = ((float)lipo.getVALRTMin()) * 0.02; // 1 LSb is 20mV. Convert to Volts.
+ Serial.print(lowVoltage, 2);
+ Serial.println(F("V"));
+
+ // Set the low voltage threshold
+ lipo.setVALRTMin((float)3.9); // Set low voltage threshold (Volts)
+
+ // Read and print the low voltage threshold
+ Serial.print(F("Low voltage threshold is now: "));
+ lowVoltage = ((float)lipo.getVALRTMin()) * 0.02; // 1 LSb is 20mV. Convert to Volts.
+ Serial.print(lowVoltage, 2);
+ Serial.println(F("V"));
+
+ // Enable the State Of Change alert
+ Serial.print(F("Enabling the 1% State Of Change alert: "));
+ if (lipo.enableSOCAlert())
+ {
+ Serial.println(F("success."));
+ }
+ else
+ {
+ Serial.println(F("FAILED!"));
+ }
+
+ // Read and print the HIBRT Active Threshold
+ Serial.print(F("Hibernate active threshold is: "));
+ float actThr = ((float)lipo.getHIBRTActThr()) * 0.00125; // 1 LSb is 1.25mV. Convert to Volts.
+ Serial.print(actThr, 5);
+ Serial.println(F("V"));
+
+ // Read and print the HIBRT Hibernate Threshold
+ Serial.print(F("Hibernate hibernate threshold is: "));
+ float hibThr = ((float)lipo.getHIBRTHibThr()) * 0.208; // 1 LSb is 0.208%/hr. Convert to %/hr.
+ Serial.print(hibThr, 3);
+ Serial.println(F("%/h"));
+}
+
+void loop()
+{
+ // Print the variables:
+ Serial.print("Voltage: ");
+ Serial.print(lipo.getVoltage()); // Print the battery voltage
+ Serial.print("V");
+
+ Serial.print(" Percentage: ");
+ Serial.print(lipo.getSOC(), 2); // Print the battery state of charge with 2 decimal places
+ Serial.print("%");
+
+ Serial.print(" Change Rate: ");
+ Serial.print(lipo.getChangeRate(), 2); // Print the battery change rate with 2 decimal places
+ Serial.print("%/hr");
+
+ Serial.print(" Alert: ");
+ Serial.print(lipo.getAlert()); // Print the generic alert flag
+
+ Serial.print(" Voltage High Alert: ");
+ Serial.print(lipo.isVoltageHigh()); // Print the alert flag
+
+ Serial.print(" Voltage Low Alert: ");
+ Serial.print(lipo.isVoltageLow()); // Print the alert flag
+
+ Serial.print(" Empty Alert: ");
+ Serial.print(lipo.isLow()); // Print the alert flag
+
+ Serial.print(" SOC 1% Change Alert: ");
+ Serial.print(lipo.isChange()); // Print the alert flag
+
+ Serial.print(" Hibernating: ");
+ Serial.print(lipo.isHibernating()); // Print the alert flag
+
+ Serial.println();
+
+ delay(500);
+}
diff --git a/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/keywords.txt b/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/keywords.txt
new file mode 100644
index 000000000..c915999ce
--- /dev/null
+++ b/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/keywords.txt
@@ -0,0 +1,65 @@
+#######################################
+# Syntax Coloring Map For MAX1704x
+#######################################
+
+#######################################
+# Datatypes (KEYWORD1)
+#######################################
+
+SFE_MAX17043 KEYWORD1
+
+#######################################
+# Methods and Functions (KEYWORD2)
+#######################################
+
+setDevice KEYWORD2
+setWirePort KEYWORD2
+begin KEYWORD2
+isConnected KEYWORD2
+enableDebugging KEYWORD2
+disableDebugging KEYWORD2
+quickStart KEYWORD2
+getVoltage KEYWORD2
+getSOC KEYWORD2
+getVersion KEYWORD2
+getThreshold KEYWORD2
+setThreshold KEYWORD2
+getAlert KEYWORD2
+clearAlert KEYWORD2
+enableSOCAlert KEYWORD2
+disableSOCAlert KEYWORD2
+sleep KEYWORD2
+wake KEYWORD2
+reset KEYWORD2
+getConfigRegister KEYWORD2
+getCompensation KEYWORD2
+setCompensation KEYWORD2
+setResetVoltage KEYWORD2
+getResetVoltage KEYWORD2
+enableComparator KEYWORD2
+disableComparator KEYWORD2
+getChangeRate KEYWORD2
+getStatus KEYWORD2
+isReset KEYWORD2
+isVoltageHigh KEYWORD2
+isVoltageLow KEYWORD2
+isVoltageReset KEYWORD2
+isLow KEYWORD2
+isChange KEYWORD2
+enableAlert KEYWORD2
+disableAlert KEYWORD2
+getVALRTMax KEYWORD2
+getVALRTMin KEYWORD2
+setVALRTMax KEYWORD2
+setVALRTMin KEYWORD2
+isHibernating KEYWORD2
+getHIBRTActThr KEYWORD2
+setHIBRTActThr KEYWORD2
+getHIBRTHibThr KEYWORD2
+setHIBRTHibThr KEYWORD2
+enableHibernate KEYWORD2
+disableHibernate KEYWORD2
+
+#######################################
+# Constants (LITERAL1)
+#######################################
diff --git a/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/library.properties b/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/library.properties
new file mode 100644
index 000000000..c47676fb9
--- /dev/null
+++ b/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/library.properties
@@ -0,0 +1,9 @@
+name=SparkFun MAX1704x Fuel Gauge Arduino Library
+version=1.0.4
+author=SparkFun Electronics
+maintainer=SparkFun Electronics
+sentence=Arduino library for the MAX17043/44/48/49 fuel gauges
+paragraph=An Arduino library to let you access all of the features of the MAX17043, MAX17044, MAX17048 and MAX17049 battery fuel gauges
+category=Sensors
+url=https://github.com/sparkfun/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library
+architectures=*
diff --git a/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/src/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library.cpp b/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/src/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library.cpp
new file mode 100644
index 000000000..324677450
--- /dev/null
+++ b/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/src/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library.cpp
@@ -0,0 +1,958 @@
+/******************************************************************************
+SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library.h
+By: Paul Clark
+October 23rd 2020
+
+Based extensively on:
+SparkFunMAX17043.cpp
+SparkFun MAX17043 Library Source File
+Jim Lindblom @ SparkFun Electronics
+Original Creation Date: June 22, 2015
+https://github.com/sparkfun/SparkFun_MAX17043_Particle_Library
+
+This file implements all functions of the MAX17043 class. Functions here range
+from higher level stuff, like reading/writing MAX17043 registers to low-level,
+hardware reads and writes.
+
+This code is released under the MIT license.
+
+Distributed as-is; no warranty is given.
+******************************************************************************/
+#include "SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library.h"
+
+SFE_MAX1704X::SFE_MAX1704X(sfe_max1704x_devices_e device)
+{
+ // Constructor
+ setDevice(device);
+}
+
+// Change the device type if required. Do this after instantiation but before .begin
+void SFE_MAX1704X::setDevice(sfe_max1704x_devices_e device)
+{
+ // Record the device type
+ _device = device;
+
+ // Define the full-scale voltage for VCELL based on the device
+ switch (device)
+ {
+ case MAX1704X_MAX17044:
+ _full_scale = 10.24; // MAX17044 VCELL is 12-bit, 2.50mV per LSB
+ break;
+ case MAX1704X_MAX17048:
+ _full_scale = 5.12; // MAX17048 VCELL is 16-bit, 78.125uV/cell per LSB
+ break;
+ case MAX1704X_MAX17049:
+ _full_scale = 10.24; // MAX17049 VCELL is 16-bit, 78.125uV/cell per LSB (i.e. 156.25uV per LSB)
+ break;
+ default: // Default is the MAX17043
+ _full_scale = 5.12; // MAX17043 VCELL is 12-bit, 1.25mV per LSB
+ break;
+ }
+}
+
+bool SFE_MAX1704X::begin(TwoWire &wirePort)
+{
+ setWirePort(wirePort); //Grab which port the user wants us to use
+
+ if (isConnected() == false)
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("begin: isConnected returned false"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return (false);
+ }
+
+ return (true);
+}
+
+// Allow _i2CPort to be set manually, so that isConnected can be called before .begin if required
+void SFE_MAX1704X::setWirePort(TwoWire &wirePort)
+{
+ _i2cPort = &wirePort; //Grab which port the user wants us to use
+}
+
+//Returns true if device is present
+bool SFE_MAX1704X::isConnected(void)
+{
+ //Updated to resolve issue #4 Dec 27th 2021
+ //Also avoid using the standard "if device answers on _deviceAddress" test
+ //(https://github.com/sparkfun/Arduino_Apollo3/issues/400#issuecomment-992631994)
+ bool success = false;
+ uint8_t retries = 3;
+ uint16_t version = 0;
+
+ while ((success == false) && (retries > 0))
+ {
+ _i2cPort->beginTransmission(MAX1704x_ADDRESS);
+ _i2cPort->write(MAX17043_VERSION); // Attempt to read the version register
+ _i2cPort->endTransmission(false); // Don't release the bus
+
+ if (_i2cPort->requestFrom(MAX1704x_ADDRESS, 2) == 2) // Attempt to read the version (2 bytes)
+ {
+ uint8_t msb = _i2cPort->read();
+ uint8_t lsb = _i2cPort->read();
+ version = ((uint16_t)msb << 8) | lsb;
+ success = true;
+ }
+ else
+ {
+ retries--;
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("SFE_MAX1704X::isConnected: retrying..."));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ delay(50);
+ }
+ }
+
+ if (!success) // Return now if the version could not be read
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("SFE_MAX1704X::isConnected: failed to detect IC!"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return (success);
+ }
+
+ //Extra test - but only for MAX17048/9 - see issue #4
+ if (_device >= MAX1704X_MAX17048)
+ {
+ //Get version should return 0x001_
+ //Not a great test but something
+ //Supported on 48/49
+ if ((version & (1 << 4)) == 0)
+ success = false;
+ }
+
+ return (success);
+}
+
+//Enable or disable the printing of debug messages
+void SFE_MAX1704X::enableDebugging(Stream &debugPort)
+{
+ #if MAX1704X_ENABLE_DEBUGLOG
+ _debugPort = &debugPort; //Grab which port the user wants us to use for debugging
+ _printDebug = true; //Should we print the commands we send? Good for debugging
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+}
+
+void SFE_MAX1704X::disableDebugging(void)
+{
+ #if MAX1704X_ENABLE_DEBUGLOG
+ _printDebug = false; //Turn off extra print statements
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+}
+
+uint8_t SFE_MAX1704X::quickStart()
+{
+ // A quick-start allows the MAX17043 to restart fuel-gauge calculations in the
+ // same manner as initial power-up of the IC. If an application’s power-up
+ // sequence is exceedingly noisy such that excess error is introduced into the
+ // IC’s “first guess” of SOC, the host can issue a quick-start to reduce the
+ // error. A quick-start is initiated by a rising edge on the QSTRT pin, or
+ // through software by writing 4000h to MODE register.
+
+ // Note: on the MAX17048/49 this will also clear / disable EnSleep
+
+ return write16(MAX17043_MODE_QUICKSTART, MAX17043_MODE);
+}
+
+float SFE_MAX1704X::getVoltage()
+{
+ uint16_t vCell;
+ vCell = read16(MAX17043_VCELL);
+
+ if (_device <= MAX1704X_MAX17044)
+ {
+ // On the MAX17043/44: vCell is a 12-bit register where each bit represents:
+ // 1.25mV on the MAX17043
+ // 2.5mV on the MAX17044
+ vCell = (vCell) >> 4; // Align the 12 bits
+
+ float divider = 4096.0 / _full_scale;
+
+ return (((float)vCell) / divider);
+ }
+ else
+ {
+ // On the MAX17048/49: vCell is a 16-bit register where each bit represents 78.125uV/cell per LSB
+ // i.e. 78.125uV per LSB on the MAX17048
+ // i.e. 156.25uV per LSB on the MAX17049
+
+ float divider = 65536.0 / _full_scale;
+
+ return (((float)vCell) / divider);
+ }
+}
+
+float SFE_MAX1704X::getSOC()
+{
+ uint16_t soc;
+ float percent;
+ soc = read16(MAX17043_SOC);
+ percent = (float)((soc & 0xFF00) >> 8);
+ percent += ((float)(soc & 0x00FF)) / 256.0;
+
+ return percent;
+}
+
+uint16_t SFE_MAX1704X::getVersion()
+{
+ return read16(MAX17043_VERSION);
+}
+
+//Supported on MAX17048/49
+uint8_t SFE_MAX1704X::getID()
+{
+ if (_device <= MAX1704X_MAX17044)
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("getID: not supported on this device"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return (0);
+ }
+
+ uint16_t vresetID = read16(MAX17048_VRESET_ID);
+ return (vresetID & 0xFF);
+}
+
+//Default is 0x4B = 75 (7bit, shifted from 0x96__)
+//40mV per bit. So default is 3.0V.
+uint8_t SFE_MAX1704X::setResetVoltage(uint8_t threshold)
+{
+ if (_device <= MAX1704X_MAX17044)
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("setResetVoltage: not supported on this device"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return (MAX17043_GENERIC_ERROR);
+ }
+
+ uint16_t vreset = read16(MAX17048_VRESET_ID);
+ vreset &= 0x01FF; // Mask out bits to set
+ vreset |= ((uint16_t)threshold << 9); // Add new threshold
+
+ return write16(vreset, MAX17048_VRESET_ID);
+}
+uint8_t SFE_MAX1704X::setResetVoltage(float threshold)
+{
+ // 7 bits. LSb = 40mV
+ uint8_t thresh = (uint8_t)(constrain(threshold, 0.0, 5.08) / 0.04);
+ return setResetVoltage(thresh);
+}
+
+uint8_t SFE_MAX1704X::getResetVoltage(void)
+{
+ if (_device <= MAX1704X_MAX17044)
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("getResetVoltage: not supported on this device"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return (0);
+ }
+
+ uint16_t threshold = read16(MAX17048_VRESET_ID) >> 9;
+ return ((uint8_t)threshold);
+}
+
+uint8_t SFE_MAX1704X::enableComparator(void)
+{
+ if (_device <= MAX1704X_MAX17044)
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("enableComparator: not supported on this device"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return (MAX17043_GENERIC_ERROR);
+ }
+
+ uint16_t vresetReg = read16(MAX17048_VRESET_ID);
+ vresetReg &= ~(1 << 8); //Clear bit to enable comparator
+ return write16(vresetReg, MAX17048_VRESET_ID);
+}
+
+uint8_t SFE_MAX1704X::disableComparator(void)
+{
+ if (_device <= MAX1704X_MAX17044)
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("disableComparator: not supported on this device"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return (MAX17043_GENERIC_ERROR);
+ }
+
+ uint16_t vresetReg = read16(MAX17048_VRESET_ID);
+ vresetReg |= (1 << 8); //Set bit to disable comparator
+ return write16(vresetReg, MAX17048_VRESET_ID);
+}
+
+float SFE_MAX1704X::getChangeRate(void)
+{
+ if (_device <= MAX1704X_MAX17044)
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("getChangeRate: not supported on this device"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return (0.0);
+ }
+
+ int16_t changeRate = read16(MAX17048_CRATE);
+ float changerate_f = changeRate * 0.208;
+ return (changerate_f);
+}
+
+uint8_t SFE_MAX1704X::getStatus(void)
+{
+ if (_device <= MAX1704X_MAX17044)
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("getStatus: not supported on this device"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return (0);
+ }
+
+ uint8_t statusReg = read16(MAX17048_STATUS) >> 8;
+ return (statusReg & 0x7F); //Highest bit is don't care
+}
+
+bool SFE_MAX1704X::isReset(bool clear)
+{
+ uint8_t status = getStatus();
+ bool flag = (status & MAX1704x_STATUS_RI) > 0;
+ if (flag && clear) // Clear the flag if requested
+ {
+ // Clear the aligned bit in the status register
+ clearStatusRegBits(MAX1704x_STATUS_RI << 8);
+ }
+ return (flag);
+}
+bool SFE_MAX1704X::isVoltageHigh(bool clear)
+{
+ uint8_t status = getStatus();
+ bool flag = (status & MAX1704x_STATUS_VH) > 0;
+ if (flag && clear) // Clear the flag if requested
+ {
+ // Clear the aligned bit in the status register
+ clearStatusRegBits(MAX1704x_STATUS_VH << 8);
+ }
+ return (flag);
+}
+bool SFE_MAX1704X::isVoltageLow(bool clear)
+{
+ uint8_t status = getStatus();
+ bool flag = (status & MAX1704x_STATUS_VL) > 0;
+ if (flag && clear) // Clear the flag if requested
+ {
+ // Clear the aligned bit in the status register
+ clearStatusRegBits(MAX1704x_STATUS_VL << 8);
+ }
+ return (flag);
+}
+bool SFE_MAX1704X::isVoltageReset(bool clear)
+{
+ uint8_t status = getStatus();
+ bool flag = (status & MAX1704x_STATUS_VR) > 0;
+ if (flag && clear) // Clear the flag if requested
+ {
+ // Clear the aligned bit in the status register
+ clearStatusRegBits(MAX1704x_STATUS_VR << 8);
+ }
+ return (flag);
+}
+bool SFE_MAX1704X::isLow(bool clear)
+{
+ uint8_t status = getStatus();
+ bool flag = (status & MAX1704x_STATUS_HD) > 0;
+ if (flag && clear) // Clear the flag if requested
+ {
+ // Clear the aligned bit in the status register
+ clearStatusRegBits(MAX1704x_STATUS_HD << 8);
+ }
+ return (flag);
+}
+bool SFE_MAX1704X::isChange(bool clear)
+{
+ uint8_t status = getStatus();
+ bool flag = (status & MAX1704x_STATUS_SC) > 0;
+ if (flag && clear) // Clear the flag if requested
+ {
+ // Clear the aligned bit in the status register
+ clearStatusRegBits(MAX1704x_STATUS_SC << 8);
+ }
+ return (flag);
+}
+
+// Clear the specified bit in the MAX17048/49 status register (PRIVATE)
+// This requires the bits in mask to be correctly aligned.
+// MAX1704x_STATUS_RI etc. will need to be shifted left by 8 bits to become aligned.
+uint8_t SFE_MAX1704X::clearStatusRegBits(uint16_t mask)
+{
+ uint16_t statusReg = read16(MAX17048_STATUS);
+ statusReg &= ~mask; // Clear the specified bits
+ return (write16(statusReg, MAX17048_STATUS)); // Write the contents back again
+}
+
+uint8_t SFE_MAX1704X::clearAlert()
+{
+ // Read config reg, so we don't modify any other values:
+ uint16_t configReg = read16(MAX17043_CONFIG);
+ configReg &= ~MAX17043_CONFIG_ALERT; // Clear ALRT bit manually.
+
+ return write16(configReg, MAX17043_CONFIG);
+}
+
+// getAlert([clear]) - Check if the MAX1704X's ALRT alert interrupt has been
+// triggered.
+// INPUT: [clear] - If [clear] is true, the alert flag will be cleared if it
+// was set.
+// OUTPUT: Returns 1 if interrupt is/was triggered, 0 if not.
+uint8_t SFE_MAX1704X::getAlert(bool clear)
+{
+ // Read config reg, so we don't modify any other values:
+ uint16_t configReg = read16(MAX17043_CONFIG);
+ if (configReg & MAX17043_CONFIG_ALERT)
+ {
+ if (clear) // If the clear flag is set
+ {
+ configReg &= ~MAX17043_CONFIG_ALERT; // Clear ALRT bit manually.
+ write16(configReg, MAX17043_CONFIG);
+ }
+ return 1;
+ }
+
+ return 0;
+}
+
+// enableSOCAlert() - (MAX17048/49) Enable the SOC change alert
+// Returns true if the SOC change alert was enabled successfully
+bool SFE_MAX1704X::enableSOCAlert()
+{
+ if (_device <= MAX1704X_MAX17044)
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("enableSOCAlert: not supported on this device"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return (false);
+ }
+
+ // Read config reg, so we don't modify any other values:
+ uint16_t configReg = read16(MAX17043_CONFIG);
+ configReg |= MAX17043_CONFIG_ALSC; // Set the ALSC bit
+ // Update the config register, return false if the write fails
+ if (write16(configReg, MAX17043_CONFIG) > 0)
+ return (false);
+ // Re-Read the config reg
+ configReg = read16(MAX17043_CONFIG);
+ // Return true if the ALSC bit is set, otherwise return false
+ return ((configReg & MAX17043_CONFIG_ALSC) > 0);
+}
+
+// disableSOCAlert() - (MAX17048/49) Disable the SOC change alert
+// Returns true if the SOC change alert was disabled successfully
+bool SFE_MAX1704X::disableSOCAlert()
+{
+ if (_device <= MAX1704X_MAX17044)
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("disableSOCAlert: not supported on this device"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return (false);
+ }
+
+ // Read config reg, so we don't modify any other values:
+ uint16_t configReg = read16(MAX17043_CONFIG);
+ configReg &= ~MAX17043_CONFIG_ALSC; // Clear the ALSC bit
+ // Update the config register, return false if the write fails
+ if (write16(configReg, MAX17043_CONFIG) > 0)
+ return (false);
+ // Re-Read the config reg
+ configReg = read16(MAX17043_CONFIG);
+ // Return true if the ALSC bit is clear, otherwise return false
+ return ((configReg & MAX17043_CONFIG_ALSC) == 0);
+}
+
+// Enable or Disable MAX17048 VRESET Alert:
+// EnVr (enable voltage reset alert) when set to 1 asserts
+// the ALRT pin when a voltage-reset event occurs under
+// the conditions described by the VRESET/ ID register.
+uint8_t SFE_MAX1704X::enableAlert(void)
+{
+ if (_device <= MAX1704X_MAX17044)
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("enableAlert: not supported on this device"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return (MAX17043_GENERIC_ERROR);
+ }
+
+ uint16_t statusReg = read16(MAX17048_STATUS);
+ statusReg |= MAX1704x_STATUS_EnVR; // Set EnVR bit
+ return write16(statusReg, MAX17048_STATUS);
+}
+
+uint8_t SFE_MAX1704X::disableAlert(void)
+{
+ if (_device <= MAX1704X_MAX17044)
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("disableAlert: not supported on this device"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return (MAX17043_GENERIC_ERROR);
+ }
+
+ uint16_t statusReg = read16(MAX17048_STATUS);
+ statusReg &= ~MAX1704x_STATUS_EnVR; // Clear EnVR bit
+ return write16(statusReg, MAX17048_STATUS);
+}
+
+uint8_t SFE_MAX1704X::getThreshold()
+{
+ uint16_t configReg = read16(MAX17043_CONFIG);
+ uint8_t threshold = (configReg & 0x001F);
+
+ // It has an LSb weight of 1%, and can be programmed from 1% to 32%.
+ // The value is (32 - ATHD)%, e.g.: 00000=32%, 00001=31%, 11111=1%.
+ // Let's convert our percent to that first:
+ threshold = 32 - threshold;
+ return threshold;
+}
+
+uint8_t SFE_MAX1704X::setThreshold(uint8_t percent)
+{
+ // The alert threshold is a 5-bit value that sets the state of charge level
+ // where an interrupt is generated on the ALRT pin.
+
+ // It has an LSb weight of 1%, and can be programmed from 1% to 32%.
+ // The value is (32 - ATHD)%, e.g.: 00000=32%, 00001=31%, 11111=1%.
+ // Let's convert our percent to that first:
+ percent = (uint8_t)constrain((float)percent, 0.0, 32.0);
+ percent = 32 - percent;
+
+ // Read config reg, so we don't modify any other values:
+ uint16_t configReg = read16(MAX17043_CONFIG);
+ configReg &= 0xFFE0; // Mask out threshold bits
+ configReg |= percent; // Add new threshold
+
+ return write16(configReg, MAX17043_CONFIG);
+}
+
+// In sleep mode, the IC halts all operations, reducing current
+// consumption to below 1μA. After exiting sleep mode,
+// the IC continues normal operation. In sleep mode, the
+// IC does not detect self-discharge. If the battery changes
+// state while the IC sleeps, the IC cannot detect it, causing
+// SOC error. Wake up the IC before charging or discharging.
+uint8_t SFE_MAX1704X::sleep()
+{
+ if (_device > MAX1704X_MAX17044)
+ {
+ // On the MAX17048, we also have to set the EnSleep bit in the MODE register
+ uint8_t result = write16(MAX17048_MODE_ENSLEEP, MAX17043_MODE);
+ if (result)
+ return (result); // Write failed. Bail.
+ }
+
+ // Read config reg, so we don't modify any other values:
+ uint16_t configReg = read16(MAX17043_CONFIG);
+ if (configReg & MAX17043_CONFIG_SLEEP)
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("sleep: MAX17043 is already sleeping!"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return MAX17043_GENERIC_ERROR; // Already sleeping, do nothing but return an error
+ }
+
+ configReg |= MAX17043_CONFIG_SLEEP; // Set sleep bit
+
+ return write16(configReg, MAX17043_CONFIG);
+}
+
+uint8_t SFE_MAX1704X::wake()
+{
+ // Read config reg, so we don't modify any other values:
+ uint16_t configReg = read16(MAX17043_CONFIG);
+ if (!(configReg & MAX17043_CONFIG_SLEEP))
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("wake: MAX17043 is already awake!"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return MAX17043_GENERIC_ERROR; // Already sleeping, do nothing but return an error
+ }
+ configReg &= ~MAX17043_CONFIG_SLEEP; // Clear sleep bit
+
+ uint8_t result = write16(configReg, MAX17043_CONFIG);
+
+ if (result)
+ return (result); // Write failed. Bail.
+
+ if (_device > MAX1704X_MAX17044)
+ {
+ // On the MAX17048, we should also clear the EnSleep bit in the MODE register
+ // Strictly, this will clear the QuickStart bit too. Which is probably a good thing,
+ // as I don't think we can do a read-modify-write?
+ return write16(0x0000, MAX17043_MODE);
+ }
+ else
+ {
+ return (result);
+ }
+}
+
+// Writing a value of 0x5400 to the CMD Register causes
+// the device to completely reset as if power had been
+// removed (see the Power-On Reset (POR) section). The
+// reset occurs when the last bit has been clocked in. The
+// IC does not respond with an I2C ACK after this command
+// sequence.
+// Output: Positive integer on success, 0 on fail.
+uint8_t SFE_MAX1704X::reset()
+{
+ return write16(MAX17043_COMMAND_POR, MAX17043_COMMAND);
+}
+
+uint8_t SFE_MAX1704X::getCompensation()
+{
+ uint16_t configReg = read16(MAX17043_CONFIG);
+ uint8_t compensation = (configReg & 0xFF00) >> 8;
+ return compensation;
+}
+
+uint16_t SFE_MAX1704X::getConfigRegister()
+{
+ return read16(MAX17043_CONFIG);
+}
+
+uint8_t SFE_MAX1704X::setCompensation(uint8_t newCompensation)
+{
+ // The CONFIG register compensates the ModelGauge algorith. The upper 8 bits
+ // of the 16-bit register control the compensation.
+ // Read the original configReg, so we can leave the lower 8 bits alone:
+ uint16_t configReg = read16(MAX17043_CONFIG);
+ configReg &= 0x00FF; // Mask out compensation bits
+ configReg |= ((uint16_t)newCompensation) << 8;
+ return write16(configReg, MAX17043_CONFIG);
+}
+
+// VALRT Register:
+// This register is divided into two thresholds: Voltage alert
+// maximum (VALRT.MAX) and minimum (VALRT. MIN).
+// Both registers have 1 LSb = 20mV. The IC alerts while
+// VCELL > VALRT.MAX or VCELL < VALRT.MIN
+uint8_t SFE_MAX1704X::setVALRTMax(uint8_t threshold)
+{
+ if (_device <= MAX1704X_MAX17044)
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("setVALRTMax: not supported on this device"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return (MAX17043_GENERIC_ERROR);
+ }
+
+ uint16_t valrt = read16(MAX17048_CVALRT);
+ valrt &= 0xFF00; // Mask off max bits
+ valrt |= (uint16_t)threshold;
+ return write16(valrt, MAX17048_CVALRT);
+}
+uint8_t SFE_MAX1704X::setVALRTMax(float threshold)
+{
+ uint8_t thresh = (uint8_t)(constrain(threshold, 0.0, 5.1) / 0.02);
+ return setVALRTMax(thresh);
+}
+
+uint8_t SFE_MAX1704X::getVALRTMax()
+{
+ if (_device <= MAX1704X_MAX17044)
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("getVALRTMax: not supported on this device"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return (0);
+ }
+
+ uint16_t valrt = read16(MAX17048_CVALRT);
+ valrt &= 0x00FF; // Mask off max bits
+ return ((uint8_t)valrt);
+}
+
+uint8_t SFE_MAX1704X::setVALRTMin(uint8_t threshold)
+{
+ if (_device <= MAX1704X_MAX17044)
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("setVALRTMin: not supported on this device"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return (MAX17043_GENERIC_ERROR);
+ }
+
+ uint16_t valrt = read16(MAX17048_CVALRT);
+ valrt &= 0x00FF; // Mask off min bits
+ valrt |= ((uint16_t)threshold) << 8;
+ return write16(valrt, MAX17048_CVALRT);
+}
+uint8_t SFE_MAX1704X::setVALRTMin(float threshold)
+{
+ uint8_t thresh = (uint8_t)(constrain(threshold, 0.0, 5.1) / 0.02);
+ return setVALRTMin(thresh);
+}
+
+uint8_t SFE_MAX1704X::getVALRTMin()
+{
+ if (_device <= MAX1704X_MAX17044)
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("getVALRTMin: not supported on this device"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return (0);
+ }
+
+ uint16_t valrt = read16(MAX17048_CVALRT);
+ valrt >>= 8; // Shift min into LSB
+ return ((uint8_t)valrt);
+}
+
+bool SFE_MAX1704X::isHibernating()
+{
+ if (_device <= MAX1704X_MAX17044)
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("isHibernating: not supported on this device"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return (false);
+ }
+
+ uint16_t mode = read16(MAX17043_MODE);
+ return ((mode & MAX17048_MODE_HIBSTAT) > 0);
+}
+
+uint8_t SFE_MAX1704X::getHIBRTActThr()
+{
+ if (_device <= MAX1704X_MAX17044)
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("getHIBRTActThr: not supported on this device"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return (0);
+ }
+
+ uint16_t hibrt = read16(MAX17048_HIBRT);
+ hibrt &= 0x00FF; // Mask off Act bits
+ return ((uint8_t)hibrt);
+}
+
+uint8_t SFE_MAX1704X::setHIBRTActThr(uint8_t threshold)
+{
+ if (_device <= MAX1704X_MAX17044)
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("setHIBRTActThr: not supported on this device"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return (MAX17043_GENERIC_ERROR);
+ }
+
+ uint16_t hibrt = read16(MAX17048_HIBRT);
+ hibrt &= 0xFF00; // Mask off Act bits
+ hibrt |= (uint16_t)threshold;
+ return write16(hibrt, MAX17048_HIBRT);
+}
+uint8_t SFE_MAX1704X::setHIBRTActThr(float threshold)
+{
+ // LSb = 1.25mV
+ uint8_t thresh = (uint8_t)(constrain(threshold, 0.0, 0.31875) / 0.00125);
+ return setHIBRTActThr(thresh);
+}
+
+uint8_t SFE_MAX1704X::getHIBRTHibThr()
+{
+ if (_device <= MAX1704X_MAX17044)
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("getHIBRTHibThr: not supported on this device"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return (0);
+ }
+
+ uint16_t hibrt = read16(MAX17048_HIBRT);
+ hibrt >>= 8; // Shift HibThr into LSB
+ return ((uint8_t)hibrt);
+}
+
+uint8_t SFE_MAX1704X::setHIBRTHibThr(uint8_t threshold)
+{
+ if (_device <= MAX1704X_MAX17044)
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("setHIBRTHibThr: not supported on this device"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return (MAX17043_GENERIC_ERROR);
+ }
+
+ uint16_t hibrt = read16(MAX17048_HIBRT);
+ hibrt &= 0x00FF; // Mask off Hib bits
+ hibrt |= ((uint16_t)threshold) << 8;
+ return write16(hibrt, MAX17048_HIBRT);
+}
+uint8_t SFE_MAX1704X::setHIBRTHibThr(float threshold)
+{
+ // LSb = 0.208%/hr
+ uint8_t thresh = (uint8_t)(constrain(threshold, 0.0, 53.04) / 0.208);
+ return setHIBRTHibThr(thresh);
+}
+
+uint8_t SFE_MAX1704X::enableHibernate()
+{
+ if (_device <= MAX1704X_MAX17044)
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("enableHibernate: not supported on this device"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return (MAX17043_GENERIC_ERROR);
+ }
+
+ return write16(MAX17048_HIBRT_ENHIB, MAX17048_HIBRT);
+}
+
+uint8_t SFE_MAX1704X::disableHibernate()
+{
+ if (_device <= MAX1704X_MAX17044)
+ {
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("disableHibernate: not supported on this device"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ return (MAX17043_GENERIC_ERROR);
+ }
+
+ return write16(MAX17048_HIBRT_DISHIB, MAX17048_HIBRT);
+}
+
+uint8_t SFE_MAX1704X::write16(uint16_t data, uint8_t address)
+{
+ uint8_t msb, lsb;
+ msb = (data & 0xFF00) >> 8;
+ lsb = (data & 0x00FF);
+ _i2cPort->beginTransmission(MAX1704x_ADDRESS);
+ _i2cPort->write(address);
+ _i2cPort->write(msb);
+ _i2cPort->write(lsb);
+ return (_i2cPort->endTransmission());
+}
+
+uint16_t SFE_MAX1704X::read16(uint8_t address)
+{
+ bool success = false;
+ uint8_t retries = 3;
+ uint16_t result = 0;
+
+ while ((success == false) && (retries > 0))
+ {
+ _i2cPort->beginTransmission(MAX1704x_ADDRESS);
+ _i2cPort->write(address);
+ _i2cPort->endTransmission(false); // Don't release the bus
+
+ if (_i2cPort->requestFrom(MAX1704x_ADDRESS, 2) == 2)
+ {
+ uint8_t msb = _i2cPort->read();
+ uint8_t lsb = _i2cPort->read();
+ result = ((uint16_t)msb << 8) | lsb;
+ success = true;
+ }
+ else
+ {
+ retries--;
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ _debugPort->println(F("SFE_MAX1704X::read16: retrying..."));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+ delay(50);
+ }
+ }
+
+ #if MAX1704X_ENABLE_DEBUGLOG
+ if (_printDebug == true)
+ {
+ if (!success)
+ _debugPort->println(F("SFE_MAX1704X::read16: failed to read data!"));
+ }
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+
+ return (result);
+}
diff --git a/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/src/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library.h b/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/src/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library.h
new file mode 100644
index 000000000..3bb63073b
--- /dev/null
+++ b/libraries/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library/src/SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library.h
@@ -0,0 +1,403 @@
+/******************************************************************************
+SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library.h
+By: Paul Clark
+October 23rd 2020
+
+Based extensively on:
+SparkFunMAX17043.h
+SparkFun MAX17043 Library Header File
+Jim Lindblom @ SparkFun Electronics
+Original Creation Date: June 22, 2015
+https://github.com/sparkfun/SparkFun_MAX17043_Particle_Library
+
+This file implements all functions of the MAX17043 class. Functions here range
+from higher level stuff, like reading/writing MAX17043 registers to low-level,
+hardware reads and writes.
+
+This code is released under the MIT license.
+
+Distributed as-is; no warranty is given.
+******************************************************************************/
+#ifndef MAX1704X_ARDUINO_LIBRARY_H
+#define MAX1704X_ARDUINO_LIBRARY_H
+
+// Uncomment the next #define to EXclude any debug logging from the code, by default debug logging code will be included
+
+// #define MAX1704X_ENABLE_DEBUGLOG 0 // OFF/disabled/excluded on demand
+
+#if (ARDUINO >= 100)
+#include "Arduino.h"
+#else
+#include "WProgram.h"
+#endif
+
+#include
+
+//Enable/disable including debug log (to allow saving some space)
+#ifndef MAX1704X_ENABLE_DEBUGLOG
+ #if defined(LIBRARIES_NO_LOG) && LIBRARIES_NO_LOG
+ #define MAX1704X_ENABLE_DEBUGLOG 0 // OFF/disabled/excluded on demand
+ #else
+ #define MAX1704X_ENABLE_DEBUGLOG 1 // ON/enabled/included by default
+ #endif
+#endif
+
+//#include "application.h"
+
+//////////////////////////
+// MAX1704x Device Enum //
+//////////////////////////
+
+typedef enum {
+ MAX1704X_MAX17043 = 0,
+ MAX1704X_MAX17044, // 2-cell version of the MAX17043 (full-scale range of 10V)
+ MAX1704X_MAX17048,
+ MAX1704X_MAX17049 // 2-cell version of the MAX17048
+} sfe_max1704x_devices_e;
+
+///////////////////////////////////
+// MAX1704x Register Definitions //
+///////////////////////////////////
+// All registers contain two bytes of data and span two addresses.
+// Registers which are present on the MAX17048/49 only are prefixed with MAX17048_
+#define MAX17043_VCELL 0x02 // R - 12-bit A/D measurement of battery voltage
+#define MAX17043_SOC 0x04 // R - 16-bit state of charge (SOC)
+#define MAX17043_MODE 0x06 // W - Sends special commands to IC
+#define MAX17043_VERSION 0x08 // R - Returns IC version
+#define MAX17048_HIBRT 0x0A // R/W - (MAX17048/49) Thresholds for entering hibernate
+#define MAX17043_CONFIG 0x0C // R/W - Battery compensation (default 0x971C)
+#define MAX17048_CVALRT 0x14 // R/W - (MAX17048/49) Configures vcell range to generate alerts (default 0x00FF)
+#define MAX17048_CRATE 0x16 // R - (MAX17048/49) Charge rate 0.208%/hr
+#define MAX17048_VRESET_ID 0x18 // R/W - (MAX17048/49) Reset voltage and ID (default 0x96__)
+#define MAX17048_STATUS 0x1A // R/W - (MAX17048/49) Status of ID (default 0x01__)
+#define MAX17043_COMMAND 0xFE // W - Sends special comands to IC
+
+///////////////////////////////////
+// MAX17043 Config Register Bits //
+///////////////////////////////////
+#define MAX17043_CONFIG_SLEEP (1 << 7)
+#define MAX17043_CONFIG_ALSC 0x0040 // MAX17048/49 only
+#define MAX17043_CONFIG_ALERT (1 << 5)
+#define MAX17043_CONFIG_THRESHOLD 0
+
+/////////////////////////////////////
+// MAX17043 Mode Register Commands //
+/////////////////////////////////////
+#define MAX17043_MODE_QUICKSTART 0x4000 // On the MAX17048/49 this also clears the EnSleep bit
+
+/////////////////////////////////
+// MAX17048 Mode Register Bits //
+/////////////////////////////////
+#define MAX17048_MODE_ENSLEEP 0x2000 // W - _Enables_ sleep mode (the SLEEP bit in the CONFIG reg engages sleep)
+#define MAX17048_MODE_HIBSTAT 0x1000 // R - indicates when the IC is in hibernate mode
+
+/////////////////////////////////////
+// MAX17048/9 Status Register Bits //
+/////////////////////////////////////
+#define MAX1704x_STATUS_RI (1 << 0) // Assumes the MSB has been shifted >> 8
+#define MAX1704x_STATUS_VH (1 << 1) // Assumes the MSB has been shifted >> 8
+#define MAX1704x_STATUS_VL (1 << 2) // Assumes the MSB has been shifted >> 8
+#define MAX1704x_STATUS_VR (1 << 3) // Assumes the MSB has been shifted >> 8
+#define MAX1704x_STATUS_HD (1 << 4) // Assumes the MSB has been shifted >> 8
+#define MAX1704x_STATUS_SC (1 << 5) // Assumes the MSB has been shifted >> 8
+#define MAX1704x_STATUS_EnVR (1 << 14) // ** Unshifted **
+
+////////////////////////////////////////
+// MAX17043 Command Register Commands //
+////////////////////////////////////////
+#define MAX17043_COMMAND_POR 0x5400
+
+///////////////////////////////////////
+// MAX17048 Hibernate Enable/Disable //
+///////////////////////////////////////
+#define MAX17048_HIBRT_ENHIB 0xFFFF // always use hibernate mode
+#define MAX17048_HIBRT_DISHIB 0x0000 // disable hibernate mode
+
+////////////////////////////////
+// MAX1704x 7-Bit I2C Address //
+////////////////////////////////
+#define MAX1704x_ADDRESS 0x36 // Unshifted I2C address. Becomes 0x6C for write and 0x6D for read.
+
+// Generic error:
+// Wire.endTransmission will return:
+// 0:success
+// 1:data too long to fit in transmit buffer
+// 2:received NACK on transmit of address
+// 3:received NACK on transmit of data
+// 4:other error
+// So, let's use "5" as a generic error value
+#define MAX17043_GENERIC_ERROR 5
+
+class SFE_MAX1704X
+{
+public:
+ SFE_MAX1704X(sfe_max1704x_devices_e device = MAX1704X_MAX17043); // Default to the 5V MAX17043
+
+ // Change the device type if required. Do this after instantiation but before .begin
+ void setDevice(sfe_max1704x_devices_e device);
+
+ // Allow _i2CPort to be set manually, so that isConnected can be called before .begin if required
+ void setWirePort(TwoWire &wirePort);
+
+ // begin() - Initializes the MAX17043.
+ bool begin(TwoWire &wirePort = Wire); //Returns true if module is detected
+
+ //Returns true if device is present
+ bool isConnected(void);
+
+ // Debug
+ void enableDebugging(Stream &debugPort = Serial); // enable debug messages
+ void disableDebugging(); // disable debug messages
+
+ // quickStart() - Restarts the MAX17043 to allow it to re-"guess" the
+ // parameters that go into its SoC algorithms. Calling this in your setup()
+ // usually results in more accurate SoC readings.
+ // Output: 0 on success, positive integer on fail.
+ uint8_t quickStart();
+
+ // getVoltage() - Get the MAX17043's voltage reading.
+ // Output: floating point value between 0-5V in 1.25mV increments.
+ float getVoltage();
+
+ // getSOC() - Get the MAX17043's state-of-charge (SOC) reading, as calculated
+ // by the IC's "ModelGauge" algorithm.
+ // The first update is available approximately 1s after POR of the IC.
+ // Output: floating point value between 0-100, representing a percentage of
+ // full charge.
+ float getSOC();
+
+ // getVersion() - Get the MAX17043's production version number.
+ // Output: 3 on success
+ uint16_t getVersion();
+
+ // getThreshold() - Get the MAX17043's current percentage threshold that will
+ // trigger an alert.
+ // Output: An integer value between 1 and 32, representing a % that will
+ // trigger an alert interrupt.
+ uint8_t getThreshold();
+
+ // setThreshold([percent]) - Set the MAX17043's percentage threshold that will
+ // trigger an alert.
+ // Input: [percent] - Percentage value that will trigger an alert interrupt.
+ // Any value between 1 and 32 is valid. Default value is 0x1C == 4%
+ // Output: 0 on success, positive integer on fail.
+ uint8_t setThreshold(uint8_t percent = 4);
+
+ // sleep() - Set the MAX17043 into sleep mode.
+ // Output: 0 on success, positive integer on fail.
+ // In sleep mode, the IC halts all operations, reducing current
+ // consumption to below 1μA. After exiting sleep mode,
+ // the IC continues normal operation. In sleep mode, the
+ // IC does not detect self-discharge. If the battery changes
+ // state while the IC sleeps, the IC cannot detect it, causing
+ // SOC error. Wake up the IC before charging or discharging.
+ uint8_t sleep();
+
+ // wake() - Wake the MAX17043 up from sleep.
+ // Output: 0 on success, positive integer on fail.
+ uint8_t wake();
+
+ // reset() - Issue a Power-on-reset command to the MAX17043. This function
+ // will reset every register in the MAX17043 to its default value.
+ // Output: Positive integer on success, 0 on fail.
+ uint8_t reset();
+
+ // getConfigRegister() - Read the 16-bit value of the CONFIG Register.
+ // Output: 16-bit integer value representing the msb and lsb bytes of the
+ // CONFIG register.
+ uint16_t getConfigRegister();
+
+ // getCompensation() - Get the ModelGauge compensation value - an obscure
+ // 8-bit value set to 0x97 by default.
+ // Output: 8-bit value read from the CONFIG register's MSB.
+ uint8_t getCompensation();
+
+ // setCompensation([newCompensation]) - Set the 8-bit compensation value. This
+ // is an obscure 8-bit value that has some effect on Maxim's ModelGauge
+ // algorithm. The POR value of RCOMP is 0x97.
+ // From the datasheet: "Contact Maxim for instructions for optimization."
+ // For best performance, the host microcontroller must measure
+ // battery temperature periodically, and compensate
+ // the RCOMP ModelGauge parameter accordingly, at least
+ // once per minute. Each custom model defines constants
+ // RCOMP0 (default is 0x97), TempCoUp (default is -0.5),
+ // and TempCoDown (default is -5.0). To calculate the new
+ // value of CONFIG.RCOMP:
+ // // T is battery temperature (degrees Celsius)
+ // if (T > 20) {
+ // RCOMP = RCOMP0 + (T - 20) x TempCoUp;
+ // }
+ // else {
+ // RCOMP = RCOMP0 + (T - 20) x TempCoDown;
+ // }
+ // Input: [newCompensation] - Should be a value between 0-255.
+ // Output: 0 on success, positive integer on fail.
+ uint8_t setCompensation(uint8_t newCompensation = 0x97);
+
+ // getID() - (MAX17048/49) Returns 8-bit OTP bits set at factory. Can be used to
+ // 'to distinguish multiple cell types in production'.
+ // Writes to these bits are ignored.
+ uint8_t getID(void);
+
+ // setResetVoltage([threshold]) - (MAX17048/49) Set the 7-bit VRESET value.
+ // A 7-bit value that controls the comparator for detecting when
+ // a battery is detached and re-connected. 40mV per bit. Default is 3.0V.
+ // For captive batteries, set to 2.5V. For
+ // removable batteries, set to at least 300mV below the
+ // application’s empty voltage, according to the desired
+ // reset threshold for your application.
+ // Input: [threshold] - Should be a value between 0-127.
+ // Output: 0 on success, positive integer on fail.
+ uint8_t setResetVoltage(uint8_t threshold = (0x96 >> 1));
+ uint8_t setResetVoltage(float threshold = 3.0); // Helper function: set threshold in Volts
+
+ // getResetVoltage() - (MAX17048/49) Get the 7-bit VRESET value
+ // Output: 7-bit value read from the VRESET/ID register's MSB.
+ // Returned value is 40mV per bit.
+ uint8_t getResetVoltage(void);
+
+ // enableComparator() - (MAX17048/49) Set bit in VRESET/ID reg
+ // Comparator is enabled by default. (Re)enable the analog comparator, uses 0.5uA.
+ // Output: 0 on success, positive integer on fail.
+ uint8_t enableComparator(void);
+
+ // disableComparator() - (MAX17048/49) Clear bit in VRESET/ID reg
+ // Disable the analog comparator, saves 0.5uA in hibernate mode.
+ // Output: 0 on success, positive integer on fail.
+ uint8_t disableComparator(void);
+
+ // getChangeRate() - (MAX17048/49) Get rate of change per hour in %
+ // Output: (signed) Float (that is the 0.208% * CRATE register value)
+ // A positive rate is charging, negative is discharge.
+ float getChangeRate();
+
+ // getStatus() - (MAX17048/49) Get the 7 bits of status register
+ // Output: 7-bits indicating various alerts
+ uint8_t getStatus();
+
+ //(MAX17048/49) Various helper functions to check bits in status register
+ // INPUT: [clear] - If [clear] is true, the alert flag will be cleared if it
+ // was set.
+ bool isReset(bool clear = false); //True after POR
+ bool isVoltageHigh(bool clear = false); //True when VCELL goes above VALRTMAX (see setVALRTMax)
+ bool isVoltageLow(bool clear = false); //True when VCELL goes below VALRTMIN (see setVALRTMin)
+ bool isVoltageReset(bool clear = false);
+ bool isLow(bool clear = false); //True when SOC crosses the value in ATHD (see setThreshold)
+ bool isChange(bool clear = false); //True when SOC changes by at least 1% and SOCAlert is enabled
+
+ // getAlert([clear]) - Check if the MAX1704X's ALRT alert interrupt has been
+ // triggered.
+ // INPUT: [clear] - If [clear] is true, the alert flag will be cleared if it
+ // was set.
+ // OUTPUT: Returns 1 if interrupt is/was triggered, 0 if not.
+ uint8_t getAlert(bool clear = false);
+
+ // clearAlert() - Clear the MAX1704X's ALRT alert flag.
+ // Output: 0 on success, positive integer on fail.
+ uint8_t clearAlert();
+
+ // enableSOCAlert() - (MAX17048/49) Enable the SOC change alert
+ // Returns true if the SOC change alert was enabled successfully
+ bool enableSOCAlert();
+
+ // disableSOCAlert() - (MAX17048/49) Disable the SOC change alert
+ // Returns true if the SOC change alert was disabled successfully
+ bool disableSOCAlert();
+
+ // Enable or Disable MAX17048/49 VRESET Alert:
+ // EnVr (enable voltage reset alert) when set to 1 asserts
+ // the ALRT pin when a voltage-reset event occurs under
+ // the conditions described by the VRESET/ ID register.
+ // enableAlert() - Set ENvR bit in STATUS register 0x1A
+ // Output: 0 on success, positive integer on fail.
+ uint8_t enableAlert();
+ // disableAlert() - Clear the ENvR bit in STATUS register 0x1A
+ // Output: 0 on success, positive integer on fail.
+ uint8_t disableAlert();
+
+ // Read and return the MAX17048/49 VALRT Maximum threshold
+ // LSb = 20mV
+ uint8_t getVALRTMax();
+
+ // Read and return the MAX17048/49 VALRT Minimum threshold
+ // LSb = 20mV
+ uint8_t getVALRTMin();
+
+ // Set the MAX17048/49 VALRT Maximum threshold
+ // Output: 0 on success, positive integer on fail.
+ // Note: this sets the threshold voltage _per cell_ (MAX17049 monitors two cells)
+ uint8_t setVALRTMax(uint8_t threshold = 0xFF); // LSb = 20mV
+ uint8_t setVALRTMax(float threshold = 5.1); // threshold is defined in Volts
+
+ // Set the MAX17048/49 VALRT Minimum threshold
+ // Output: 0 on success, positive integer on fail.
+ // Note: this sets the threshold voltage _per cell_ (MAX17049 monitors two cells)
+ uint8_t setVALRTMin(uint8_t threshold = 0x00); // LSb = 20mV
+ uint8_t setVALRTMin(float threshold = 0.0); // threshold is defined in Volts
+
+ // Read and return the MAX17048/49 Hibernate Status flag
+ bool isHibernating();
+
+ // Read and return the MAX17048/49 HIBRT Active Threshold
+ // LSb = 1.25mV
+ uint8_t getHIBRTActThr();
+
+ // Set the MAX17048/49 HIBRT Active Threshold
+ // Output: 0 on success, positive integer on fail.
+ uint8_t setHIBRTActThr(uint8_t threshold); // LSb = 1.25mV
+ uint8_t setHIBRTActThr(float threshold); // Helper function: set threshold in Volts
+
+ // Read and return the MAX17048/49 HIBRT Hibernate Threshold
+ // LSb = 0.208%/hr
+ uint8_t getHIBRTHibThr();
+
+ // Set the MAX17048/49 HIBRT Hibernate Threshold
+ // Output: 0 on success, positive integer on fail.
+ uint8_t setHIBRTHibThr(uint8_t threshold); // LSb = 0.208%/hr
+ uint8_t setHIBRTHibThr(float threshold); // Helper function: set threshold in percent
+
+ // Place the MAX17048/49 into hibernate
+ // Sets the HIBRT register to 0xFFFF
+ // Output: 0 on success, positive integer on fail.
+ uint8_t enableHibernate();
+
+ // Disable hibernate on the MAX17048/49
+ // Sets the HIBRT register to 0x0000
+ // Output: 0 on success, positive integer on fail.
+ uint8_t disableHibernate();
+
+ //Lower level functions but exposed incase user wants them
+
+ // write16([data], [address]) - Write 16 bits to the requested address. After
+ // writing the address to be written, two sequential 8-bit writes will occur.
+ // the msb is written first, then lsb.
+ // Input: [data] - A 16-bit integer to be written to the device.
+ // [address] - An 8-bit address to be written to.
+ // Output: 0 on success, positive integer on fail.
+ uint8_t write16(uint16_t data, uint8_t address);
+
+ // read16([address]) - Read 16-bits from the requested address of a device.
+ // Input: [address] - An 8-bit address to be read from.
+ // Output: A 16-bit value read from the device's address will be returned.
+ uint16_t read16(uint8_t address);
+
+private:
+ //Variables
+ TwoWire *_i2cPort; //The generic connection to user's chosen I2C hardware
+
+ #if MAX1704X_ENABLE_DEBUGLOG
+ Stream *_debugPort; //The stream to send debug messages to if enabled. Usually Serial.
+ bool _printDebug = false; //Flag to print debugging variables
+ #endif // if MAX1704X_ENABLE_DEBUGLOG
+
+ // Clear the specified bit(s) in the MAX17048/49 status register
+ // This requires the bits in mask to be correctly aligned.
+ // MAX1704x_STATUS_RI etc. will need to be shifted left by 8 bits to become aligned.
+ // Output: 0 on success, positive integer on fail.
+ uint8_t clearStatusRegBits(uint16_t mask);
+
+ int _device = MAX1704X_MAX17043; // Default to MAX17043
+ float _full_scale = 5.12; // Default: full-scale for the MAX17043
+};
+
+#endif