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@3:0bad8eec80ee, 2020-08-26 (annotated)
- Committer:
- kuutei
- Date:
- Wed Aug 26 02:21:29 2020 +0000
- Revision:
- 3:0bad8eec80ee
- Parent:
- 2:18d8f9d3286c
- Child:
- 4:f63aab9fec77
switching to other ds18b20 library
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 | 3:0bad8eec80ee | 15 | #define DS18B20_DATA D4 |
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 | 2:18d8f9d3286c | 147 | //Initialize sensor |
kuutei | 2:18d8f9d3286c | 148 | if(ds1820_sensor.begin()) { |
kuutei | 2:18d8f9d3286c | 149 | ds1820_sensor.startConversion(); // start temperature conversion |
kuutei | 2:18d8f9d3286c | 150 | ThisThread::sleep_for(1); // let DS1820 complete the temperature conversion |
kuutei | 2:18d8f9d3286c | 151 | pc.printf("Initial DS18B20 temp = %3.2f\r\n", ds1820_sensor.read()); // read temperature |
kuutei | 2:18d8f9d3286c | 152 | //Without temperature sensor, charging will not work (unless minimum temperature set below -310.0) |
kuutei | 2:18d8f9d3286c | 153 | }else{ |
kuutei | 2:18d8f9d3286c | 154 | pc.printf("No DS1820 sensor found!\r\n"); |
kuutei | 2:18d8f9d3286c | 155 | } |
kuutei | 2:18d8f9d3286c | 156 | |
kuutei | 0:56122e281547 | 157 | while(true) |
kuutei | 0:56122e281547 | 158 | { |
kuutei | 1:7749656733dd | 159 | ds1820_sensor.startConversion(); // start temperature conversion from analog to digital |
kuutei | 1:7749656733dd | 160 | // let DS1820 complete the temperature conversion |
kuutei | 1:7749656733dd | 161 | ThisThread::sleep_for(1.0); |
kuutei | 1:7749656733dd | 162 | ds18b20_result = ds1820_sensor.read(temp); // read temperature from DS1820 and perform cyclic redundancy check (CRC) |
kuutei | 0:56122e281547 | 163 | |
kuutei | 1:7749656733dd | 164 | switch (ds18b20_result) { |
kuutei | 1:7749656733dd | 165 | case 0: // no errors -> 'temp' contains the value of measured temperature |
kuutei | 1:7749656733dd | 166 | //pc.printf("temp = %3.4f%cC\r\n", temp, 176); |
kuutei | 1:7749656733dd | 167 | ds18b20_temperature = temp; |
kuutei | 1:7749656733dd | 168 | break; |
kuutei | 1:7749656733dd | 169 | |
kuutei | 1:7749656733dd | 170 | case 1: // no sensor present -> 'temp' is not updated |
kuutei | 1:7749656733dd | 171 | //pc.printf("no sensor present\n\r"); |
kuutei | 1:7749656733dd | 172 | ds18b20_temperature = -302.0; |
kuutei | 1:7749656733dd | 173 | break; |
kuutei | 1:7749656733dd | 174 | |
kuutei | 1:7749656733dd | 175 | case 2: // CRC error -> 'temp' is not updated |
kuutei | 1:7749656733dd | 176 | //pc.printf("CRC error\r\n"); |
kuutei | 1:7749656733dd | 177 | ds18b20_temperature = -303.0; |
kuutei | 1:7749656733dd | 178 | } |
kuutei | 0:56122e281547 | 179 | |
kuutei | 0:56122e281547 | 180 | ThisThread::sleep_for(250); |
kuutei | 0:56122e281547 | 181 | |
kuutei | 0:56122e281547 | 182 | } |
kuutei | 0:56122e281547 | 183 | } |
kuutei | 0:56122e281547 | 184 | |
kuutei | 0:56122e281547 | 185 | // Detect battery presence by voltage activity |
kuutei | 2:18d8f9d3286c | 186 | void BatteryPresenceThread() |
kuutei | 0:56122e281547 | 187 | { |
kuutei | 2:18d8f9d3286c | 188 | while(true) |
kuutei | 0:56122e281547 | 189 | { |
kuutei | 2:18d8f9d3286c | 190 | if(bat_voltage_avg > MIN_DETECT_VOLTAGE) |
kuutei | 2:18d8f9d3286c | 191 | { |
kuutei | 2:18d8f9d3286c | 192 | batteryPresenceState = true; |
kuutei | 2:18d8f9d3286c | 193 | } |
kuutei | 2:18d8f9d3286c | 194 | else |
kuutei | 2:18d8f9d3286c | 195 | { |
kuutei | 2:18d8f9d3286c | 196 | batteryPresenceState = false; |
kuutei | 2:18d8f9d3286c | 197 | } |
kuutei | 2:18d8f9d3286c | 198 | |
kuutei | 2:18d8f9d3286c | 199 | ThisThread::sleep_for(250); |
kuutei | 1:7749656733dd | 200 | } |
kuutei | 0:56122e281547 | 201 | } |
kuutei | 0:56122e281547 | 202 | |
kuutei | 0:56122e281547 | 203 | void TP4056ControlThread() |
kuutei | 0:56122e281547 | 204 | { |
kuutei | 0:56122e281547 | 205 | //uint64_t now = Kernel::get_ms_count(); |
kuutei | 0:56122e281547 | 206 | uint64_t chargeStartTime = 0; |
kuutei | 0:56122e281547 | 207 | |
kuutei | 0:56122e281547 | 208 | bool enableCharging = false; //internal variable to track whether TP4056 CE should be enabled or not |
kuutei | 0:56122e281547 | 209 | |
kuutei | 0:56122e281547 | 210 | |
kuutei | 0:56122e281547 | 211 | while(true) |
kuutei | 0:56122e281547 | 212 | { |
kuutei | 0:56122e281547 | 213 | //First check conditions to see if charging should be enabled or disabled |
kuutei | 3:0bad8eec80ee | 214 | // bool temperature_en = ( ( ds18b20_temperature < MAX_TEMPERATURE ) && ( ds18b20_temperature > MIN_TEMPERATURE ) ); |
kuutei | 3:0bad8eec80ee | 215 | bool temperature_en = true; //override as sensor code is bugged |
kuutei | 1:7749656733dd | 216 | bool voltage_en = ( ( bat_voltage_avg < MAX_VOLTAGE ) && ( bat_voltage_avg > MIN_VOLTAGE ) ); |
kuutei | 2:18d8f9d3286c | 217 | bool presence_en = batteryPresenceState; |
kuutei | 1:7749656733dd | 218 | bool charge_time_exceeded = ( (Kernel::get_ms_count() - chargeStartTime ) > MAX_TIME_ms); |
kuutei | 1:7749656733dd | 219 | |
kuutei | 0:56122e281547 | 220 | //Charging can be enabled if battery is present, no protections triggered, and user starts the charge |
kuutei | 0:56122e281547 | 221 | if(enableCharging == false) |
kuutei | 1:7749656733dd | 222 | { |
kuutei | 2:18d8f9d3286c | 223 | if( voltage_en && temperature_en && presence_en && !charge_time_exceeded && buttonPressed ) |
kuutei | 1:7749656733dd | 224 | { |
kuutei | 1:7749656733dd | 225 | enableCharging = true; |
kuutei | 2:18d8f9d3286c | 226 | chargeStartTime = Kernel::get_ms_count(); |
kuutei | 1:7749656733dd | 227 | buttonPressed = false; |
kuutei | 1:7749656733dd | 228 | } |
kuutei | 1:7749656733dd | 229 | } |
kuutei | 1:7749656733dd | 230 | //Charging must be stopped if overvoltage, overtemperature, overtime, battery removed, or user pushes button |
kuutei | 1:7749656733dd | 231 | else |
kuutei | 0:56122e281547 | 232 | { |
kuutei | 1:7749656733dd | 233 | //Disable charging if any protection condition is triggered |
kuutei | 2:18d8f9d3286c | 234 | if( !voltage_en || !temperature_en || !presence_en || charge_time_exceeded ) |
kuutei | 1:7749656733dd | 235 | { |
kuutei | 1:7749656733dd | 236 | enableCharging = false; |
kuutei | 1:7749656733dd | 237 | } |
kuutei | 1:7749656733dd | 238 | //or if user pushed button |
kuutei | 1:7749656733dd | 239 | else if(buttonPressed) |
kuutei | 3:0bad8eec80ee | 240 | { |
kuutei | 3:0bad8eec80ee | 241 | enableCharging = false; |
kuutei | 1:7749656733dd | 242 | buttonPressed = false; |
kuutei | 1:7749656733dd | 243 | } |
kuutei | 0:56122e281547 | 244 | } |
kuutei | 0:56122e281547 | 245 | |
kuutei | 0:56122e281547 | 246 | |
kuutei | 0:56122e281547 | 247 | //With charge state calculated, realize it on the CE pin |
kuutei | 0:56122e281547 | 248 | //Allow pullup to 5V to enable charging at CE pin |
kuutei | 0:56122e281547 | 249 | if(enableCharging) |
kuutei | 0:56122e281547 | 250 | { |
kuutei | 0:56122e281547 | 251 | toggleOut.write(1); //open drain mode -> HiZ |
kuutei | 0:56122e281547 | 252 | chargeStartTime = Kernel::get_ms_count(); |
kuutei | 0:56122e281547 | 253 | } |
kuutei | 0:56122e281547 | 254 | //To disable charging, open drain the CE pin |
kuutei | 0:56122e281547 | 255 | else |
kuutei | 0:56122e281547 | 256 | { |
kuutei | 0:56122e281547 | 257 | toggleOut.write(0); //open drain, pull to GND -> overpull 470k pullup that brings 5V to CE |
kuutei | 0:56122e281547 | 258 | } |
kuutei | 0:56122e281547 | 259 | |
kuutei | 0:56122e281547 | 260 | //Update flag that indicates state of TP4056 CE pin to other threads |
kuutei | 1:7749656733dd | 261 | TP4056ChargingState = enableCharging; |
kuutei | 0:56122e281547 | 262 | |
kuutei | 2:18d8f9d3286c | 263 | ThisThread::sleep_for(100); |
kuutei | 0:56122e281547 | 264 | } |
kuutei | 0:56122e281547 | 265 | } |
kuutei | 0:56122e281547 | 266 | |
kuutei | 0:56122e281547 | 267 | void oledOutputThread() |
kuutei | 0:56122e281547 | 268 | { |
kuutei | 0:56122e281547 | 269 | while(true) |
kuutei | 0:56122e281547 | 270 | { |
kuutei | 0:56122e281547 | 271 | oled_i2c.clear(); |
kuutei | 0:56122e281547 | 272 | |
kuutei | 0:56122e281547 | 273 | std::stringstream stream; |
kuutei | 0:56122e281547 | 274 | stream << std::fixed << std::setprecision(4) << bat_voltage_avg; |
kuutei | 0:56122e281547 | 275 | //std::string voltage_output = "Voltage: "+std::to_string(bat_voltage); |
kuutei | 0:56122e281547 | 276 | std::string voltage_output = "Voltage: " + stream.str(); |
kuutei | 0:56122e281547 | 277 | oled_i2c.drawString(0, 0, voltage_output.c_str() ); |
kuutei | 0:56122e281547 | 278 | |
kuutei | 1:7749656733dd | 279 | if(TP4056ChargingState){ |
kuutei | 0:56122e281547 | 280 | oled_i2c.drawString(0, 16, "CE: Enabled"); |
kuutei | 0:56122e281547 | 281 | } else { |
kuutei | 0:56122e281547 | 282 | oled_i2c.drawString(0, 16, "CE: Disabled"); |
kuutei | 0:56122e281547 | 283 | } |
kuutei | 0:56122e281547 | 284 | |
kuutei | 0:56122e281547 | 285 | |
kuutei | 0:56122e281547 | 286 | stream.str(""); |
kuutei | 2:18d8f9d3286c | 287 | stream << std::fixed << std::setprecision(4) << ds18b20_temperature; |
kuutei | 2:18d8f9d3286c | 288 | std::string ds18_str = "Temp: " + stream.str(); |
kuutei | 2:18d8f9d3286c | 289 | oled_i2c.drawString(0,16*2, ds18_str.c_str() ); |
kuutei | 2:18d8f9d3286c | 290 | //stream << std::fixed << std::setprecision(4) << vddref_voltage; |
kuutei | 2:18d8f9d3286c | 291 | //std::string vddref_output = "VDDREF: " + stream.str(); |
kuutei | 2:18d8f9d3286c | 292 | //oled_i2c.drawString(0,16*2, vddref_output.c_str() ); |
kuutei | 0:56122e281547 | 293 | |
kuutei | 0:56122e281547 | 294 | |
kuutei | 0:56122e281547 | 295 | oled_i2c.display(); |
kuutei | 0:56122e281547 | 296 | ThisThread::sleep_for(250); |
kuutei | 0:56122e281547 | 297 | } |
kuutei | 0:56122e281547 | 298 | |
kuutei | 0:56122e281547 | 299 | } |
kuutei | 0:56122e281547 | 300 | |
kuutei | 0:56122e281547 | 301 | int main() |
kuutei | 0:56122e281547 | 302 | { |
kuutei | 0:56122e281547 | 303 | pc.baud(9600); |
kuutei | 0:56122e281547 | 304 | pc.printf("Started\r\n"); |
kuutei | 0:56122e281547 | 305 | |
kuutei | 0:56122e281547 | 306 | //BUILT IN LED THREAD |
kuutei | 0:56122e281547 | 307 | Thread led1; |
kuutei | 0:56122e281547 | 308 | //osStatus err = led1.start(&blinkled); |
kuutei | 0:56122e281547 | 309 | led1.start(blinkled); |
kuutei | 0:56122e281547 | 310 | |
kuutei | 0:56122e281547 | 311 | // CONFIGURE TP4056 CE CONTROL FOR OPEN DRAIN WITH EXTERNAL 5V PULLUP |
kuutei | 0:56122e281547 | 312 | //https://forums.mbed.com/t/how-to-configure-open-drain-output-pin-on-stm32/7007 |
kuutei | 0:56122e281547 | 313 | toggleOut.mode(OpenDrainNoPull); |
kuutei | 0:56122e281547 | 314 | |
kuutei | 2:18d8f9d3286c | 315 | // TEMPERATURE INPUT THREAD |
kuutei | 2:18d8f9d3286c | 316 | Thread ds18b20_temperature_thread; |
kuutei | 2:18d8f9d3286c | 317 | ds18b20_temperature_thread.start(TemperatureInputThread); |
kuutei | 2:18d8f9d3286c | 318 | |
kuutei | 0:56122e281547 | 319 | // CHARGE ENABLE CONTROL THREAD |
kuutei | 0:56122e281547 | 320 | Thread tp4056_control_thread; |
kuutei | 0:56122e281547 | 321 | tp4056_control_thread.start(TP4056ControlThread); |
kuutei | 0:56122e281547 | 322 | |
kuutei | 2:18d8f9d3286c | 323 | // PRESENCE DETECTION THREAD |
kuutei | 2:18d8f9d3286c | 324 | Thread bat_presence_thread; |
kuutei | 2:18d8f9d3286c | 325 | bat_presence_thread.start(BatteryPresenceThread); |
kuutei | 2:18d8f9d3286c | 326 | |
kuutei | 0:56122e281547 | 327 | //OLED 128x64 INIT AND THREAD |
kuutei | 0:56122e281547 | 328 | //initialize ssd1306 on i2c0 |
kuutei | 0:56122e281547 | 329 | oled_i2c.init(); |
kuutei | 0:56122e281547 | 330 | oled_i2c.flipScreenVertically(); |
kuutei | 0:56122e281547 | 331 | oled_i2c.setFont(ArialMT_Plain_16); |
kuutei | 0:56122e281547 | 332 | oled_i2c.drawString(0,0,"init!"); |
kuutei | 0:56122e281547 | 333 | oled_i2c.display(); |
kuutei | 0:56122e281547 | 334 | |
kuutei | 0:56122e281547 | 335 | Thread oled_thread; |
kuutei | 0:56122e281547 | 336 | oled_thread.start(oledOutputThread); |
kuutei | 0:56122e281547 | 337 | |
kuutei | 0:56122e281547 | 338 | // START/STOP CHARGE BUTTON |
kuutei | 0:56122e281547 | 339 | chargeButton.rise(&buttonISR); |
kuutei | 0:56122e281547 | 340 | |
kuutei | 0:56122e281547 | 341 | |
kuutei | 0:56122e281547 | 342 | float bat_voltage_min; |
kuutei | 0:56122e281547 | 343 | float bat_voltage_max; |
kuutei | 0:56122e281547 | 344 | float bat_voltage_avg_sum; |
kuutei | 0:56122e281547 | 345 | |
kuutei | 0:56122e281547 | 346 | uint64_t now = Kernel::get_ms_count(); |
kuutei | 0:56122e281547 | 347 | uint64_t lastADCStartTime = now; |
kuutei | 0:56122e281547 | 348 | |
kuutei | 0:56122e281547 | 349 | while(true) |
kuutei | 0:56122e281547 | 350 | { |
kuutei | 0:56122e281547 | 351 | // reset min and max values |
kuutei | 0:56122e281547 | 352 | bat_voltage_min = 10.0; |
kuutei | 0:56122e281547 | 353 | bat_voltage_max = -10.0; |
kuutei | 0:56122e281547 | 354 | bat_voltage_avg_sum = 0.0; |
kuutei | 0:56122e281547 | 355 | |
kuutei | 0:56122e281547 | 356 | lastADCStartTime = Kernel::get_ms_count(); |
kuutei | 0:56122e281547 | 357 | for(int i = 0; i < 1000; i++) |
kuutei | 0:56122e281547 | 358 | { |
kuutei | 0:56122e281547 | 359 | bat_voltage = readVoltageDivider_Calibrated(); |
kuutei | 0:56122e281547 | 360 | vddref_voltage = readRefVoltage(); |
kuutei | 0:56122e281547 | 361 | bat_voltage_avg_sum += bat_voltage; |
kuutei | 0:56122e281547 | 362 | if( bat_voltage < bat_voltage_min ) |
kuutei | 0:56122e281547 | 363 | { |
kuutei | 0:56122e281547 | 364 | bat_voltage_min = bat_voltage; |
kuutei | 0:56122e281547 | 365 | } |
kuutei | 0:56122e281547 | 366 | if( bat_voltage > bat_voltage_max ) |
kuutei | 0:56122e281547 | 367 | { |
kuutei | 0:56122e281547 | 368 | bat_voltage_max = bat_voltage; |
kuutei | 0:56122e281547 | 369 | } |
kuutei | 0:56122e281547 | 370 | |
kuutei | 0:56122e281547 | 371 | ThisThread::sleep_for(1); |
kuutei | 0:56122e281547 | 372 | } |
kuutei | 0:56122e281547 | 373 | now = Kernel::get_ms_count(); |
kuutei | 0:56122e281547 | 374 | |
kuutei | 0:56122e281547 | 375 | bat_voltage_avg = bat_voltage_avg_sum/1000.0; |
kuutei | 0:56122e281547 | 376 | |
kuutei | 0:56122e281547 | 377 | pc.printf("\r\nADC0 Reading: %6.4f\r\n", bat_voltage); |
kuutei | 0:56122e281547 | 378 | pc.printf("ADC0 1s min: %6.4f\r\n", bat_voltage_min); |
kuutei | 0:56122e281547 | 379 | pc.printf("ADC0 1s max: %6.4f\r\n", bat_voltage_max); |
kuutei | 0:56122e281547 | 380 | pc.printf("ADC0 1s avg: %6.4f\r\n", bat_voltage_avg); |
kuutei | 2:18d8f9d3286c | 381 | pc.printf("ADC0 time (nominal 1000ms): %llu\r\n", (now-lastADCStartTime)); |
kuutei | 0:56122e281547 | 382 | pc.printf("VDDREF Reading: %6.4f\r\n", vddref_voltage); |
kuutei | 2:18d8f9d3286c | 383 | pc.printf("Temp: %6.4f\r\n", ds18b20_temperature); |
kuutei | 2:18d8f9d3286c | 384 | pc.printf("Bat present: %d\r\n", batteryPresenceState); |
kuutei | 0:56122e281547 | 385 | |
kuutei | 0:56122e281547 | 386 | } |
kuutei | 0:56122e281547 | 387 | |
kuutei | 0:56122e281547 | 388 | } |