Final project repo for ECE 495

Dependencies:   Adafruit_GFX_MBED Adafruit_ILI9341 BurstSPI DS1820 mbed mbed-rtos ltc2991_lib

Committer:
bdk9
Date:
Wed Dec 14 07:01:33 2016 +0000
Revision:
5:c1c710391df2
Parent:
3:a1b5d7541c69
big update yo

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bdk9 0:7ba4e0775670 1
bdk9 0:7ba4e0775670 2 #include "mbed.h"
bdk9 0:7ba4e0775670 3 #include "rtos.h"
bdk9 0:7ba4e0775670 4 #include "DS1820.h"
bdk9 0:7ba4e0775670 5 #include "TemperatureScreen.h"
bdk9 0:7ba4e0775670 6 #include "VoltageScreen.h"
bdk9 0:7ba4e0775670 7 #include "CurrentScreen.h"
bdk9 0:7ba4e0775670 8 #include "Display.h"
bdk9 5:c1c710391df2 9 #include "LTC2991.h"
bdk9 5:c1c710391df2 10 #include <stdarg.h>
bdk9 5:c1c710391df2 11
bdk9 5:c1c710391df2 12 struct SerialMessages {
bdk9 5:c1c710391df2 13 char *error_msg;
bdk9 5:c1c710391df2 14 char *next_screen;
bdk9 5:c1c710391df2 15 char *fet_state;
bdk9 5:c1c710391df2 16 char *fet_policy;
bdk9 5:c1c710391df2 17 char *relay_state;
bdk9 5:c1c710391df2 18 char *relay_policy;
bdk9 5:c1c710391df2 19 char *fan_voltage;
bdk9 5:c1c710391df2 20 };
bdk9 5:c1c710391df2 21
bdk9 5:c1c710391df2 22 struct PowerPolicy {
bdk9 5:c1c710391df2 23 int fet_id;
bdk9 5:c1c710391df2 24 int cur_id;
bdk9 5:c1c710391df2 25 double amp_max;
bdk9 5:c1c710391df2 26 PowerPolicy *next;
bdk9 5:c1c710391df2 27 };
bdk9 0:7ba4e0775670 28
bdk9 2:0a07f99e32c9 29 #define NUM_DS1820 1
bdk9 2:0a07f99e32c9 30 #define PIN_DS1820 PC_0
bdk9 0:7ba4e0775670 31
bdk9 0:7ba4e0775670 32 // DEVICES
bdk9 0:7ba4e0775670 33 DS1820* thermometers[NUM_DS1820];
bdk9 2:0a07f99e32c9 34 Adafruit_ILI9341 tft(PA_13, PA_15, PA_14);
bdk9 0:7ba4e0775670 35 Display disp;
bdk9 0:7ba4e0775670 36 RawSerial pc(USBTX, USBRX);
bdk9 0:7ba4e0775670 37 DigitalOut led(LED1);
bdk9 5:c1c710391df2 38 DigitalOut *fetPin[6];
bdk9 0:7ba4e0775670 39
bdk9 0:7ba4e0775670 40 // THREADS
bdk9 0:7ba4e0775670 41 Thread display_thread(osPriorityNormal, DEFAULT_STACK_SIZE, NULL);
bdk9 5:c1c710391df2 42 Thread fast_data_thread(osPriorityNormal, DEFAULT_STACK_SIZE, NULL);
bdk9 0:7ba4e0775670 43 Thread slow_data_thread(osPriorityNormal, DEFAULT_STACK_SIZE, NULL);
bdk9 3:a1b5d7541c69 44 Thread serial_thread(osPriorityNormal, DEFAULT_STACK_SIZE, NULL);
bdk9 0:7ba4e0775670 45
bdk9 0:7ba4e0775670 46 // DATA VARIABLES
bdk9 5:c1c710391df2 47 double temperatures[6];
bdk9 5:c1c710391df2 48 double old_temperatures[6];
bdk9 5:c1c710391df2 49 double voltages[4];
bdk9 5:c1c710391df2 50 double currents[10];
bdk9 5:c1c710391df2 51
bdk9 5:c1c710391df2 52 SerialMessages messages;
bdk9 5:c1c710391df2 53 PowerPolicy *head;
bdk9 5:c1c710391df2 54 PowerPolicy *tail;
bdk9 5:c1c710391df2 55
bdk9 5:c1c710391df2 56 double max_system_current = 30.0;
bdk9 5:c1c710391df2 57 DigitalOut relay_control(PA_0); //TODO update
bdk9 5:c1c710391df2 58 PwmOut fan_control(PA_0); // TODO update pin (FET controlling fan)
bdk9 0:7ba4e0775670 59
bdk9 0:7ba4e0775670 60 // DRAWING VARIABLES
bdk9 0:7ba4e0775670 61 int margin;
bdk9 5:c1c710391df2 62 int max_temp_plot = 75;
bdk9 0:7ba4e0775670 63 int axes_x_cur;
bdk9 0:7ba4e0775670 64 int axes_x_min, axes_x_max;
bdk9 0:7ba4e0775670 65 int axes_y_bot, axes_y_top;
bdk9 5:c1c710391df2 66 int temp_colors[6];
bdk9 5:c1c710391df2 67 int temp_label_rect_y[6];
bdk9 5:c1c710391df2 68 char *temp_label_str[6];
bdk9 5:c1c710391df2 69 int temp_label_str_x[6];
bdk9 5:c1c710391df2 70 int temp_label_str_y[6];
bdk9 5:c1c710391df2 71 int temp_val_y[6];
bdk9 0:7ba4e0775670 72 bool plotFlag;
bdk9 5:c1c710391df2 73 bool errFlag = false;
bdk9 5:c1c710391df2 74 char *errMsg;
bdk9 0:7ba4e0775670 75
bdk9 0:7ba4e0775670 76 // FUNCTION DECLARATIONS
bdk9 0:7ba4e0775670 77 int main();
bdk9 0:7ba4e0775670 78
bdk9 0:7ba4e0775670 79 // setup
bdk9 0:7ba4e0775670 80 void ds1820_init();
bdk9 0:7ba4e0775670 81 // thread drivers
bdk9 3:a1b5d7541c69 82 void display_task();
bdk9 0:7ba4e0775670 83 void slow_data_task();
bdk9 2:0a07f99e32c9 84 void fast_data_task();
bdk9 3:a1b5d7541c69 85 void serial_task();
bdk9 0:7ba4e0775670 86 // data read functions
bdk9 0:7ba4e0775670 87 void read_temps();
bdk9 0:7ba4e0775670 88 // ISRs
bdk9 5:c1c710391df2 89 void execute_command(char *cmd);
bdk9 0:7ba4e0775670 90 void parse_command();
bdk9 0:7ba4e0775670 91 // helpers
bdk9 0:7ba4e0775670 92 int scale_temp(double val, int min_domain, int max_domain, int min_range, int max_range);
bdk9 5:c1c710391df2 93
bdk9 5:c1c710391df2 94 void power_policy_init();
bdk9 5:c1c710391df2 95 void add_power_policy(int fet, int cur, double amps);
bdk9 5:c1c710391df2 96
bdk9 5:c1c710391df2 97 int8_t ack; // 0 == ack, 1 == no ack
bdk9 5:c1c710391df2 98 const uint16_t LTC2991_TIMEOUT=1000; //!< Configures the maximum timeout allowed for an LTC2991 read.
bdk9 5:c1c710391df2 99
bdk9 5:c1c710391df2 100 //These pins for the nucleo nucleo f401re
bdk9 5:c1c710391df2 101 LTC2991 *ltc0 = new LTC2991(I2C_SDA, I2C_SCL);
bdk9 5:c1c710391df2 102 LTC2991 *ltc1 = new LTC2991(PB_3, PB_10);
bdk9 5:c1c710391df2 103 LTC2991 *ltc2 = new LTC2991(PB_4, PA_8);
bdk9 5:c1c710391df2 104 float readSingle(LTC2991 *l, int p);
bdk9 5:c1c710391df2 105 float readDiff(LTC2991 *l, int upper_pin);
bdk9 5:c1c710391df2 106 void ltc_init();
bdk9 5:c1c710391df2 107
bdk9 5:c1c710391df2 108
bdk9 0:7ba4e0775670 109
bdk9 5:c1c710391df2 110 void ltc_init() {
bdk9 5:c1c710391df2 111 ack = 0;
bdk9 5:c1c710391df2 112
bdk9 5:c1c710391df2 113 while (true)
bdk9 5:c1c710391df2 114 {
bdk9 5:c1c710391df2 115 int failures = 0;
bdk9 5:c1c710391df2 116 pc.printf("booting LTC0\n");
bdk9 5:c1c710391df2 117 ack |= ltc0->LTC2991_register_write(LTC2991_I2C_ADDRESS, LTC2991_CHANNEL_ENABLE_REG, LTC2991_ENABLE_ALL_CHANNELS); //! Enables all channels
bdk9 5:c1c710391df2 118 ack |= ltc0->LTC2991_register_write(LTC2991_I2C_ADDRESS, LTC2991_CONTROL_V1234_REG, 0x00); //! Sets registers to default starting values.
bdk9 5:c1c710391df2 119 ack |= ltc0->LTC2991_register_write(LTC2991_I2C_ADDRESS, LTC2991_CONTROL_V5678_REG, 0x00);
bdk9 5:c1c710391df2 120 ack |= ltc0->LTC2991_register_write(LTC2991_I2C_ADDRESS, LTC2991_CONTROL_PWM_Tinternal_REG, LTC2991_REPEAT_MODE); //! Configures LTC2991 for Repeated Acquisition mode
bdk9 5:c1c710391df2 121
bdk9 5:c1c710391df2 122 if (ack != 0) {
bdk9 5:c1c710391df2 123 pc.printf("Error: No Acknowledge LTC0. Check I2C Address.\n");
bdk9 5:c1c710391df2 124 failures++;
bdk9 5:c1c710391df2 125 }
bdk9 5:c1c710391df2 126
bdk9 5:c1c710391df2 127 pc.printf("booting LTC1\n");
bdk9 5:c1c710391df2 128 ack |= ltc1->LTC2991_register_write(LTC2991_I2C_ADDRESS, LTC2991_CHANNEL_ENABLE_REG, LTC2991_ENABLE_ALL_CHANNELS); //! Enables all channels
bdk9 5:c1c710391df2 129 ack |= ltc1->LTC2991_register_write(LTC2991_I2C_ADDRESS, LTC2991_CONTROL_V1234_REG, 0x00); //! Sets registers to default starting values.
bdk9 5:c1c710391df2 130 ack |= ltc1->LTC2991_register_write(LTC2991_I2C_ADDRESS, LTC2991_CONTROL_V5678_REG, 0x00);
bdk9 5:c1c710391df2 131 ack |= ltc1->LTC2991_register_write(LTC2991_I2C_ADDRESS, LTC2991_CONTROL_PWM_Tinternal_REG, LTC2991_REPEAT_MODE); //! Configures LTC2991 for Repeated Acquisition mode
bdk9 5:c1c710391df2 132
bdk9 5:c1c710391df2 133 if (ack != 0) {
bdk9 5:c1c710391df2 134 pc.printf("Error: No Acknowledge LTC1. Check I2C Address.\n");
bdk9 5:c1c710391df2 135 failures++;
bdk9 5:c1c710391df2 136 }
bdk9 5:c1c710391df2 137
bdk9 5:c1c710391df2 138 pc.printf("booting LTC2\n");
bdk9 5:c1c710391df2 139 ack |= ltc2->LTC2991_register_write(LTC2991_I2C_ADDRESS, LTC2991_CHANNEL_ENABLE_REG, LTC2991_ENABLE_ALL_CHANNELS); //! Enables all channels
bdk9 5:c1c710391df2 140 ack |= ltc2->LTC2991_register_write(LTC2991_I2C_ADDRESS, LTC2991_CONTROL_V1234_REG, 0x00); //! Sets registers to default starting values.
bdk9 5:c1c710391df2 141 ack |= ltc2->LTC2991_register_write(LTC2991_I2C_ADDRESS, LTC2991_CONTROL_V5678_REG, 0x00);
bdk9 5:c1c710391df2 142 ack |= ltc2->LTC2991_register_write(LTC2991_I2C_ADDRESS, LTC2991_CONTROL_PWM_Tinternal_REG, LTC2991_REPEAT_MODE); //! Configures LTC2991 for Repeated Acquisition mode
bdk9 5:c1c710391df2 143
bdk9 5:c1c710391df2 144 if (ack != 0) {
bdk9 5:c1c710391df2 145 pc.printf("Error: No Acknowledge LTC2. Check I2C Address.\n");
bdk9 5:c1c710391df2 146 failures++;
bdk9 5:c1c710391df2 147 }
bdk9 5:c1c710391df2 148
bdk9 5:c1c710391df2 149 if (failures > 0) {
bdk9 5:c1c710391df2 150 wait_ms(500);
bdk9 5:c1c710391df2 151 } else {
bdk9 5:c1c710391df2 152 break;
bdk9 5:c1c710391df2 153 }
bdk9 5:c1c710391df2 154 }
bdk9 0:7ba4e0775670 155 }
bdk9 0:7ba4e0775670 156
bdk9 5:c1c710391df2 157
bdk9 3:a1b5d7541c69 158 void display_task() {
bdk9 0:7ba4e0775670 159 while(1) {
bdk9 5:c1c710391df2 160 if (errFlag) {
bdk9 5:c1c710391df2 161 disp.error("A Fault Occured");
bdk9 5:c1c710391df2 162 errFlag = false;
bdk9 5:c1c710391df2 163 }
bdk9 5:c1c710391df2 164 else {
bdk9 5:c1c710391df2 165 disp.update();
bdk9 5:c1c710391df2 166 }
bdk9 0:7ba4e0775670 167 Thread::wait(1000);
bdk9 0:7ba4e0775670 168 }
bdk9 0:7ba4e0775670 169 }
bdk9 0:7ba4e0775670 170
bdk9 0:7ba4e0775670 171 void read_temps() {
bdk9 0:7ba4e0775670 172 double temp;
bdk9 0:7ba4e0775670 173 thermometers[0]->convertTemperature(false, DS1820::all_devices);
bdk9 0:7ba4e0775670 174 for (int i=0; i<NUM_DS1820; i++) {
bdk9 0:7ba4e0775670 175 temp = (double) thermometers[i]->temperature();
bdk9 0:7ba4e0775670 176 if (temp > 0 && temp < 150) {
bdk9 0:7ba4e0775670 177 old_temperatures[i] = temperatures[i];
bdk9 0:7ba4e0775670 178 temperatures[i] = temp;
bdk9 0:7ba4e0775670 179 }
bdk9 0:7ba4e0775670 180 }
bdk9 0:7ba4e0775670 181 }
bdk9 0:7ba4e0775670 182
bdk9 0:7ba4e0775670 183 void slow_data_task() {
bdk9 0:7ba4e0775670 184 //get initial reading
bdk9 0:7ba4e0775670 185 read_temps();
bdk9 0:7ba4e0775670 186
bdk9 0:7ba4e0775670 187 while(1) {
bdk9 0:7ba4e0775670 188 read_temps();
bdk9 0:7ba4e0775670 189 Thread::wait(500);
bdk9 0:7ba4e0775670 190 }
bdk9 0:7ba4e0775670 191 }
bdk9 0:7ba4e0775670 192
bdk9 3:a1b5d7541c69 193 void fast_data_task() {
bdk9 5:c1c710391df2 194 while(1) {
bdk9 5:c1c710391df2 195 // Voltages
bdk9 5:c1c710391df2 196 for (int i=0; i<4; i++) {
bdk9 5:c1c710391df2 197 voltages[i] = readSingle(ltc2, i+5);
bdk9 5:c1c710391df2 198 }
bdk9 5:c1c710391df2 199 // Currents
bdk9 5:c1c710391df2 200 currents[0] = readDiff(ltc0, 2);
bdk9 5:c1c710391df2 201 currents[1] = readDiff(ltc0, 4);
bdk9 5:c1c710391df2 202 currents[2] = readDiff(ltc0, 6);
bdk9 5:c1c710391df2 203 currents[3] = readDiff(ltc0, 8);
bdk9 5:c1c710391df2 204 currents[4] = readDiff(ltc1, 2);
bdk9 5:c1c710391df2 205 currents[5] = readDiff(ltc1, 4);
bdk9 5:c1c710391df2 206 currents[6] = readDiff(ltc1, 6);
bdk9 5:c1c710391df2 207 currents[7] = readDiff(ltc1, 8);
bdk9 5:c1c710391df2 208 currents[8] = readDiff(ltc2, 2);
bdk9 5:c1c710391df2 209 currents[9] = readDiff(ltc2, 4);
bdk9 5:c1c710391df2 210
bdk9 5:c1c710391df2 211 //Iterate over all power policies and act accordingly
bdk9 5:c1c710391df2 212 PowerPolicy *p = head;
bdk9 5:c1c710391df2 213 while (p->next != NULL) {
bdk9 5:c1c710391df2 214 if (currents[p->cur_id] > p->amp_max) {
bdk9 5:c1c710391df2 215 //Shutdown condition reached. Turn off until restart and alert
bdk9 5:c1c710391df2 216 *(fetPin[p->fet_id]) = 0;
bdk9 5:c1c710391df2 217 errFlag = 1; //Notify
bdk9 5:c1c710391df2 218 sprintf(errMsg, "Overcurrent: %.2f on FET %d", currents[p->cur_id], p->fet_id);
bdk9 5:c1c710391df2 219 pc.printf("PWR: ERR: %s\n", errMsg);
bdk9 5:c1c710391df2 220 }
bdk9 5:c1c710391df2 221 p = p->next;
bdk9 5:c1c710391df2 222 }
bdk9 5:c1c710391df2 223
bdk9 5:c1c710391df2 224 Thread::wait(10);
bdk9 5:c1c710391df2 225 }
bdk9 3:a1b5d7541c69 226 }
bdk9 3:a1b5d7541c69 227
bdk9 3:a1b5d7541c69 228 void serial_task() {
bdk9 3:a1b5d7541c69 229 while(1) {
bdk9 3:a1b5d7541c69 230 pc.printf("PWR: hey");
bdk9 3:a1b5d7541c69 231 Thread::wait(5000);
bdk9 3:a1b5d7541c69 232 }
bdk9 3:a1b5d7541c69 233 }
bdk9 3:a1b5d7541c69 234
bdk9 0:7ba4e0775670 235 // Discover DS1820 probes on pin defined by PIN_DS1820
bdk9 0:7ba4e0775670 236 void ds1820_init() {
bdk9 0:7ba4e0775670 237 // Initialize the thermometer array to DS1820 objects
bdk9 0:7ba4e0775670 238 int num_devices = 0;
bdk9 0:7ba4e0775670 239 while(DS1820::unassignedProbe(PIN_DS1820)) {
bdk9 0:7ba4e0775670 240 thermometers[num_devices] = new DS1820(PIN_DS1820);
bdk9 0:7ba4e0775670 241 num_devices++;
bdk9 0:7ba4e0775670 242 if (num_devices == NUM_DS1820)
bdk9 0:7ba4e0775670 243 break;
bdk9 0:7ba4e0775670 244 }
bdk9 0:7ba4e0775670 245 pc.printf("Found %d device(s)\r\n\n", num_devices);
bdk9 0:7ba4e0775670 246 }
bdk9 0:7ba4e0775670 247
bdk9 0:7ba4e0775670 248
bdk9 2:0a07f99e32c9 249 char buff[64];
bdk9 0:7ba4e0775670 250 int loc = 0;
bdk9 0:7ba4e0775670 251
bdk9 5:c1c710391df2 252
bdk9 0:7ba4e0775670 253 void execute_command(char *cmd) {
bdk9 5:c1c710391df2 254 char msg_type[3];
bdk9 5:c1c710391df2 255 strncpy(msg_type, cmd, 1);
bdk9 5:c1c710391df2 256 //pc.printf("%s\n", msg_type);
bdk9 5:c1c710391df2 257 // ERROR MESSAGE
bdk9 5:c1c710391df2 258 if (!strcmp(msg_type, messages.error_msg)) {
bdk9 5:c1c710391df2 259 errFlag = true;
bdk9 5:c1c710391df2 260 sprintf(errMsg, "%s", cmd);
bdk9 5:c1c710391df2 261 }
bdk9 5:c1c710391df2 262 // SWITCH SCREEN
bdk9 5:c1c710391df2 263 else if (!strcmp(msg_type, messages.next_screen)) {
bdk9 5:c1c710391df2 264 disp.switch_screen();
bdk9 5:c1c710391df2 265 }
bdk9 5:c1c710391df2 266 // RELAY STATE
bdk9 5:c1c710391df2 267 else if (!strcmp(msg_type, messages.relay_state)) {
bdk9 5:c1c710391df2 268 int n;
bdk9 5:c1c710391df2 269 sscanf(cmd, "R,%d\n", n);
bdk9 5:c1c710391df2 270 relay_control = n;
bdk9 5:c1c710391df2 271 }
bdk9 5:c1c710391df2 272 // RELAY POLICY UPDATE
bdk9 5:c1c710391df2 273 else if (!strcmp(msg_type, messages.relay_policy)) {
bdk9 5:c1c710391df2 274 sscanf(cmd, "G,%2.2f\n", max_system_current);
bdk9 5:c1c710391df2 275 }
bdk9 5:c1c710391df2 276 // FET STATE
bdk9 5:c1c710391df2 277 else if (!strcmp(msg_type, messages.fet_state)) {
bdk9 5:c1c710391df2 278 int fet, n;
bdk9 5:c1c710391df2 279 sscanf(cmd, "T,%d,%d\n", fet, n);
bdk9 5:c1c710391df2 280 *(fetPin[fet]) = n;
bdk9 5:c1c710391df2 281 }
bdk9 5:c1c710391df2 282 // FET POLICY UPDATE
bdk9 5:c1c710391df2 283 else if (!strcmp(msg_type, messages.fet_policy)) {
bdk9 5:c1c710391df2 284 int fet_id;
bdk9 5:c1c710391df2 285 int cur_id;
bdk9 5:c1c710391df2 286 double amp_max;
bdk9 5:c1c710391df2 287 sscanf(cmd, "C,%d,%d,%2.2f\n", fet_id, cur_id, amp_max);
bdk9 5:c1c710391df2 288 add_power_policy(fet_id, cur_id, amp_max);
bdk9 5:c1c710391df2 289 }
bdk9 5:c1c710391df2 290 else if (!strcmp(msg_type, messages.fan_voltage)) {
bdk9 5:c1c710391df2 291 double fan_volts;
bdk9 5:c1c710391df2 292 sscanf(cmd, "F,%2.2f\n", fan_volts);
bdk9 5:c1c710391df2 293 // TODO CONVERT TO PWM VALUE
bdk9 5:c1c710391df2 294 int pwm_val = (int) ((fan_volts / 12.0)) * 100;
bdk9 5:c1c710391df2 295 fan_control.period_us(100);
bdk9 5:c1c710391df2 296 fan_control.pulsewidth_us(pwm_val);
bdk9 5:c1c710391df2 297 }
bdk9 5:c1c710391df2 298 // BAD MESSAGE - IMPROPER FORMAT
bdk9 5:c1c710391df2 299 else {
bdk9 5:c1c710391df2 300 // pc.printf("BAD MESSAGE\n");
bdk9 5:c1c710391df2 301 // lol u dumb
bdk9 5:c1c710391df2 302 }
bdk9 0:7ba4e0775670 303 }
bdk9 0:7ba4e0775670 304
bdk9 0:7ba4e0775670 305 void parse_command() {
bdk9 0:7ba4e0775670 306 buff[loc] = USART2->DR;
bdk9 0:7ba4e0775670 307 loc += 1;
bdk9 2:0a07f99e32c9 308 if (buff[loc-1] == '\n') {
bdk9 0:7ba4e0775670 309 execute_command(buff);
bdk9 2:0a07f99e32c9 310 memset(&buff[0], 0, sizeof(buff));
bdk9 0:7ba4e0775670 311 loc = 0;
bdk9 0:7ba4e0775670 312 }
bdk9 0:7ba4e0775670 313 }
bdk9 0:7ba4e0775670 314
bdk9 5:c1c710391df2 315 void power_policy_init() {
bdk9 5:c1c710391df2 316 head->fet_id = 0;
bdk9 5:c1c710391df2 317 head->cur_id = 0;
bdk9 5:c1c710391df2 318 head->amp_max = 30.0;
bdk9 5:c1c710391df2 319 head->next = NULL;
bdk9 5:c1c710391df2 320 tail = head;
bdk9 5:c1c710391df2 321 for (int i=1; i<6; i++) {
bdk9 5:c1c710391df2 322 add_power_policy(i, i, 30.0);
bdk9 5:c1c710391df2 323 }
bdk9 5:c1c710391df2 324 }
bdk9 0:7ba4e0775670 325
bdk9 5:c1c710391df2 326 void add_power_policy(int fet, int cur, double amps) {
bdk9 5:c1c710391df2 327 PowerPolicy *pp;
bdk9 5:c1c710391df2 328 pp->fet_id = fet;
bdk9 5:c1c710391df2 329 pp->cur_id = cur;
bdk9 5:c1c710391df2 330 pp->amp_max = amps;
bdk9 5:c1c710391df2 331 pp->next = NULL;
bdk9 5:c1c710391df2 332 tail->next = pp;
bdk9 5:c1c710391df2 333 tail = pp;
bdk9 5:c1c710391df2 334 }
bdk9 5:c1c710391df2 335
bdk9 5:c1c710391df2 336 void serial_message_init() {
bdk9 5:c1c710391df2 337 messages.error_msg = "E";
bdk9 5:c1c710391df2 338 messages.next_screen = "D";
bdk9 5:c1c710391df2 339 messages.fet_state = "T";
bdk9 5:c1c710391df2 340 messages.fet_policy = "C";
bdk9 5:c1c710391df2 341 messages.relay_state = "R";
bdk9 5:c1c710391df2 342 messages.relay_policy = "G";
bdk9 5:c1c710391df2 343 messages.fan_voltage = "F";
bdk9 5:c1c710391df2 344 }
bdk9 5:c1c710391df2 345
bdk9 0:7ba4e0775670 346 int main() {
bdk9 3:a1b5d7541c69 347 // Setup serial interrupts
bdk9 0:7ba4e0775670 348 pc.attach(&parse_command);
bdk9 3:a1b5d7541c69 349
bdk9 5:c1c710391df2 350 // Initialize power policy
bdk9 5:c1c710391df2 351 power_policy_init();
bdk9 5:c1c710391df2 352
bdk9 5:c1c710391df2 353 // Initialize serial message types
bdk9 5:c1c710391df2 354 serial_message_init();
bdk9 5:c1c710391df2 355
bdk9 3:a1b5d7541c69 356 // Setup temperature sensors
bdk9 0:7ba4e0775670 357 ds1820_init();
bdk9 0:7ba4e0775670 358
bdk9 5:c1c710391df2 359 // Init LTCs
bdk9 5:c1c710391df2 360 ltc_init();
bdk9 5:c1c710391df2 361
bdk9 3:a1b5d7541c69 362 // Setup display
bdk9 0:7ba4e0775670 363 tft.begin();
bdk9 0:7ba4e0775670 364 tft.fillScreen(BLACK);
bdk9 0:7ba4e0775670 365 tft.setRotation(1);
bdk9 0:7ba4e0775670 366 TemperatureScreen ts(0, &tft);
bdk9 0:7ba4e0775670 367 VoltageScreen vs(1, &tft);
bdk9 0:7ba4e0775670 368 CurrentScreen cs(2, &tft);
bdk9 0:7ba4e0775670 369 Screen *s[3] = {&ts, &vs, &cs};
bdk9 0:7ba4e0775670 370 disp.set_screens(s, 3);
bdk9 5:c1c710391df2 371
bdk9 5:c1c710391df2 372 //TODO: UPDATE THESE PINS TO BE ACCURATE
bdk9 5:c1c710391df2 373 //Setup fet pins
bdk9 5:c1c710391df2 374 *(fetPin[0]) = DigitalOut(PA_0);
bdk9 5:c1c710391df2 375 *(fetPin[1]) = DigitalOut(PA_0);
bdk9 5:c1c710391df2 376 *(fetPin[2]) = DigitalOut(PA_0);
bdk9 5:c1c710391df2 377 *(fetPin[3]) = DigitalOut(PA_0);
bdk9 5:c1c710391df2 378 *(fetPin[4]) = DigitalOut(PA_0);
bdk9 5:c1c710391df2 379 *(fetPin[5]) = DigitalOut(PA_0);
bdk9 0:7ba4e0775670 380
bdk9 3:a1b5d7541c69 381 // Setup RTOS threads
bdk9 5:c1c710391df2 382 fast_data_thread.start(fast_data_task);
bdk9 0:7ba4e0775670 383 slow_data_thread.start(slow_data_task);
bdk9 0:7ba4e0775670 384 wait_ms(1000);
bdk9 3:a1b5d7541c69 385 display_thread.start(display_task);
bdk9 5:c1c710391df2 386 //serial_thread.start(serial_task);
bdk9 0:7ba4e0775670 387 }
bdk9 0:7ba4e0775670 388
bdk9 0:7ba4e0775670 389
bdk9 0:7ba4e0775670 390
bdk9 0:7ba4e0775670 391
bdk9 0:7ba4e0775670 392
bdk9 0:7ba4e0775670 393
bdk9 0:7ba4e0775670 394
bdk9 0:7ba4e0775670 395 // TEMPERATURE DISPLAY
bdk9 0:7ba4e0775670 396 TemperatureScreen::TemperatureScreen(int id, Adafruit_ILI9341 *tft) : Screen(id, tft) { }
bdk9 0:7ba4e0775670 397
bdk9 0:7ba4e0775670 398 void TemperatureScreen::init() {
bdk9 0:7ba4e0775670 399 margin = 10;
bdk9 0:7ba4e0775670 400
bdk9 0:7ba4e0775670 401 axes_x_min = 120;
bdk9 0:7ba4e0775670 402 axes_x_max = _tft->width() - margin;
bdk9 0:7ba4e0775670 403 axes_y_bot = _tft->height() - margin;
bdk9 0:7ba4e0775670 404 axes_y_top = 40;
bdk9 0:7ba4e0775670 405
bdk9 0:7ba4e0775670 406 temp_colors[0] = CYAN;
bdk9 0:7ba4e0775670 407 temp_colors[1] = YELLOW;
bdk9 0:7ba4e0775670 408 temp_colors[2] = GREEN;
bdk9 5:c1c710391df2 409 temp_colors[3] = RED;
bdk9 5:c1c710391df2 410 temp_colors[4] = BLUE;
bdk9 5:c1c710391df2 411 temp_colors[5] = MAGENTA;
bdk9 5:c1c710391df2 412
bdk9 5:c1c710391df2 413 temp_label_str[0] = "CPU";
bdk9 5:c1c710391df2 414 temp_label_str[1] = "AMBIENT";
bdk9 5:c1c710391df2 415 temp_label_str[2] = "MOTOR 1";
bdk9 5:c1c710391df2 416 temp_label_str[3] = "MOTOR 2";
bdk9 5:c1c710391df2 417 temp_label_str[4] = "MOTOR 3";
bdk9 5:c1c710391df2 418 temp_label_str[5] = "MOTOR 4";
bdk9 5:c1c710391df2 419
bdk9 5:c1c710391df2 420 temp_label_rect_y[0] = margin;
bdk9 5:c1c710391df2 421 temp_label_rect_y[1] = margin+38;
bdk9 5:c1c710391df2 422 temp_label_rect_y[2] = margin+78;
bdk9 5:c1c710391df2 423 temp_label_rect_y[3] = margin+118;
bdk9 5:c1c710391df2 424 temp_label_rect_y[4] = margin+158;
bdk9 5:c1c710391df2 425 temp_label_rect_y[5] = margin+198;
bdk9 5:c1c710391df2 426
bdk9 5:c1c710391df2 427 temp_label_str_x[0] = margin+30;
bdk9 5:c1c710391df2 428 temp_label_str_x[1] = margin+10;
bdk9 5:c1c710391df2 429 temp_label_str_x[2] = margin+10;
bdk9 5:c1c710391df2 430 temp_label_str_x[3] = margin+10;
bdk9 5:c1c710391df2 431 temp_label_str_x[4] = margin+10;
bdk9 5:c1c710391df2 432 temp_label_str_x[5] = margin+10;
bdk9 5:c1c710391df2 433
bdk9 5:c1c710391df2 434 temp_label_str_y[0] = margin+1;
bdk9 5:c1c710391df2 435 temp_label_str_y[1] = margin+41;
bdk9 5:c1c710391df2 436 temp_label_str_y[2] = margin+81;
bdk9 5:c1c710391df2 437 temp_label_str_y[3] = margin+121;
bdk9 5:c1c710391df2 438 temp_label_str_y[4] = margin+161;
bdk9 5:c1c710391df2 439 temp_label_str_y[5] = margin+201;
bdk9 5:c1c710391df2 440
bdk9 5:c1c710391df2 441 temp_val_y[0] = margin+21;
bdk9 5:c1c710391df2 442 temp_val_y[1] = margin+61;
bdk9 5:c1c710391df2 443 temp_val_y[2] = margin+101;
bdk9 5:c1c710391df2 444 temp_val_y[3] = margin+141;
bdk9 5:c1c710391df2 445 temp_val_y[4] = margin+181;
bdk9 5:c1c710391df2 446 temp_val_y[5] = margin+221;
bdk9 0:7ba4e0775670 447
bdk9 0:7ba4e0775670 448 // draw background
bdk9 0:7ba4e0775670 449 _tft->fillScreen(BLACK);
bdk9 0:7ba4e0775670 450 _tft->setTextSize(2);
bdk9 0:7ba4e0775670 451 _tft->setTextColor(WHITE);
bdk9 0:7ba4e0775670 452 _tft->setCursor(155, margin);
bdk9 0:7ba4e0775670 453 _tft->print("TEMPERATURE");
bdk9 0:7ba4e0775670 454
bdk9 5:c1c710391df2 455 // draw temperature labels
bdk9 5:c1c710391df2 456 for (int i=0; i<6; i++) {
bdk9 5:c1c710391df2 457 _tft->fillRect(margin, temp_label_rect_y[i], axes_x_min-2*margin, 18, temp_colors[i]);
bdk9 5:c1c710391df2 458 _tft->setCursor(temp_label_str_x[i], temp_label_str_y[i]);
bdk9 5:c1c710391df2 459 _tft->setTextColor(BLACK);
bdk9 5:c1c710391df2 460 _tft->print(temp_label_str[i]);
bdk9 5:c1c710391df2 461 }
bdk9 5:c1c710391df2 462
bdk9 0:7ba4e0775670 463 // x-axis
bdk9 0:7ba4e0775670 464 _tft->drawFastHLine(axes_x_min, axes_y_bot, axes_x_max-axes_x_min, WHITE);
bdk9 0:7ba4e0775670 465 // y-axis
bdk9 0:7ba4e0775670 466 _tft->drawFastVLine(axes_x_min, axes_y_top, axes_y_bot-axes_y_top, WHITE);
bdk9 0:7ba4e0775670 467
bdk9 0:7ba4e0775670 468 axes_x_min += 1;
bdk9 0:7ba4e0775670 469 axes_x_max -= 1;
bdk9 0:7ba4e0775670 470 axes_y_bot -= 1;
bdk9 0:7ba4e0775670 471 axes_y_top += 1;
bdk9 0:7ba4e0775670 472 axes_x_cur = axes_x_min;
bdk9 0:7ba4e0775670 473 }
bdk9 0:7ba4e0775670 474
bdk9 0:7ba4e0775670 475 int scale_temp(double val, int min_domain, int max_domain, int min_range, int max_range) {
bdk9 0:7ba4e0775670 476 return (int) max_range - ((val - (min_domain)) / (max_domain - min_domain)) * (max_range - min_range);
bdk9 0:7ba4e0775670 477 }
bdk9 0:7ba4e0775670 478
bdk9 0:7ba4e0775670 479 void TemperatureScreen::update() {
bdk9 0:7ba4e0775670 480 if (plotFlag) {
bdk9 0:7ba4e0775670 481 _tft->fillRect(axes_x_min, axes_y_top, _tft->width()-axes_x_min, axes_y_bot-axes_y_top, BLACK);
bdk9 0:7ba4e0775670 482 plotFlag = false;
bdk9 0:7ba4e0775670 483 }
bdk9 0:7ba4e0775670 484 int y_new, y_old;
bdk9 0:7ba4e0775670 485 for (int i=0; i<NUM_DS1820; i++) {
bdk9 5:c1c710391df2 486 _tft->fillRect(margin, temp_val_y[i], axes_x_min-2*margin, 15, BLACK);
bdk9 0:7ba4e0775670 487 char str[10];
bdk9 0:7ba4e0775670 488 sprintf(str, "%.2f C", temperatures[i]);
bdk9 5:c1c710391df2 489 _tft->setCursor(margin+10, temp_val_y[i]);
bdk9 0:7ba4e0775670 490 _tft->setTextColor(temp_colors[i]);
bdk9 0:7ba4e0775670 491 _tft->print(str);
bdk9 5:c1c710391df2 492 y_new = scale_temp(temperatures[i], 0, max_temp_plot, axes_y_top, axes_y_bot);
bdk9 5:c1c710391df2 493 y_old = scale_temp(old_temperatures[i], 0, max_temp_plot, axes_y_top, axes_y_bot);
bdk9 0:7ba4e0775670 494 _tft->drawLine(axes_x_cur, y_old, axes_x_cur+3, y_new, temp_colors[i]);
bdk9 0:7ba4e0775670 495 }
bdk9 0:7ba4e0775670 496 axes_x_cur += 3;
bdk9 0:7ba4e0775670 497 if (axes_x_cur >= axes_x_max) {
bdk9 0:7ba4e0775670 498 plotFlag = true;
bdk9 0:7ba4e0775670 499 axes_x_cur = axes_x_min;
bdk9 0:7ba4e0775670 500 }
bdk9 0:7ba4e0775670 501 }
bdk9 0:7ba4e0775670 502
bdk9 5:c1c710391df2 503 void TemperatureScreen::error(char *msg) {
bdk9 5:c1c710391df2 504 _tft->fillScreen(RED);
bdk9 5:c1c710391df2 505 _tft->setCursor(_tft->width() / 2 - 50, _tft->height() / 2);
bdk9 5:c1c710391df2 506 _tft->setTextColor(BLACK);
bdk9 5:c1c710391df2 507 _tft->print(msg);
bdk9 5:c1c710391df2 508 wait_ms(3000);
bdk9 5:c1c710391df2 509 init();
bdk9 5:c1c710391df2 510 }
bdk9 5:c1c710391df2 511
bdk9 0:7ba4e0775670 512
bdk9 0:7ba4e0775670 513
bdk9 0:7ba4e0775670 514 // VOLTAGE DISPLAY
bdk9 0:7ba4e0775670 515 VoltageScreen::VoltageScreen(int id, Adafruit_ILI9341 *tft) : Screen(id, tft) { }
bdk9 0:7ba4e0775670 516
bdk9 0:7ba4e0775670 517 void VoltageScreen::init() {
bdk9 5:c1c710391df2 518 _tft->fillScreen(BLACK);
bdk9 5:c1c710391df2 519
bdk9 0:7ba4e0775670 520 }
bdk9 0:7ba4e0775670 521
bdk9 0:7ba4e0775670 522 void VoltageScreen::update() {
bdk9 5:c1c710391df2 523
bdk9 0:7ba4e0775670 524 }
bdk9 0:7ba4e0775670 525
bdk9 5:c1c710391df2 526 void VoltageScreen::error(char *msg) {
bdk9 5:c1c710391df2 527 _tft->fillScreen(RED);
bdk9 5:c1c710391df2 528 _tft->setCursor(_tft->width() / 2 - 50, _tft->height() / 2);
bdk9 5:c1c710391df2 529 _tft->print(msg);
bdk9 5:c1c710391df2 530 wait_ms(3000);
bdk9 5:c1c710391df2 531 init();
bdk9 5:c1c710391df2 532 }
bdk9 5:c1c710391df2 533
bdk9 0:7ba4e0775670 534
bdk9 0:7ba4e0775670 535
bdk9 0:7ba4e0775670 536
bdk9 0:7ba4e0775670 537 // CURRENT DISPLAY
bdk9 0:7ba4e0775670 538 CurrentScreen::CurrentScreen(int id, Adafruit_ILI9341 *tft) : Screen(id, tft) { }
bdk9 0:7ba4e0775670 539
bdk9 0:7ba4e0775670 540 void CurrentScreen::init() {
bdk9 0:7ba4e0775670 541 _tft->fillScreen(BLUE);
bdk9 0:7ba4e0775670 542 }
bdk9 0:7ba4e0775670 543
bdk9 0:7ba4e0775670 544 void CurrentScreen::update() {
bdk9 5:c1c710391df2 545
bdk9 5:c1c710391df2 546 }
bdk9 5:c1c710391df2 547
bdk9 5:c1c710391df2 548 void CurrentScreen::error(char *msg) {
bdk9 5:c1c710391df2 549 _tft->fillScreen(RED);
bdk9 5:c1c710391df2 550 _tft->setCursor(_tft->width() / 2 - 50, _tft->height() / 2);
bdk9 5:c1c710391df2 551 _tft->print(msg);
bdk9 5:c1c710391df2 552 wait_ms(3000);
bdk9 5:c1c710391df2 553 init();
bdk9 5:c1c710391df2 554 }
bdk9 5:c1c710391df2 555
bdk9 5:c1c710391df2 556
bdk9 5:c1c710391df2 557 // LTC READING
bdk9 5:c1c710391df2 558 // read single pins 1 - 8
bdk9 5:c1c710391df2 559 float readSingle(LTC2991 *l, int p) {
bdk9 5:c1c710391df2 560 int v_control_reg, v_msb;
bdk9 5:c1c710391df2 561 switch (p) {
bdk9 5:c1c710391df2 562 case 1:
bdk9 5:c1c710391df2 563 v_control_reg = LTC2991_CONTROL_V1234_REG;
bdk9 5:c1c710391df2 564 v_msb = LTC2991_V1_MSB_REG;
bdk9 5:c1c710391df2 565 break;
bdk9 5:c1c710391df2 566 case 2:
bdk9 5:c1c710391df2 567 v_control_reg = LTC2991_CONTROL_V1234_REG;
bdk9 5:c1c710391df2 568 v_msb = LTC2991_V2_MSB_REG;
bdk9 5:c1c710391df2 569 break;
bdk9 5:c1c710391df2 570 case 3:
bdk9 5:c1c710391df2 571 v_control_reg = LTC2991_CONTROL_V1234_REG;
bdk9 5:c1c710391df2 572 v_msb = LTC2991_V3_MSB_REG;
bdk9 5:c1c710391df2 573 break;
bdk9 5:c1c710391df2 574 case 4:
bdk9 5:c1c710391df2 575 v_control_reg = LTC2991_CONTROL_V1234_REG;
bdk9 5:c1c710391df2 576 v_msb = LTC2991_V4_MSB_REG;
bdk9 5:c1c710391df2 577 break;
bdk9 5:c1c710391df2 578 case 5:
bdk9 5:c1c710391df2 579 v_control_reg = LTC2991_CONTROL_V5678_REG;
bdk9 5:c1c710391df2 580 v_msb = LTC2991_V5_MSB_REG;
bdk9 5:c1c710391df2 581 break;
bdk9 5:c1c710391df2 582 case 6:
bdk9 5:c1c710391df2 583 v_control_reg = LTC2991_CONTROL_V5678_REG;
bdk9 5:c1c710391df2 584 v_msb = LTC2991_V6_MSB_REG;
bdk9 5:c1c710391df2 585 break;
bdk9 5:c1c710391df2 586 case 7:
bdk9 5:c1c710391df2 587 v_control_reg = LTC2991_CONTROL_V5678_REG;
bdk9 5:c1c710391df2 588 v_msb = LTC2991_V7_MSB_REG;
bdk9 5:c1c710391df2 589 break;
bdk9 5:c1c710391df2 590 case 8:
bdk9 5:c1c710391df2 591 v_control_reg = LTC2991_CONTROL_V5678_REG;
bdk9 5:c1c710391df2 592 v_msb = LTC2991_V8_MSB_REG;
bdk9 5:c1c710391df2 593 break;
bdk9 5:c1c710391df2 594 }
bdk9 5:c1c710391df2 595
bdk9 5:c1c710391df2 596 int8_t data_valid;
bdk9 5:c1c710391df2 597 int16_t code;
bdk9 5:c1c710391df2 598 float voltage;
bdk9 5:c1c710391df2 599 ack = 0;
bdk9 5:c1c710391df2 600 ack |= l->LTC2991_register_set_clear_bits(LTC2991_I2C_ADDRESS, v_control_reg, 0x00, LTC2991_V1_V2_DIFFERENTIAL_ENABLE | LTC2991_V1_V2_TEMP_ENABLE);
bdk9 5:c1c710391df2 601 ack |= l->LTC2991_adc_read_new_data(LTC2991_I2C_ADDRESS, v_msb, &code, &data_valid, LTC2991_TIMEOUT);
bdk9 5:c1c710391df2 602 voltage = l->LTC2991_code_to_single_ended_voltage(code, LTC2991_SINGLE_ENDED_lsb);
bdk9 5:c1c710391df2 603 if (ack != 0) {
bdk9 5:c1c710391df2 604 pc.printf("Error: No Acknowledge\n");
bdk9 5:c1c710391df2 605 }
bdk9 5:c1c710391df2 606 return voltage;
bdk9 5:c1c710391df2 607 }
bdk9 5:c1c710391df2 608
bdk9 5:c1c710391df2 609 float readDiff(LTC2991 *l, int upper_pin) {
bdk9 5:c1c710391df2 610 int v_control_reg, v_msb;
bdk9 5:c1c710391df2 611 switch (upper_pin) {
bdk9 5:c1c710391df2 612 case 2:
bdk9 5:c1c710391df2 613 v_control_reg = LTC2991_CONTROL_V1234_REG;
bdk9 5:c1c710391df2 614 v_msb = LTC2991_V2_MSB_REG;
bdk9 5:c1c710391df2 615 break;
bdk9 5:c1c710391df2 616 case 4:
bdk9 5:c1c710391df2 617 v_control_reg = LTC2991_CONTROL_V1234_REG;
bdk9 5:c1c710391df2 618 v_msb = LTC2991_V4_MSB_REG;
bdk9 5:c1c710391df2 619 break;
bdk9 5:c1c710391df2 620 case 6:
bdk9 5:c1c710391df2 621 v_control_reg = LTC2991_CONTROL_V5678_REG;
bdk9 5:c1c710391df2 622 v_msb = LTC2991_V6_MSB_REG;
bdk9 5:c1c710391df2 623 break;
bdk9 5:c1c710391df2 624 case 8:
bdk9 5:c1c710391df2 625 v_control_reg = LTC2991_CONTROL_V5678_REG;
bdk9 5:c1c710391df2 626 v_msb = LTC2991_V8_MSB_REG;
bdk9 5:c1c710391df2 627 break;
bdk9 5:c1c710391df2 628 }
bdk9 5:c1c710391df2 629 int8_t data_valid;
bdk9 5:c1c710391df2 630 int16_t code;
bdk9 5:c1c710391df2 631 float voltage;
bdk9 5:c1c710391df2 632 ack = 0;
bdk9 5:c1c710391df2 633 ack |= l->LTC2991_register_set_clear_bits(LTC2991_I2C_ADDRESS, v_control_reg, LTC2991_V1_V2_DIFFERENTIAL_ENABLE, LTC2991_V1_V2_TEMP_ENABLE);
bdk9 5:c1c710391df2 634 ack |= l->LTC2991_adc_read_new_data(LTC2991_I2C_ADDRESS, v_msb, &code, &data_valid, LTC2991_TIMEOUT);
bdk9 5:c1c710391df2 635 voltage = l->LTC2991_code_to_differential_voltage(code, LTC2991_DIFFERENTIAL_lsb);
bdk9 5:c1c710391df2 636 if (ack != 0) {
bdk9 5:c1c710391df2 637 pc.printf("Error: No Acknowledge.\n");
bdk9 5:c1c710391df2 638 }
bdk9 5:c1c710391df2 639 return voltage;
bdk9 5:c1c710391df2 640 }