smart sensor code initial version

Dependencies:   mbed-src-KL05Z-smart-sensor

Committer:
vincenxp
Date:
Tue Mar 26 10:50:33 2019 +0000
Revision:
3:d908dc9882d2
Parent:
2:5dacfd690a75
Child:
4:a2f83fac24bc
run6 for Cz

Who changed what in which revision?

UserRevisionLine numberNew contents of line
vincenxp 0:10bf1bb6d2b5 1 /****************************************************************************************
vincenxp 0:10bf1bb6d2b5 2 *
vincenxp 0:10bf1bb6d2b5 3 * MIT License (https://spdx.org/licenses/MIT.html)
vincenxp 0:10bf1bb6d2b5 4 * Copyright 2018 NXP
vincenxp 0:10bf1bb6d2b5 5 *
vincenxp 0:10bf1bb6d2b5 6 * MBED code for KL05Z-based "smart" current sensor, which measures current in
vincenxp 0:10bf1bb6d2b5 7 * three ranges. Intended to be used with an aggregator board which triggers sensors
vincenxp 0:10bf1bb6d2b5 8 * on all instrumented rails and then sequentially reads the data from each out over I2C.
vincenxp 0:10bf1bb6d2b5 9 *
vincenxp 0:10bf1bb6d2b5 10 * Because there is no crystal on the board, need to edit source mbed-dev library
vincenxp 0:10bf1bb6d2b5 11 * to use internal oscillator with pound-define:
vincenxp 0:10bf1bb6d2b5 12 * change to "#define CLOCK_SETUP 0" in file:
vincenxp 0:10bf1bb6d2b5 13 * mbed-dev/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL05Z/device/system_MKL05Z4.c
vincenxp 0:10bf1bb6d2b5 14 *
vincenxp 0:10bf1bb6d2b5 15 ****************************************************************************************/
vincenxp 0:10bf1bb6d2b5 16
vincenxp 1:587e0346abca 17 /****************************************************************************************
vincenxp 1:587e0346abca 18 * Add a uart trace instead of I2C
vincenxp 1:587e0346abca 19 * For the uart trace:
vincenxp 1:587e0346abca 20 * * add a timestamp (returns the timestamp of the current measure)
vincenxp 1:587e0346abca 21 * * do not average the measures:
vincenxp 1:587e0346abca 22 * + add a paramter to the existing function to set the number of samples to be
vincenxp 1:587e0346abca 23 * averaged (I2C legacy)
vincenxp 1:587e0346abca 24 * * set to 0 the different settling time:
vincenxp 1:587e0346abca 25 * + do not see dysfunction so far for the FET settling time neither for the voltage
vincenxp 1:587e0346abca 26 * divider
vincenxp 1:587e0346abca 27 * + do not see the need in case of the voltage or current measurement. It is
vincenxp 1:587e0346abca 28 * mentionned that this is for the B2902A settling time, so i guess this when the
vincenxp 1:587e0346abca 29 * SMU is used. It should not be the case by default anyway!
vincenxp 1:587e0346abca 30 *
vincenxp 1:587e0346abca 31 * Use few defines to instrument the code as below:
vincenxp 1:587e0346abca 32 *
vincenxp 1:587e0346abca 33 * | USEI2CNOTUART | DEBUG | TRACEPRINT | BUFFMEASURES | comment
vincenxp 1:587e0346abca 34 * | 1 | 0 | 0 | 0 | legacy mode - modify the KL25Z code to output the sensor number, voltage and current information
vincenxp 1:587e0346abca 35 * | 0 | 0 | 0 | 0 | uart trace: print thru the uart console the result of the measures: timestamp, voltage, current
vincenxp 1:587e0346abca 36 * | 0 | 0 | 1 | 0 | same as above but print also the time consumes to print those data!
vincenxp 1:587e0346abca 37 * | 0 | 1 | 0 | 0 | uart trace: print thru the uart console many measures (see define below) but impact the sampling rate
vincenxp 1:587e0346abca 38 * | 0 | 1 | 1 | 0 | same as above but uprint also the time consumes to print those data!
vincenxp 1:587e0346abca 39 * | 0 | 0 | 0 | 1 | use a buffer to store the measures and print the entire buffer one it is full; improve the sampling rate but the buffer size is limited
vincenxp 1:587e0346abca 40 *
vincenxp 1:587e0346abca 41 ****************************************************************************************/
vincenxp 0:10bf1bb6d2b5 42 #include <mbed.h>
vincenxp 0:10bf1bb6d2b5 43
vincenxp 1:587e0346abca 44 // Select the I2C trace or the uart trace for debug
vincenxp 0:10bf1bb6d2b5 45 #define USEI2CNOTUART 0
vincenxp 0:10bf1bb6d2b5 46
vincenxp 1:587e0346abca 47 // Custom setup in case of I2C
vincenxp 1:587e0346abca 48 #define I2CCUSTOM 0
vincenxp 1:587e0346abca 49
vincenxp 1:587e0346abca 50 // If BUFFMEASURES == 1 : fill up a buffer of measures (timestamp, vdd & current only) and then send the whole buffer thru the uart console & loop
vincenxp 1:587e0346abca 51 // * buffer size is limited to the 4k of RAM (1 measure of timestamp or volt or current is a float, each of 4 bytes)
vincenxp 1:587e0346abca 52 #define BUFFMEASURES 0
vincenxp 1:587e0346abca 53
vincenxp 1:587e0346abca 54 // If TRACEPRINT == 1 : trace the time comnsumes by the printf to the uart console
vincenxp 2:5dacfd690a75 55 #define TRACEPRINT 0
vincenxp 1:587e0346abca 56
vincenxp 1:587e0346abca 57 // If DEBUG == 1 : do not buffer the measures but send the measures thru the uart console (measures duration (volt + current), sensor number, timestamps, voltage, current, high current, mid current, low current
vincenxp 2:5dacfd690a75 58 #define DEBUG 0
vincenxp 1:587e0346abca 59
vincenxp 0:10bf1bb6d2b5 60 // set things up...
vincenxp 0:10bf1bb6d2b5 61 #if (USEI2CNOTUART == 1)
vincenxp 0:10bf1bb6d2b5 62 I2CSlave slave(PTB4, PTB3);
vincenxp 1:587e0346abca 63 #if (I2CCUSTOM == 1)
vincenxp 1:587e0346abca 64 int n_meas=1; // number of averages when measuring...
vincenxp 1:587e0346abca 65 #else
vincenxp 1:587e0346abca 66 int n_meas=25; // number of averages when measuring...
vincenxp 1:587e0346abca 67 #endif
vincenxp 0:10bf1bb6d2b5 68 #else
vincenxp 0:10bf1bb6d2b5 69 Serial uart(PTB3, PTB4); // tx, rx
vincenxp 1:587e0346abca 70 int n_meas=1; // number of averages when measuring...
vincenxp 1:587e0346abca 71 Timer timer; // I2C trace isn't prototype with timestamp
vincenxp 1:587e0346abca 72 float timestamp;
vincenxp 1:587e0346abca 73 #endif
vincenxp 1:587e0346abca 74
vincenxp 1:587e0346abca 75 #if (BUFFMEASURES == 1)
vincenxp 1:587e0346abca 76 // Define BUFFERSIZE to 250
vincenxp 1:587e0346abca 77 // * 250 * 3 (float) * 4 (4 bytes for each float) = 3000 bytes almost 3kBytes out of the 4
vincenxp 1:587e0346abca 78 #define BUFFERSIZE 200
vincenxp 1:587e0346abca 79
vincenxp 1:587e0346abca 80 // buffer to store timestamp, voltage & current
vincenxp 1:587e0346abca 81 float buffer[BUFFERSIZE][3];
vincenxp 1:587e0346abca 82 #endif
vincenxp 1:587e0346abca 83
vincenxp 1:587e0346abca 84 #ifndef BUFFERSIZE
vincenxp 1:587e0346abca 85 #define BUFFERSIZE 0
vincenxp 0:10bf1bb6d2b5 86 #endif
vincenxp 0:10bf1bb6d2b5 87
vincenxp 0:10bf1bb6d2b5 88 // These will be used for identifying smart sensor build options:
vincenxp 0:10bf1bb6d2b5 89 // voltage range (0-3.3V, 0-6.6V, and 12V), and
vincenxp 0:10bf1bb6d2b5 90 // current range (high: 4A max, and low: 1.65A max)
vincenxp 0:10bf1bb6d2b5 91 // (default pin pulls are pull up...)
vincenxp 0:10bf1bb6d2b5 92 // But this still needs to be implemented per schematic...
vincenxp 0:10bf1bb6d2b5 93 DigitalIn gpio0(PTA3); // R8
vincenxp 0:10bf1bb6d2b5 94 DigitalIn C_RANGE(PTA4); // R9
vincenxp 0:10bf1bb6d2b5 95 DigitalIn V_RANGE0(PTA5); // R10
vincenxp 0:10bf1bb6d2b5 96 DigitalIn V_RANGE1(PTA6); // R11
vincenxp 0:10bf1bb6d2b5 97
vincenxp 0:10bf1bb6d2b5 98 // configure pins for measurements...
vincenxp 0:10bf1bb6d2b5 99 // analog inputs from sense amps and rail voltage (divider)...
vincenxp 0:10bf1bb6d2b5 100 AnalogIn HIGH_ADC(PTB10);
vincenxp 0:10bf1bb6d2b5 101 AnalogIn VRAIL_ADC(PTB11);
vincenxp 0:10bf1bb6d2b5 102 AnalogIn LOW1_ADC(PTA9);
vincenxp 0:10bf1bb6d2b5 103 AnalogIn LOW2_ADC(PTA8);
vincenxp 0:10bf1bb6d2b5 104 // outputs which control switching FETs...
vincenxp 0:10bf1bb6d2b5 105 DigitalOut VRAIL_MEAS(PTA7); // turns on Q7, connecting voltage divider
vincenxp 0:10bf1bb6d2b5 106 DigitalOut LOW_ENABLE(PTB0); // turns on Q4, turning off Q1, enabling low measurement
vincenxp 0:10bf1bb6d2b5 107 DigitalOut LOW1(PTB2); // turns on Q5, turning off Q2, disconnecting shunt R1
vincenxp 0:10bf1bb6d2b5 108 DigitalOut LOW2(PTB1); // turns on Q6, turning off Q3, disconnecting shunt R2
vincenxp 0:10bf1bb6d2b5 109
vincenxp 1:587e0346abca 110 //VB
vincenxp 1:587e0346abca 111 //DigitalOut OPT3(PTB13);
vincenxp 0:10bf1bb6d2b5 112
vincenxp 0:10bf1bb6d2b5 113 // set initial, default I2C listening address...
vincenxp 0:10bf1bb6d2b5 114 // same one for all sensors so we don't need to individually program each one...
vincenxp 0:10bf1bb6d2b5 115 int address = 0x48 << 1;
vincenxp 0:10bf1bb6d2b5 116 // buffers for I2C communication
vincenxp 0:10bf1bb6d2b5 117 char buf[15], inbuf[10];
vincenxp 0:10bf1bb6d2b5 118 char obuf[10], cbuf[10]; // another buf for compressed output...
vincenxp 0:10bf1bb6d2b5 119
vincenxp 0:10bf1bb6d2b5 120 // variables...
vincenxp 0:10bf1bb6d2b5 121 int i, j, n=0;
vincenxp 0:10bf1bb6d2b5 122 bool waiting;
vincenxp 0:10bf1bb6d2b5 123 bool big_data = false; // flag to save time during ISR
vincenxp 0:10bf1bb6d2b5 124 // only process uncompressed data if explicitly called for...
vincenxp 0:10bf1bb6d2b5 125
vincenxp 0:10bf1bb6d2b5 126 // these unions enable converting float val to bytes for transmission over I2C...
vincenxp 0:10bf1bb6d2b5 127 union u_tag {
vincenxp 0:10bf1bb6d2b5 128 char b[4];
vincenxp 0:10bf1bb6d2b5 129 float fval;
vincenxp 0:10bf1bb6d2b5 130 int ival;
vincenxp 0:10bf1bb6d2b5 131 } u, v;
vincenxp 0:10bf1bb6d2b5 132
vincenxp 0:10bf1bb6d2b5 133
vincenxp 0:10bf1bb6d2b5 134 // define measurement result and status variables...
vincenxp 0:10bf1bb6d2b5 135 float measurement1;
vincenxp 0:10bf1bb6d2b5 136 float measurement2;
vincenxp 0:10bf1bb6d2b5 137 char status=0;
vincenxp 1:587e0346abca 138
vincenxp 0:10bf1bb6d2b5 139 float vref =3.3;
vincenxp 0:10bf1bb6d2b5 140 float factor_H = vref / 0.8;
vincenxp 0:10bf1bb6d2b5 141 float factor_L1 = vref / (0.05 * 1000);
vincenxp 0:10bf1bb6d2b5 142 float factor_L2 = vref / (2 * 1000);
vincenxp 0:10bf1bb6d2b5 143
vincenxp 1:587e0346abca 144 #if (USEI2CNOTUART == 1)
vincenxp 1:587e0346abca 145 #if (I2CCUSTOM == 1)
vincenxp 1:587e0346abca 146 int wait_mbbb = 0;
vincenxp 1:587e0346abca 147 int wait_high = 0;
vincenxp 1:587e0346abca 148 int wait_low1 = 0;
vincenxp 1:587e0346abca 149 int wait_low2 = 0;
vincenxp 1:587e0346abca 150 int wait_vrail = 0;
vincenxp 1:587e0346abca 151 #else
vincenxp 0:10bf1bb6d2b5 152 int wait_mbbb = 5;
vincenxp 0:10bf1bb6d2b5 153 int wait_high = 250;
vincenxp 0:10bf1bb6d2b5 154 int wait_low1 = 250;
vincenxp 0:10bf1bb6d2b5 155 int wait_low2 = 500;
vincenxp 0:10bf1bb6d2b5 156 int wait_vrail = 200;
vincenxp 1:587e0346abca 157 #endif
vincenxp 1:587e0346abca 158 #else
vincenxp 1:587e0346abca 159 int wait_mbbb = 5;//VB
vincenxp 1:587e0346abca 160 int wait_high = 250;//VB
vincenxp 1:587e0346abca 161 int wait_low1 = 250;//VB
vincenxp 1:587e0346abca 162 int wait_low2 = 500;//VB
vincenxp 1:587e0346abca 163 int wait_vrail = 200;//VB
vincenxp 1:587e0346abca 164 #endif
vincenxp 0:10bf1bb6d2b5 165
vincenxp 1:587e0346abca 166 // Store the 3 current sensors' value
vincenxp 1:587e0346abca 167 float current[3];
vincenxp 0:10bf1bb6d2b5 168
vincenxp 0:10bf1bb6d2b5 169 /***********************************************************************************
vincenxp 0:10bf1bb6d2b5 170 *
vincenxp 0:10bf1bb6d2b5 171 * FUNCTIONS FOR MEASURING CURRENT AND VOLTAGE
vincenxp 0:10bf1bb6d2b5 172 *
vincenxp 0:10bf1bb6d2b5 173 ************************************************************************************/
vincenxp 0:10bf1bb6d2b5 174
vincenxp 0:10bf1bb6d2b5 175 void enableHighRange(){
vincenxp 0:10bf1bb6d2b5 176 LOW_ENABLE = 0; // short both low current shunts, close Q1
vincenxp 1:587e0346abca 177 //VB #if (USEI2CNOTUART == 1 && CUSTOM == 0)
vincenxp 0:10bf1bb6d2b5 178 wait_us(wait_mbbb); // delay for FET to settle... (make before break)
vincenxp 1:587e0346abca 179 //VB #endif
vincenxp 0:10bf1bb6d2b5 180 LOW1 = 0; LOW2 = 0; // connect both shunts to make lower series resistance
vincenxp 1:587e0346abca 181 VRAIL_MEAS = 0; // disconnect rail voltage divider
vincenxp 1:587e0346abca 182 //VB #if (USEI2CNOTUART == 1 && CUSTOM == 0)
vincenxp 0:10bf1bb6d2b5 183 wait_us(wait_high); // wait for B2902A settling...
vincenxp 1:587e0346abca 184 //VB #endif
vincenxp 0:10bf1bb6d2b5 185 }
vincenxp 0:10bf1bb6d2b5 186
vincenxp 0:10bf1bb6d2b5 187 void enableLow1Range(){
vincenxp 0:10bf1bb6d2b5 188 LOW1 = 0; LOW2 = 1; // disconnect LOW2 shunt so LOW1 can measure
vincenxp 1:587e0346abca 189 //VB #if (USEI2CNOTUART == 1 && CUSTOM == 0)
vincenxp 0:10bf1bb6d2b5 190 wait_us(wait_mbbb); // delay for FET to settle... (make before break)
vincenxp 1:587e0346abca 191 //VB #endif
vincenxp 0:10bf1bb6d2b5 192 LOW_ENABLE = 1; // unshort low current shunts, open Q1
vincenxp 0:10bf1bb6d2b5 193 VRAIL_MEAS = 0; // disconnect rail voltage divider
vincenxp 1:587e0346abca 194 //VB #if (USEI2CNOTUART == 1 && CUSTOM == 0)
vincenxp 0:10bf1bb6d2b5 195 wait_us(wait_low1); // wait for B2902A settling...
vincenxp 1:587e0346abca 196 //VB #endif
vincenxp 0:10bf1bb6d2b5 197 }
vincenxp 0:10bf1bb6d2b5 198
vincenxp 0:10bf1bb6d2b5 199 void enableLow2Range(){
vincenxp 0:10bf1bb6d2b5 200 LOW1 = 1; LOW2 = 0; // disconnect LOW1 shunt so LOW2 can measure
vincenxp 1:587e0346abca 201 //VB #if (USEI2CNOTUART == 1 && CUSTOM == 0)
vincenxp 0:10bf1bb6d2b5 202 wait_us(wait_mbbb); // delay for FET to settle... (make before break)
vincenxp 1:587e0346abca 203 //VB #endif
vincenxp 0:10bf1bb6d2b5 204 LOW_ENABLE = 1; // unshort low current shunts, open Q1
vincenxp 0:10bf1bb6d2b5 205 VRAIL_MEAS = 0; // disconnect rail voltage divider
vincenxp 1:587e0346abca 206 //VB #if (USEI2CNOTUART == 1 && CUSTOM == 0)
vincenxp 0:10bf1bb6d2b5 207 wait_us(wait_low2); // wait for B2902A settling...
vincenxp 1:587e0346abca 208 //VB #endif
vincenxp 0:10bf1bb6d2b5 209 }
vincenxp 0:10bf1bb6d2b5 210
vincenxp 0:10bf1bb6d2b5 211 void enableRailV(){
vincenxp 0:10bf1bb6d2b5 212 VRAIL_MEAS = 1; // turn on Q7, to enable R3-R4 voltage divider
vincenxp 1:587e0346abca 213 //VB #if (USEI2CNOTUART == 1 && CUSTOM == 0)
vincenxp 0:10bf1bb6d2b5 214 wait_us(wait_vrail); // wait for divider to settle...
vincenxp 0:10bf1bb6d2b5 215 // Compensation cap can be used to make
vincenxp 0:10bf1bb6d2b5 216 // voltage at ADC a "square wave" but it is
vincenxp 0:10bf1bb6d2b5 217 // rail voltage and FET dependent. Cap will
vincenxp 0:10bf1bb6d2b5 218 // need tuning if this wait time is to be
vincenxp 0:10bf1bb6d2b5 219 // removed/reduced.
vincenxp 0:10bf1bb6d2b5 220 //
vincenxp 0:10bf1bb6d2b5 221 // So, as it turns out, this settling time and
vincenxp 0:10bf1bb6d2b5 222 // compensation capacitance are voltage dependent
vincenxp 0:10bf1bb6d2b5 223 // because of the depletion region changes in the
vincenxp 0:10bf1bb6d2b5 224 // FET. Reminiscent of grad school and DLTS.
vincenxp 0:10bf1bb6d2b5 225 // Gotta love device physics...
vincenxp 1:587e0346abca 226 //VB #endif
vincenxp 0:10bf1bb6d2b5 227 }
vincenxp 0:10bf1bb6d2b5 228
vincenxp 0:10bf1bb6d2b5 229 // when a divider is present, turn it off to remove the current it draws...
vincenxp 0:10bf1bb6d2b5 230 void disableRailV(){
vincenxp 0:10bf1bb6d2b5 231 VRAIL_MEAS = 0; // turn off Q7, disabling R3-R4 voltage divider
vincenxp 0:10bf1bb6d2b5 232 }
vincenxp 0:10bf1bb6d2b5 233
vincenxp 0:10bf1bb6d2b5 234 // measure high range current...
vincenxp 0:10bf1bb6d2b5 235 float measureHigh(int nbMeas){
vincenxp 0:10bf1bb6d2b5 236 float highI=0;
vincenxp 0:10bf1bb6d2b5 237 enableHighRange();
vincenxp 0:10bf1bb6d2b5 238 for (i = 0; i < nbMeas; i++){
vincenxp 0:10bf1bb6d2b5 239 highI += HIGH_ADC;
vincenxp 0:10bf1bb6d2b5 240 }
vincenxp 0:10bf1bb6d2b5 241 highI = factor_H * highI/nbMeas;
vincenxp 1:587e0346abca 242 #if (USEI2CNOTUART == 0)
vincenxp 0:10bf1bb6d2b5 243 timestamp = timer.read();
vincenxp 1:587e0346abca 244 #endif
vincenxp 0:10bf1bb6d2b5 245 return highI;
vincenxp 0:10bf1bb6d2b5 246 }
vincenxp 0:10bf1bb6d2b5 247
vincenxp 0:10bf1bb6d2b5 248 // mesaure mid range current...
vincenxp 0:10bf1bb6d2b5 249 float measureLow1(bool autorange, int nbMeas){
vincenxp 0:10bf1bb6d2b5 250 float low1I=0;
vincenxp 0:10bf1bb6d2b5 251 if (!autorange) enableLow1Range();
vincenxp 0:10bf1bb6d2b5 252 for (i = 0; i < nbMeas; i++){
vincenxp 0:10bf1bb6d2b5 253 low1I += LOW1_ADC;
vincenxp 0:10bf1bb6d2b5 254 }
vincenxp 3:d908dc9882d2 255 //VBrun6 if (!autorange) enableHighRange();
vincenxp 0:10bf1bb6d2b5 256 low1I = factor_L1 * low1I/nbMeas;
vincenxp 1:587e0346abca 257 #if (USEI2CNOTUART == 0)
vincenxp 0:10bf1bb6d2b5 258 timestamp = timer.read();
vincenxp 1:587e0346abca 259 #endif
vincenxp 0:10bf1bb6d2b5 260 return low1I;
vincenxp 0:10bf1bb6d2b5 261 }
vincenxp 0:10bf1bb6d2b5 262
vincenxp 0:10bf1bb6d2b5 263 // measure low range current...
vincenxp 0:10bf1bb6d2b5 264 float measureLow2(bool autorange, int nbMeas){
vincenxp 0:10bf1bb6d2b5 265 float low2I=0;
vincenxp 0:10bf1bb6d2b5 266 if (!autorange) enableLow2Range();
vincenxp 0:10bf1bb6d2b5 267 for (i = 0; i < nbMeas; i++){
vincenxp 0:10bf1bb6d2b5 268 low2I += LOW2_ADC;
vincenxp 0:10bf1bb6d2b5 269 }
vincenxp 3:d908dc9882d2 270 //VBrun6 if (!autorange) enableHighRange();
vincenxp 0:10bf1bb6d2b5 271 low2I = factor_L2 * low2I/nbMeas;
vincenxp 1:587e0346abca 272 #if (USEI2CNOTUART == 0)
vincenxp 0:10bf1bb6d2b5 273 timestamp = timer.read();
vincenxp 1:587e0346abca 274 #endif
vincenxp 0:10bf1bb6d2b5 275 return low2I;
vincenxp 0:10bf1bb6d2b5 276 }
vincenxp 0:10bf1bb6d2b5 277
vincenxp 0:10bf1bb6d2b5 278 // this function measures current, autoranging as necessary
vincenxp 0:10bf1bb6d2b5 279 // to get the best measurement...
vincenxp 0:10bf1bb6d2b5 280 // hard coded values for switching ranges needs to be made
vincenxp 0:10bf1bb6d2b5 281 // dynamic so 4.125A/1.65A ranges can be used...
vincenxp 1:587e0346abca 282
vincenxp 1:587e0346abca 283
vincenxp 1:587e0346abca 284 float measureAutoI(int nbMeas){
vincenxp 0:10bf1bb6d2b5 285 float tempI;
vincenxp 3:d908dc9882d2 286 //VBrun5+run6 enableHighRange(); // this should already be the case, but do it anyway...
vincenxp 1:587e0346abca 287 #if (USEI2CNOTUART == 0)
vincenxp 0:10bf1bb6d2b5 288 current[0] = 0;
vincenxp 0:10bf1bb6d2b5 289 current[1] = 0;
vincenxp 0:10bf1bb6d2b5 290 current[2] = 0;
vincenxp 1:587e0346abca 291 #endif
vincenxp 0:10bf1bb6d2b5 292 tempI = measureHigh(nbMeas);
vincenxp 1:587e0346abca 293 #if (USEI2CNOTUART == 0)
vincenxp 0:10bf1bb6d2b5 294 current[0] = tempI;
vincenxp 1:587e0346abca 295 #endif
vincenxp 0:10bf1bb6d2b5 296 status = 1;
vincenxp 0:10bf1bb6d2b5 297 // if current is below this threshold, use LOW1 to measure...
vincenxp 0:10bf1bb6d2b5 298 if (tempI < 0.060) {
vincenxp 3:d908dc9882d2 299 //VBrun5+run6 enableLow1Range();
vincenxp 0:10bf1bb6d2b5 300 tempI = measureLow1(false, nbMeas); // call function
vincenxp 1:587e0346abca 301 #if (USEI2CNOTUART == 0)
vincenxp 0:10bf1bb6d2b5 302 current[1] = tempI;
vincenxp 1:587e0346abca 303 #endif
vincenxp 0:10bf1bb6d2b5 304 status = 2;
vincenxp 0:10bf1bb6d2b5 305 // if current is below this threshold, use LOW2 to measure...
vincenxp 0:10bf1bb6d2b5 306 if (tempI < 0.0009){
vincenxp 3:d908dc9882d2 307 //VBrun5+run6 enableLow2Range(); // change FETs to enable LOW2 measurement...
vincenxp 0:10bf1bb6d2b5 308 tempI = measureLow2(false, nbMeas);
vincenxp 1:587e0346abca 309 #if (USEI2CNOTUART == 0)
vincenxp 0:10bf1bb6d2b5 310 current[2] = tempI;
vincenxp 1:587e0346abca 311 #endif
vincenxp 0:10bf1bb6d2b5 312 status = 3;
vincenxp 0:10bf1bb6d2b5 313 }
vincenxp 3:d908dc9882d2 314 //VBrun5 enableHighRange();
vincenxp 3:d908dc9882d2 315 enableHighRange();
vincenxp 0:10bf1bb6d2b5 316 }
vincenxp 0:10bf1bb6d2b5 317 return tempI;
vincenxp 0:10bf1bb6d2b5 318 }
vincenxp 0:10bf1bb6d2b5 319
vincenxp 0:10bf1bb6d2b5 320
vincenxp 0:10bf1bb6d2b5 321 // measure the rail voltage, default being with
vincenxp 0:10bf1bb6d2b5 322 // need to add logic for 5V/12V/arbitraryV range...
vincenxp 1:587e0346abca 323 float measureRailV(int nbMeas){
vincenxp 0:10bf1bb6d2b5 324 float railv=0;
vincenxp 0:10bf1bb6d2b5 325 enableRailV(); // switch FETs so divider is connected...
vincenxp 0:10bf1bb6d2b5 326 for (i = 0; i < nbMeas; i++){
vincenxp 0:10bf1bb6d2b5 327 railv += VRAIL_ADC; // read voltage at divider output...
vincenxp 0:10bf1bb6d2b5 328 }
vincenxp 0:10bf1bb6d2b5 329 disableRailV(); // now disconnect the voltage divider
vincenxp 0:10bf1bb6d2b5 330 railv = vref * (railv/nbMeas); // compute average
vincenxp 0:10bf1bb6d2b5 331 // Convert to voltage by multiplying by "mult"
vincenxp 0:10bf1bb6d2b5 332 if (vref==12.0) railv = railv * 0.24770642201;
vincenxp 0:10bf1bb6d2b5 333 return railv;
vincenxp 0:10bf1bb6d2b5 334 }
vincenxp 1:587e0346abca 335
vincenxp 1:587e0346abca 336
vincenxp 1:587e0346abca 337
vincenxp 1:587e0346abca 338
vincenxp 1:587e0346abca 339
vincenxp 1:587e0346abca 340 #if (USEI2CNOTUART == 1)
vincenxp 0:10bf1bb6d2b5 341 /***********************************************************************************
vincenxp 0:10bf1bb6d2b5 342 *
vincenxp 0:10bf1bb6d2b5 343 * INTERRUPT SERVICE ROUTINE
vincenxp 0:10bf1bb6d2b5 344 *
vincenxp 0:10bf1bb6d2b5 345 ************************************************************************************/
vincenxp 1:587e0346abca 346
vincenxp 0:10bf1bb6d2b5 347 // measurements are only taken during ISR, triggered by aggregator on IRQ line...
vincenxp 0:10bf1bb6d2b5 348 // this could have been implemented differently, but this was simple...
vincenxp 0:10bf1bb6d2b5 349 // If coulomb counting is desired, this code would probably need to change...
vincenxp 0:10bf1bb6d2b5 350 void interrupt_service(){
vincenxp 0:10bf1bb6d2b5 351 // make measurement... (this is currently just a placeholder...)
vincenxp 0:10bf1bb6d2b5 352 status = 0; // clear status byte.. allow measurement functions to modify...
vincenxp 1:587e0346abca 353 measurement1 = measureAutoI(n_meas);
vincenxp 1:587e0346abca 354 measurement2 = measureRailV(n_meas);
vincenxp 0:10bf1bb6d2b5 355 n += 10; //increment interrupt counter...
vincenxp 0:10bf1bb6d2b5 356
vincenxp 0:10bf1bb6d2b5 357 // prepare data for transport, in the event that aggregator asks for short format...
vincenxp 0:10bf1bb6d2b5 358
vincenxp 0:10bf1bb6d2b5 359 // compressed data format, 4 bytes total, with a status nibble
vincenxp 0:10bf1bb6d2b5 360 // Each byte has form: (s*128) + (digit1*10) + (digit2), which fits into 8 bits
vincenxp 0:10bf1bb6d2b5 361 // Each value is composed of two bytes with form above, first three digits are
vincenxp 0:10bf1bb6d2b5 362 // the mantissa and the last digit is the exponent. Two values is four bytes, so
vincenxp 0:10bf1bb6d2b5 363 // that allows four status bits to be included.
vincenxp 0:10bf1bb6d2b5 364 sprintf(buf, "%4.2e", measurement1);
vincenxp 0:10bf1bb6d2b5 365 buf[10] = (buf[0]-48)*10 + (buf[2]-48); // no decimal, we use fixed point...
vincenxp 0:10bf1bb6d2b5 366 buf[11] = (buf[3]-48)*10 + (buf[7]-48); // no 'e', and no exp sign, since we know that's negative...
vincenxp 0:10bf1bb6d2b5 367 sprintf(buf, "%4.2e", measurement2);
vincenxp 0:10bf1bb6d2b5 368 buf[12] = (buf[0]-48)*10 + (buf[2]-48); // no decimal, we use fixed point...
vincenxp 0:10bf1bb6d2b5 369 buf[13] = (buf[3]-48)*10 + (buf[7]-48); // no 'e', and no exp sign, since we know that's negative...
vincenxp 0:10bf1bb6d2b5 370
vincenxp 0:10bf1bb6d2b5 371 // add in the four status bits...
vincenxp 0:10bf1bb6d2b5 372 buf[10] = buf[10] | (status & 1<<3)<<4;
vincenxp 0:10bf1bb6d2b5 373 buf[11] = buf[11] | (status & 1<<2)<<5;
vincenxp 0:10bf1bb6d2b5 374 buf[12] = buf[12] | (status & 1<<1)<<6;
vincenxp 0:10bf1bb6d2b5 375 buf[13] = buf[13] | (status & 1<<0)<<7;
vincenxp 0:10bf1bb6d2b5 376
vincenxp 0:10bf1bb6d2b5 377 // Convert each 32-bit floating point measurement value into 4 bytes
vincenxp 0:10bf1bb6d2b5 378 // using union, so we can send bytes over I2C...
vincenxp 0:10bf1bb6d2b5 379 u.fval = measurement1;
vincenxp 0:10bf1bb6d2b5 380 v.fval = measurement2;
vincenxp 0:10bf1bb6d2b5 381
vincenxp 0:10bf1bb6d2b5 382 // now fill the buffers with the stuff generated above so it can be sent over I2C:
vincenxp 0:10bf1bb6d2b5 383
vincenxp 0:10bf1bb6d2b5 384 // stuff latest measurement float values into bytes of buf for next transmission...
vincenxp 0:10bf1bb6d2b5 385 // buffer format: 4 bytes = (float) V, 4 bytes = (float) I, 1 byte status
vincenxp 0:10bf1bb6d2b5 386 for (j=0; j<4; j++) buf[j] = u.b[j]; // voltage
vincenxp 0:10bf1bb6d2b5 387 for (j=0; j<4; j++) buf[j+4] = v.b[j]; // current
vincenxp 0:10bf1bb6d2b5 388 buf[8] = status;
vincenxp 0:10bf1bb6d2b5 389
vincenxp 0:10bf1bb6d2b5 390 // transfer compressed measurement data to output buffers...
vincenxp 1:587e0346abca 391 for (j=0; j<9; j++) obuf[j] = buf[j];
vincenxp 1:587e0346abca 392 for (j=0; j<4; j++) cbuf[j] = buf[j+10];
vincenxp 0:10bf1bb6d2b5 393
vincenxp 0:10bf1bb6d2b5 394 } //ISR
vincenxp 0:10bf1bb6d2b5 395 #endif
vincenxp 1:587e0346abca 396
vincenxp 0:10bf1bb6d2b5 397
vincenxp 1:587e0346abca 398
vincenxp 0:10bf1bb6d2b5 399
vincenxp 0:10bf1bb6d2b5 400 /***********************************************************************************
vincenxp 0:10bf1bb6d2b5 401 *
vincenxp 0:10bf1bb6d2b5 402 * MAIN CODE
vincenxp 0:10bf1bb6d2b5 403 *
vincenxp 0:10bf1bb6d2b5 404 ************************************************************************************/
vincenxp 0:10bf1bb6d2b5 405
vincenxp 0:10bf1bb6d2b5 406 // main...
vincenxp 0:10bf1bb6d2b5 407 int main() {
vincenxp 0:10bf1bb6d2b5 408
vincenxp 1:587e0346abca 409 buf[0] = 0;
vincenxp 1:587e0346abca 410
vincenxp 1:587e0346abca 411 #if (USEI2CNOTUART == 0)
vincenxp 0:10bf1bb6d2b5 412 float volt = 0;
vincenxp 0:10bf1bb6d2b5 413 float curr_sensor = 0;
vincenxp 1:587e0346abca 414 #if (DEBUG == 1)
vincenxp 1:587e0346abca 415 int sensor = 0;
vincenxp 1:587e0346abca 416 int timeStart=0, timeEnd=0;
vincenxp 1:587e0346abca 417 #endif
vincenxp 1:587e0346abca 418 #if (TRACEPRINT == 1)
vincenxp 1:587e0346abca 419 float before_printf=0, after_printf=0;
vincenxp 1:587e0346abca 420 #endif
vincenxp 1:587e0346abca 421
vincenxp 1:587e0346abca 422 uart.baud(115200);
vincenxp 1:587e0346abca 423 uart.printf("\r\nData from current sensor...\n");
vincenxp 1:587e0346abca 424 uart.printf("\r\nNumber of sample(s) for averaging measurement: %d", n_meas);
vincenxp 1:587e0346abca 425 uart.printf("\r\nModes:");
vincenxp 1:587e0346abca 426 if (DEBUG) {
vincenxp 1:587e0346abca 427 uart.printf("\r\n DEBUG: YES");
vincenxp 1:587e0346abca 428 } else {
vincenxp 1:587e0346abca 429 uart.printf("\r\n DEBUG: NO");
vincenxp 1:587e0346abca 430 }
vincenxp 1:587e0346abca 431 if (TRACEPRINT) {
vincenxp 1:587e0346abca 432 uart.printf("\r\n TRACEPRINT: YES");
vincenxp 1:587e0346abca 433 } else {
vincenxp 1:587e0346abca 434 uart.printf("\r\n TRACEPRINT: NO");
vincenxp 1:587e0346abca 435 }
vincenxp 1:587e0346abca 436 if (BUFFMEASURES) {
vincenxp 1:587e0346abca 437 uart.printf("\r\n BUFFMEASURES: YES");
vincenxp 1:587e0346abca 438 uart.printf("\r\n buffer size: %d\n", BUFFERSIZE);
vincenxp 1:587e0346abca 439 } else {
vincenxp 1:587e0346abca 440 uart.printf("\r\n BUFFMEASURES: NO");
vincenxp 1:587e0346abca 441 }
vincenxp 1:587e0346abca 442
vincenxp 1:587e0346abca 443 uart.printf("\r\nDelay for FET switching: %d us", wait_mbbb);
vincenxp 1:587e0346abca 444 uart.printf("\r\nDelay for HIGH current sensor switching: %d us", wait_high);
vincenxp 1:587e0346abca 445 uart.printf("\r\nDelay for MID current sensor switching: %d us", wait_low1);
vincenxp 1:587e0346abca 446 uart.printf("\r\nDelay for LOW current sensor switching: %d us", wait_low2);
vincenxp 1:587e0346abca 447 uart.printf("\r\nDelay for voltage sensor switching: %d us", wait_vrail);
vincenxp 1:587e0346abca 448
vincenxp 1:587e0346abca 449
vincenxp 1:587e0346abca 450 // turn on pull ups for option resistors, since resistors pull down pins
vincenxp 1:587e0346abca 451 C_RANGE.mode(PullUp);
vincenxp 1:587e0346abca 452 V_RANGE0.mode(PullUp);
vincenxp 1:587e0346abca 453 V_RANGE1.mode(PullUp);
vincenxp 1:587e0346abca 454 // change calculation multipliers according to option resistors:
vincenxp 1:587e0346abca 455 i = V_RANGE1*2 + V_RANGE0;
vincenxp 1:587e0346abca 456 if (i==1) vref = 6.6;
vincenxp 1:587e0346abca 457 if (i==2) vref = 12.0;
vincenxp 1:587e0346abca 458 if (C_RANGE==0) {
vincenxp 1:587e0346abca 459 factor_H = vref / 2.0;
vincenxp 1:587e0346abca 460 factor_L1 = vref / (0.15 * 1000);
vincenxp 1:587e0346abca 461 factor_L2 = vref / (15 * 1000);
vincenxp 1:587e0346abca 462 }
vincenxp 1:587e0346abca 463
vincenxp 1:587e0346abca 464 uart.printf("\r\n\nFactor_H: %f", factor_H);
vincenxp 1:587e0346abca 465 uart.printf("\r\nFactor_L1: %f", factor_L1);
vincenxp 1:587e0346abca 466 uart.printf("\r\nFactor_L2: %f", factor_L2);
vincenxp 1:587e0346abca 467
vincenxp 1:587e0346abca 468
vincenxp 1:587e0346abca 469 //VB to debug the latency to compensate the FET peak current
vincenxp 1:587e0346abca 470 #if 0
vincenxp 1:587e0346abca 471 float tempI=0;
vincenxp 1:587e0346abca 472
vincenxp 1:587e0346abca 473 enableHighRange(); // this should already be the case, but do it anyway...
vincenxp 1:587e0346abca 474 #if (USEI2CNOTUART == 0)
vincenxp 1:587e0346abca 475 current[0] = 0;
vincenxp 1:587e0346abca 476 current[1] = 0;
vincenxp 1:587e0346abca 477 current[2] = 0;
vincenxp 1:587e0346abca 478 #endif
vincenxp 1:587e0346abca 479 tempI = measureHigh(1);
vincenxp 1:587e0346abca 480 #if (USEI2CNOTUART == 0)
vincenxp 1:587e0346abca 481 current[0] = tempI;
vincenxp 1:587e0346abca 482 #endif
vincenxp 1:587e0346abca 483 status = 1;
vincenxp 1:587e0346abca 484 // if current is below this threshold, use LOW1 to measure...
vincenxp 1:587e0346abca 485 if (tempI < 0.060) {
vincenxp 1:587e0346abca 486 enableLow1Range();
vincenxp 1:587e0346abca 487 tempI = measureLow1(false, 1); // call function
vincenxp 1:587e0346abca 488 #if (USEI2CNOTUART == 0)
vincenxp 1:587e0346abca 489 current[1] = tempI;
vincenxp 1:587e0346abca 490 #endif
vincenxp 1:587e0346abca 491 status = 2;
vincenxp 1:587e0346abca 492 // if current is below this threshold, use LOW2 to measure...
vincenxp 1:587e0346abca 493 if (tempI < 0.0009){
vincenxp 1:587e0346abca 494 while (1) {
vincenxp 1:587e0346abca 495 timer.reset();
vincenxp 1:587e0346abca 496 timer.start();
vincenxp 1:587e0346abca 497 volt = measureRailV(n_meas);
vincenxp 1:587e0346abca 498 enableLow2Range(); // change FETs to enable LOW2 measurement...
vincenxp 1:587e0346abca 499 for (int idx_meas = 0; idx_meas < BUFFERSIZE; idx_meas++) {
vincenxp 1:587e0346abca 500 enableLow2Range();
vincenxp 1:587e0346abca 501 wait_us(100);
vincenxp 1:587e0346abca 502 tempI = factor_L2 * LOW2_ADC;
vincenxp 1:587e0346abca 503 //wait_us(500);
vincenxp 1:587e0346abca 504 enableHighRange();
vincenxp 1:587e0346abca 505 timestamp = timer.read();
vincenxp 1:587e0346abca 506 buffer[idx_meas][0] = timestamp;
vincenxp 1:587e0346abca 507 buffer[idx_meas][1] = volt;
vincenxp 1:587e0346abca 508 buffer[idx_meas][2] = tempI;
vincenxp 1:587e0346abca 509 }
vincenxp 1:587e0346abca 510 for (int idx_meas = 0; idx_meas < BUFFERSIZE; idx_meas++) {
vincenxp 1:587e0346abca 511 uart.printf("\r\n%d %f %f %f", idx_meas, buffer[idx_meas][0], buffer[idx_meas][1], buffer[idx_meas][2]);
vincenxp 1:587e0346abca 512 }
vincenxp 1:587e0346abca 513 }
vincenxp 1:587e0346abca 514 }
vincenxp 1:587e0346abca 515 }
vincenxp 1:587e0346abca 516 #else
vincenxp 1:587e0346abca 517 //End of VB
vincenxp 1:587e0346abca 518
vincenxp 1:587e0346abca 519 #if (DEBUG == 1)
vincenxp 1:587e0346abca 520 #if (TRACEPRINT == 0)
vincenxp 1:587e0346abca 521 uart.printf("\r\n\nMeasuresDuration(us)(V,I) sensor timestamp(s) Voltage(V) Current(A) HighSensor(A) MidSensor(A) LowSensor(A)");
vincenxp 1:587e0346abca 522 #else
vincenxp 1:587e0346abca 523 uart.printf("\r\n\nMeasuresDuration(us)(V,I) sensor timestamp(s) Voltage(V) Current(A) HighSensor(A) MidSensor(A) LowSensor(A) UartPrintDuration(us)");
vincenxp 1:587e0346abca 524 #endif
vincenxp 1:587e0346abca 525 #elif (BUFFMEASURES == 1)
vincenxp 1:587e0346abca 526 uart.printf("\r\n\nidx timestamp(s) Voltage(V) Current(A)");
vincenxp 1:587e0346abca 527 #else
vincenxp 1:587e0346abca 528 #if (TRACEPRINT == 0)
vincenxp 1:587e0346abca 529 uart.printf("\r\n\ntimestamp(s) Voltage(V) Current(A)");
vincenxp 1:587e0346abca 530 #else
vincenxp 1:587e0346abca 531 uart.printf("\r\n\ntimestamp(s) Voltage(V) Current(A) UartPrintDuration(us)");
vincenxp 1:587e0346abca 532 #endif
vincenxp 1:587e0346abca 533 #endif
vincenxp 0:10bf1bb6d2b5 534
vincenxp 1:587e0346abca 535 #if (BUFFMEASURES == 0)
vincenxp 0:10bf1bb6d2b5 536 timer.reset();
vincenxp 0:10bf1bb6d2b5 537 timer.start();
vincenxp 1:587e0346abca 538 #endif
vincenxp 0:10bf1bb6d2b5 539
vincenxp 0:10bf1bb6d2b5 540 while (1) {
vincenxp 0:10bf1bb6d2b5 541
vincenxp 1:587e0346abca 542 #if (DEBUG == 1)
vincenxp 1:587e0346abca 543 timeStart = timer.read_us();
vincenxp 1:587e0346abca 544 #endif
vincenxp 1:587e0346abca 545 #if (BUFFMEASURES == 1)
vincenxp 1:587e0346abca 546 timer.reset();
vincenxp 1:587e0346abca 547 timer.start();
vincenxp 1:587e0346abca 548 for (int idx_meas = 0; idx_meas < BUFFERSIZE; idx_meas++) {
vincenxp 1:587e0346abca 549 volt = measureRailV(n_meas);
vincenxp 1:587e0346abca 550 curr_sensor = measureAutoI(n_meas);
vincenxp 1:587e0346abca 551 buffer[idx_meas][0] = timestamp;
vincenxp 1:587e0346abca 552 buffer[idx_meas][1] = volt;
vincenxp 1:587e0346abca 553 buffer[idx_meas][2] = curr_sensor;
vincenxp 1:587e0346abca 554 }
vincenxp 1:587e0346abca 555 #else
vincenxp 1:587e0346abca 556 volt = measureRailV(n_meas);
vincenxp 1:587e0346abca 557 curr_sensor = measureAutoI(n_meas);
vincenxp 1:587e0346abca 558 #endif
vincenxp 1:587e0346abca 559 #if (DEBUG == 1)
vincenxp 1:587e0346abca 560 timeEnd = timer.read_us();
vincenxp 1:587e0346abca 561 #endif
vincenxp 1:587e0346abca 562 #if (TRACEPRINT == 1)
vincenxp 1:587e0346abca 563 before_printf = timer.read();
vincenxp 1:587e0346abca 564 #endif
vincenxp 1:587e0346abca 565 #if (DEBUG == 1)
vincenxp 1:587e0346abca 566 uart.printf("\r\n%d %d %f %f %f %f %f %f", timeEnd-timeStart, sensor, timestamp, volt, curr_sensor, current[0], current[1], current[2]);
vincenxp 1:587e0346abca 567 #elif (BUFFMEASURES == 1)
vincenxp 1:587e0346abca 568 for (int idx_meas = 0; idx_meas < BUFFERSIZE; idx_meas++) {
vincenxp 1:587e0346abca 569 uart.printf("\r\n%d %f %f %f", idx_meas, buffer[idx_meas][0], buffer[idx_meas][1], buffer[idx_meas][2]);
vincenxp 1:587e0346abca 570 }
vincenxp 1:587e0346abca 571 #else
vincenxp 1:587e0346abca 572 uart.printf("\r\n%f %f %f", timestamp, volt, curr_sensor);
vincenxp 1:587e0346abca 573 #endif
vincenxp 1:587e0346abca 574 #if (TRACEPRINT == 1)
vincenxp 1:587e0346abca 575 after_printf = timer.read();
vincenxp 1:587e0346abca 576 uart.printf(" %f", after_printf - before_printf);
vincenxp 1:587e0346abca 577 #endif
vincenxp 0:10bf1bb6d2b5 578 }
vincenxp 1:587e0346abca 579 #endif
vincenxp 1:587e0346abca 580 #else
vincenxp 0:10bf1bb6d2b5 581
vincenxp 0:10bf1bb6d2b5 582 wait_us(200); // wait before reassigning SWD pin so as to not get locked out...
vincenxp 0:10bf1bb6d2b5 583 DigitalIn my_select(PTA2); // this is the individual line to each sensor...
vincenxp 0:10bf1bb6d2b5 584
vincenxp 0:10bf1bb6d2b5 585
vincenxp 0:10bf1bb6d2b5 586 while (my_select) {
vincenxp 0:10bf1bb6d2b5 587 // wait here until aggregator signals us for address reassignment...
vincenxp 0:10bf1bb6d2b5 588 } // end while
vincenxp 0:10bf1bb6d2b5 589
vincenxp 0:10bf1bb6d2b5 590 // Need to wait to set up I2C until after we've come out of wait loop above...
vincenxp 0:10bf1bb6d2b5 591 // Setting up the I2C earlier starts it listening on the bus even if it's not
vincenxp 0:10bf1bb6d2b5 592 // being polled, which means that multiple sensors will respond, hanging the bus...
vincenxp 0:10bf1bb6d2b5 593 slave.frequency(400000); // go as fast as possible...
vincenxp 0:10bf1bb6d2b5 594 slave.address(address); // listen on the default address...
vincenxp 0:10bf1bb6d2b5 595
vincenxp 0:10bf1bb6d2b5 596 while (!my_select) {
vincenxp 0:10bf1bb6d2b5 597 // listen for new address, then repeat it back aggregator...
vincenxp 0:10bf1bb6d2b5 598 waiting = true;
vincenxp 0:10bf1bb6d2b5 599 while (waiting && !my_select){
vincenxp 0:10bf1bb6d2b5 600 int i = slave.receive();
vincenxp 0:10bf1bb6d2b5 601 switch (i) {
vincenxp 0:10bf1bb6d2b5 602 case I2CSlave::WriteAddressed:
vincenxp 0:10bf1bb6d2b5 603 slave.read(buf, 1);
vincenxp 0:10bf1bb6d2b5 604 // we just got our new address, provided my_select subsequently changes...
vincenxp 0:10bf1bb6d2b5 605 waiting = false;
vincenxp 0:10bf1bb6d2b5 606 break;
vincenxp 0:10bf1bb6d2b5 607 case I2CSlave::ReadAddressed:
vincenxp 0:10bf1bb6d2b5 608 slave.write(buf, 1);
vincenxp 0:10bf1bb6d2b5 609 // write back our new address to confirm we go it...
vincenxp 0:10bf1bb6d2b5 610 waiting = false;
vincenxp 0:10bf1bb6d2b5 611 break;
vincenxp 0:10bf1bb6d2b5 612 }
vincenxp 0:10bf1bb6d2b5 613 }
vincenxp 0:10bf1bb6d2b5 614 } // end while, waiting for address reassignment...
vincenxp 0:10bf1bb6d2b5 615
vincenxp 0:10bf1bb6d2b5 616 // we fell out of loop above, so now change our I2C address to the newly assigned one...
vincenxp 0:10bf1bb6d2b5 617 // this newly assigned address will not change until we're reset...
vincenxp 0:10bf1bb6d2b5 618 slave.address(buf[0]);
vincenxp 0:10bf1bb6d2b5 619
vincenxp 0:10bf1bb6d2b5 620 // enable interrupts, need to wait until after getting new I2C address,
vincenxp 0:10bf1bb6d2b5 621 // since we cannot respond until we have our new address...
vincenxp 0:10bf1bb6d2b5 622 InterruptIn triggerIRQ(PTA0); // this is the ganged interrupt signal to all sensors
vincenxp 0:10bf1bb6d2b5 623 triggerIRQ.rise(&interrupt_service); // attach the service routine...
vincenxp 0:10bf1bb6d2b5 624
vincenxp 0:10bf1bb6d2b5 625 // make sure we can receive at the new address...
vincenxp 0:10bf1bb6d2b5 626 // this isn't absolutely necessary, but it's a good check...
vincenxp 0:10bf1bb6d2b5 627 // if this is removed, the corresponding write in the aggregator code needs to go, too
vincenxp 0:10bf1bb6d2b5 628 waiting = true;
vincenxp 0:10bf1bb6d2b5 629 while (waiting){
vincenxp 0:10bf1bb6d2b5 630 i = slave.receive();
vincenxp 0:10bf1bb6d2b5 631 switch (i) {
vincenxp 0:10bf1bb6d2b5 632 case I2CSlave::ReadAddressed:
vincenxp 0:10bf1bb6d2b5 633 slave.write(buf, 1);
vincenxp 0:10bf1bb6d2b5 634 waiting = false;
vincenxp 0:10bf1bb6d2b5 635 break;
vincenxp 0:10bf1bb6d2b5 636 case I2CSlave::WriteAddressed:
vincenxp 0:10bf1bb6d2b5 637 slave.read(buf, 1);
vincenxp 0:10bf1bb6d2b5 638 waiting = false;
vincenxp 0:10bf1bb6d2b5 639 break;
vincenxp 0:10bf1bb6d2b5 640 }
vincenxp 0:10bf1bb6d2b5 641 }
vincenxp 0:10bf1bb6d2b5 642
vincenxp 0:10bf1bb6d2b5 643
vincenxp 0:10bf1bb6d2b5 644 /******************************************************************************/
vincenxp 0:10bf1bb6d2b5 645 // this is the main loop:
vincenxp 0:10bf1bb6d2b5 646 // We just sit here and wait for I2C commands and triggers on IRQ line...
vincenxp 0:10bf1bb6d2b5 647 //
vincenxp 0:10bf1bb6d2b5 648 // A triggerIRQ causes measurements in ISR, aggregator must wait at least
vincenxp 0:10bf1bb6d2b5 649 // long enough for it to finish before reading back the result(s).
vincenxp 0:10bf1bb6d2b5 650 //
vincenxp 0:10bf1bb6d2b5 651 // results are sent in 9 byte packets: 4 for voltage, 4 for current, and one status,
vincenxp 0:10bf1bb6d2b5 652 // where voltage and current are floats in units of V and A. Status byte will be
vincenxp 0:10bf1bb6d2b5 653 // packed with something later, yet to be defined.
vincenxp 0:10bf1bb6d2b5 654 //
vincenxp 0:10bf1bb6d2b5 655 // What should be implemented are additional things like setting and reading
vincenxp 0:10bf1bb6d2b5 656 // back the delays in the GPIO control functions, turning on and off averaging
vincenxp 0:10bf1bb6d2b5 657 // so we can see what the min and max values are (which also helps tell if we
vincenxp 0:10bf1bb6d2b5 658 // don't have enough delay in the GPIO functions), and possibly other stuff
vincenxp 0:10bf1bb6d2b5 659 // not thought of yet... Definitely not an exercise for this pasta programmer...
vincenxp 0:10bf1bb6d2b5 660 //
vincenxp 0:10bf1bb6d2b5 661 while (1) {
vincenxp 0:10bf1bb6d2b5 662 i = slave.receive();
vincenxp 0:10bf1bb6d2b5 663 switch (i) {
vincenxp 0:10bf1bb6d2b5 664 case I2CSlave::ReadAddressed:
vincenxp 0:10bf1bb6d2b5 665 if (my_select){ // if high, send uncompressed format...
vincenxp 0:10bf1bb6d2b5 666 slave.write(obuf, 9);
vincenxp 0:10bf1bb6d2b5 667 waiting = false;
vincenxp 0:10bf1bb6d2b5 668 } else { // if low, send compressed format...
vincenxp 0:10bf1bb6d2b5 669 slave.write(cbuf, 4);
vincenxp 0:10bf1bb6d2b5 670 waiting = false;
vincenxp 0:10bf1bb6d2b5 671 }
vincenxp 0:10bf1bb6d2b5 672 break;
vincenxp 0:10bf1bb6d2b5 673 case I2CSlave::WriteAddressed:
vincenxp 0:10bf1bb6d2b5 674 // slave.read(inbuf, 1);
vincenxp 0:10bf1bb6d2b5 675 // waiting = false;
vincenxp 0:10bf1bb6d2b5 676 // break;
vincenxp 0:10bf1bb6d2b5 677 if (my_select){ // if high, receive two bytes...
vincenxp 0:10bf1bb6d2b5 678 slave.read(inbuf, 2);
vincenxp 0:10bf1bb6d2b5 679 waiting = false;
vincenxp 0:10bf1bb6d2b5 680 // if we're here, we've recieved two words, so we update the
vincenxp 0:10bf1bb6d2b5 681 // appropriate parameter.
vincenxp 0:10bf1bb6d2b5 682 switch (inbuf[0]) {
vincenxp 0:10bf1bb6d2b5 683 case 0:
vincenxp 0:10bf1bb6d2b5 684 wait_mbbb = inbuf[1];
vincenxp 0:10bf1bb6d2b5 685 break;
vincenxp 0:10bf1bb6d2b5 686 case 1:
vincenxp 0:10bf1bb6d2b5 687 wait_high = inbuf[1]*8;
vincenxp 0:10bf1bb6d2b5 688 break;
vincenxp 0:10bf1bb6d2b5 689 case 2:
vincenxp 0:10bf1bb6d2b5 690 wait_low1 = inbuf[1]*8;
vincenxp 0:10bf1bb6d2b5 691 break;
vincenxp 0:10bf1bb6d2b5 692 case 3:
vincenxp 0:10bf1bb6d2b5 693 wait_low2 = inbuf[1]*8;
vincenxp 0:10bf1bb6d2b5 694 break;
vincenxp 0:10bf1bb6d2b5 695 case 4:
vincenxp 0:10bf1bb6d2b5 696 wait_vrail = inbuf[1]*8;
vincenxp 0:10bf1bb6d2b5 697 break;
vincenxp 0:10bf1bb6d2b5 698 case 5:
vincenxp 0:10bf1bb6d2b5 699 n_meas = inbuf[1];
vincenxp 0:10bf1bb6d2b5 700 break;
vincenxp 0:10bf1bb6d2b5 701 } // switch
vincenxp 0:10bf1bb6d2b5 702 // and since we're still here, place the new values
vincenxp 0:10bf1bb6d2b5 703 // in obuf so we can read back all paramters values
vincenxp 0:10bf1bb6d2b5 704 obuf[0] = wait_mbbb;
vincenxp 0:10bf1bb6d2b5 705 obuf[1] = wait_high/8;
vincenxp 0:10bf1bb6d2b5 706 obuf[2] = wait_low1/8;
vincenxp 0:10bf1bb6d2b5 707 obuf[3] = wait_low2/8;
vincenxp 0:10bf1bb6d2b5 708 obuf[4] = wait_vrail/8;
vincenxp 0:10bf1bb6d2b5 709 obuf[5] = n_meas;
vincenxp 0:10bf1bb6d2b5 710 obuf[6] = 0;
vincenxp 0:10bf1bb6d2b5 711 obuf[7] = 0;
vincenxp 0:10bf1bb6d2b5 712 obuf[8] = 0;
vincenxp 0:10bf1bb6d2b5 713 } else { ;// if low, receive one byte...
vincenxp 0:10bf1bb6d2b5 714 slave.read(inbuf, 1);
vincenxp 0:10bf1bb6d2b5 715 waiting = false;
vincenxp 0:10bf1bb6d2b5 716 }
vincenxp 0:10bf1bb6d2b5 717 } // switch
vincenxp 0:10bf1bb6d2b5 718 } // while(1)
vincenxp 0:10bf1bb6d2b5 719 #endif
vincenxp 0:10bf1bb6d2b5 720
vincenxp 0:10bf1bb6d2b5 721 }