This class provides APIs to all of the registers of the TI BQ35100 battery gauge, as used on the u-blox C030 primary battery shield.

Dependents:   example-battery-gauge-bq35100

Committer:
RobMeades
Date:
Fri Nov 10 17:07:06 2017 +0000
Revision:
2:4c699a813451
Parent:
1:ee7cc8d75283
Functionality at equivalent level to the BQ27411 battery driver.  Good enough for now.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
RobMeades 0:cec745c014b7 1 #include "mbed.h"
RobMeades 0:cec745c014b7 2 #include "greentea-client/test_env.h"
RobMeades 0:cec745c014b7 3 #include "unity.h"
RobMeades 0:cec745c014b7 4 #include "utest.h"
RobMeades 0:cec745c014b7 5 #include "battery_gauge_bq35100.h"
RobMeades 0:cec745c014b7 6
RobMeades 0:cec745c014b7 7 using namespace utest::v1;
RobMeades 0:cec745c014b7 8
RobMeades 0:cec745c014b7 9 // ----------------------------------------------------------------
RobMeades 0:cec745c014b7 10 // COMPILE-TIME MACROS
RobMeades 0:cec745c014b7 11 // ----------------------------------------------------------------
RobMeades 0:cec745c014b7 12
RobMeades 1:ee7cc8d75283 13 // The gauge enable pin
RobMeades 1:ee7cc8d75283 14 #define GAUGE_ENABLE_PIN D4
RobMeades 1:ee7cc8d75283 15
RobMeades 1:ee7cc8d75283 16 // Pick some sensible minimum and maximum numbers
RobMeades 1:ee7cc8d75283 17 #define MAX_TEMPERATURE_READING_C 80
RobMeades 1:ee7cc8d75283 18 #define MIN_TEMPERATURE_READING_C -20
RobMeades 1:ee7cc8d75283 19 #define MIN_VOLTAGE_READING_MV 0
RobMeades 1:ee7cc8d75283 20 #define MAX_VOLTAGE_READING_MV 12000
RobMeades 1:ee7cc8d75283 21 #define MAX_CURRENT_READING_MA 2000
RobMeades 1:ee7cc8d75283 22 #define MIN_CURRENT_READING_MA -2000
RobMeades 1:ee7cc8d75283 23 #define MIN_CAPACITY_READING_UAH 0
RobMeades 2:4c699a813451 24 #define MAX_CAPACITY_READING_UAH 32177000 // Some randomly chosen
RobMeades 2:4c699a813451 25 #define SET_DESIGN_CAPACITY_MAH 32177 // values that match
RobMeades 2:4c699a813451 26
RobMeades 1:ee7cc8d75283 27
RobMeades 0:cec745c014b7 28 // ----------------------------------------------------------------
RobMeades 0:cec745c014b7 29 // PRIVATE VARIABLES
RobMeades 0:cec745c014b7 30 // ----------------------------------------------------------------
RobMeades 0:cec745c014b7 31
RobMeades 0:cec745c014b7 32 // I2C interface
RobMeades 0:cec745c014b7 33 I2C * gpI2C = new I2C(I2C_SDA, I2C_SCL);
RobMeades 0:cec745c014b7 34
RobMeades 0:cec745c014b7 35 // ----------------------------------------------------------------
RobMeades 0:cec745c014b7 36 // PRIVATE FUNCTIONS
RobMeades 0:cec745c014b7 37 // ----------------------------------------------------------------
RobMeades 0:cec745c014b7 38
RobMeades 0:cec745c014b7 39 // ----------------------------------------------------------------
RobMeades 0:cec745c014b7 40 // TESTS
RobMeades 0:cec745c014b7 41 // ----------------------------------------------------------------
RobMeades 0:cec745c014b7 42
RobMeades 0:cec745c014b7 43 // Test that the BQ35100 battery gauge can be initialised
RobMeades 0:cec745c014b7 44 void test_init() {
RobMeades 0:cec745c014b7 45 BatteryGaugeBq35100 * pBatteryGauge = new BatteryGaugeBq35100();
RobMeades 0:cec745c014b7 46
RobMeades 1:ee7cc8d75283 47 TEST_ASSERT_FALSE(pBatteryGauge->init(NULL, GAUGE_ENABLE_PIN));
RobMeades 1:ee7cc8d75283 48 TEST_ASSERT(pBatteryGauge->init(gpI2C, GAUGE_ENABLE_PIN));
RobMeades 1:ee7cc8d75283 49 }
RobMeades 1:ee7cc8d75283 50
RobMeades 1:ee7cc8d75283 51 // Test that a temperature reading can be performed
RobMeades 1:ee7cc8d75283 52 void test_temperature() {
RobMeades 1:ee7cc8d75283 53 BatteryGaugeBq35100 * pBatteryGauge = new BatteryGaugeBq35100();
RobMeades 1:ee7cc8d75283 54 int32_t temperatureC = MIN_TEMPERATURE_READING_C - 1;
RobMeades 1:ee7cc8d75283 55
RobMeades 1:ee7cc8d75283 56 // Call should fail if the battery gauge has not been initialised
RobMeades 1:ee7cc8d75283 57 TEST_ASSERT_FALSE(pBatteryGauge->getTemperature(&temperatureC));
RobMeades 1:ee7cc8d75283 58
RobMeades 1:ee7cc8d75283 59 // Normal case
RobMeades 1:ee7cc8d75283 60 TEST_ASSERT(pBatteryGauge->init(gpI2C, GAUGE_ENABLE_PIN));
RobMeades 1:ee7cc8d75283 61 TEST_ASSERT(pBatteryGauge->getTemperature(&temperatureC));
RobMeades 1:ee7cc8d75283 62 printf ("Temperature %d C.\n", (int) temperatureC);
RobMeades 1:ee7cc8d75283 63 // Range check
RobMeades 1:ee7cc8d75283 64 TEST_ASSERT((temperatureC >= MIN_TEMPERATURE_READING_C) && (temperatureC <= MAX_TEMPERATURE_READING_C));
RobMeades 1:ee7cc8d75283 65
RobMeades 1:ee7cc8d75283 66 // The parameter is allowed to be NULL
RobMeades 1:ee7cc8d75283 67 TEST_ASSERT(pBatteryGauge->getTemperature(NULL));
RobMeades 1:ee7cc8d75283 68 }
RobMeades 1:ee7cc8d75283 69
RobMeades 1:ee7cc8d75283 70 // Test that a voltage reading can be performed
RobMeades 1:ee7cc8d75283 71 void test_voltage() {
RobMeades 1:ee7cc8d75283 72 BatteryGaugeBq35100 * pBatteryGauge = new BatteryGaugeBq35100();
RobMeades 1:ee7cc8d75283 73 int32_t voltageMV = MIN_VOLTAGE_READING_MV - 1;
RobMeades 1:ee7cc8d75283 74
RobMeades 1:ee7cc8d75283 75 // Call should fail if the battery gauge has not been initialised
RobMeades 1:ee7cc8d75283 76 TEST_ASSERT_FALSE(pBatteryGauge->getVoltage(&voltageMV));
RobMeades 1:ee7cc8d75283 77
RobMeades 1:ee7cc8d75283 78 // Normal case
RobMeades 1:ee7cc8d75283 79 TEST_ASSERT(pBatteryGauge->init(gpI2C, GAUGE_ENABLE_PIN));
RobMeades 1:ee7cc8d75283 80 TEST_ASSERT(pBatteryGauge->getVoltage(&voltageMV));
RobMeades 1:ee7cc8d75283 81 printf ("Voltage %.3f V.\n", ((float) voltageMV) / 1000);
RobMeades 1:ee7cc8d75283 82 // Range check
RobMeades 1:ee7cc8d75283 83 TEST_ASSERT((voltageMV >= MIN_VOLTAGE_READING_MV) && (voltageMV <= MAX_VOLTAGE_READING_MV));
RobMeades 1:ee7cc8d75283 84
RobMeades 1:ee7cc8d75283 85 // The parameter is allowed to be NULL
RobMeades 1:ee7cc8d75283 86 TEST_ASSERT(pBatteryGauge->getVoltage(NULL));
RobMeades 1:ee7cc8d75283 87 }
RobMeades 1:ee7cc8d75283 88
RobMeades 1:ee7cc8d75283 89 // Test that a current reading can be performed
RobMeades 1:ee7cc8d75283 90 void test_current() {
RobMeades 1:ee7cc8d75283 91 BatteryGaugeBq35100 * pBatteryGauge = new BatteryGaugeBq35100();
RobMeades 1:ee7cc8d75283 92 int32_t currentMA = MIN_CURRENT_READING_MA - 1;
RobMeades 1:ee7cc8d75283 93
RobMeades 1:ee7cc8d75283 94 // Call should fail if the battery gauge has not been initialised
RobMeades 1:ee7cc8d75283 95 TEST_ASSERT_FALSE(pBatteryGauge->getCurrent(&currentMA));
RobMeades 1:ee7cc8d75283 96
RobMeades 1:ee7cc8d75283 97 // Normal case
RobMeades 1:ee7cc8d75283 98 TEST_ASSERT(pBatteryGauge->init(gpI2C, GAUGE_ENABLE_PIN));
RobMeades 1:ee7cc8d75283 99 TEST_ASSERT(pBatteryGauge->getCurrent(&currentMA));
RobMeades 1:ee7cc8d75283 100 printf ("Current %.3f A.\n", ((float) currentMA) / 1000);
RobMeades 1:ee7cc8d75283 101 // Range check
RobMeades 1:ee7cc8d75283 102 TEST_ASSERT((currentMA >= MIN_CURRENT_READING_MA) && (currentMA <= MAX_CURRENT_READING_MA));
RobMeades 1:ee7cc8d75283 103
RobMeades 1:ee7cc8d75283 104 // The parameter is allowed to be NULL
RobMeades 1:ee7cc8d75283 105 TEST_ASSERT(pBatteryGauge->getCurrent(NULL));
RobMeades 1:ee7cc8d75283 106 }
RobMeades 1:ee7cc8d75283 107
RobMeades 1:ee7cc8d75283 108 // Test that a capacity used reading can be performed
RobMeades 1:ee7cc8d75283 109 void test_used_capacity() {
RobMeades 1:ee7cc8d75283 110 BatteryGaugeBq35100 * pBatteryGauge = new BatteryGaugeBq35100();
RobMeades 1:ee7cc8d75283 111 uint32_t capacityUAh = MIN_CAPACITY_READING_UAH - 1;
RobMeades 1:ee7cc8d75283 112
RobMeades 1:ee7cc8d75283 113 // Call should fail if the battery gauge has not been initialised
RobMeades 1:ee7cc8d75283 114 TEST_ASSERT_FALSE(pBatteryGauge->getUsedCapacity(&capacityUAh));
RobMeades 1:ee7cc8d75283 115
RobMeades 1:ee7cc8d75283 116 // Normal case
RobMeades 1:ee7cc8d75283 117 TEST_ASSERT(pBatteryGauge->init(gpI2C, GAUGE_ENABLE_PIN));
RobMeades 1:ee7cc8d75283 118 TEST_ASSERT(pBatteryGauge->getUsedCapacity(&capacityUAh));
RobMeades 1:ee7cc8d75283 119 printf ("Used capacity %.3f mAh.\n", ((float) capacityUAh) / 1000);
RobMeades 1:ee7cc8d75283 120 // Range check
RobMeades 1:ee7cc8d75283 121 TEST_ASSERT((capacityUAh >= MIN_CAPACITY_READING_UAH) && (capacityUAh <= MAX_CAPACITY_READING_UAH));
RobMeades 1:ee7cc8d75283 122
RobMeades 1:ee7cc8d75283 123 // The parameter is allowed to be NULL
RobMeades 1:ee7cc8d75283 124 TEST_ASSERT(pBatteryGauge->getUsedCapacity(NULL));
RobMeades 1:ee7cc8d75283 125 }
RobMeades 1:ee7cc8d75283 126
RobMeades 1:ee7cc8d75283 127 // Test that the design capacity can be set and read
RobMeades 1:ee7cc8d75283 128 void test_design_capacity() {
RobMeades 1:ee7cc8d75283 129 BatteryGaugeBq35100 * pBatteryGauge = new BatteryGaugeBq35100();
RobMeades 1:ee7cc8d75283 130 uint32_t originalDesignCapacity;
RobMeades 1:ee7cc8d75283 131 uint32_t newDesignCapacity = SET_DESIGN_CAPACITY_MAH;
RobMeades 1:ee7cc8d75283 132 uint32_t readDesignCapacity = 0;
RobMeades 1:ee7cc8d75283 133
RobMeades 1:ee7cc8d75283 134 // Calls should fail if the battery gauge has not been initialised
RobMeades 1:ee7cc8d75283 135 TEST_ASSERT_FALSE(pBatteryGauge->getDesignCapacity(&readDesignCapacity));
RobMeades 1:ee7cc8d75283 136 TEST_ASSERT_FALSE(pBatteryGauge->setDesignCapacity(newDesignCapacity));
RobMeades 1:ee7cc8d75283 137
RobMeades 1:ee7cc8d75283 138 // First get the original design capacity
RobMeades 1:ee7cc8d75283 139 TEST_ASSERT(pBatteryGauge->init(gpI2C, GAUGE_ENABLE_PIN));
RobMeades 1:ee7cc8d75283 140 TEST_ASSERT(pBatteryGauge->getDesignCapacity(&originalDesignCapacity));
RobMeades 1:ee7cc8d75283 141 printf ("Design capacity was originally %d mAh.\n", (unsigned int) originalDesignCapacity);
RobMeades 1:ee7cc8d75283 142
RobMeades 1:ee7cc8d75283 143 // Avoid the old and new values being the same
RobMeades 1:ee7cc8d75283 144 if (originalDesignCapacity == newDesignCapacity) {
RobMeades 1:ee7cc8d75283 145 newDesignCapacity--;
RobMeades 1:ee7cc8d75283 146 }
RobMeades 1:ee7cc8d75283 147
RobMeades 1:ee7cc8d75283 148 // Now set a new value
RobMeades 1:ee7cc8d75283 149 TEST_ASSERT(pBatteryGauge->setDesignCapacity(newDesignCapacity));
RobMeades 1:ee7cc8d75283 150 printf ("Design capacity set to %d mAh.\n", (unsigned int) newDesignCapacity);
RobMeades 1:ee7cc8d75283 151
RobMeades 1:ee7cc8d75283 152 // Read the value back and check that it's been set
RobMeades 1:ee7cc8d75283 153 TEST_ASSERT(pBatteryGauge->getDesignCapacity(&readDesignCapacity));
RobMeades 1:ee7cc8d75283 154 printf ("Design capacity was read as %d mAh.\n", (unsigned int) readDesignCapacity);
RobMeades 1:ee7cc8d75283 155 TEST_ASSERT(readDesignCapacity = newDesignCapacity)
RobMeades 1:ee7cc8d75283 156
RobMeades 1:ee7cc8d75283 157 // The parameter in the get call is allowed to be NULL
RobMeades 1:ee7cc8d75283 158 TEST_ASSERT(pBatteryGauge->getDesignCapacity(NULL));
RobMeades 1:ee7cc8d75283 159
RobMeades 1:ee7cc8d75283 160 // Put the original value back
RobMeades 1:ee7cc8d75283 161 TEST_ASSERT(pBatteryGauge->setDesignCapacity(originalDesignCapacity));
RobMeades 1:ee7cc8d75283 162 printf ("Design capacity returned to %d mAh.\n", (unsigned int) originalDesignCapacity);
RobMeades 1:ee7cc8d75283 163 }
RobMeades 1:ee7cc8d75283 164
RobMeades 1:ee7cc8d75283 165 // Test that a remaining capacity reading can be performed
RobMeades 1:ee7cc8d75283 166 void test_remaining_capacity() {
RobMeades 1:ee7cc8d75283 167 BatteryGaugeBq35100 * pBatteryGauge = new BatteryGaugeBq35100();
RobMeades 1:ee7cc8d75283 168 uint32_t capacityUAh = MIN_CAPACITY_READING_UAH - 1;
RobMeades 1:ee7cc8d75283 169
RobMeades 1:ee7cc8d75283 170 // Call should fail if the battery gauge has not been initialised
RobMeades 1:ee7cc8d75283 171 TEST_ASSERT_FALSE(pBatteryGauge->getRemainingCapacity(&capacityUAh));
RobMeades 1:ee7cc8d75283 172
RobMeades 1:ee7cc8d75283 173 // Normal case
RobMeades 1:ee7cc8d75283 174 TEST_ASSERT(pBatteryGauge->init(gpI2C, GAUGE_ENABLE_PIN));
RobMeades 1:ee7cc8d75283 175 TEST_ASSERT(pBatteryGauge->getRemainingCapacity(&capacityUAh));
RobMeades 1:ee7cc8d75283 176 printf ("Remaining capacity %.3f mAh.\n", ((float) capacityUAh) / 1000);
RobMeades 1:ee7cc8d75283 177 // Range check
RobMeades 1:ee7cc8d75283 178 TEST_ASSERT((capacityUAh >= MIN_CAPACITY_READING_UAH) && (capacityUAh <= MAX_CAPACITY_READING_UAH));
RobMeades 1:ee7cc8d75283 179
RobMeades 1:ee7cc8d75283 180 // The parameter is allowed to be NULL
RobMeades 1:ee7cc8d75283 181 TEST_ASSERT(pBatteryGauge->getRemainingCapacity(NULL));
RobMeades 1:ee7cc8d75283 182 }
RobMeades 1:ee7cc8d75283 183
RobMeades 1:ee7cc8d75283 184 // Test that a remaining precentage reading can be performed
RobMeades 1:ee7cc8d75283 185 void test_remaining_percentage() {
RobMeades 1:ee7cc8d75283 186 BatteryGaugeBq35100 * pBatteryGauge = new BatteryGaugeBq35100();
RobMeades 1:ee7cc8d75283 187 int32_t percentage = -1;
RobMeades 1:ee7cc8d75283 188
RobMeades 1:ee7cc8d75283 189 // Call should fail if the battery gauge has not been initialised
RobMeades 1:ee7cc8d75283 190 TEST_ASSERT_FALSE(pBatteryGauge->getRemainingPercentage(&percentage));
RobMeades 1:ee7cc8d75283 191
RobMeades 1:ee7cc8d75283 192 // Normal case
RobMeades 1:ee7cc8d75283 193 TEST_ASSERT(pBatteryGauge->init(gpI2C, GAUGE_ENABLE_PIN));
RobMeades 1:ee7cc8d75283 194 TEST_ASSERT(pBatteryGauge->getRemainingPercentage(&percentage));
RobMeades 1:ee7cc8d75283 195 printf ("Remaining capacity %d%%.\n", (signed int) percentage);
RobMeades 1:ee7cc8d75283 196 // Range check
RobMeades 1:ee7cc8d75283 197 TEST_ASSERT((percentage >= 0) && (percentage <= 100));
RobMeades 1:ee7cc8d75283 198
RobMeades 1:ee7cc8d75283 199 // The parameter is allowed to be NULL
RobMeades 1:ee7cc8d75283 200 TEST_ASSERT(pBatteryGauge->getRemainingPercentage(NULL));
RobMeades 1:ee7cc8d75283 201 }
RobMeades 1:ee7cc8d75283 202
RobMeades 2:4c699a813451 203 // Test behaviours with gauging on
RobMeades 2:4c699a813451 204 void test_gauging() {
RobMeades 2:4c699a813451 205 BatteryGaugeBq35100 * pBatteryGauge = new BatteryGaugeBq35100();
RobMeades 2:4c699a813451 206 uint32_t capacityUAh = MIN_CAPACITY_READING_UAH - 1;
RobMeades 2:4c699a813451 207
RobMeades 2:4c699a813451 208 // Call should fail if the battery gauge has not been initialised
RobMeades 2:4c699a813451 209 TEST_ASSERT_FALSE(pBatteryGauge->enableGauge());
RobMeades 2:4c699a813451 210 TEST_ASSERT_FALSE(pBatteryGauge->disableGauge());
RobMeades 2:4c699a813451 211 TEST_ASSERT_FALSE(pBatteryGauge->isGaugeEnabled());
RobMeades 2:4c699a813451 212
RobMeades 2:4c699a813451 213 // Normal case, gauging should be off to begin with
RobMeades 2:4c699a813451 214 TEST_ASSERT(pBatteryGauge->init(gpI2C, GAUGE_ENABLE_PIN));
RobMeades 2:4c699a813451 215 TEST_ASSERT_FALSE(pBatteryGauge->isGaugeEnabled());
RobMeades 2:4c699a813451 216
RobMeades 2:4c699a813451 217 // Enable gauge, without non-volatile storage
RobMeades 2:4c699a813451 218
RobMeades 2:4c699a813451 219 TEST_ASSERT(pBatteryGauge->enableGauge());
RobMeades 2:4c699a813451 220 TEST_ASSERT(pBatteryGauge->getUsedCapacity(&capacityUAh));
RobMeades 2:4c699a813451 221 printf ("Used capacity %.3f mAh.\n", ((float) capacityUAh) / 1000);
RobMeades 2:4c699a813451 222 // Range check
RobMeades 2:4c699a813451 223 TEST_ASSERT((capacityUAh >= MIN_CAPACITY_READING_UAH) && (capacityUAh <= MAX_CAPACITY_READING_UAH));
RobMeades 2:4c699a813451 224 TEST_ASSERT(pBatteryGauge->isGaugeEnabled());
RobMeades 2:4c699a813451 225 TEST_ASSERT(pBatteryGauge->disableGauge());
RobMeades 2:4c699a813451 226 TEST_ASSERT_FALSE(pBatteryGauge->isGaugeEnabled());
RobMeades 2:4c699a813451 227
RobMeades 2:4c699a813451 228 // Enable gauge, with non-volatile storage
RobMeades 2:4c699a813451 229 TEST_ASSERT(pBatteryGauge->enableGauge(true));
RobMeades 2:4c699a813451 230 TEST_ASSERT(pBatteryGauge->getUsedCapacity(&capacityUAh));
RobMeades 2:4c699a813451 231 printf ("Used capacity %.3f mAh.\n", ((float) capacityUAh) / 1000);
RobMeades 2:4c699a813451 232 // Range check
RobMeades 2:4c699a813451 233 // TODO: any way to check that the non-volatileness has worked?
RobMeades 2:4c699a813451 234 TEST_ASSERT((capacityUAh >= MIN_CAPACITY_READING_UAH) && (capacityUAh <= MAX_CAPACITY_READING_UAH));
RobMeades 2:4c699a813451 235 TEST_ASSERT(pBatteryGauge->isGaugeEnabled());
RobMeades 2:4c699a813451 236 TEST_ASSERT(pBatteryGauge->disableGauge());
RobMeades 2:4c699a813451 237 TEST_ASSERT_FALSE(pBatteryGauge->isGaugeEnabled());
RobMeades 2:4c699a813451 238 }
RobMeades 2:4c699a813451 239
RobMeades 2:4c699a813451 240 // Test the new battery call
RobMeades 2:4c699a813451 241 void test_new_battery() {
RobMeades 2:4c699a813451 242 BatteryGaugeBq35100 * pBatteryGauge = new BatteryGaugeBq35100();
RobMeades 2:4c699a813451 243 uint32_t originalDesignCapacity;
RobMeades 2:4c699a813451 244 uint32_t newDesignCapacity = SET_DESIGN_CAPACITY_MAH;
RobMeades 2:4c699a813451 245 uint32_t readDesignCapacity = 0;
RobMeades 2:4c699a813451 246
RobMeades 2:4c699a813451 247 // Call should fail if the battery gauge has not been initialised
RobMeades 2:4c699a813451 248 TEST_ASSERT_FALSE(pBatteryGauge->newBattery(1000));
RobMeades 2:4c699a813451 249
RobMeades 2:4c699a813451 250 // Normal case
RobMeades 2:4c699a813451 251 TEST_ASSERT(pBatteryGauge->init(gpI2C, GAUGE_ENABLE_PIN));
RobMeades 2:4c699a813451 252 // Get the original design capacity so that we can set it back
RobMeades 2:4c699a813451 253 // at the end
RobMeades 2:4c699a813451 254 TEST_ASSERT(pBatteryGauge->getDesignCapacity(&originalDesignCapacity));
RobMeades 2:4c699a813451 255 printf ("Design capacity was originally %d mAh.\n", (unsigned int) originalDesignCapacity);
RobMeades 2:4c699a813451 256
RobMeades 2:4c699a813451 257 // Avoid the old and new values being the same
RobMeades 2:4c699a813451 258 if (originalDesignCapacity == newDesignCapacity) {
RobMeades 2:4c699a813451 259 newDesignCapacity--;
RobMeades 2:4c699a813451 260 }
RobMeades 2:4c699a813451 261
RobMeades 2:4c699a813451 262 // Now add the new battery
RobMeades 2:4c699a813451 263 TEST_ASSERT(pBatteryGauge->newBattery(newDesignCapacity));
RobMeades 2:4c699a813451 264 printf ("New battery added with design capacity %d mAh.\n", (unsigned int) newDesignCapacity);
RobMeades 2:4c699a813451 265
RobMeades 2:4c699a813451 266 // Read the value back and check that it's been set
RobMeades 2:4c699a813451 267 TEST_ASSERT(pBatteryGauge->getDesignCapacity(&readDesignCapacity));
RobMeades 2:4c699a813451 268 printf ("Design capacity was read as %d mAh.\n", (unsigned int) readDesignCapacity);
RobMeades 2:4c699a813451 269 TEST_ASSERT(readDesignCapacity = newDesignCapacity)
RobMeades 2:4c699a813451 270
RobMeades 2:4c699a813451 271 // Put the original value back
RobMeades 2:4c699a813451 272 TEST_ASSERT(pBatteryGauge->setDesignCapacity(originalDesignCapacity));
RobMeades 2:4c699a813451 273 printf ("Design capacity returned to %d mAh.\n", (unsigned int) originalDesignCapacity);
RobMeades 2:4c699a813451 274 }
RobMeades 2:4c699a813451 275
RobMeades 2:4c699a813451 276 // Test get/set config
RobMeades 2:4c699a813451 277 void test_advanced_get_set_config() {
RobMeades 2:4c699a813451 278 BatteryGaugeBq35100 * pBatteryGauge = new BatteryGaugeBq35100();
RobMeades 2:4c699a813451 279 int32_t address = 0x4036; // Manufacturer Info Block A01, a 1 byte field
RobMeades 2:4c699a813451 280 char originalValue;
RobMeades 2:4c699a813451 281 char oldValue;
RobMeades 2:4c699a813451 282 char newValue;
RobMeades 2:4c699a813451 283
RobMeades 2:4c699a813451 284 // Calls should fail if the battery gauge has not been initialised
RobMeades 2:4c699a813451 285 TEST_ASSERT_FALSE(pBatteryGauge->advancedGetConfig(address, &originalValue, sizeof(originalValue)));
RobMeades 2:4c699a813451 286 TEST_ASSERT_FALSE(pBatteryGauge->advancedSetConfig(address, &newValue, sizeof(newValue)));
RobMeades 2:4c699a813451 287
RobMeades 2:4c699a813451 288 // Initialise the battery gauge
RobMeades 2:4c699a813451 289 TEST_ASSERT(pBatteryGauge->init(gpI2C, GAUGE_ENABLE_PIN));
RobMeades 2:4c699a813451 290
RobMeades 2:4c699a813451 291 // Normal case
RobMeades 2:4c699a813451 292 TEST_ASSERT(pBatteryGauge->advancedGetConfig(address, &originalValue, sizeof(originalValue)));
RobMeades 2:4c699a813451 293 // Invert the result and write it back
RobMeades 2:4c699a813451 294 oldValue = originalValue;
RobMeades 2:4c699a813451 295 printf ("Original value was 0x%02x.\n", oldValue);
RobMeades 2:4c699a813451 296 newValue = ~oldValue;
RobMeades 2:4c699a813451 297 printf ("Setting it to 0x%02x.\n", newValue);
RobMeades 2:4c699a813451 298 TEST_ASSERT(pBatteryGauge->advancedSetConfig(address, &newValue, sizeof(newValue)));
RobMeades 2:4c699a813451 299 // Read it and check that it has changed
RobMeades 2:4c699a813451 300 TEST_ASSERT(pBatteryGauge->advancedGetConfig(address, &oldValue, sizeof(oldValue)));
RobMeades 2:4c699a813451 301 printf ("Read back 0x%02x.\n", oldValue);
RobMeades 2:4c699a813451 302 TEST_ASSERT_EQUAL_UINT8(newValue, oldValue);
RobMeades 2:4c699a813451 303
RobMeades 2:4c699a813451 304 // Put the original value back again
RobMeades 2:4c699a813451 305 TEST_ASSERT(pBatteryGauge->advancedSetConfig(address, &originalValue, sizeof(originalValue)));
RobMeades 2:4c699a813451 306 }
RobMeades 2:4c699a813451 307
RobMeades 2:4c699a813451 308 // Send a control word
RobMeades 2:4c699a813451 309 void test_advanced_control() {
RobMeades 2:4c699a813451 310 BatteryGaugeBq35100 * pBatteryGauge = new BatteryGaugeBq35100();
RobMeades 2:4c699a813451 311 uint16_t controlWord = 0x0003; // get HW version
RobMeades 2:4c699a813451 312 uint16_t response = 0;
RobMeades 2:4c699a813451 313
RobMeades 2:4c699a813451 314 // Call should fail if the battery gauge has not been initialised
RobMeades 2:4c699a813451 315 TEST_ASSERT_FALSE(pBatteryGauge->advancedSendControlWord(controlWord, &response));
RobMeades 2:4c699a813451 316
RobMeades 2:4c699a813451 317 // Initialise the battery gauge
RobMeades 2:4c699a813451 318 TEST_ASSERT(pBatteryGauge->init(gpI2C, GAUGE_ENABLE_PIN));
RobMeades 2:4c699a813451 319
RobMeades 2:4c699a813451 320 // Normal case
RobMeades 2:4c699a813451 321 TEST_ASSERT(pBatteryGauge->advancedSendControlWord(controlWord, &response));
RobMeades 2:4c699a813451 322 // FW version must be 0x00a8
RobMeades 2:4c699a813451 323 TEST_ASSERT_EQUAL_UINT16(0x00a8, response);
RobMeades 2:4c699a813451 324
RobMeades 2:4c699a813451 325 // The parameter is allowed to be null
RobMeades 2:4c699a813451 326 TEST_ASSERT(pBatteryGauge->advancedSendControlWord(controlWord, NULL));
RobMeades 2:4c699a813451 327 }
RobMeades 2:4c699a813451 328
RobMeades 2:4c699a813451 329 // Read using a standard command
RobMeades 2:4c699a813451 330 void test_advanced_get() {
RobMeades 2:4c699a813451 331 BatteryGaugeBq35100 * pBatteryGauge = new BatteryGaugeBq35100();
RobMeades 2:4c699a813451 332 uint8_t address = 0x06; // Temperature
RobMeades 2:4c699a813451 333 uint16_t value = 0;
RobMeades 2:4c699a813451 334 int32_t temperatureC = -1;
RobMeades 2:4c699a813451 335
RobMeades 2:4c699a813451 336 // Call should fail if the battery gauge has not been initialised
RobMeades 2:4c699a813451 337 TEST_ASSERT_FALSE(pBatteryGauge->advancedGet(address, &value));
RobMeades 2:4c699a813451 338
RobMeades 2:4c699a813451 339 // Initialise the battery gauge
RobMeades 2:4c699a813451 340 TEST_ASSERT(pBatteryGauge->init(gpI2C, GAUGE_ENABLE_PIN));
RobMeades 2:4c699a813451 341
RobMeades 2:4c699a813451 342 // Normal case
RobMeades 2:4c699a813451 343 TEST_ASSERT(pBatteryGauge->advancedGet(address, &value));
RobMeades 2:4c699a813451 344 // Get the temperature via the standard API command
RobMeades 2:4c699a813451 345 TEST_ASSERT(pBatteryGauge->getTemperature(&temperatureC));
RobMeades 2:4c699a813451 346 // Convert the value returned into a temperature reading and compare
RobMeades 2:4c699a813451 347 // it with the real answer, allowing a 1 degree tolerance in case
RobMeades 2:4c699a813451 348 // it has changed between readings.
RobMeades 2:4c699a813451 349 TEST_ASSERT_INT32_WITHIN (1, temperatureC, ((int32_t) value / 10) - 273);
RobMeades 2:4c699a813451 350
RobMeades 2:4c699a813451 351 // The parameter is allowed to be null
RobMeades 2:4c699a813451 352 TEST_ASSERT(pBatteryGauge->advancedGet(address, NULL));
RobMeades 2:4c699a813451 353 }
RobMeades 2:4c699a813451 354
RobMeades 1:ee7cc8d75283 355 // Test that the security mode of the chip can be changed
RobMeades 1:ee7cc8d75283 356 void test_advanced_security_mode() {
RobMeades 1:ee7cc8d75283 357 BatteryGaugeBq35100 * pBatteryGauge = new BatteryGaugeBq35100();
RobMeades 1:ee7cc8d75283 358 BatteryGaugeBq35100::SecurityMode securityMode;
RobMeades 1:ee7cc8d75283 359
RobMeades 1:ee7cc8d75283 360 // Get the existing device mode and then set it to sealed
RobMeades 1:ee7cc8d75283 361 TEST_ASSERT(pBatteryGauge->init(gpI2C, GAUGE_ENABLE_PIN));
RobMeades 1:ee7cc8d75283 362 printf ("Calling advancedGetSecurityMode()...\n");
RobMeades 1:ee7cc8d75283 363 securityMode = pBatteryGauge->advancedGetSecurityMode();
RobMeades 1:ee7cc8d75283 364 printf ("Calling advancedSetSecurityMode(SECURITY_MODE_SEALED)...\n");
RobMeades 1:ee7cc8d75283 365 TEST_ASSERT(pBatteryGauge->advancedSetSecurityMode(BatteryGaugeBq35100::SECURITY_MODE_SEALED));
RobMeades 1:ee7cc8d75283 366
RobMeades 1:ee7cc8d75283 367 delete pBatteryGauge;
RobMeades 1:ee7cc8d75283 368 pBatteryGauge = new BatteryGaugeBq35100();
RobMeades 1:ee7cc8d75283 369 // Calls should fail if the battery gauge has not been initialised
RobMeades 1:ee7cc8d75283 370 printf ("Calling advancedGetSecurityMode()...\n");
RobMeades 1:ee7cc8d75283 371 TEST_ASSERT(pBatteryGauge->advancedGetSecurityMode() == BatteryGaugeBq35100::SECURITY_MODE_UNKNOWN);
RobMeades 1:ee7cc8d75283 372 printf ("Calling advancedSetSecurityMode(SECURITY_MODE_UNSEALED)...\n");
RobMeades 1:ee7cc8d75283 373 TEST_ASSERT_FALSE(pBatteryGauge->advancedSetSecurityMode(BatteryGaugeBq35100::SECURITY_MODE_UNSEALED));
RobMeades 1:ee7cc8d75283 374
RobMeades 1:ee7cc8d75283 375 // Normal case
RobMeades 1:ee7cc8d75283 376 printf ("Calling init()...\n");
RobMeades 1:ee7cc8d75283 377 TEST_ASSERT(pBatteryGauge->init(gpI2C, GAUGE_ENABLE_PIN));
RobMeades 1:ee7cc8d75283 378 printf ("Calling advancedGetSecurityMode()...\n");
RobMeades 1:ee7cc8d75283 379 TEST_ASSERT(pBatteryGauge->advancedGetSecurityMode() == BatteryGaugeBq35100::SECURITY_MODE_SEALED);
RobMeades 1:ee7cc8d75283 380
RobMeades 1:ee7cc8d75283 381 // These calls should fail
RobMeades 1:ee7cc8d75283 382 // TODO do a thing that only works when unsealed
RobMeades 1:ee7cc8d75283 383 // TODO do a thing that only works when full access
RobMeades 1:ee7cc8d75283 384
RobMeades 1:ee7cc8d75283 385 // Now unseal it
RobMeades 1:ee7cc8d75283 386 printf ("Calling advancedSetSecurityMode(SECURITY_MODE_UNSEALED)...\n");
RobMeades 1:ee7cc8d75283 387 TEST_ASSERT(pBatteryGauge->advancedSetSecurityMode(BatteryGaugeBq35100::SECURITY_MODE_UNSEALED));
RobMeades 1:ee7cc8d75283 388
RobMeades 1:ee7cc8d75283 389 // This call should now pass
RobMeades 1:ee7cc8d75283 390 // TODO do a thing that only works when unsealed
RobMeades 1:ee7cc8d75283 391
RobMeades 1:ee7cc8d75283 392 // But this should still fail
RobMeades 1:ee7cc8d75283 393 // TODO do a thing that only works when full access
RobMeades 1:ee7cc8d75283 394
RobMeades 1:ee7cc8d75283 395 // Seal it again
RobMeades 1:ee7cc8d75283 396 printf ("Calling advancedSetSecurityMode(SECURITY_MODE_SEALED)...\n");
RobMeades 1:ee7cc8d75283 397 TEST_ASSERT(pBatteryGauge->advancedSetSecurityMode(BatteryGaugeBq35100::SECURITY_MODE_SEALED));
RobMeades 1:ee7cc8d75283 398
RobMeades 1:ee7cc8d75283 399 // Now allow full access, which should fail as you can't get there from SEALED
RobMeades 1:ee7cc8d75283 400 printf ("Calling advancedSetSecurityMode(SECURITY_MODE_FULL_ACCESS)...\n");
RobMeades 1:ee7cc8d75283 401 TEST_ASSERT_FALSE(pBatteryGauge->advancedSetSecurityMode(BatteryGaugeBq35100::SECURITY_MODE_FULL_ACCESS));
RobMeades 1:ee7cc8d75283 402
RobMeades 1:ee7cc8d75283 403 // Now unseal it
RobMeades 1:ee7cc8d75283 404 printf ("Calling advancedSetSecurityMode(SECURITY_MODE_UNSEALED)...\n");
RobMeades 1:ee7cc8d75283 405 TEST_ASSERT(pBatteryGauge->advancedSetSecurityMode(BatteryGaugeBq35100::SECURITY_MODE_UNSEALED));
RobMeades 1:ee7cc8d75283 406
RobMeades 1:ee7cc8d75283 407 // *Now* allow full access, which should succeed
RobMeades 1:ee7cc8d75283 408 printf ("Calling advancedSetSecurityMode(SECURITY_MODE_FULL_ACCESS)...\n");
RobMeades 1:ee7cc8d75283 409 TEST_ASSERT(pBatteryGauge->advancedSetSecurityMode(BatteryGaugeBq35100::SECURITY_MODE_FULL_ACCESS));
RobMeades 1:ee7cc8d75283 410
RobMeades 1:ee7cc8d75283 411 // These calls should now both pass
RobMeades 1:ee7cc8d75283 412 // TODO do a thing that only works when unsealed
RobMeades 1:ee7cc8d75283 413 // TODO do a thing that only works when full access
RobMeades 1:ee7cc8d75283 414
RobMeades 1:ee7cc8d75283 415 // Put the device back the way it was
RobMeades 1:ee7cc8d75283 416 TEST_ASSERT(pBatteryGauge->advancedSetSecurityMode(securityMode));
RobMeades 1:ee7cc8d75283 417 }
RobMeades 1:ee7cc8d75283 418
RobMeades 2:4c699a813451 419 // Reset the BQ35100 battery gauge chip
RobMeades 1:ee7cc8d75283 420 void test_advanced_reset() {
RobMeades 1:ee7cc8d75283 421 BatteryGaugeBq35100 * pBatteryGauge = new BatteryGaugeBq35100();
RobMeades 1:ee7cc8d75283 422 BatteryGaugeBq35100::SecurityMode securityMode;
RobMeades 1:ee7cc8d75283 423
RobMeades 1:ee7cc8d75283 424 // Call should fail if the battery gauge has not been initialised
RobMeades 1:ee7cc8d75283 425 TEST_ASSERT_FALSE(pBatteryGauge->advancedReset());
RobMeades 1:ee7cc8d75283 426
RobMeades 1:ee7cc8d75283 427 // Get the existing security mode and then set it to unsealed
RobMeades 1:ee7cc8d75283 428 TEST_ASSERT(pBatteryGauge->init(gpI2C, GAUGE_ENABLE_PIN));
RobMeades 1:ee7cc8d75283 429
RobMeades 1:ee7cc8d75283 430 printf ("Calling advancedGetSecurityMode()...\n");
RobMeades 1:ee7cc8d75283 431 securityMode = pBatteryGauge->advancedGetSecurityMode();
RobMeades 1:ee7cc8d75283 432 printf ("Calling advancedSetSecurityMode(SECURITY_MODE_UNSEALED)...\n");
RobMeades 1:ee7cc8d75283 433 TEST_ASSERT(pBatteryGauge->advancedSetSecurityMode(BatteryGaugeBq35100::SECURITY_MODE_UNSEALED));
RobMeades 1:ee7cc8d75283 434
RobMeades 1:ee7cc8d75283 435 // TODO: modify a thing that will later be reset
RobMeades 1:ee7cc8d75283 436
RobMeades 1:ee7cc8d75283 437 // Now reset the chip
RobMeades 1:ee7cc8d75283 438 printf ("Calling advancedReset()...\n");
RobMeades 1:ee7cc8d75283 439 TEST_ASSERT(pBatteryGauge->advancedReset());
RobMeades 1:ee7cc8d75283 440
RobMeades 1:ee7cc8d75283 441 // TODO check that the thing has been reset
RobMeades 1:ee7cc8d75283 442
RobMeades 1:ee7cc8d75283 443 // Put the security mode back to what it was
RobMeades 1:ee7cc8d75283 444 TEST_ASSERT(pBatteryGauge->advancedSetSecurityMode(securityMode));
RobMeades 0:cec745c014b7 445 }
RobMeades 0:cec745c014b7 446
RobMeades 0:cec745c014b7 447 // ----------------------------------------------------------------
RobMeades 0:cec745c014b7 448 // TEST ENVIRONMENT
RobMeades 0:cec745c014b7 449 // ----------------------------------------------------------------
RobMeades 0:cec745c014b7 450
RobMeades 0:cec745c014b7 451 // Setup the test environment
RobMeades 0:cec745c014b7 452 utest::v1::status_t test_setup(const size_t number_of_cases) {
RobMeades 0:cec745c014b7 453 // Setup Greentea, timeout is long enough to run these tests with
RobMeades 0:cec745c014b7 454 // DEBUG_BQ35100 defined
RobMeades 2:4c699a813451 455 GREENTEA_SETUP(250, "default_auto");
RobMeades 0:cec745c014b7 456 return verbose_test_setup_handler(number_of_cases);
RobMeades 0:cec745c014b7 457 }
RobMeades 0:cec745c014b7 458
RobMeades 0:cec745c014b7 459 // Test cases
RobMeades 0:cec745c014b7 460 Case cases[] = {
RobMeades 1:ee7cc8d75283 461 Case("Initialisation", test_init),
RobMeades 1:ee7cc8d75283 462 Case("Temperature read", test_temperature),
RobMeades 1:ee7cc8d75283 463 Case("Voltage read", test_voltage),
RobMeades 1:ee7cc8d75283 464 Case("Current read", test_current),
RobMeades 1:ee7cc8d75283 465 Case("Used capacity read", test_used_capacity),
RobMeades 1:ee7cc8d75283 466 Case("Design capacity read/set", test_design_capacity),
RobMeades 1:ee7cc8d75283 467 Case("Remaining capacity read", test_remaining_capacity),
RobMeades 1:ee7cc8d75283 468 Case("Remaining precentage read", test_remaining_percentage),
RobMeades 2:4c699a813451 469 Case("Gauging", test_gauging),
RobMeades 2:4c699a813451 470 Case("New battery", test_new_battery),
RobMeades 2:4c699a813451 471 Case("Advanced get/set config", test_advanced_get_set_config),
RobMeades 2:4c699a813451 472 Case("Advanced control", test_advanced_control),
RobMeades 2:4c699a813451 473 Case("Advanced get", test_advanced_get),
RobMeades 1:ee7cc8d75283 474 Case("Advanced security mode", test_advanced_security_mode),
RobMeades 1:ee7cc8d75283 475 Case("Advanced reset", test_advanced_reset)
RobMeades 0:cec745c014b7 476 };
RobMeades 0:cec745c014b7 477
RobMeades 0:cec745c014b7 478 Specification specification(test_setup, cases);
RobMeades 0:cec745c014b7 479
RobMeades 0:cec745c014b7 480 // ----------------------------------------------------------------
RobMeades 0:cec745c014b7 481 // MAIN
RobMeades 0:cec745c014b7 482 // ----------------------------------------------------------------
RobMeades 0:cec745c014b7 483
RobMeades 0:cec745c014b7 484 // Entry point into the tests
RobMeades 0:cec745c014b7 485 int main() {
RobMeades 0:cec745c014b7 486 bool success = false;
RobMeades 0:cec745c014b7 487
RobMeades 0:cec745c014b7 488 if (gpI2C != NULL) {
RobMeades 0:cec745c014b7 489 success = !Harness::run(specification);
RobMeades 0:cec745c014b7 490 } else {
RobMeades 0:cec745c014b7 491 printf ("Unable to instantiate I2C interface.\n");
RobMeades 0:cec745c014b7 492 }
RobMeades 0:cec745c014b7 493
RobMeades 0:cec745c014b7 494 return success;
RobMeades 0:cec745c014b7 495 }
RobMeades 0:cec745c014b7 496
RobMeades 0:cec745c014b7 497 // End Of File