![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Hooks into the CE pin of TP4056 to add some extra features - overvolt cutoff - overtime cutoff - overtemperature cutoff (by use of MCP9808) - info on little OLED screen - battery presence detection Future features - current detection and cutoff (waiting for INA219 breakout for this) - Runtime configurable parameters by serial - Send stats over serial to desktop application Known flaws - see readme Circuit schematic coming soon (tm), see readme Designed and tested for nucleo F303RE but should be easily adaptable to any board. License: GPL v3
Dependencies: OLED_SSD1306 MCP9808
main.cpp@1:7749656733dd, 2020-08-24 (annotated)
- Committer:
- kuutei
- Date:
- Mon Aug 24 05:29:53 2020 +0000
- Revision:
- 1:7749656733dd
- Parent:
- 0:56122e281547
- Child:
- 2:18d8f9d3286c
sort of working
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kuutei | 0:56122e281547 | 1 | #include "mbed.h" |
kuutei | 0:56122e281547 | 2 | #include "platform/mbed_thread.h" |
kuutei | 0:56122e281547 | 3 | |
kuutei | 0:56122e281547 | 4 | #include <string> |
kuutei | 0:56122e281547 | 5 | #include <iomanip> |
kuutei | 0:56122e281547 | 6 | #include <sstream> |
kuutei | 0:56122e281547 | 7 | |
kuutei | 0:56122e281547 | 8 | #include "SSD1306I2C.h" |
kuutei | 1:7749656733dd | 9 | #include "DS1820.h" |
kuutei | 0:56122e281547 | 10 | |
kuutei | 0:56122e281547 | 11 | #define OLED_ADR 0x3C |
kuutei | 0:56122e281547 | 12 | #define OLED_SDA I2C_SDA |
kuutei | 0:56122e281547 | 13 | #define OLED_SCL I2C_SCL |
kuutei | 0:56122e281547 | 14 | |
kuutei | 1:7749656733dd | 15 | #define DS18B20_DATA PB_4 |
kuutei | 1:7749656733dd | 16 | |
kuutei | 0:56122e281547 | 17 | |
kuutei | 0:56122e281547 | 18 | // Blinking rate in milliseconds |
kuutei | 0:56122e281547 | 19 | #define BLINKING_RATE_MS 5000 |
kuutei | 0:56122e281547 | 20 | |
kuutei | 0:56122e281547 | 21 | #define VOLTAGE_DIVIDER_R1 99800 |
kuutei | 0:56122e281547 | 22 | #define VOLTAGE_DIVIDER_R2 99100 |
kuutei | 0:56122e281547 | 23 | |
kuutei | 0:56122e281547 | 24 | Serial pc(USBTX,USBRX); |
kuutei | 0:56122e281547 | 25 | |
kuutei | 1:7749656733dd | 26 | SSD1306I2C oled_i2c(OLED_ADR, OLED_SDA, OLED_SCL); |
kuutei | 1:7749656733dd | 27 | |
kuutei | 1:7749656733dd | 28 | DS1820 ds1820_sensor(DS18B20_DATA); |
kuutei | 1:7749656733dd | 29 | |
kuutei | 0:56122e281547 | 30 | //DigitalIn mybutton(USER_BUTTON); |
kuutei | 0:56122e281547 | 31 | AnalogIn divider_analogin(A0); |
kuutei | 0:56122e281547 | 32 | AnalogIn vref(ADC_VREF); |
kuutei | 0:56122e281547 | 33 | |
kuutei | 0:56122e281547 | 34 | //AnalogIn adc_refint(VREF_INT); |
kuutei | 0:56122e281547 | 35 | |
kuutei | 0:56122e281547 | 36 | DigitalInOut toggleOut(PA_14, PIN_OUTPUT, OpenDrainNoPull, 0); |
kuutei | 1:7749656733dd | 37 | bool TP4056ChargingState = false; //reflects internal state of TP4056 control thread |
kuutei | 0:56122e281547 | 38 | |
kuutei | 0:56122e281547 | 39 | InterruptIn chargeButton(USER_BUTTON); |
kuutei | 1:7749656733dd | 40 | volatile bool buttonPressed = false; //set to true by button ISR, set to false when acknowledged |
kuutei | 0:56122e281547 | 41 | |
kuutei | 1:7749656733dd | 42 | bool batteryPresenceState = false; |
kuutei | 0:56122e281547 | 43 | |
kuutei | 0:56122e281547 | 44 | float bat_voltage = -1.11; |
kuutei | 0:56122e281547 | 45 | float bat_voltage_avg = -1.11; |
kuutei | 0:56122e281547 | 46 | float vddref_voltage = -1.11; |
kuutei | 0:56122e281547 | 47 | |
kuutei | 1:7749656733dd | 48 | float ds18b20_temperature = -301.0; |
kuutei | 0:56122e281547 | 49 | |
kuutei | 0:56122e281547 | 50 | //Configurable protection conditions |
kuutei | 0:56122e281547 | 51 | float MAX_VOLTAGE = 4.25; //default: no more than 4.25v |
kuutei | 0:56122e281547 | 52 | float MIN_VOLTAGE = 2.5; //default: no less than 2.5v |
kuutei | 1:7749656733dd | 53 | float MIN_DETECT_VOLTAGE = 0.5; //default: no less than 0.3v |
kuutei | 0:56122e281547 | 54 | float MAX_TEMPERATURE = 40.0; //default: no more than 40C |
kuutei | 0:56122e281547 | 55 | float MIN_TEMPERATURE = 10.0; //default: no less than 10C |
kuutei | 0:56122e281547 | 56 | uint64_t MAX_TIME_ms = 3600000; //default: no more than 1h |
kuutei | 0:56122e281547 | 57 | |
kuutei | 0:56122e281547 | 58 | |
kuutei | 0:56122e281547 | 59 | void blinkled() |
kuutei | 0:56122e281547 | 60 | { |
kuutei | 0:56122e281547 | 61 | // Initialise the digital pin LED1 as an output |
kuutei | 0:56122e281547 | 62 | DigitalOut led(LED1); |
kuutei | 0:56122e281547 | 63 | |
kuutei | 0:56122e281547 | 64 | while (true) { |
kuutei | 0:56122e281547 | 65 | led = !led; |
kuutei | 0:56122e281547 | 66 | ThisThread::sleep_for(BLINKING_RATE_MS); |
kuutei | 0:56122e281547 | 67 | } |
kuutei | 0:56122e281547 | 68 | } |
kuutei | 0:56122e281547 | 69 | |
kuutei | 0:56122e281547 | 70 | |
kuutei | 0:56122e281547 | 71 | // Button to initiate / stop charging |
kuutei | 0:56122e281547 | 72 | // Called on button rise |
kuutei | 0:56122e281547 | 73 | // Set to true to signal to EN control thread that button was pressed |
kuutei | 1:7749656733dd | 74 | void buttonISR() |
kuutei | 0:56122e281547 | 75 | { |
kuutei | 1:7749656733dd | 76 | static uint64_t lastButtonPushTime = 0; |
kuutei | 1:7749656733dd | 77 | |
kuutei | 0:56122e281547 | 78 | uint64_t now = Kernel::get_ms_count(); |
kuutei | 1:7749656733dd | 79 | |
kuutei | 0:56122e281547 | 80 | const uint64_t buttonMinimumWaitTime = 500; //minimum 500 ms wait between button pushes |
kuutei | 0:56122e281547 | 81 | |
kuutei | 0:56122e281547 | 82 | if(Kernel::get_ms_count() - lastButtonPushTime > buttonMinimumWaitTime) |
kuutei | 0:56122e281547 | 83 | { |
kuutei | 0:56122e281547 | 84 | buttonPressed = true; |
kuutei | 1:7749656733dd | 85 | lastButtonPushTime = now; |
kuutei | 0:56122e281547 | 86 | } |
kuutei | 0:56122e281547 | 87 | |
kuutei | 0:56122e281547 | 88 | } |
kuutei | 0:56122e281547 | 89 | |
kuutei | 0:56122e281547 | 90 | float readRefVoltage() |
kuutei | 0:56122e281547 | 91 | { |
kuutei | 0:56122e281547 | 92 | double vdd; |
kuutei | 0:56122e281547 | 93 | double vdd_calibed; |
kuutei | 0:56122e281547 | 94 | double vref_calibed; |
kuutei | 0:56122e281547 | 95 | double vref_f; |
kuutei | 0:56122e281547 | 96 | uint16_t vref_u16; |
kuutei | 0:56122e281547 | 97 | uint16_t vref_cal; |
kuutei | 0:56122e281547 | 98 | |
kuutei | 0:56122e281547 | 99 | vref_cal= *((uint16_t*)VREFINT_CAL_ADDR); //F303RE |
kuutei | 0:56122e281547 | 100 | |
kuutei | 0:56122e281547 | 101 | vref_u16 = vref.read_u16(); |
kuutei | 0:56122e281547 | 102 | //1.22 comes from 3.3 * 1524 / 4095 - voltage at calibration time times calibration measurement divided by maximum counts |
kuutei | 0:56122e281547 | 103 | //vdd = 1.228132 / vref.read(); |
kuutei | 0:56122e281547 | 104 | vdd = 3.3 * (double)vref_cal / 4095.0 / vref.read(); |
kuutei | 0:56122e281547 | 105 | |
kuutei | 0:56122e281547 | 106 | return vdd; |
kuutei | 0:56122e281547 | 107 | } |
kuutei | 0:56122e281547 | 108 | |
kuutei | 0:56122e281547 | 109 | //Reads voltage divider, and uses internal calibrated reference voltage to calculate real voltage |
kuutei | 0:56122e281547 | 110 | //Not 100% accurate, but better than assuming 3.3v |
kuutei | 0:56122e281547 | 111 | float readVoltageDivider_Calibrated() |
kuutei | 0:56122e281547 | 112 | { |
kuutei | 0:56122e281547 | 113 | uint16_t vref_cal= *((uint16_t*)VREFINT_CAL_ADDR); //factory calibration value for 3.3v |
kuutei | 0:56122e281547 | 114 | uint16_t vref_u16 = vref.read_u16(); //read the internal voltage calibration |
kuutei | 0:56122e281547 | 115 | float vdd = 3.3 * (double)vref_cal / 4095.0 / vref.read(); |
kuutei | 0:56122e281547 | 116 | |
kuutei | 0:56122e281547 | 117 | //ain.read() returns float value between 0 and 1 |
kuutei | 0:56122e281547 | 118 | float reading = divider_analogin.read(); |
kuutei | 0:56122e281547 | 119 | |
kuutei | 0:56122e281547 | 120 | //pc.printf("raw reading: %f\r\n", reading); |
kuutei | 0:56122e281547 | 121 | |
kuutei | 0:56122e281547 | 122 | return reading * vdd * (VOLTAGE_DIVIDER_R1 + VOLTAGE_DIVIDER_R2) / VOLTAGE_DIVIDER_R2; |
kuutei | 0:56122e281547 | 123 | |
kuutei | 0:56122e281547 | 124 | } |
kuutei | 0:56122e281547 | 125 | |
kuutei | 0:56122e281547 | 126 | //Measurement assuming 3.3v - for comparison to calibrated reading only |
kuutei | 0:56122e281547 | 127 | //Can be very inaccurate as nucleo voltage regulator drops as far as 3.2v |
kuutei | 0:56122e281547 | 128 | float readVoltageDivider_3v3() |
kuutei | 0:56122e281547 | 129 | { |
kuutei | 0:56122e281547 | 130 | uint16_t vref_cal= *((uint16_t*)VREFINT_CAL_ADDR); //factory calibration value for 3.3v |
kuutei | 0:56122e281547 | 131 | uint16_t vref_u16 = vref.read_u16(); //read the internal voltage calibration |
kuutei | 0:56122e281547 | 132 | float vdd = 3.3 * (double)vref_cal / 4095.0 / vref.read(); |
kuutei | 0:56122e281547 | 133 | |
kuutei | 0:56122e281547 | 134 | //ain.read() returns float value between 0 and 1 |
kuutei | 0:56122e281547 | 135 | float reading = divider_analogin.read(); |
kuutei | 0:56122e281547 | 136 | |
kuutei | 0:56122e281547 | 137 | return reading * vdd * (VOLTAGE_DIVIDER_R1 + VOLTAGE_DIVIDER_R2) / VOLTAGE_DIVIDER_R2; |
kuutei | 0:56122e281547 | 138 | |
kuutei | 0:56122e281547 | 139 | } |
kuutei | 0:56122e281547 | 140 | |
kuutei | 0:56122e281547 | 141 | // Reads DS18B20 sense temperature |
kuutei | 0:56122e281547 | 142 | void TemperatureInputThread() |
kuutei | 0:56122e281547 | 143 | { |
kuutei | 1:7749656733dd | 144 | int ds18b20_result = 0; |
kuutei | 1:7749656733dd | 145 | float temp; |
kuutei | 1:7749656733dd | 146 | |
kuutei | 0:56122e281547 | 147 | while(true) |
kuutei | 0:56122e281547 | 148 | { |
kuutei | 1:7749656733dd | 149 | ds1820_sensor.startConversion(); // start temperature conversion from analog to digital |
kuutei | 1:7749656733dd | 150 | // let DS1820 complete the temperature conversion |
kuutei | 1:7749656733dd | 151 | ThisThread::sleep_for(1.0); |
kuutei | 1:7749656733dd | 152 | ds18b20_result = ds1820_sensor.read(temp); // read temperature from DS1820 and perform cyclic redundancy check (CRC) |
kuutei | 0:56122e281547 | 153 | |
kuutei | 1:7749656733dd | 154 | switch (ds18b20_result) { |
kuutei | 1:7749656733dd | 155 | case 0: // no errors -> 'temp' contains the value of measured temperature |
kuutei | 1:7749656733dd | 156 | //pc.printf("temp = %3.4f%cC\r\n", temp, 176); |
kuutei | 1:7749656733dd | 157 | ds18b20_temperature = temp; |
kuutei | 1:7749656733dd | 158 | break; |
kuutei | 1:7749656733dd | 159 | |
kuutei | 1:7749656733dd | 160 | case 1: // no sensor present -> 'temp' is not updated |
kuutei | 1:7749656733dd | 161 | //pc.printf("no sensor present\n\r"); |
kuutei | 1:7749656733dd | 162 | ds18b20_temperature = -302.0; |
kuutei | 1:7749656733dd | 163 | break; |
kuutei | 1:7749656733dd | 164 | |
kuutei | 1:7749656733dd | 165 | case 2: // CRC error -> 'temp' is not updated |
kuutei | 1:7749656733dd | 166 | //pc.printf("CRC error\r\n"); |
kuutei | 1:7749656733dd | 167 | ds18b20_temperature = -303.0; |
kuutei | 1:7749656733dd | 168 | } |
kuutei | 0:56122e281547 | 169 | |
kuutei | 0:56122e281547 | 170 | ThisThread::sleep_for(250); |
kuutei | 0:56122e281547 | 171 | |
kuutei | 0:56122e281547 | 172 | } |
kuutei | 0:56122e281547 | 173 | } |
kuutei | 0:56122e281547 | 174 | |
kuutei | 0:56122e281547 | 175 | // Detect battery presence by voltage activity |
kuutei | 0:56122e281547 | 176 | bool batteryPresent() |
kuutei | 0:56122e281547 | 177 | { |
kuutei | 1:7749656733dd | 178 | if(bat_voltage_avg > MIN_DETECT_VOLTAGE) |
kuutei | 0:56122e281547 | 179 | { |
kuutei | 0:56122e281547 | 180 | return true; |
kuutei | 0:56122e281547 | 181 | } |
kuutei | 1:7749656733dd | 182 | else |
kuutei | 1:7749656733dd | 183 | { |
kuutei | 1:7749656733dd | 184 | return false; |
kuutei | 1:7749656733dd | 185 | } |
kuutei | 0:56122e281547 | 186 | } |
kuutei | 0:56122e281547 | 187 | |
kuutei | 0:56122e281547 | 188 | void TP4056ControlThread() |
kuutei | 0:56122e281547 | 189 | { |
kuutei | 0:56122e281547 | 190 | //uint64_t now = Kernel::get_ms_count(); |
kuutei | 0:56122e281547 | 191 | uint64_t chargeStartTime = 0; |
kuutei | 0:56122e281547 | 192 | |
kuutei | 0:56122e281547 | 193 | bool enableCharging = false; //internal variable to track whether TP4056 CE should be enabled or not |
kuutei | 0:56122e281547 | 194 | |
kuutei | 0:56122e281547 | 195 | |
kuutei | 0:56122e281547 | 196 | while(true) |
kuutei | 0:56122e281547 | 197 | { |
kuutei | 0:56122e281547 | 198 | //First check conditions to see if charging should be enabled or disabled |
kuutei | 1:7749656733dd | 199 | bool temperature_en = ( ( ds18b20_temperature < MAX_TEMPERATURE ) && ( ds18b20_temperature > MIN_TEMPERATURE ) ); |
kuutei | 1:7749656733dd | 200 | bool voltage_en = ( ( bat_voltage_avg < MAX_VOLTAGE ) && ( bat_voltage_avg > MIN_VOLTAGE ) ); |
kuutei | 1:7749656733dd | 201 | bool presence_en = batteryPresent(); |
kuutei | 1:7749656733dd | 202 | bool charge_time_exceeded = ( (Kernel::get_ms_count() - chargeStartTime ) > MAX_TIME_ms); |
kuutei | 1:7749656733dd | 203 | |
kuutei | 0:56122e281547 | 204 | //Charging can be enabled if battery is present, no protections triggered, and user starts the charge |
kuutei | 0:56122e281547 | 205 | if(enableCharging == false) |
kuutei | 1:7749656733dd | 206 | { |
kuutei | 1:7749656733dd | 207 | if( voltage_en && temperature_en && presence_en && buttonPressed ) |
kuutei | 1:7749656733dd | 208 | { |
kuutei | 1:7749656733dd | 209 | enableCharging = true; |
kuutei | 1:7749656733dd | 210 | buttonPressed = false; |
kuutei | 1:7749656733dd | 211 | } |
kuutei | 1:7749656733dd | 212 | } |
kuutei | 1:7749656733dd | 213 | //Charging must be stopped if overvoltage, overtemperature, overtime, battery removed, or user pushes button |
kuutei | 1:7749656733dd | 214 | else |
kuutei | 0:56122e281547 | 215 | { |
kuutei | 1:7749656733dd | 216 | //Disable charging if any protection condition is triggered |
kuutei | 1:7749656733dd | 217 | if( !voltage_en || !temperature_en || !presence_en ) |
kuutei | 1:7749656733dd | 218 | { |
kuutei | 1:7749656733dd | 219 | enableCharging = false; |
kuutei | 1:7749656733dd | 220 | } |
kuutei | 1:7749656733dd | 221 | //or if user pushed button |
kuutei | 1:7749656733dd | 222 | else if(buttonPressed) |
kuutei | 1:7749656733dd | 223 | { |
kuutei | 1:7749656733dd | 224 | buttonPressed = false; |
kuutei | 1:7749656733dd | 225 | } |
kuutei | 0:56122e281547 | 226 | } |
kuutei | 0:56122e281547 | 227 | |
kuutei | 0:56122e281547 | 228 | |
kuutei | 0:56122e281547 | 229 | //With charge state calculated, realize it on the CE pin |
kuutei | 0:56122e281547 | 230 | //Allow pullup to 5V to enable charging at CE pin |
kuutei | 0:56122e281547 | 231 | if(enableCharging) |
kuutei | 0:56122e281547 | 232 | { |
kuutei | 0:56122e281547 | 233 | toggleOut.write(1); //open drain mode -> HiZ |
kuutei | 0:56122e281547 | 234 | chargeStartTime = Kernel::get_ms_count(); |
kuutei | 0:56122e281547 | 235 | } |
kuutei | 0:56122e281547 | 236 | //To disable charging, open drain the CE pin |
kuutei | 0:56122e281547 | 237 | else |
kuutei | 0:56122e281547 | 238 | { |
kuutei | 0:56122e281547 | 239 | toggleOut.write(0); //open drain, pull to GND -> overpull 470k pullup that brings 5V to CE |
kuutei | 0:56122e281547 | 240 | } |
kuutei | 0:56122e281547 | 241 | |
kuutei | 0:56122e281547 | 242 | //Update flag that indicates state of TP4056 CE pin to other threads |
kuutei | 1:7749656733dd | 243 | TP4056ChargingState = enableCharging; |
kuutei | 0:56122e281547 | 244 | |
kuutei | 0:56122e281547 | 245 | ThisThread::sleep_for(100); |
kuutei | 0:56122e281547 | 246 | } |
kuutei | 0:56122e281547 | 247 | } |
kuutei | 0:56122e281547 | 248 | |
kuutei | 0:56122e281547 | 249 | void oledOutputThread() |
kuutei | 0:56122e281547 | 250 | { |
kuutei | 0:56122e281547 | 251 | while(true) |
kuutei | 0:56122e281547 | 252 | { |
kuutei | 0:56122e281547 | 253 | oled_i2c.clear(); |
kuutei | 0:56122e281547 | 254 | |
kuutei | 0:56122e281547 | 255 | std::stringstream stream; |
kuutei | 0:56122e281547 | 256 | stream << std::fixed << std::setprecision(4) << bat_voltage_avg; |
kuutei | 0:56122e281547 | 257 | //std::string voltage_output = "Voltage: "+std::to_string(bat_voltage); |
kuutei | 0:56122e281547 | 258 | std::string voltage_output = "Voltage: " + stream.str(); |
kuutei | 0:56122e281547 | 259 | oled_i2c.drawString(0, 0, voltage_output.c_str() ); |
kuutei | 0:56122e281547 | 260 | |
kuutei | 1:7749656733dd | 261 | if(TP4056ChargingState){ |
kuutei | 0:56122e281547 | 262 | oled_i2c.drawString(0, 16, "CE: Enabled"); |
kuutei | 0:56122e281547 | 263 | } else { |
kuutei | 0:56122e281547 | 264 | oled_i2c.drawString(0, 16, "CE: Disabled"); |
kuutei | 0:56122e281547 | 265 | } |
kuutei | 0:56122e281547 | 266 | |
kuutei | 0:56122e281547 | 267 | |
kuutei | 0:56122e281547 | 268 | stream.str(""); |
kuutei | 0:56122e281547 | 269 | stream << std::fixed << std::setprecision(4) << vddref_voltage; |
kuutei | 0:56122e281547 | 270 | std::string vddref_output = "VDDREF: " + stream.str(); |
kuutei | 0:56122e281547 | 271 | oled_i2c.drawString(0,16*2, vddref_output.c_str() ); |
kuutei | 0:56122e281547 | 272 | |
kuutei | 0:56122e281547 | 273 | |
kuutei | 0:56122e281547 | 274 | oled_i2c.display(); |
kuutei | 0:56122e281547 | 275 | ThisThread::sleep_for(250); |
kuutei | 0:56122e281547 | 276 | } |
kuutei | 0:56122e281547 | 277 | |
kuutei | 0:56122e281547 | 278 | } |
kuutei | 0:56122e281547 | 279 | |
kuutei | 0:56122e281547 | 280 | int main() |
kuutei | 0:56122e281547 | 281 | { |
kuutei | 0:56122e281547 | 282 | pc.baud(9600); |
kuutei | 0:56122e281547 | 283 | pc.printf("Started\r\n"); |
kuutei | 0:56122e281547 | 284 | |
kuutei | 0:56122e281547 | 285 | //BUILT IN LED THREAD |
kuutei | 0:56122e281547 | 286 | Thread led1; |
kuutei | 0:56122e281547 | 287 | //osStatus err = led1.start(&blinkled); |
kuutei | 0:56122e281547 | 288 | led1.start(blinkled); |
kuutei | 0:56122e281547 | 289 | |
kuutei | 0:56122e281547 | 290 | // CONFIGURE TP4056 CE CONTROL FOR OPEN DRAIN WITH EXTERNAL 5V PULLUP |
kuutei | 0:56122e281547 | 291 | //https://forums.mbed.com/t/how-to-configure-open-drain-output-pin-on-stm32/7007 |
kuutei | 0:56122e281547 | 292 | toggleOut.mode(OpenDrainNoPull); |
kuutei | 0:56122e281547 | 293 | |
kuutei | 0:56122e281547 | 294 | // CHARGE ENABLE CONTROL THREAD |
kuutei | 0:56122e281547 | 295 | Thread tp4056_control_thread; |
kuutei | 0:56122e281547 | 296 | tp4056_control_thread.start(TP4056ControlThread); |
kuutei | 0:56122e281547 | 297 | |
kuutei | 0:56122e281547 | 298 | //OLED 128x64 INIT AND THREAD |
kuutei | 0:56122e281547 | 299 | //initialize ssd1306 on i2c0 |
kuutei | 0:56122e281547 | 300 | oled_i2c.init(); |
kuutei | 0:56122e281547 | 301 | oled_i2c.flipScreenVertically(); |
kuutei | 0:56122e281547 | 302 | oled_i2c.setFont(ArialMT_Plain_16); |
kuutei | 0:56122e281547 | 303 | oled_i2c.drawString(0,0,"init!"); |
kuutei | 0:56122e281547 | 304 | oled_i2c.display(); |
kuutei | 0:56122e281547 | 305 | |
kuutei | 0:56122e281547 | 306 | Thread oled_thread; |
kuutei | 0:56122e281547 | 307 | oled_thread.start(oledOutputThread); |
kuutei | 0:56122e281547 | 308 | |
kuutei | 0:56122e281547 | 309 | // START/STOP CHARGE BUTTON |
kuutei | 0:56122e281547 | 310 | chargeButton.rise(&buttonISR); |
kuutei | 0:56122e281547 | 311 | |
kuutei | 0:56122e281547 | 312 | |
kuutei | 0:56122e281547 | 313 | float bat_voltage_min; |
kuutei | 0:56122e281547 | 314 | float bat_voltage_max; |
kuutei | 0:56122e281547 | 315 | float bat_voltage_avg_sum; |
kuutei | 0:56122e281547 | 316 | |
kuutei | 0:56122e281547 | 317 | uint64_t now = Kernel::get_ms_count(); |
kuutei | 0:56122e281547 | 318 | uint64_t lastADCStartTime = now; |
kuutei | 0:56122e281547 | 319 | |
kuutei | 0:56122e281547 | 320 | while(true) |
kuutei | 0:56122e281547 | 321 | { |
kuutei | 0:56122e281547 | 322 | // reset min and max values |
kuutei | 0:56122e281547 | 323 | bat_voltage_min = 10.0; |
kuutei | 0:56122e281547 | 324 | bat_voltage_max = -10.0; |
kuutei | 0:56122e281547 | 325 | bat_voltage_avg_sum = 0.0; |
kuutei | 0:56122e281547 | 326 | |
kuutei | 0:56122e281547 | 327 | lastADCStartTime = Kernel::get_ms_count(); |
kuutei | 0:56122e281547 | 328 | for(int i = 0; i < 1000; i++) |
kuutei | 0:56122e281547 | 329 | { |
kuutei | 0:56122e281547 | 330 | bat_voltage = readVoltageDivider_Calibrated(); |
kuutei | 0:56122e281547 | 331 | vddref_voltage = readRefVoltage(); |
kuutei | 0:56122e281547 | 332 | bat_voltage_avg_sum += bat_voltage; |
kuutei | 0:56122e281547 | 333 | if( bat_voltage < bat_voltage_min ) |
kuutei | 0:56122e281547 | 334 | { |
kuutei | 0:56122e281547 | 335 | bat_voltage_min = bat_voltage; |
kuutei | 0:56122e281547 | 336 | } |
kuutei | 0:56122e281547 | 337 | if( bat_voltage > bat_voltage_max ) |
kuutei | 0:56122e281547 | 338 | { |
kuutei | 0:56122e281547 | 339 | bat_voltage_max = bat_voltage; |
kuutei | 0:56122e281547 | 340 | } |
kuutei | 0:56122e281547 | 341 | |
kuutei | 0:56122e281547 | 342 | ThisThread::sleep_for(1); |
kuutei | 0:56122e281547 | 343 | } |
kuutei | 0:56122e281547 | 344 | now = Kernel::get_ms_count(); |
kuutei | 0:56122e281547 | 345 | |
kuutei | 0:56122e281547 | 346 | bat_voltage_avg = bat_voltage_avg_sum/1000.0; |
kuutei | 0:56122e281547 | 347 | |
kuutei | 0:56122e281547 | 348 | pc.printf("\r\nADC0 Reading: %6.4f\r\n", bat_voltage); |
kuutei | 0:56122e281547 | 349 | pc.printf("ADC0 1s min: %6.4f\r\n", bat_voltage_min); |
kuutei | 0:56122e281547 | 350 | pc.printf("ADC0 1s max: %6.4f\r\n", bat_voltage_max); |
kuutei | 0:56122e281547 | 351 | pc.printf("ADC0 1s avg: %6.4f\r\n", bat_voltage_avg); |
kuutei | 0:56122e281547 | 352 | pc.printf("VDDREF Reading: %6.4f\r\n", vddref_voltage); |
kuutei | 1:7749656733dd | 353 | pc.printf("ADC0 time (nominal 1000ms): %llu\r\n", (now-lastADCStartTime)); |
kuutei | 0:56122e281547 | 354 | |
kuutei | 0:56122e281547 | 355 | } |
kuutei | 0:56122e281547 | 356 | |
kuutei | 0:56122e281547 | 357 | } |