This class provides APIs to all of the registers of the TI BQ27441 battery gauge, as used on the u-blox C030 board. The caller should instantiate an I2C interface and pass this to init(), which will initialise the chip and place it into its lowest power state. When battery gauging is enabled, the getRemainingCapacity()/getRemainingPercentage() API calls may be used; otherwise the chip will be maintained in its lowest power state until a voltage/current/temperature reading is requested.

Dependents:   example-battery-gauge-bq27441

Files at this revision

API Documentation at this revision

Comitter:
rob.meades@u-blox.com
Date:
Wed Jun 14 17:11:40 2017 +0100
Parent:
4:e6208506ebc7
Child:
6:998cc334f8f2
Commit message:
Add ability to enable/disable battery detection and make sure that it is switched off when the tests are run on the u-blox C030 platform (since the BIN pin is not connected).

Changed in this revision

TESTS/unit_tests/default/main.cpp Show annotated file Show diff for this revision Revisions of this file
battery_gauge_bq27441.h Show annotated file Show diff for this revision Revisions of this file
bq27441.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/TESTS/unit_tests/default/main.cpp	Wed Jun 07 10:32:54 2017 +0000
+++ b/TESTS/unit_tests/default/main.cpp	Wed Jun 14 17:11:40 2017 +0100
@@ -80,6 +80,11 @@
     TEST_ASSERT_FALSE(pBatteryGauge->enableGauge());
     
     TEST_ASSERT(pBatteryGauge->init(gpI2C));
+#ifdef TARGET_UBLOX_C030
+    // Battery detection is not supported on C030
+    TEST_ASSERT(pBatteryGauge->disableBatteryDetect());
+#endif
+
     // Normal case
     TEST_ASSERT(pBatteryGauge->enableGauge());
     TEST_ASSERT(pBatteryGauge->isGaugeEnabled());
@@ -106,6 +111,10 @@
     
     // Normal case
     TEST_ASSERT(pBatteryGauge->init(gpI2C));
+#ifdef TARGET_UBLOX_C030
+    // Battery detection is not supported on C030
+    TEST_ASSERT(pBatteryGauge->disableBatteryDetect());
+#endif
     TEST_ASSERT(pBatteryGauge->isBatteryDetected());
 }
 
@@ -120,7 +129,7 @@
     // Normal case
     TEST_ASSERT(pBatteryGauge->init(gpI2C));
     TEST_ASSERT(pBatteryGauge->getTemperature(&temperatureC));
-    printf ("Temperature %d C.\n", temperatureC);
+    printf ("Temperature %d C.\n", (int) temperatureC);
     // Range check
     TEST_ASSERT((temperatureC >= MIN_TEMPERATURE_READING_C) && (temperatureC <= MAX_TEMPERATURE_READING_C));
     
@@ -195,8 +204,13 @@
     
     // Normal case
     TEST_ASSERT(pBatteryGauge->init(gpI2C));
+#ifdef TARGET_UBLOX_C030
+    // Battery detection is not supported on C030
+    // and battery detect is required for the "gauging" type APIs
+    TEST_ASSERT(pBatteryGauge->disableBatteryDetect());
+#endif
     TEST_ASSERT(pBatteryGauge->getRemainingPercentage(&batteryPercent));
-    printf ("Remaining percentage %d%%.\n", batteryPercent);
+    printf ("Remaining percentage %d%%.\n", (int) batteryPercent);
     // Range check
     TEST_ASSERT((batteryPercent >= 0) && (batteryPercent <= 100));
 
@@ -222,7 +236,7 @@
     subClassId = 80;
     memset(&(data1[0]), 0, sizeof (data1));
     TEST_ASSERT(pBatteryGauge->advancedGetConfig(subClassId, offset, length, &(data1[0])));
-    printf("%d bytes received from subClassID %d, offset %d:\n", length, subClassId, offset);
+    printf("%d bytes received from subClassID %d, offset %d:\n", (int) length, subClassId, (int) offset);
     printBytesAsHex(&(data1[0]), length);
     TEST_ASSERT_EQUAL_UINT32 (0xdeadbeef, deadArea1);
     
@@ -231,7 +245,7 @@
     length = MAX_CONFIG_BLOCK_SIZE - 16;
     memset(&(data2[0]), 0, sizeof (data2));
     TEST_ASSERT(pBatteryGauge->advancedGetConfig(subClassId, offset, length, &(data2[0])));
-    printf("%d bytes received from subClassID %d, offset %d:\n", length, subClassId, offset);
+    printf("%d bytes received from subClassID %d, offset %d:\n", (int) length, subClassId, (int) offset);
     printBytesAsHex(&(data2[0]), length);
     // The second 16 bytes of data1 and the first 16 bytes of data2 should match
     TEST_ASSERT_EQUAL_UINT8_ARRAY(&(data1[16]), &(data2[0]), 16);
@@ -242,7 +256,7 @@
     length = MAX_CONFIG_BLOCK_SIZE;
     memset(&(data1[0]), 0, sizeof (data1));
     TEST_ASSERT(pBatteryGauge->advancedGetConfig(subClassId, offset, length, &(data1[0])));
-    printf("%d bytes received from subClassID %d, offset %d:\n", length, subClassId, offset);
+    printf("%d bytes received from subClassID %d, offset %d:\n", (int) length, subClassId, (int) offset);
     printBytesAsHex(&(data1[0]), length);
     TEST_ASSERT_EQUAL_UINT32 (0xdeadbeef, deadArea1);
 
@@ -250,7 +264,7 @@
     length = 16;
     memset(&(data2[0]), 0, sizeof (data2));
     TEST_ASSERT(pBatteryGauge->advancedGetConfig(subClassId, offset, length, &(data2[0])));
-    printf("%d bytes received from subClassID %d, offset %d:\n", length, subClassId, offset);
+    printf("%d bytes received from subClassID %d, offset %d:\n", (int) length, subClassId, (int) offset);
     printBytesAsHex(&(data2[0]), length);
     // The first 16 bytes of data1 and data2 should match
     TEST_ASSERT_EQUAL_UINT8_ARRAY(&(data1[0]), &(data2[0]), length);
@@ -278,7 +292,7 @@
     length = 2;
     memset(&(data1[0]), 0, sizeof (data1));
     TEST_ASSERT(pBatteryGauge->advancedGetConfig(subClassId, offset, length, &(data1[0])));
-    printf("%d bytes received from subClassID %d, offset %d:\n", length, subClassId, offset);
+    printf("%d bytes received from subClassID %d, offset %d:\n", (int) length, subClassId, (int) offset);
     printBytesAsHex(&(data1[0]), length);
     TEST_ASSERT_EQUAL_UINT32 (0xdeadbeef, deadArea1);
     
@@ -287,7 +301,7 @@
     printf ("Modified data block:\n");
     printBytesAsHex(&(data1[0]), length);
     TEST_ASSERT(pBatteryGauge->advancedSetConfig(subClassId, offset, length, &(data1[0])));
-    printf("%d bytes written to subClassID %d, offset %d:\n", length, subClassId, offset);
+    printf("%d bytes written to subClassID %d, offset %d:\n", (int) length, subClassId, (int) offset);
 
     // Read it back and check that the Delta Voltage really is the new value
     subClassId = 82;
@@ -295,7 +309,7 @@
     length = 9;
     memset(&(data2[0]), 0, sizeof (data2));
     TEST_ASSERT(pBatteryGauge->advancedGetConfig(subClassId, offset, length, &(data2[0])));
-    printf("%d bytes received from subClassID %d, offset %d:\n", length, subClassId, offset);
+    printf("%d bytes received from subClassID %d, offset %d:\n", (int) length, subClassId, (int) offset);
     printBytesAsHex(&(data2[0]), length);
     TEST_ASSERT_EQUAL_UINT32 (0xdeadbeef, deadArea1);
     TEST_ASSERT_EQUAL_UINT32 (data1[0], data2[7]);
@@ -304,7 +318,7 @@
     // Now put Delta Voltage back as it was
     (data2[8])--;
     TEST_ASSERT(pBatteryGauge->advancedSetConfig(subClassId, offset, length, &(data2[0])));
-    printf("%d bytes written to subClassID %d, offset %d:\n", length, subClassId, offset);
+    printf("%d bytes written to subClassID %d, offset %d:\n", (int) length, subClassId, (int) offset);
 }
 
 // Test fail cases of the advanced configuration functions
@@ -405,6 +419,10 @@
 
     // Make sure that the device is not sealed from a previous field test run
     TEST_ASSERT(pBatteryGauge->init(gpI2C));
+#ifdef TARGET_UBLOX_C030
+    // Battery detection is not supported on C030
+    TEST_ASSERT(pBatteryGauge->disableBatteryDetect());
+#endif
     TEST_ASSERT(pBatteryGauge->advancedUnseal());
 
     delete pBatteryGauge;
--- a/battery_gauge_bq27441.h	Wed Jun 07 10:32:54 2017 +0000
+++ b/battery_gauge_bq27441.h	Wed Jun 14 17:11:40 2017 +0100
@@ -74,7 +74,22 @@
     */
     bool isGaugeEnabled(void);
     
+    /** Enable the battery detect pin of the chip.
+    * Default is enabled.
+    * @return true if successful, otherwise false.
+    */
+    bool enableBatteryDetect ();
+
+    /** Disable the battery detect pin of the chip and
+    * assume that the battery is ALWAYS connected.
+    * Default is that battery detect is enabled.
+    * @return true if successful, otherwise false.
+    */
+    bool disableBatteryDetect (void);
+
     /** Determine whether a battery has been detected or not.
+    * If battery detection is disabled, this function will always
+    * return true.
     * @return true if a battery has been detected, otherwise false.
     */
     bool isBatteryDetected (void);
--- a/bq27441.cpp	Wed Jun 07 10:32:54 2017 +0000
+++ b/bq27441.cpp	Wed Jun 14 17:11:40 2017 +0100
@@ -137,7 +137,7 @@
         if (offset / 32 == (offset + length - 1) / 32) {
         
 #ifdef DEBUG_BQ27441
-            printf("BatteryGaugeBq27441 (I2C 0x%02x): preparing to read %d byte(s) from offset %d of sub-class %d.\n", gAddress >> 1, length, offset, subClassId);
+            printf("BatteryGaugeBq27441 (I2C 0x%02x): preparing to read %d byte(s) from offset %d of sub-class %d.\n", gAddress >> 1, (int) length, (int) offset, subClassId);
 #endif
             // Handle unsealing
             wasSealed = isSealed();
@@ -182,7 +182,7 @@
 #endif
                                     } else {
 #ifdef DEBUG_BQ27441
-                                        printf("BatteryGaugeBq27441 (I2C 0x%02x): couldn't read all %d bytes of config.\r", gAddress >> 1, length);
+                                        printf("BatteryGaugeBq27441 (I2C 0x%02x): couldn't read all %d bytes of config.\r", gAddress >> 1, (int) length);
 #endif
                                     }
                                 } else {
@@ -217,7 +217,7 @@
             }
         } else {
 #ifdef DEBUG_BQ27441
-            printf("BatteryGaugeBq27441 (I2C 0x%02x): offset (%d) is in different 32 byte block to offset + length (%d) [length is %d].\n", gAddress >> 1, offset, offset + length, length);
+            printf("BatteryGaugeBq27441 (I2C 0x%02x): offset (%d) is in different 32 byte block to offset + length (%d) [length is %d].\n", gAddress >> 1, (int) offset, (int) (offset + length), (int) length);
 #endif
         }
     }
@@ -250,7 +250,7 @@
         // The offset + length combination must not cross a 32-byte boundary
         if (offset / 32 == (offset + length - 1) / 32) {        
 #ifdef DEBUG_BQ27441
-            printf("BatteryGaugeBq27441 (I2C 0x%02x): preparing to write %d byte(s) to offset %d of sub-class %d.\n", gAddress >> 1, length, offset, subClassId);
+            printf("BatteryGaugeBq27441 (I2C 0x%02x): preparing to write %d byte(s) to offset %d of sub-class %d.\n", gAddress >> 1, (int) length, (int) offset, subClassId);
 #endif
             // Handle unsealing
             wasSealed = isSealed();
@@ -361,7 +361,7 @@
                                                 }
                                             } else {
 #ifdef DEBUG_BQ27441
-                                                printf("BatteryGaugeBq27441 (I2C 0x%02x): couldn't write all %d bytes during config update.\n", gAddress >> 1, length);
+                                                printf("BatteryGaugeBq27441 (I2C 0x%02x): couldn't write all %d bytes during config update.\n", gAddress >> 1, (int) length);
 #endif
                                             }
                                         } else {
@@ -406,7 +406,7 @@
             }
         } else {
 #ifdef DEBUG_BQ27441
-            printf("BatteryGaugeBq27441 (I2C 0x%02x): offset (%d) is in different 32 byte block to offset + length (%d) [length is %d].\n", gAddress >> 1, offset, offset + length, length);
+            printf("BatteryGaugeBq27441 (I2C 0x%02x): offset (%d) is in different 32 byte block to offset + length (%d) [length is %d].\n", gAddress >> 1, (int) offset, (int) (offset + length), (int) length);
 #endif
         }
     }
@@ -736,6 +736,96 @@
     return gGaugeOn;
 }
 
+// Disable the battery detect pin.
+bool BatteryGaugeBq27441::disableBatteryDetect (void)
+{
+    bool success = false;
+    char data[3];
+    
+    if (gReady && (gpI2c != NULL)) {
+        gpI2c->lock();
+        // Read the OpConfig register which is in the Registers sub-class
+        // (64) at offset 0.
+        if (readExtendedData(64, 0, 2, &(data[0]))) {
+#ifdef DEBUG_BQ27441
+            printf("BatteryGaugeBq27441 (I2C 0x%02x): OpConfig is 0x%02x%02x.\r\n", gAddress >> 1, data[0], data[1]);
+#endif                        
+            // Battery Insertion Enabled is bit 5 of the high byte of OpConfig.
+            // 1 means that the battery input pin is enabled
+            if (((data[0] & (1 << 5)) != 0)) {
+                // Clear the BIE bit 'cos it's set and is shouldn't be
+                data[0] &= ~(1 << 5);
+                // Write the new value back
+                if (writeExtendedData(64, 0, 2, &(data[0]))) {
+                    // Send the Battery Inserted message as we can't do gauging otherwise
+                    data[0] = 0x00;  // Set address to first register for control
+                    data[1] = 0x0C;  // First byte of BAT_INSERT sub-command (0x0C)
+                    data[2] = 0x00;  // Second byte of BAT_INSERT sub-command (0x00)
+                    success = gpI2c->write(gAddress, &(data[0]), 3) == 0;
+#ifdef DEBUG_BQ27441
+                    if (success) {
+                        printf("BatteryGaugeBq27441 (I2C 0x%02x): BIE disabled, BAT_INSERT sent, OpConfig becomes 0x%02x%02x.\r\n", gAddress >> 1, data[0], data[1]);
+                    }
+#endif
+                }
+            } else {
+                success = true;
+            }
+        }
+        
+        // Set hibernate again if we are not monitoring
+        if (!gGaugeOn) {
+            setHibernate();
+        }
+
+        gpI2c->unlock();
+    }
+    
+    return success;
+}
+
+// Enable the battery detect pin.
+bool BatteryGaugeBq27441::enableBatteryDetect (void)
+{
+    bool success = false;
+    char data[3];
+    
+    if (gReady && (gpI2c != NULL)) {
+        gpI2c->lock();
+        // Read the OpConfig register which is in the Registers sub-class
+        // (64) at offset 0.
+        if (readExtendedData(64, 0, 2, &(data[0]))) {
+#ifdef DEBUG_BQ27441
+            printf("BatteryGaugeBq27441 (I2C 0x%02x): OpConfig is 0x%02x%02x.\r\n", gAddress >> 1, data[0], data[1]);
+#endif                        
+            // Battery Insertion Enabled is bit 5 of the high byte of OpConfig.
+            // 1 means that the battery input pin is enabled
+            if (((data[0] & (1 << 5)) == 0)) {
+                // Set the BIE bit 'cos it's not set and needs to be
+                data[0] |= 1 << 5;
+                // Write the new value back
+                success = writeExtendedData(64, 0, 2, &(data[0]));
+#ifdef DEBUG_BQ27441
+                if (success) {
+                    printf("BatteryGaugeBq27441 (I2C 0x%02x): BIE enabled, OpConfig becomes 0x%02x%02x.\r\n", gAddress >> 1, data[0], data[1]);
+                }
+#endif                        
+            } else {
+                success = true;
+            }
+        }
+        
+        // Set hibernate again if we are not monitoring
+        if (!gGaugeOn) {
+            setHibernate();
+        }
+
+        gpI2c->unlock();
+    }
+    
+    return success;
+}
+
 // Check whether a battery has been detected or not.
 bool BatteryGaugeBq27441::isBatteryDetected (void)
 {
@@ -799,7 +889,7 @@
                 }
 
 #ifdef DEBUG_BQ27441
-                printf("BatteryGaugeBq27441 (I2C 0x%02x): chip temperature %.1f K, so %d C.\n", gAddress >> 1, ((float) data) / 10, temperatureC);
+                printf("BatteryGaugeBq27441 (I2C 0x%02x): chip temperature %.1f K, so %d C.\n", gAddress >> 1, ((float) data) / 10, (int) temperatureC);
 #endif
             }
         
@@ -871,7 +961,7 @@
                 }
 
 #ifdef DEBUG_BQ27441
-                printf("BatteryGaugeBq27441 (I2C 0x%02x): current %d mA.\n", gAddress >> 1, currentMA);
+                printf("BatteryGaugeBq27441 (I2C 0x%02x): current %d mA.\n", gAddress >> 1, (int) currentMA);
 #endif
             }
 
@@ -976,7 +1066,7 @@
         success = readExtendedData(subClassId, offset, length, pData);
 #ifdef DEBUG_BQ27441
         if (success) {
-            printf("BatteryGaugeBq27441 (I2C 0x%02x): read extended data with subClassId %d from offset %d.\n", gAddress >> 1, subClassId, offset);
+            printf("BatteryGaugeBq27441 (I2C 0x%02x): read extended data with subClassId %d from offset %d.\n", gAddress >> 1, subClassId, (int) offset);
         }
 #endif
 
@@ -1002,7 +1092,7 @@
         success = writeExtendedData(subClassId, offset, length, pData);
 #ifdef DEBUG_BQ27441
         if (success) {
-            printf("BatteryGaugeBq27441 (I2C 0x%02x): written %d byte(s) of extended data with subClassId %d from offset %d.\n", gAddress >> 1, length, subClassId, offset);
+            printf("BatteryGaugeBq27441 (I2C 0x%02x): written %d byte(s) of extended data with subClassId %d from offset %d.\n", gAddress >> 1, (int) length, subClassId, (int) offset);
         }
 #endif