Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Diff: main.cpp
- Revision:
- 0:f665998783a2
diff -r 000000000000 -r f665998783a2 main.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Tue Jan 05 16:42:58 2016 +0000
@@ -0,0 +1,667 @@
+#include "mbed.h"
+#include "math.h"
+
+#define ERR_WRITING_CONFIG_FILE 0
+#define ERR_LPC1768_RESET 1
+
+#define AVERAGE 0
+#define BIN 1
+#define RAW 2
+
+#define BIDIRECTIONAL 0
+#define UNIDIRECTIONAL 1
+
+
+enum OpModes {measuring, calibrating, silent, diagnostics};
+
+void initialiseData();
+void stdDevCalc();
+void processCommandString();
+void processAnalogs();
+void outputData();
+void sendDataPacket();
+void readConfigFile();
+void writeConfigFile();
+
+
+
+Serial pc(USBTX, USBRX);
+Ticker inputTicker;
+Ticker outputTicker;
+AnalogIn anIn1(p15);
+AnalogIn anIn2(p16);
+DigitalOut unusedAnalog3(p17); //AnalogIn anIn3(p17);
+DigitalOut unusedAnalog4(p18); // AnalogOut analogOut(p18); //AnalogIn anIn4(p18);
+DigitalOut unusedAnalog5(p19); //AnalogIn anIn5(p19);
+DigitalOut unusedAnalog6(p20);
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+DigitalOut led3(LED3);
+DigitalOut led4(LED4);
+DigitalOut scope1(p21);
+DigitalOut scope2(p22);
+Serial rs232(p28, p27); // tx, rx
+LocalFileSystem local("local");
+
+float anIn1Filter;
+float anIn2Filter;
+float anIn1Raw[100];
+float anIn1Bin[100];
+int anIn1Cnt[100];
+int anIn1Idx;
+float anIn2Raw[100];
+float anIn2Bin[100];
+int anIn2Cnt[100];
+int anIn2Idx;
+int filterAlgorithm;
+float anIn1Normalised;
+float anIn2Normalised;
+float anIn1NormOffset;
+float anIn1NormRange;
+float anIn2NormOffset;
+float anIn2NormRange;
+float anIn1CalibOffset;
+float anIn1CalibRange;
+//float anIn1Calibrated;
+float directionalBirefValue;
+float directionalBirefStdDev;
+float anIn1Sum;
+float anIn1SumSqr;
+float stdDevCount;
+//float sensorTemperature;
+int commsState;
+char cmdChar;
+char cmdBuff[20];
+int cmdIdx;
+OpModes opMode;
+bool calibRqst;
+bool paramRqst;
+bool reportError;
+int errorNum;
+float rawAnalogTemp;
+bool dataPacketToSend = false;
+int outputMode = BIDIRECTIONAL;
+
+int main()
+{
+ char rcvChar;
+
+ // report reset
+ errorNum = ERR_LPC1768_RESET;
+ reportError = true;
+
+ // initialise variables
+ initialiseData();
+
+ // read analog input calibration and normailsation values
+ readConfigFile();
+
+ // initialise 500 usec ticker - current analog processing algorithm takes 600 uS
+ //inputTicker.attach_us(&processAnalogs, 1000);
+
+ // initialise 50 msec ticker
+ outputTicker.attach_us(&outputData, 50000);
+
+ // configure the serial output port speed
+ rs232.baud(115200);
+
+ wait_ms(1);
+
+ // do forever
+ while (1)
+ {
+ if (rs232.readable())
+ {
+ // now go through comms state machine
+ switch (commsState)
+ {
+ case 1: // waiting for a command character
+ //if (rs232.readable())
+ {
+ rcvChar = rs232.getc();
+
+ // if command character
+ if (rcvChar == '*')
+ {
+ // go to next state of comms stateful machine
+ commsState = 2;
+ }
+ //printf("1 - %c\n", rcvChar);
+ }
+ break;
+ case 2:
+ // get the command parameter
+ cmdChar = rs232.getc();
+
+ // move to next state
+ commsState = 3;
+ //pc.printf("2 - %c\n", cmdChar);
+ break;
+ case 3:
+ // get the next character
+ rcvChar = rs232.getc();
+
+ //pc.printf("3 - %c\n", rcvChar);
+ // if it is the end of the command
+ if (rcvChar == ';')
+ {
+ // terminate any string that may be in cmdBuff
+ cmdBuff[cmdIdx] = '\0';
+
+ // move to next state
+ //commsState = 4;
+
+ // process the rest of the command string
+ processCommandString();
+
+ // go back to start of state sequencer
+ commsState = 1;
+
+ // reset index into command buffer
+ cmdIdx = 0;
+ }
+ else
+ {
+ // add the character to the buffer
+ cmdBuff[cmdIdx] = rcvChar;
+
+ // increment the index
+ cmdIdx++;
+
+ // check if is going to exceed the buffer
+ if (cmdIdx >= 20)
+ {
+ // reset state back to looking for a command character
+ commsState = 1;
+
+ // reset index into command buffer
+ cmdIdx = 0;
+ }
+ }
+ break;
+ case 4:
+ //pc.printf("4\n");
+ // process the rest of the command string
+// processCommandString();
+
+ // go back to start of state sequencer
+// commsState = 1;
+
+ // reset index into command buffer
+// cmdIdx = 0;
+ break;
+ default:
+ break;
+ }
+ }
+
+ // read and process analog inputs each time round the loop
+ processAnalogs();
+
+ //sendDataPacket();
+
+ //if (dataPacketToSend)
+ //{
+ //sendDataPacket();
+
+ //dataPacketToSend = false;
+ //}
+
+ // wait a while then loop again
+ wait_ms(1);
+ }
+}
+
+
+
+
+
+
+void initialiseData()
+{
+ // initialise any data values used in the processing of the birefringence signals
+
+ // go directly into measure mode
+ opMode = measuring;
+
+ // initialise the analog input filter variables
+ anIn1Filter = anIn1.read();
+ anIn2Filter = anIn2.read();
+ filterAlgorithm = BIN; //AVERAGE // BIN //RAW
+
+ // initialise standard deviation accumulators
+ anIn1Sum = 0.0;
+ anIn1SumSqr = 0.0;
+ stdDevCount = 0;
+
+ // initialise the comms state machine variable to 1
+ commsState = 1;
+
+ // set index for start of command buffer
+ cmdIdx = 0;
+
+ // set flags to false
+ calibRqst = false;
+ paramRqst = false;
+
+ // prepare analog buffer indexes and buffer values
+ anIn1Idx = 0;
+ anIn2Idx = 0;
+ for (int i=0; i<100; i++)
+ {
+ anIn1Raw[i] = anIn1.read();
+ anIn2Raw[i] = anIn2.read();
+ }
+
+ //rawAnalogTemp = anIn6.read();
+ }
+
+
+
+void processCommandString()
+{
+ float fnum = 0.0;
+
+ // if anything in the cmd buffer
+ if (cmdIdx > 0)
+ {
+ // convert the string in the comms buffer into a float
+ sscanf(cmdBuff, "%f", &fnum);
+ }
+
+ switch (cmdChar)
+ {
+ case '1': // normalised measure offset
+ anIn1NormOffset = fnum;
+ break;
+ case '2': // normalised measure range
+ anIn1NormRange = fnum;
+ break;
+ case '3': // normalised reference offset
+ anIn2NormOffset = fnum;
+ break;
+ case '4': // normalised reference range
+ anIn2NormRange = fnum;
+ break;
+ case '5': // calibration offset
+ anIn1CalibOffset = fnum;
+ break;
+ case '6': // calibration range
+ anIn1CalibRange = fnum;
+ break;
+ case '7': // the point at which the measured goes from -ve to +ve
+ //refXoverPoint = fnum;
+ break;
+ case '8': //
+ break;
+ case '9': //
+ break;
+ case 'd': // switch to diagnostics mode
+ opMode = diagnostics;
+ break;
+ case 'f': // filter ratio
+ filterAlgorithm = (int)fnum;
+ //pc.printf("f %d\n", filterAlgorithm);
+ break;
+ case 'o': // output mode
+ outputMode = (int)fnum;
+ //pc.printf("f %d\n", filterAlgorithm);
+ break;
+ case 'm': // switch to measure mode
+ opMode = measuring;
+ break;
+ case 's': // switch to silent mode
+ opMode = silent;
+ break;
+ case 'c': // switch to calibrate mode
+ opMode = calibrating;
+ break;
+ case 'p': // switch to calibrate mode
+ paramRqst = true;
+ break;
+ case 'w': // write the config to the file system
+ writeConfigFile();
+ break;
+ default:
+ break;
+ }
+}
+
+
+
+void processAnalogs()
+{
+ float analogInput;
+
+ // set digital output 1 & 2 to be used by scope for timing measurement
+ scope1 = 1;
+ scope2 = 1;
+
+ // read the internal temperature sensor, filter by only allowing 0.1% of reading to get through
+ //sensorTemperature = anIn6.read();
+
+ // read biref measure signal - anIn1
+ analogInput = anIn1.read();
+ anIn1Raw[anIn1Idx] = analogInput;
+
+ // increment and check index for wrap
+ anIn1Idx++;
+ if (anIn1Idx >=100)
+ anIn1Idx = 0;
+
+ switch(filterAlgorithm)
+ {
+ case RAW:
+ default:
+ anIn1Filter = analogInput;
+ led1 = 1;
+ led2 = 0;
+ led3 = 0;
+ break;
+ case AVERAGE:
+ led1 = 0;
+ led3 = 0;
+ led2 = 1;
+ // average last 100 readings
+ float accum = 0.0;
+ for (int i=0; i<100; i++)
+ {
+ accum += anIn1Raw[i];
+ }
+ anIn1Filter = accum / 100.0;
+ break;
+ case BIN:
+ led1 = 0;
+ led2 = 0;
+ led3 = 1;
+ // clear bins
+ for (int i=0; i<100; i++)
+ {
+ anIn1Bin[i] = 0.0;
+ anIn1Cnt[i] = 0;;
+ }
+
+ // sort into the appropriate bin
+ for (int i=0; i<100; i++)
+ {
+ uint16_t bin = anIn1Raw[i] * 100.0;
+ if (bin >= 100)
+ bin = 99;
+ anIn1Bin[bin] += anIn1Raw[i];
+ anIn1Cnt[bin]++;
+ }
+
+ // find bin with most entries
+ int maxCnt = 0;
+ int maxIdx = 0;
+ for (int i=0; i<100; i++)
+ {
+ if (anIn1Cnt[i] > maxCnt)
+ {
+ maxCnt = anIn1Cnt[i];
+ maxIdx = i;
+ }
+ }
+
+ // avergae the values in that bin to get the current reading
+ anIn1Filter = anIn1Bin[maxIdx] / (float)maxCnt;
+ break;
+ }
+
+ // clear digitanl output 1 to time analog read call
+ scope1 = 0;
+
+ // normalise the measure signal
+ anIn1Normalised = (anIn1Filter - anIn1NormOffset) / anIn1NormRange;
+
+ // write to analog output
+ //analogOut.write(anIn1Normalised);
+
+ // read biref reference signal - anIn2
+ analogInput = anIn2.read();
+ anIn2Raw[anIn2Idx] = analogInput;
+
+ // increment and check index for wrap
+ anIn2Idx++;
+ if (anIn2Idx >=100)
+ anIn2Idx = 0;
+
+ switch(filterAlgorithm)
+ {
+ case RAW:
+ default:
+ anIn2Filter = analogInput;
+ break;
+ case AVERAGE:
+ // average last 100 readings
+ float accum = 0.0;
+ for (int i=0; i<100; i++)
+ {
+ accum += anIn2Raw[i];
+ }
+ anIn2Filter = accum / 100.0;
+ break;
+ case BIN:
+ // clear bins
+ for (int i=0; i<100; i++)
+ {
+ anIn2Bin[i] = 0.0;
+ anIn2Cnt[i] = 0;;
+ }
+
+ // sort into the appropriate bin
+ for (int i=0; i<100; i++)
+ {
+ uint16_t bin = anIn2Raw[i] * 100.0;
+ if (bin >= 100)
+ bin = 99;
+ anIn2Bin[bin] += anIn2Raw[i];
+ anIn2Cnt[bin]++;
+ }
+
+ // find bin with most entries
+ int maxCnt = 0;
+ int maxIdx = 0;
+ for (int i=0; i<100; i++)
+ {
+ if (anIn2Cnt[i] > maxCnt)
+ {
+ maxCnt = anIn2Cnt[i];
+ maxIdx = i;
+ }
+ }
+
+ // avergae the values in that bin to get the current reading
+ anIn2Filter = anIn2Bin[maxIdx] / (float)maxCnt;
+ break;
+ }
+
+ // normalise the reference signal
+ anIn2Normalised = (anIn2Filter - anIn2NormOffset) / anIn2NormRange;
+
+ if (outputMode == BIDIRECTIONAL)
+ {
+ // determine sign of the reading (if normalised measure > normalised reference it is positive)
+ if (anIn1Normalised < anIn2Normalised)
+ anIn1Normalised *= -1.0;
+ }
+
+ // save the directional birefringence value
+ directionalBirefValue = anIn1Normalised;
+
+ // add to standard deviation accumulators
+ anIn1Sum += anIn1Normalised;
+ anIn1SumSqr += (anIn1Normalised * anIn1Normalised);
+
+ // increment standard deviation counter
+ stdDevCount++;
+
+ // if enough readings for the standard deviation calculation
+ if (stdDevCount >= 100)
+ {
+ // calculate the standard deviation
+ // std dev = sqrt( (n * sum(x2) - sum(x)2)) / (n * (n - 1)))
+ directionalBirefStdDev = ((stdDevCount * anIn1SumSqr) - (anIn1Sum * anIn1Sum)) / (stdDevCount * (stdDevCount - 1));
+ if (directionalBirefStdDev > 0.0)
+ directionalBirefStdDev = sqrt(directionalBirefStdDev);
+ else
+ directionalBirefStdDev = sqrt(-directionalBirefStdDev);
+
+ // clear standard deviation accumulators for next set of readings
+ anIn1Sum = 0.0;
+ anIn1SumSqr = 0.0;
+ stdDevCount = 0;
+ }
+
+ // clear scope 2 so we can determine how long this takes
+ scope2 = 0;
+}
+
+
+
+void outputData()
+{
+
+ dataPacketToSend = true;
+
+ sendDataPacket();
+}
+
+
+
+void sendDataPacket()
+{
+ // every 10 milliseconds
+ // send data packet out of serial port
+ // if inputs are read every 100 usecs then we have 100 readings in the averaged measured vale and the standard deviation value
+
+ // send out through the serial port if in measure mode
+ if (opMode == measuring)
+ rs232.printf("m %6.4f %6.4f\n", directionalBirefValue, directionalBirefStdDev );
+
+ if (opMode == diagnostics)
+ rs232.printf("d %6.4f %6.4f %6.4f %6.4f %6.4f %6.4f\n", anIn1Filter, anIn2Filter, anIn1Normalised, anIn2Normalised, directionalBirefValue, directionalBirefStdDev );
+
+ if (opMode == calibrating)
+ rs232.printf("c %5.3f %5.3f\n", anIn1Filter, anIn2Filter);
+
+
+ if (calibRqst)
+ {
+ rs232.printf("c %5.3f %5.3f\n", anIn1Filter, anIn2Filter);
+ calibRqst = false;
+ }
+
+ if (paramRqst)
+ {
+ rs232.printf("p %5.3f %5.3f %5.3f %5.3f %5.3f %5.3f %2d\n", anIn1NormOffset, anIn1NormRange, anIn2NormOffset, anIn2NormRange, anIn1CalibOffset, anIn1CalibRange, filterAlgorithm );
+ paramRqst = false;
+ }
+
+ if (reportError)
+ {
+ rs232.printf("e %d\n", errorNum);
+ reportError = false;
+ }
+}
+
+
+
+void readConfigFile()
+{
+
+ FILE *fp = fopen("/local/config.dat", "r");
+
+ if (fp != NULL)
+ {
+ //led4 = !led4;
+ //fgets(str, 20, fp);
+ pc.printf("reading config file\n");
+ fscanf(fp, "%f", &anIn1NormOffset);
+ fscanf(fp, "%f", &anIn1NormRange);
+ fscanf(fp, "%f", &anIn1CalibOffset);
+ fscanf(fp, "%f", &anIn1CalibRange);
+ fscanf(fp, "%f", &anIn2NormOffset);
+ fscanf(fp, "%f", &anIn2NormRange);
+ fscanf(fp, "%d", &filterAlgorithm);
+ fscanf(fp, "%d", &outputMode);
+ fclose(fp);
+
+ pc.printf("anIn1NormOffset %5.3f\n", anIn1NormOffset);
+ pc.printf("anIn1NormRange %5.3f\n", anIn1NormRange);
+ pc.printf("anIn2NormOffset %5.3f\n", anIn2NormOffset);
+ pc.printf("anIn2NormRange %5.3f\n", anIn2NormRange);
+ pc.printf("anIn1CalibOffset %5.3f\n", anIn1CalibOffset);
+ pc.printf("anIn1CalibRange %5.3f\n", anIn1CalibRange);
+
+ // check if values are sensible
+ if (anIn1NormRange == 0.0)
+ {
+ anIn1NormRange = 1.0;
+ pc.printf("anIn1NormRange bad value\n");
+ }
+ if (anIn2NormRange == 0.0)
+ {
+ anIn2NormRange = 1.0;
+ pc.printf("anIn2NormRange bad value\n");
+ }
+ if (anIn1CalibRange == 0.0)
+ {
+ anIn1CalibRange = 1.0;
+ pc.printf("anIn1CalibRange bad value\n");
+ }
+ }
+ else
+ {
+ anIn1NormOffset = 0.0;
+ anIn1NormRange = 1.0;
+ anIn1CalibOffset = 0.0;
+ anIn1CalibRange = 1.0;
+ anIn2NormOffset = 0.0;
+ anIn2NormRange = 1.0;
+ filterAlgorithm = BIN;
+ outputMode = BIDIRECTIONAL;
+
+ writeConfigFile();
+ }
+}
+
+
+
+void writeConfigFile()
+{
+
+ pc.printf("anIn1NormOffset %5.3f\n", anIn1NormOffset);
+ pc.printf("anIn1NormRange %5.3f\n", anIn1NormRange);
+ pc.printf("anIn2NormOffset %5.3f\n", anIn2NormOffset);
+ pc.printf("anIn2NormRange %5.3f\n", anIn2NormRange);
+ pc.printf("anIn1CalibOffset %5.3f\n", anIn1CalibOffset);
+ pc.printf("anIn1CalibRange %5.3f\n", anIn1CalibRange);
+
+ if (anIn1NormRange != 0.0 && anIn1CalibRange != 0.0 && anIn2NormRange != 0.0)
+ {
+ FILE *fp = fopen("/local/config.dat", "w");
+
+ if (fp != NULL)
+ {
+ pc.printf("Writing config file\n");
+
+ fprintf(fp, "%5.3f\n", anIn1NormOffset);
+ fprintf(fp, "%5.3f\n", anIn1NormRange);
+ fprintf(fp, "%5.3f\n", anIn1CalibOffset);
+ fprintf(fp, "%5.3f\n", anIn1CalibRange);
+ fprintf(fp, "%5.3f\n", anIn2NormOffset);
+ fprintf(fp, "%5.3f\n", anIn2NormRange);
+ fprintf(fp, "%2d\n", filterAlgorithm);
+ fprintf(fp, "%2d\n", outputMode);
+ fclose(fp);
+ reportError = false;
+ }
+ }
+ else
+ {
+ errorNum = ERR_WRITING_CONFIG_FILE;
+ reportError = true;
+ }
+}
+