Brian Pearson / Mbed 2 deprecated LPC1768BirefSensor

Dependencies:   mbed

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;
+    }
+}
+