Brian Pearson
/
LPC1768OpacityMeterUSB
Opacity meter with USB interface
main.cpp
- Committer:
- BPPearson
- Date:
- 2016-01-05
- Revision:
- 0:8ce24e6c4de1
File content as of revision 0:8ce24e6c4de1:
#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); } }