Brian Pearson
/
LPC1768OpacityMeterUSB
Opacity meter with USB interface
Diff: main.cpp
- Revision:
- 0:8ce24e6c4de1
diff -r 000000000000 -r 8ce24e6c4de1 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Tue Jan 05 16:44:57 2016 +0000 @@ -0,0 +1,524 @@ +#include "mbed.h" +#include "USBHID.h" +#include "ByteOperations.h" +#include "USBHIDProtocol.h" + +#define COMMAND 0 +#define DATA 1 + +#define AVERAGE 0 +#define MEDIAN 1 +#define BINAVERAGE 2 +#define RATEOFCHANGE 3 + +#define VERSION 0x01 + +Serial pc(USBTX, USBRX); +DigitalOut led1(LED1); +DigitalOut led2(LED2); +DigitalOut led3(LED3); +DigitalOut led4(LED4); +AnalogIn opacity(p20); +AnalogOut fOpacity(p18); +BusInOut databus(p8, p9, p10, p11, p12, p13, p14, p15); +DigitalOut registerSelect(p5); +DigitalOut readWriteClock(p7); +DigitalOut readWrite(p6); +//DigitalIn unlocked(p8); +Ticker updateLCD; +Ticker processOpacity; +LocalFileSystem local("local"); + +USBHID *hid; +HID_REPORT send_report __attribute__((aligned (4))); // Aligned for fast access +HID_REPORT recv_report __attribute__((aligned (4))); // Aligned for fast access + +float instantOpacity; +float filteredOpacity = 0.0; +float Opacity = 0.0; +char *helloStr = "Hello"; +int filterAlgorithm = AVERAGE; +float anIn1Sum; +float anIn1SumSqr; +float stdDevCount; +float standardDeviation; +float calibFactor = 1.0; +int showCalibFactor = 0; +float anInVals[100]; +int anInIdx = 0; +float binVal[10]; +int binCnt[10]; +int maxCnt = 0; +int maxIdx = 0; + + +void readConfigFile() +{ + + FILE *fp = fopen("/local/config.dat", "r"); + + if (fp != NULL) + { + fscanf(fp, "%f", &calibFactor); + fscanf(fp, "%d", &filterAlgorithm); + fclose(fp); + } +} + + + +void writeConfigFile() +{ + FILE *fp = fopen("/local/config.dat", "w"); + + if (fp != NULL) + { + fprintf(fp, "%5.3f\n", calibFactor); + fprintf(fp, "%1d\n", filterAlgorithm); + fclose(fp); + } +} + + + +void empty_report(HID_REPORT *data){ + register uint32_t *p = (uint32_t *)data->data; + for( register int i=0; i<((sizeof(HID_REPORT)-1)/4); i++ ){ + *p = 0xFFFFFFFF; + p++; + } +} + +void checkForUSBRequest() +{ + char *cptrR; + char *cptrT; + float fTmp; + //bool updatePIDValues = false; + + //try to read a msg + if(hid->readNB(&recv_report)){ + + // set character pointer to start of the parameter for set commands + cptrR = (char *)&recv_report.data[1]; + cptrT = (char *)&send_report.data[1]; + + led2 = 1; + + // Data packet received, start parsing + int irx=0; + int itx=0; + + send_report.data[itx++] = recv_report.data[0]; + + switch ( recv_report.data[irx++] ){ + case CMD_SYS_CHECK : + send_report.data[itx++] = VERSION; + break; + + case CMD_SYS_RESET : + // Soft reset + empty_report(&recv_report); + break; + + case CMD_GET_RAW_OPACITY: + // return the raw opacity value + sprintf(cptrT, "%6.5f", instantOpacity * 100.0); + pc.printf("instant opacity = %f\n", instantOpacity * 100.0); + break; + case CMD_GET_FILTERED_OPACITY: + // return filtered opacity + sprintf(cptrT, "%6.5f", Opacity); + pc.printf("filtered opacity = %f\n", Opacity); + break; + case CMD_GET_CALIB_FACTOR: + // return calibration factor + sprintf(cptrT, "%6.5f", calibFactor); + pc.printf("calibration factor = %f\n", calibFactor); + break; + case CMD_SET_CALIB_FACTOR: + // set calibration factor to value in packet + sscanf(cptrR, "%f", &calibFactor); + writeConfigFile(); + pc.printf("Set calibFactor to %f\n", calibFactor); + break; + case CMD_GET_FILTER_MODE: + // return filter algorithm value + sprintf(cptrT, "%6.3f", (float)filterAlgorithm); + pc.printf("filterAlgorithm = %d\n", filterAlgorithm); + break; + case CMD_SET_FILTER_MODE: + // set filter alogirthm + sscanf(cptrR, "%f", &fTmp); + filterAlgorithm = (int)fTmp; + writeConfigFile(); + pc.printf("Set filter algorithm to %d\n", filterAlgorithm); + break; + case 0xEE : { + hid->sendNB(&send_report); + //WatchDog_us bello(100); + } + break; + + default: + send_report.data[0] = 0xFF; //Failure + break; + } // Switch + + // Return command + optional new args + hid->send(&send_report); + + // 0xFF unused bytes + empty_report(&recv_report); + empty_report(&send_report); + + led2 = 0; + } // if packet +} + + + +void writeToLCD(bool rs, char data){ + + // set register select pin + registerSelect = rs; + + // set read/write pin to write + readWrite = 0; + + // set bus as output + databus.output(); + + // put data onto bus + databus = data; + + // pulse read/write clock + readWriteClock = 1; + + wait_us(1); + + readWriteClock = 0; + + wait_us(1); + + // clear data bus + databus = 0; + + //pc.printf("%02x\n", data); + +} + + +char readFromLCD(bool rs){ + + char data; + + // set register select pin + registerSelect = rs; + + // set read/write pin to read + readWrite = 1; + + // set bus as output + databus.input(); + + // put data onto bus + data = databus; + + // pulse read/write clock + readWriteClock = 1; + + wait_us(10); + + readWriteClock = 0; + + return data; +} + + +void resetLCD(){ +} + + +void initLCD(){ + + // wait 15 ms to allow LCD to initialise + wait_ms(15); + + // set interface for 8 bit mode + writeToLCD(COMMAND, 0x30); + + // give it time + wait_ms(5); + + // set interface for 8 bit mode again + writeToLCD(COMMAND, 0x30); + + // give it time + wait_us(100); + + // set interface for 8 bit mode again, last one before we can configure the display + writeToLCD(COMMAND, 0x30); + + // give it time + wait_us(500); + + // set interface for 8 bit mode, 2 display lines and 5 x 8 character font + writeToLCD(COMMAND, 0x38); + + // give it time + wait_us(100); + + // display off + writeToLCD(COMMAND, 0x08); + + // give it time + wait_us(100); + + // clear the screen + writeToLCD(COMMAND, 0x01); + + // give it time to finish + wait_ms(2); + + // set entry mode to increment cursor position cursor on write + writeToLCD(COMMAND, 0x03); + + // give it time to finish + wait_us(100); + + // position cursor at home + writeToLCD(COMMAND, 0x02); + + // give it time to finish + wait_ms(2); + + // display on + writeToLCD(COMMAND, 0x0F); +} + + + + +void positionCursor(uint8_t x, uint8_t y){ + + if (x > 7) x = 0; + + if (y == 1) + writeToLCD(COMMAND, 0x80 + 0x40 + x); + else + writeToLCD(COMMAND, 0x80 + 0x00 + x); + + wait_us(50); +} + + +void displayString(int x, int y, char *str){ + + // position cursor + positionCursor(x, y); + + // write string to screen + for (int i=0; i<strlen(str); i++){ + writeToLCD(DATA, str[i]); + + wait_us(50); + } +} + + +void standardDeviationCalc(float opacity) +{ + // add to standard deviation accumulators + anIn1Sum += opacity; + anIn1SumSqr += (opacity * opacity); + + // 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))) + standardDeviation = ((stdDevCount * anIn1SumSqr) - (anIn1Sum * anIn1Sum)) / (stdDevCount * (stdDevCount - 1)); + if (standardDeviation > 0.0) + standardDeviation = sqrt(standardDeviation); + else + standardDeviation = sqrt(-standardDeviation); + + // clear standard deviation accumulators for next set of readings + anIn1Sum = 0.0; + anIn1SumSqr = 0.0; + stdDevCount = 0; + } + } + + + void updateDisplay(){ + char str[20]; + + sprintf( str, "o %5.1f", Opacity); + + displayString(0, 0, str); + + //if (showCalibFactor == 0){ + //sprintf( str, "s %5.2f", standardDeviation); + + //displayString(0, 1, str); + //} + //else{ + //sprintf( str, "m %5.2f", calibFactor); + + //displayString(0, 1, str); + + //showCalibFactor--; + //} +} + + + void updateOpacity() +{ + + // read next analog input value into circular buffer, adjust reading for max value is 3.1 on 3.3V input + anInVals[anInIdx] = opacity.read() * 1.0674; + + // increment anInIdx and check for wrap + anInIdx++; + if (anInIdx >= 100) + anInIdx = 0; + + // filter analog inputs with required algorithm + switch (filterAlgorithm) + { + case AVERAGE: + float accumulator = 0.0; + for (int i=0; i<100; i++) + { + accumulator += anInVals[i]; + } + instantOpacity = accumulator / 100; + break; + case MEDIAN: + float tempF; + for (int j=1; j<100; j++) + { + for (int i=1; i<100; i++) + { + if (anInVals[i] < anInVals[i-1]) + { + // swap places + tempF = anInVals[i-1] ; + anInVals[i-1] = anInVals[i]; + anInVals[i] = tempF; + } + } + } + instantOpacity = anInVals[49]; + break; + case BINAVERAGE: + // initialise bins to zero + for (int i=0; i<10; i++) + { + binVal[i] = 0.0; + binCnt[i] = 0; + } + + // sort analog input values into one of ten bins + for (int i=0; i<100; i++) + { + int binIdx = anInVals[i] * 10.0; + if (binIdx > 9) + binIdx = 9; + binVal[binIdx] += anInVals[i]; + binCnt[binIdx]++; + } + + maxCnt = 0; + maxIdx = 0; + // find the bin with most values added + for (int i=0; i<10; i++) + { + if (binCnt[i] > maxCnt) + { + maxCnt = binCnt[i]; + maxIdx = i; + } + } + + instantOpacity = binVal[maxIdx] / binCnt[maxIdx]; + break; + case RATEOFCHANGE: + break; + default: + break; + } + + // do standard deviation on the smoothed opacity value + standardDeviationCalc(instantOpacity); + + // apply a filter to the instant reading to get the filtered reading + filteredOpacity = (instantOpacity * 0.05) + (filteredOpacity * 0.95); + + // calculate opacity reading as 0..100% + Opacity = filteredOpacity * calibFactor * 100.0; + + // write opacity value to analog output as 0..1.0 value + fOpacity.write(Opacity / 100.0); +} + + +int main() { + + printf("initLCD()\n"); + + initLCD(); + + filterAlgorithm = BINAVERAGE; + + //calibUp.mode(PullUp); + //calibDown.mode(PullUp); + //unlocked.mode(PullUp); + //calibUp.attach_deasserted(&incCalibFactor); + //calibUp.attach_deasserted_held(&incCalibFactor); + //calibDown.attach_deasserted(&decCalibFactor); + //calibDown.attach_deasserted_held(&decCalibFactor); + + //calibUp.setSampleFrequency(); + //calibDown.setSampleFrequency(); + + printf("readConfigFile()\n"); + + readConfigFile(); + + printf("start updateLCD ticker\n"); + + updateLCD.attach(&updateDisplay, 0.5); + + printf("read opacity 10 times\n"); + + // initialise analog input values + for (int i=0; i<100; i++) + anInVals[i] = opacity.read(); + + printf("start processOpacity ticker\n"); + + // start ticker to read and filter the opacity input + processOpacity.attach(&updateOpacity, 0.1); + + printf("initialise USB\n"); + + // USB Initialize + static USBHID hid_object(64, 64); + hid = &hid_object; + send_report.length = 64; + + while(1){ + + // check for any commands from host computer + checkForUSBRequest(); + + wait_ms(10); + } + +}