10Hz GPS, MEgasquirt, SD Card, ADxl345, 20x4 LCD datalogger
Dependencies: ADXL345 10HzGPSdatalogger mbed
main.cpp
- Committer:
- jpnovak
- Date:
- 2015-11-28
- Revision:
- 0:b8d7df90819e
File content as of revision 0:b8d7df90819e:
//Code Designed to display run-time variables from a Megasquirt Fuel Injection controller. //This is the base code to load variables and print to LCD and write them to a file. File format is .FRD for import into EFI Analytics tuner Studio #include "mbed.h" #include "gps.h" //////////////////////include for GPS Code ///////////////////////////// #include "data.h" //////////////////////include for GPS Code ///////////////////////////// #include "TextLCD.h" #include "SDFileSystem.h" #include "SerialBuffered.h" #include "ADXL345.h" //SD Card pin assignment SDFileSystem sd(p11, p12, p13, p14, "sd");//DI, D0, SCK, CS //local file system. LocalFileSystem local("local"); AnalogIn SDenable(p20);//define SD card switch DigitalOut myled1(LED1);//define LED Serial loggerSerial(USBTX, USBRX); Timer t; Serial pc(USBTX, USBRX); TextLCD lcd(p21, p22, p23, p24, p25, p26, p30, 20 ,4); //Define LCD pins //Acclerometer - SparkFun ADXL345 16G pin assignment ADXL345 accelerometer(p5, p6, p7, p8); //SPI DI, D0, SCK, CS //Serial usb(USBTX, USBRX); //define USB connection pins SerialBuffered megasquirt(120, p28, p27); // RS232 TX/RX that 120 is the size of the read buffer it will make for you DigitalOut usb_activity(LED1); //define USB activity DigitalOut megasquirt_activity(LED2); //define Megasquirt activity int column; int row; int i; char c; int dataflag; /////////////////////////////////////Define GPS Variables////////////////////////////////// float time1; char statusGPS; float Lat1; float Long1; char Lat_h1; char Long_h1; float time_GPS1; float speed_k1; float speed_mph1; float heading1; ///////////////////define buffers////////////////////////// unsigned char tmp_data[16]; int tmp; unsigned char buf[120]; float Time; ////////////////////////////define MS variables//////////////////////// long float SecL; //get secoonds long float PW;//get pulseWidth1 long float PW2; //get pulseWidth2 int RPM; //get Rpm int DutyCycle; //Injector Duty Cycle int DutyCycle2; //Injector Bank2 Duty Cycle long float SparkAdv; //get advance float squirt; //get squirt float Engine; //get squirt float afrtgt1; //get AFR target - Table 1 float afrtgt2; //get AFR target - Table 2 float wbo2_en1; //get WideBand Valid1 float wbo2_en2; //get WideBand Valid2 long float barometer; //get Barometer long float MAP; //get manifold absolute pressure MAP long float MAT; //get manifold absolute temperature (MAT) long float CLT; //get coolant temperature (CLT) long float TP; //get Throttle Position Sensor (TPS) long float vBatt; //get BAttery Voltage long float AFR; //get Realtime AFR for VE1 long float AFR2; //get Realtime AFR for VE2 long float knock; //get Knock Threshold Value long float Gego; //get egoCorrrection1 amount % long float Gego2; //get egoCorrrection2 amount % long float Gair; //get air correction (G_air) long float Gwarmup; //get Warmup Enrichment long float TPSacc; //get accel enrichment (ms) long float TPScut; //get TPS based fuel cut % long float Gbaro; //get baroCorrection % long float Gammae; //get gammaEnrich % long float veCurr1; //get Current VE value Table 1 long float veCurr2; //get Current VE value Table 2 long float IAC; //get IAC Step % long float ColdAdv; //get Cold Ignition Advance long float tpsDOT; //get Rate of Change TPS long float mapDOT; //get Rate of Change MAP long float Dwell; //get Ignition Dwell long float maf; //get MAF - Mass Air Flow long float fuelload; //get MAP/TPS Blend % long float Ethanol; //get fuel load percent alchohol char portstatus; //get Spare Port Status char knockRetard; //get Knock timing retard (deg) long float EAEFuelCorr; //get EAE Fuel correction long float egoV; //get egoV long float egoV2; //get egoV2 char status1; //get Status1 char status2; //get Status2 char status3; //get Status3 char status4; //get Status4 long float looptime; //get looptime char status5; //get Status5 long float tpsADC; //get tpsADC long float fuelload2; //get fuelload2 long float ignload; //get ignload long float ignload2; //get ignload2 char syncstatus; //get Sync-Status (0 - sync-error, 1 - syncstatus) float deltaT; //get deltaT long float wallfuel; //get wallfuel int runtime; unsigned char data_out; int n; char MSII_288Header[] = {0x46,0x52,0x44,0x00,0x00,0x00,0x00,0x01,0x4b,0x61,0xf1,0x63,0x4d,0x53,0x49,0x49,0x20,0x52,0x65,0x76,0x20,0x32,0x2e,0x38,0x38,0x30,0x30,0x30,0x20,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x00,0x70};//file header char MSIIExtraHeader[] = {0x46,0x52,0x44,0x00,0x00,0x00,0x00,0x01,0x4b,0x6a,0xf3,0xa8,0x4d,0x53,0x32,0x45,0x78,0x74,0x72,0x61,0x20,0x52,0x65,0x6c,0x20,0x32,0x2e,0x31,0x2e,0x31,0x62,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x51,0x00,0x91}; char parse_header[] = {0x01,0x00};//data header //////////////////////////define accelerometer variables///////////////////// float x1;// new variable for math for acceleration parameters float y1;// new variable for math for acceleration parameters float z1;// new variable for math for acceleration parameters float x2;// new variable for math for acceleration parameters float y2;// new variable for math for acceleration parameters float z2;// new variable for math for acceleration parameters /////////////////////////define accelerometer variables///////////////////// int readings[3] = {0, 0, 0}; float XaccelADC; float YaccelADC; float ZaccelADC; float Xaccel_g; float Yaccel_g; float Zaccel_g; /*LCD 4x20 parallel code pin assignment*/ //TextLCD lcd(p21, p22, p23, p24, p25, p26, p30, 20, 4); // (rs, rw, e, d0, d1, d2, d3, n_column, n_rows) //define file write //AnalogIn file_writeenable(p20);//define SD card switch //enter main loop int main() { ////start main program loop //Acceleromater setup //Go into standby mode to configure the device. accelerometer.setPowerControl(0x00); //Full resolution, +/-16g, 4mg/LSB. accelerometer.setDataFormatControl(0x0B); //3.2kHz data rate. accelerometer.setDataRate(ADXL345_3200HZ); //Measurement mode. accelerometer.setPowerControl(0x08); ///////////////////////////GPS setup//////////////////// pc.baud(115200); gps.baud(115200); //////////////////////include for GPS Code ///////////////////////////// /////Startup Screen//////////// lcd.cls(); //lcd.init_Display(); //DigitalOut myled(LED1); lcd.cls(); lcd.printf(" Dashview V3 "); wait(1.5); lcd.cls(); lcd.printf(" Hello "); wait(0.5); lcd.locate(0,1); lcd.printf("Have A Great Drive"); wait(2.0); lcd.cls(); ////////////End Startup Screen////////// megasquirt.baud(115200); //define MEgasquirt serial speed loggerSerial.baud(115200); //define connection speed // unsigned char tmp; // unsigned char data_in; /////////file header setup /////Setup file header for Datalog. /////File header is comma delimited for import to Excel or most video editing software overaly. FILE *fp = fopen("/sd/datalog.csv", "a"); //print header for MS.csv file fprintf(fp, "MSII Rev 2.88000, \ntime1,Lat1,Long1,speed_mph1,heading1,Xaccel_g, Yaccel_g, Zaccel_g,\n"); fclose(fp); t.start(); dataflag=0; i = 0; while (1) { ///start functional loop ////////turn on swtich to Pin 20 to write to SD card/////////////// ////////file formate is .csv for import into Excel and also MegaLog Viewer if (SDenable > 0.5) { //switch enable = ON dataflag = 1; myled1 = 1; // printf("Opening File...\n"); // Drive should be marked as removed FILE *fp = fopen("/sd/datalog.csv", "a"); ///open file //write xls buffer from Megasquirt if(fp == NULL) { error("Could not open file for write\n"); } //if (dataflag == 1) { ///////Begin Dataflag loop////////////////// // for (i = 0; i<5 ; i++) //{ ///start for loop count /////////////////BEGIN DATA COLLECTION LOOP #1///////////////////////////////////// ///////////////////////////////GPS Code///////////////////////////////////// getGPSstring(1); ///////convert string format to floating to perform math functions ///////////////////// if (sscanf(gpsString, "$GPRMC,%s",rmc1) >= 1) { sep = 0; parseRMC(); sscanf(time_GPS, "%f", &time1); sscanf(status, "%c", &statusGPS); sscanf(Lat, "%f", &Lat1); sscanf(Lat_h, "%c", &Lat_h1); sscanf(Long, "%f", &Long1); sscanf(Long_h, "%c", &Long_h1); sscanf(time_GPS, "%f", &time_GPS1); sscanf(speed_k, "%f", &speed_k1); sscanf(heading, "%f", &heading1); } speed_mph1 = speed_k1 * 1.15077; ////convert Knots to mph Lat1 = Lat1/100; /////Convert format for google maps overlay Long1 = Long1/-100; /////Convert format for google maps overlay lcd.locate(10,1); lcd.printf("Spd:%4.1f", speed_mph1); //pc.printf("time:%8.1f Lat:%9.6f Long:%9.6f Spd:%4.1f heading:%5.1f \r\n",time1,Lat1,Long1,speed_mph1,heading1); ///////////////////////////////////End GPS Code/////////////////////////////////////////////// ///////////////Accelerometer code begin here//////////////////////////////////// { accelerometer.getOutput(readings); XaccelADC = (int16_t)readings[0]; YaccelADC = (int16_t)readings[1]; ZaccelADC = (int16_t)readings[2]; Xaccel_g = (XaccelADC/256); Yaccel_g = (YaccelADC/256); Zaccel_g = (ZaccelADC/256); // uncommment to display Accelerometer // lcd.locate(0,0);/// define LCD location // lcd.printf("%4.2f, %4.2f, %4.2f", Xaccel_g, Yaccel_g, Zaccel_g); ///////Lateral Acceleration bar Graph /////////////////////// ///////////////X-direction accleration bar graph///////////////// /* x1 = Xaccel_g * 10;//scale one g to display resolution if (x1 < 0);//for negative g values { x2 = 10 + x1;//offset negative values for positive graph lcd.locate(0,3); /// define LCD location for (i=0; i<10; i++) { if (i < x2) lcd.putc(0x20);//write single space character else lcd.putc(0xFF);//write single clock space } } if (x1 > 0);//for positive g values { lcd.locate(10,3);/// define LCD location for (i=0; i<10; i++) { if (i < x1) lcd.putc(0xFF);//write single block character else lcd.putc(0x20);//write single blank space } } */ ////////////Forward/Braking Acceleration bar Graph /////////////////////// y1 = Yaccel_g * 10;//scale one g to display resolution if (y1 < 0);//for negative g values { y2 = 10 + y1;//offset negative values for positive graph lcd.locate(0,3); /// define LCD location for (i=0; i<10; i++) { if (i < y2) lcd.putc(0x20);//write single space character else lcd.putc(0xFF);//write single clock space } } if (y1 > 0);//for positive g values { lcd.locate(10,3);/// define LCD location for (i=0; i<10; i++) { if (i < y1) lcd.putc(0xFF);//write single block character else lcd.putc(0x20);//write single blank space } } ////////////End Accelerometer code ////////////////////////////////////////////// fprintf(fp, "%.3f, %9.6f, %9.6f, %3.1f,%4.1f, %.3f, %.3f, %.3f", time1,Lat1,Long1,speed_mph1,heading1,Xaccel_g, Yaccel_g, Zaccel_g); pc.printf("%.3f, %9.6f, %9.6f, %3.1f,%4.1f, %.3f, %.3f, %.3f, \r\n", time1,Lat1,Long1,speed_mph1,heading1,Xaccel_g, Yaccel_g, Zaccel_g); ////////Get Megasquirt Runtime data buffer////////////// //poll serial device for data stream (a,0,6) to (request, return, confirm) megasquirt.putc(97);//send 97 for run parameters, 83 for board revision, 81 code for revision number wait(0.005); megasquirt.putc(0); wait(0.005); megasquirt.putc(6); int actuallyRead = megasquirt.readBytes( buf, 112); // where 112 is the number of bytes you are expecting from MSII outpc buffer //decodeMS Runtime Data Buffer(); Time = t.read();//read value from timer in ms ////////Decode MS Runtime Data Buffer//// ////The following code will parse the runtime data buffer from MSExtra-2 //Position of the runtime bits given on msextra.com //Scalar math completed where known //get seconds - runtime of MS tmp = buf[0]; tmp = tmp << 8; SecL = tmp | buf[1]; //MSseconds = MSseconds/256; //get pulseWidth1 tmp = buf[2]; tmp = tmp << 8; tmp = tmp | buf[3]; PW = tmp*0.000666; //get pulseWidth2 tmp = buf[4]; tmp = tmp << 8; tmp = tmp | buf[5]; PW2 = tmp*0.000666; //get Rpm tmp = buf[6]; tmp = tmp << 8; RPM = tmp | buf[7]; //Calculate DutyCycle DutyCycle = (PW * (RPM / 60)) / 10; //Calculate DutyCycle2 DutyCycle2 = (PW2 * (RPM / 60)) / 10; //get advance tmp = buf[8]; tmp = tmp << 8; tmp = tmp | buf[9]; SparkAdv = tmp/10; //get manifold absolute pressure MAP tmp = buf[18]; tmp = tmp << 8; MAP = tmp | buf[19]; MAP = MAP/10; //get manifold absolute temperature (MAT) tmp = buf[20]; tmp = tmp << 8; MAT = tmp | buf[21]; MAT = MAT/10; ///for Farenheit // MAT = 0.555*(MAT - 32); //for Celcius //get coolant temperature (CLT) tmp = buf[22]; tmp = tmp << 8; CLT = tmp | buf[23]; CLT = CLT/10; //CLT = 0.555*(CLT - 32); //for Celciuss //get Throttle Position Sensor (TPS) tmp = buf[24]; tmp = tmp << 8; TP = tmp | buf[25]; TP = TP / 10; //get BAttery Voltage tmp = buf[26]; tmp = tmp << 8; vBatt = tmp | buf[27]; vBatt = vBatt /10, //get Realtime AFR for VE1 tmp = buf[28]; tmp = tmp << 8; AFR = tmp | buf[29]; AFR = AFR /10; // /////////////// Print Display Variables ////////////////// ///print bargraph of TPS /* lcd.locate(15,1); // for (i=0; i<20; i++){ // if (i<TPS) lcd.printf(0xFF); // else lcd.printf(0x20); // } lcd.printf("%i ",TPS); */ //get Rpm lcd.locate(0,0); lcd.printf("RPM= %i ",RPM); //get AFR //AFR = tmp/10; lcd.locate(10,0); lcd.printf("AFR= %4.1f", AFR); //get Map //MAP = MAP/10; ///will print MAP at atmospheric and Boost on turbo (Bar) if (MAP >100) { MAP = (MAP - 100)/100; lcd.locate (0,1); lcd.printf("%.1f Bar",MAP); } else { lcd.locate(0,1); lcd.printf("MAP= %4.1f", MAP); } //get Clt //CLT = CLT/10; lcd.locate(0,2); if (CLT < 120) { lcd.printf(" Warm Up "); } else { lcd.printf("CLT= %4.1f", CLT); } //get MAT lcd.locate(10,2); lcd.printf("MAT= %4.1f", MAT); //////////////Template to print variable/////////// //Use code to add variable to display output ///// /* //get Variable //MAP = MAP/10; lcd.locate(10,1); position on LCD lcd.printf("Variable= %4.1f", Variable); //format print X.Y is number of data characters total and how many are past decimal point */ /////////////////////////end MS Code//////////////////////////////// fprintf(fp, "%8.3f, %i, %4.1f, %3f, %4.1f, %4.1f, %5.1f, %5.1f, %f, %.3f, %.3f,\r\n", Time, RPM, MAP, TP, vBatt, AFR, MAT, CLT, PW, DutyCycle, SparkAdv); /////////////////END DATA COLLECTION LOOP #1///////////////////////////////////// } ///end for loop count //pc.printf("print complete");//debug statement ///////end Dataflag loop////////////////// //pc.printf("close file"); // debug statement fclose(fp); ///close file dataflag = 0; //close flag and reset counter i=0; ///reset counter i ///end datalog - return to function } // end switch enable loop // // else //If switch NOT enabled begin else loop 2 // { myled1 = 0; /////////////////BEGIN DATA COLLECTION LOOP #2///////////////////////////////////// ///////////////////////////////GPS Code///////////////////////////////////// getGPSstring(1); ///////convert string format to floating to perform math functions ///////////////////// if (sscanf(gpsString, "$GPRMC,%s",rmc1) >= 1) { sep = 0; parseRMC(); sscanf(time_GPS, "%f", &time1); sscanf(Lat, "%f", &Lat1); sscanf(Lat_h, "%c", &Lat_h1); sscanf(Long, "%f", &Long1); sscanf(Long_h, "%c", &Long_h1); sscanf(time_GPS, "%f", &time_GPS1); sscanf(speed_k, "%f", &speed_k1); sscanf(heading, "%f", &heading1); } speed_mph1 = speed_k1 * 1.15077; ////convert Knots to mph Lat1 = Lat1/100; /////Convert format for google maps overlay Long1 = Long1/-100; /////Convert format for google maps overlay lcd.locate(10,1); lcd.printf("Spd:%4.1f ", speed_mph1); //pc.printf("time:%8.1f Lat:%9.6f Long:%9.6f Spd:%4.1f heading:%5.1f %.3f, %.3f, %.3f \r\n",time1,Lat1,Long1,speed_mph1,heading1,Xaccel_g, Yaccel_g, Zaccel_g, ); ///////////////////////////////////End GPS Code/////////////////////////////////////////////// ///////////////Accelerometer code begin here//////////////////////////////////// accelerometer.getOutput(readings); XaccelADC = (int16_t)readings[0]; YaccelADC = (int16_t)readings[1]; ZaccelADC = (int16_t)readings[2]; Xaccel_g = (XaccelADC/256); Yaccel_g = (YaccelADC/256); Zaccel_g = (ZaccelADC/256); // uncommment to display Accelerometer // lcd.locate(0,0);/// define LCD location // lcd.printf("%4.2f, %4.2f, %4.2f", Xaccel_g, Yaccel_g, Zaccel_g); ///////Lateral Acceleration bar Graph /////////////////////// ///////////////X-direction accleration bar graph///////////////// /* x1 = Xaccel_g * 10;//scale one g to display resolution if (x1 < 0);//for negative g values { x2 = 10 + x1;//offset negative values for positive graph lcd.locate(0,3); /// define LCD location for (i=0; i<10; i++) { if (i < x2) lcd.putc(0x20);//write single space character else lcd.putc(0xFF);//write single clock space } } if (x1 > 0);//for positive g values { lcd.locate(10,3);/// define LCD location for (i=0; i<10; i++) { if (i < x1) lcd.putc(0xFF);//write single block character else lcd.putc(0x20);//write single blank space } } */ ////////////Forward/Braking Acceleration bar Graph /////////////////////// y1 = Yaccel_g * 10;//scale one g to display resolution if (y1 < 0);//for negative g values { y2 = 10 + y1;//offset negative values for positive graph lcd.locate(0,3); /// define LCD location for (i=0; i<10; i++) { if (i < y2) lcd.putc(0x20);//write single space character else lcd.putc(0xFF);//write single clock space } } if (y1 > 0);//for positive g values { lcd.locate(10,3);/// define LCD location for (i=0; i<10; i++) { if (i < y1) lcd.putc(0xFF);//write single block character else lcd.putc(0x20);//write single blank space } } pc.printf("%.3f, %9.6f, %9.6f, %3.1f,%4.1f, %.3f, %.3f, %.3f, \r\n", time1,Lat1,Long1,speed_mph1,heading1,Xaccel_g, Yaccel_g, Zaccel_g); ////////Get Megasquirt Runtime data buffer////////////// //poll serial device for data stream (a,0,6) to (request, return, confirm) megasquirt.putc(97);//send 97 for run parameters, 83 for board revision, 81 code for revision number wait(0.005); megasquirt.putc(0); wait(0.005); megasquirt.putc(6); int actuallyRead = megasquirt.readBytes( buf, 112); // where 112 is the number of bytes you are expecting from MSII outpc buffer //decodeMS Runtime Data Buffer(); Time = t.read();//read value from timer in ms ////////Decode MS Runtime Data Buffer//// ////The following code will parse the runtime data buffer from MSExtra-2 //Position of the runtime bits given on msextra.com //Scalar math completed where known //get seconds - runtime of MS tmp = buf[0]; tmp = tmp << 8; SecL = tmp | buf[1]; //MSseconds = MSseconds/256; //get pulseWidth1 tmp = buf[2]; tmp = tmp << 8; tmp = tmp | buf[3]; PW = tmp*0.000666; //get pulseWidth2 tmp = buf[4]; tmp = tmp << 8; tmp = tmp | buf[5]; PW2 = tmp*0.000666; //get Rpm tmp = buf[6]; tmp = tmp << 8; RPM = tmp | buf[7]; //Calculate DutyCycle DutyCycle = (PW * (RPM / 60)) / 10; //Calculate DutyCycle2 DutyCycle2 = (PW2 * (RPM / 60)) / 10; //get advance tmp = buf[8]; tmp = tmp << 8; tmp = tmp | buf[9]; SparkAdv = tmp/10; //get manifold absolute pressure MAP tmp = buf[18]; tmp = tmp << 8; MAP = tmp | buf[19]; MAP = MAP/10; //get manifold absolute temperature (MAT) tmp = buf[20]; tmp = tmp << 8; MAT = tmp | buf[21]; MAT = MAT/10; ///for Farenheit // MAT = 0.555*(MAT - 32); //for Celcius //get coolant temperature (CLT) tmp = buf[22]; tmp = tmp << 8; CLT = tmp | buf[23]; CLT = CLT/10; //CLT = 0.555*(CLT - 32); //for Celciuss //get Throttle Position Sensor (TPS) tmp = buf[24]; tmp = tmp << 8; TP = tmp | buf[25]; TP = TP / 10; //get BAttery Voltage tmp = buf[26]; tmp = tmp << 8; vBatt = tmp | buf[27]; vBatt = vBatt /10, //get Realtime AFR for VE1 tmp = buf[28]; tmp = tmp << 8; AFR = tmp | buf[29]; AFR = AFR /10; // /////////////// Print Display Variables ////////////////// ///print bargraph of TPS /* lcd.locate(15,1); // for (i=0; i<20; i++){ // if (i<TPS) lcd.printf(0xFF); // else lcd.printf(0x20); // } lcd.printf("%i ",TPS); */ //get Rpm lcd.locate(0,0); lcd.printf("RPM= %i ",RPM); //get AFR //AFR = tmp/10; lcd.locate(10,0); lcd.printf("AFR= %4.1f", AFR); //get Map //MAP = MAP/10; ///will print MAP at atmospheric and Boost on turbo (Bar) if (MAP >100) { MAP = (MAP - 100)/100; lcd.locate (0,1); lcd.printf("%.1f Bar",MAP); } else { lcd.locate(0,1); lcd.printf("MAP= %4.1f", MAP); } //get Clt //CLT = CLT/10; lcd.locate(0,2); if (CLT < 120) { lcd.printf(" Warm Up "); } else { lcd.printf("CLT= %4.1f", CLT); } //get MAT lcd.locate(10,2); lcd.printf("MAT= %4.1f", MAT); //////////////Template to print variable/////////// //Use code to add variable to display output ///// /* //get Variable //MAP = MAP/10; lcd.locate(10,1); position on LCD lcd.printf("Variable= %4.1f", Variable); //format print X.Y is number of data characters total and how many are past decimal point */ /////////////////////////end MS Code//////////////////////////////// /////////////////END DATA COLLECTION LOOP #2///////////////////////////////////// // } ///end else loop 2 ///////////////end datalog code/////////////////////////////////////////////// } ///exit while loop } //exit main loop