
aggregator code initial version add plot menu to continuously print #sensor, V, I on uart
Diff: kl25-aggregator-plot.cpp
- Revision:
- 0:667d2b410f9a
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kl25-aggregator-plot.cpp Tue Mar 26 08:37:58 2019 +0000 @@ -0,0 +1,329 @@ +/******************************************************************************* +* +* MIT License (https://spdx.org/licenses/MIT.html) +* Copyright 2018 NXP +* +* MBED code for FRDM-KL25Z aggregator. Configures and triggers "smart" sensors. +* Aggregates data and sends up the line to a host computer over USB serial. +* Other FRDM boards (K64F or K66F) may be used for ethernet connection or for +* more local memory or faster processing speed. +* +* +* !!! 3Dec18: This now appears to be fixed with current version of library.. +* !!! must use mbed-2 from 20 Mar 2018 or serial port won't work !!! +* !!! do not update mbed library... !!! +* +********************************************************************************/ + +#include "mbed.h" + +// Custom setup +#define CUSTOM 1 + +char version_info[] = "3 Dec 2018"; // date info... + +Serial uart(USBTX, USBRX); // standard FRDM board USBx + +// set up GPIO connections... +DigitalOut reset(PTB0); // PTA1 on smart sensor board +DigitalOut interrupt(PTB1); // PTA0 on smart sensor board +const int sensors = 14; +DigitalOut select[sensors] = // PTA2 on smart sensor board + { (PTD4), (PTA12), (PTA4), (PTA5), (PTC8), (PTC9), (PTA13), + (PTD5), (PTD0), (PTD2), (PTD3), (PTD1), (PTB3), (PTB2)}; +I2C i2c(PTE0, PTE1); + +int addr8bit = 0x48 << 1; // default start addr for communication with sensors + +// multipliers of ten used for decompressing data... +// *note* this array fails when it's not a const. index 4 returns zero for some +// reason... maybe mbed, not sure... seems to be mbed-2 related... +const float pow10[14] = {1.0, 1.0e-1, 1.0e-2, 1.0e-3, 1.0e-4, 1.0e-5, 1.0e-6, + 1.0e-7, 1.0e-8, 1.0e-9, 1.0e-10, 1.0e-11, 1.0e-12, 1.0e-13}; + + +// some more variables... +int n, i, j, k, status, temp; +#if (CUSTOM == 1) +int delay=0; // starting delay for measurement updates... +#else +int delay=500000; // starting delay for measurement updates... +#endif +long int count=0; +char cmd[20]; // buffer for holding data sent to/from sensor boards +char params[sensors][10];// array to keep sensor parameter data... +bool deebug=false; // flag to print extra stuff for debug... +float v1, v2, i1, i2; // for holding full float vs. compressed 3-sigfig measurements +bool full = false; // boolean to control whether full binary numbers sent +bool gui = true; // flag to print data out in compressed format +bool plot = true; // flag use to send data in a plot-able format +bool barg = false; // flag for bar graph... + +// timer so we can time how long things take... +Timer t; + +// set up various arrays related to smart sensors... +bool present[sensors] = { false, false }; // whether or not a sensor is present +bool continuous = true; // flag for making continuous vs. triggered measurements... +// this array of addresses also needed to be made a const array or +// some values would inexplicably change and cause I2C errors +// (because the address in the array gets changed somehow)... const fixes... +// this seems to be mbed-2 related... +const short int address[sensors] = // assigned address for each sensor + { 0x50<<1, 0x51<<1, 0x52<<1, 0x53<<1, 0x54<<1, + 0x55<<1, 0x56<<1, 0x57<<1, 0x58<<1, 0x59<<1, + 0x5a<<1, 0x5b<<1, 0x5c<<1, 0x5d<<1 }; + +// this union allows easily converting float value to bare bytes and back again... +union u_tag { + char b[4]; + float fval; + int bobo; + } volt[2], curr[2]; // voltage and current value from sensor + + + +// function that sends measurement trigger pulse to all sensors, singalling +// them to take a measurement which will be subsequently and sequentially read... +void send_trigger(){ + interrupt = 1; + wait_us(50); + interrupt = 0; +} + + + +// main code starts here... +int main() { + + // set things up... + reset = 0; // place sensors in reset + interrupt = 0; // place trigger line low + for (k=0; k<sensors; k++) select[k] = 1; // set each sensor's select line high + + i2c.frequency(400000); // set I2C frequency + uart.baud(115200); // set UART baud rate + uart.printf("\r\n\r\n\e[2J%s\r\nI'm here...\r\n ", version_info); // signal that we're off and running... + // where \e[2J clears the screen... + + // loop forever (although, as code has evolved, this loop never completes...) + while(1) { + reset = 0; // issue a global reset + wait(0.01); // wait a bit + reset = 1; // release reset + count++; // overall iteration count + uart.printf("\r\n\r\nReleased reset... %d\r\n", count); + + wait(0.0005); // wait a little bit... + + // iterate to identify and configure each connected sensor... + for (k=0; k<sensors; k++){ // loop over all sensors + present[k] = false; // set presence to false before looking for sensor... + + select[k] = 0; // smake sensor select line low to start address reassignment + uart.printf("Asserted select[%X] line low... \r\n", k); + + wait(0.001); // wait a bit... + + // write the new address to sensor and then read it back to verify... + cmd[0] = address[k]; + n = i2c.write( addr8bit, cmd, 1); + uart.printf("Wrote: %x error %d \r\n", cmd[0], n); + if (n==0) present[k] = true; // a sensor IS connected on this select line, since it ACKed + if (present[k]){ + cmd[0] = 0; // clear cmd... + wait(0.0001); + n = i2c.read( addr8bit, cmd, 1); + uart.printf(" ===> Read back: %x error %d\r\n", cmd[0], n); + // here we're reading it back but we're not actually checking the value... + // just assuming that since we were able to write, we'll read the same + // value back... + } else i2c.stop(); // not present, error condition... + + wait(0.0001); + select[k] = 1; // set sensor's select line high, telling it to change its I2C addr + uart.printf("Sending select[%X] back high to change address... \r\n", k); + + if (present[k]) { + // now check that the address change was successful... + // write to the new address, there is currently no error out + // if sensor does not respond... + wait(0.0001); + cmd[0]=0xff; + n = i2c.write( address[k], cmd, 1); + if (n==0) { uart.printf("\r\nSensor %X configured... now to test... \r\n\r\n", k); } + else present[k]=false; + } // endif + + if (present[k]) { + // read parameters from sensor + // Need to do this sequence without a trigger, since that'll cause an interrupt + // and clobber any pre-loaded paramter data... + cmd[0] = 99; // make a dummy write in order to pre-load parameter buffer... + n = i2c.write( address[k], cmd, 2 ); + wait(0.001); + // here's where we actually read the parameters: + n = i2c.read( address[k], params[k], 9 ); // select is already high from above, so we don't need to do it again... + uart.printf("\r\n params %d %d %d %d %d %d \r\n", params[k][0], params[k][1]*8, params[k][2]*8, params[k][3]*8, params[k][4]*8, params[k][5]); + + #if (CUSTOM == 0) + // now add one to each parameter to make sure we can write them all... + // will see below if it worked... (we'll see it down below) + for (i=0; i<6; i++){ + cmd[0] = i; + cmd[1] = params[k][i]+1; + uart.printf(" %d, %d, %d %d \r\n", k, i, cmd[0], cmd[1]); + n = i2c.write( address[k], cmd, 2 ); + wait(0.01); + } + #endif + + } + + } // for k + + wait(0.0005); + + // ****************************************************************** + // read data from all connected sensors... + // ****************************************************************** + while (1) { + //if (!gui) uart.printf("\r\nTriggering measurement... \r\n"); + //else uart.printf("\e[2J\r\n"); // # (A) (V)\r\n"); + t.start(); + send_trigger(); // trigger tells all connected sensors to make the measurements + #if (CUSTOM == 0) + wait_ms(8.75); // need to give enough time to make them... + #endif + for (k=0; k<sensors; k++){ // iterate over all sensors + if (present[k]){ // if a sensor is present, read its data + + if (full){ + // full floating point data tranfer... + n = i2c.read( address[k], cmd, 9 ); + if (deebug && !gui) uart.printf(" I2C adddr: 0x%X %X\r\n", address[k], k); + // unstuff the bytes back into floating point values... + for (j=0; j<4; j++) curr[k].b[j] = cmd[j]; + for (j=0; j<4; j++) volt[k].b[j] = cmd[j+4]; + v1 = volt[k].fval; i1 = curr[k].fval; + if (!gui) uart.printf(" Sensor %X: ===> %4.2e %4.2e 0x%x err %d\r\n", k, volt[k].fval, curr[k].fval, cmd[8], n); + } // if (full) + + // compressed data transfer with status nibble: 2 float values of 3 sig figs each + status nibble: + // where each value is 3 digits, single digit exponent, and two status bits packed into 2 bytes + // four bytes in total... + select[k] = 0; // indicate that we want to read compressed data from sensor... + n = i2c.read( address[k], cmd, 4 ); + select[k] = 1; + // pull out status bits from the four received bytes... + status = (cmd[0]&(1<<7))>>4 | (cmd[1]&(1<<7))>>5 | (cmd[2]&(1<<7))>>6 | (cmd[3]&(1<<7))>>7 ; + if (deebug && !gui) uart.printf(" %02d %02d %02d %02d %8.6f %d %8.6f %d\r\n", cmd[0]&0x7f, cmd[1]&0x7f, cmd[2]&0x7f, cmd[3]&0x7f, + pow10[(int)(((cmd[1]&(0x7f)) % 10)+2)], (int) (((cmd[1]&(0x7f)) % 10)+2), + pow10[(int)(((cmd[3]&(0x7f)) % 10)+2)], (int) (((cmd[3]&(0x7f)) % 10)+2)); + // now reconstruct the two float values... + curr[k].fval = (float) ( (cmd[0]&(0x7f))*10 + (cmd[1]&(0x7f))/10 ) * pow10[((cmd[1]&(0x7f)) % 10)+2]; + volt[k].fval = (float) ( (cmd[2]&(0x7f))*10 + (cmd[3]&(0x7f))/10 ) * pow10[((cmd[3]&(0x7f)) % 10)+2]; + v2 = volt[k].fval; i2 = curr[k].fval; + if (!gui) uart.printf(" compd %X: ===> %4.2e V %4.2e A %d err %d\r\n", k, volt[k].fval, curr[k].fval, status, n); + if (deebug && !gui) printf(" volt? %s current? %s \r\n", + (abs(v1-v2)/v1 <0.05) ? "true" : "false", + (abs(i1-i2)/i1 <0.05) ? "true" : "false"); + + // if we're in gui mode, this is the only line that'll print out for each attached sensor... + if (gui && full) uart.printf(" %X %4.2e %4.2e %4.2e %4.2e \r\n", k, v1, v2, i1, i2); + else { + if (plot) uart.printf("%X %5.3f %8.6f\r\n", k , v2, i2); + //uart.printf(" #%X %4.2e V %4.2e A ", k , v2, i2); + if (barg) for (j=0; j<40*i2; j++) uart.printf("*"); + uart.printf("\r"); + } // else + + // parameter readback from sensor + // !! Smart Sensor's selelct line needs to be high while doing this !! + // Need to do this sequence without a trigger, since that'll cause an interrupt + // and clobber any pre-loaded paramter data... + if (deebug && !gui) { + cmd[0] = 99; // dummy write to pre-load parameter buffer... + n = i2c.write( address[k], cmd, 2 ); + n = i2c.read( address[k], params[k], 9 ); // select is already high from above, so we don't need to do it again... + uart.printf(" params %d %d %d %d %d %d \r\n", params[k][0], params[k][1]*8, params[k][2]*8, params[k][3]*8, params[k][4]*8, params[k][5]); + } + } + else{ + //uart.printf(" !!! device %d missing... \r\n", k); + } //endif + } // for k + // wait_ms(250); + while (t.read_us()<delay){ + // wait until delay worth of time has elapsed... + } + t.stop(); + t.reset(); + + if (!continuous) while (!uart.readable()); // wait here until we get text, if in triggered mode... + while (uart.readable()){ + temp = uart.getc(); + if (deebug) printf ("%d\r\n", temp); + if (temp==(int) '+') { + delay += 100000; + if (delay > 2000000) delay = 2000000; + } + if (temp==(int) '-') { + delay -=100000; + #if (CUSTOM == 0) + if (delay < 14300) delay = 14300; + #else + if (delay < 0) delay = 0; + #endif + } + if (temp==(int) 't') { + uart.printf ("\r\nDelay value = %d\r\n", delay); + } + if (temp==(int) '_') { + delay = 500000; + } + if (temp==(int) 'c') { + continuous = !continuous; + } + if (temp==(int) 'd') { + deebug = !deebug; + } + if (temp==(int) 'g') { + gui = false; + } + if (temp==(int) 'G') { + gui = true; + } + if (temp==(int) 'p') { + plot = true; + } + if (temp==(int) 'b') { + barg = !barg; + } + + if (temp==(int) 'h') { + uart.printf("\r\n\r\n"); + uart.printf("+/- add/remove update time\r\n"); + uart.printf("_ half second update rate\r\n"); + uart.printf("b toggle bar graph in gui mode\r\n"); + uart.printf("c toggle continuous/single trigger\r\n"); + uart.printf("t trigger and print current delay value\r\n"); + uart.printf("d toggle debug flag\r\n"); + uart.printf("g turn off gui mode\r\n"); + uart.printf("G turn on gui mode\r\n"); + uart.printf("p plot data\r\n"); + uart.printf("h print this help\r\n"); + uart.printf("\r\n"); + wait(5); + } + + + } // while uart.readable... + + } // while read from sensors... + // ***************************************************************** + // end data read + // ***************************************************************** + } // while main, should never actually fall out to here... + +} // main