Template for LPC1768
Dependencies: Gimbal MLX90620 Socket lwip-eth lwip-sys lwip mbed-rtos mbed
Fork of EkkoEye by
main.cpp
- Committer:
- gardnmc
- Date:
- 2016-04-14
- Revision:
- 54:aaf6b5ceedd8
- Parent:
- 53:72f350a6d09c
File content as of revision 54:aaf6b5ceedd8:
#include "mbed.h" #include "EthernetInterface.h" #include "CMLX90620.h" #include "base.h" #include <string.h> #include <time.h> #define MAX_CHARS 1024 Serial pc(USBTX, USBRX); Ticker Pulser; /* DigitalOut xStep(LED1); DigitalOut xDir(LED2); DigitalOut yStep(LED3); DigitalOut yDir(LED4); DigitalIn xStop(p20); DigitalOut laser(p11); */ DigitalOut xStep(p14); DigitalOut xDir(p26); DigitalOut yStep(p6); DigitalOut yDir(p5); DigitalOut enable(p22); DigitalOut newenable(p25); DigitalOut laser(p20); DigitalIn xHome(p15); DigitalIn yHome(p13); // DigitalIn m0X(p19); // Must be set to float to achieve some micro-step values DigitalOut m1X(p18); DigitalOut m0X(p19); //DigitalIn m0Y(p8); // Must be set to float to achieve some micro-step values DigitalOut m1Y(p11); DigitalOut m0Y(p8); char* EEbuf = new char[256]; // buffer for contents of EEPROM char* RamCmmd = new char[8]; // holds / sends MLX90620 RAM commands char* RamBuf = new char[128]; // 0x3f words, values are 'unsigned short' float Ta = 0.0; // Ambient temperature from MLX float TempPxl = 0.0; // Interim measure for use with centre pixel of 16x4 MLX array int mgTick=0; // Used as a general reference by core Timer ISR MLX90620 mlx(p9, p10, "mlx"); // Constructor for mlx class ROTATION rotn; // Structure for x and y rotation values CGimbal gimbal(&xStep, &xDir, &yStep, &yDir); // Constructor for gimbal CGimbal * pGimbal=NULL; // Pointer to gimbal class for easing argument passing int main() { char cmd; int timeout=1200; init(); pc.printf("Initialising Network...\r\n"); EthernetInterface eth; eth.init(); //Use DHCP eth.connect(); pc.printf("IP Address is %s\r\n", eth.getIPAddress()); while (1) { cmd = handleSerial(); // Checks for any input from user and returns single char command token switch(cmd) { case 'G' : // Hand over to server case 'g' : ServerLoop(); break; case 'h' : // Go to Home position case 'H' : enable.write(1); pGimbal->Home(); enable.write(0); break; case 'L' : // Laser ON laser = ON; pc.printf("Laser ON\r\n"); break; case 'l' : // Laser OFF laser = OFF; pc.printf("Laser OFF\r\n"); break; case 'm' : // Perform a meander-scan and take readings case 'M' : pGimbal->MeanderScan(); break; case 'r' : // Rotate to absolute (x,y) position, perform homing reference first Rotate(rotn); break; case 'R' : // Rotate to absolute (x,y) position direct without homing first RotateNoHome(rotn); break; case 't' : // Execute a tour using internal stored waypoints case 'T' : Tour(); timeout = 600; break; case 'v' : // Measure the temperature at the current position case 'V' : // xStop(); Measure(); break; case 'z' : // Set this position as the home reference case 'Z' : // xStop(); Zero(); break; default : break; } wait(0.1); } eth.disconnect(); } /* * Set all parameters to a known state */ int init() { int i; laser.write(0); // Ensure the laser is off enable.write(0); // Disable the x and y motor drivers pc.baud(115200); // Set the USB virtual comm port baud rate to 115200 pGimbal = &gimbal; // Determine the pointer to the gimbal class Pulser.attach_us(Pulse, 10); // Start the ISR ticker event every 10us xHome.mode(PullUp); // Enable weak pull-up yHome.mode(PullUp); // Enable weak pull-up wait(1); // m0X.mode(PullNone); // Disable pull-up to force it to float m0X.write(1); // Set X micro-step to 1/16 m1X.write(1); // Set X micro-step to 1/16 // m0Y.mode(PullNone); // Disable pull-up to force it to float m0Y.write(1); // Set Y micro-step to 1/16 m1Y.write(1); // Set Y micro-step to 1/16 mlx.LoadEEPROM(); // if returns non 0, MLX90620 may not be connected to i2c bus mlx.SetOscTrimReg(); // if returns non 0, MLX90620 is having RAM access problems with i2c bus mlx.SetConfigReg(); // if returns non 0, shouldn't be any i2c problems at this point mlx.StartMeasurement(); newenable.write(1); // newenable is a temporary over-ride for the motor enable signal // Insert some random way-points into the tour for testing only (will get over-written by remote server anyway) srand (time(NULL)); for (i=0; i<MAX_TOUR; i++) { gimbal.m_TourPoints[X_AXIS][i] = (0x3fffffff - rand()) / 13421760; gimbal.m_TourPoints[Y_AXIS][i] = (0x3fffffff - rand()) / 13421760; } return(0); /* * Manual entries instead... * * gimbal.m_TourPoints[X_AXIS][0] = 50; gimbal.m_TourPoints[X_AXIS][1] = -50; gimbal.m_TourPoints[X_AXIS][2] = 100; gimbal.m_TourPoints[X_AXIS][3] = -100; gimbal.m_TourPoints[X_AXIS][4] = 100; gimbal.m_TourPoints[X_AXIS][5] = -100; gimbal.m_TourPoints[X_AXIS][6] = 50; gimbal.m_TourPoints[X_AXIS][7] = -50; * * * */ } /* * Parse the response from the remote server and determine the number of way-points and respective x,y coordinates */ int parseServerResponse(char * buffer, CGimbal * pgimbal) { char * startstr=NULL; char * endstr=NULL; int PointIdx=0; // Typical Server Response... // {"status":"1 readings imported","readingVals":[{"xAngle":5,"yAngle":0},{"xAngle":13,"yAngle":4}]} startstr = strstr(buffer, "status\":\""); while (startstr) { startstr = strstr(startstr, "xAngle"); endstr = strstr(startstr, ","); if (startstr) { pgimbal->m_TourPoints[X_AXIS][PointIdx] = strtol(startstr+8, &endstr, 10); startstr = strstr(startstr, "yAngle"); endstr = strstr(startstr, "}"); if (startstr) { pgimbal->m_TourPoints[Y_AXIS][PointIdx] = strtol(startstr+8, &endstr, 10); PointIdx++; } } } return(PointIdx); } /* * Retrieves the MLX data, currently only prints it to stdout (USB virt comm port) */ float ReadMLX(void) { int chk = 0x200; // Running flag in config register int i, j; // Used only for future meander-scan operation float tPix=0.0; // Stores temperature of centre pixel mlx.CalcTa_To(); // Get ambient temperature Ta = mlx.GetDieTemp(); // pc.printf("\nTa = %3.1f\r\n", Ta); mlx.StartMeasurement(); // Starts a conversion wait (.5); // Allow time for gimbal to settle laser.write(1); // Switch on laser wait (.5); // Allow time to settle while(chk > 0) // 1 second should have been ample time to complete a conversion, but check the completion flag anyway { chk = mlx.GetConfigReg() & 0x200; // Completion flag is b9 of config register if(chk == 0) mlx.LoadMLXRam(); // Retrieve the values from the MLX Ram contents else wait_ms(200); } /* for(i = 0; i < 16; i++) // The MLX pixel format is 16 columms of 4 rows rather than 4 rows of 16 columns { // So values have to be read out x0y0, x0y1, x0y2, x0y3 rather than x0y0, x1y0, x2y0 ... for (j=0; j<4; j++) { TempPxl = mlx.CalcPixel(j + i*4); pc.printf("%3.1f ", TempPxl); } printf("\r\n"); } printf("\r\n"); */ tPix = mlx.CalcPixel(31); // Centre pixel laser.write(0); // Switch off laser return(tPix); } /* * Performs an HTTP transaction with the remote server and stores the response in the char * data buffer */ void ContactServer(char * data) { TCPSocketConnection sock; int ret; sock.connect("ekko.legendary-services.com", 80); char http_cmd[] = "GET /api/ekkocam?data="; char http_data[256]; char readingvals[256]; char http_footer[] = "Host: ekko.legendary-services.com\r\nAccept: application/json\r\n\r\n\r\n"; sprintf(readingvals, "\"readingVals\":[{"); for (ret=0; ret < pGimbal->m_NumWaypoints -1; ret++) { sprintf(http_data, "\"xAngle\":%3.1f,\"yAngle\":%3.1f,\"temperature\":%3.1f", pGimbal->m_TourPoints[X_AXIS][ret], pGimbal->m_TourPoints[Y_AXIS][ret], pGimbal->m_PointTemperature[ret]); // temporary use of http_data array to conserve RAM strcat(http_data, ","); strcat(readingvals, http_data); } // No comma on the last entry... sprintf(http_data, "\"xAngle\":%3.1f,\"yAngle\":%3.1f,\"temperature\":%3.1f", pGimbal->m_TourPoints[X_AXIS][ret], pGimbal->m_TourPoints[Y_AXIS][ret], pGimbal->m_PointTemperature[ret]); // temporary use of http_data array to conserve RAM strcat(readingvals, http_data); // Dummy time value is 1458085736 sprintf(http_data, "{\"systemID\":\"hello\",\"sensorID\":\"Ekko0001\",\"eventID\":\"132\",\"utcStamp\":\"%ld\",%s}]} HTTP/1.0\r\n", time(NULL), readingvals); sprintf(data, "%s%s%s", (char *)http_cmd, (char *)http_data, (char *)http_footer); printf("\f%s", (char *)data); sock.send_all(data, strlen(data)); while (true) { ret = sock.receive_all(data, MAX_CHARS -1); if (ret <= 0) break; data[ret] = '\0'; pc.printf("Received %d bytes:\r\n%s\r\n", ret, data); } sock.close(); } /* * Communicate with server, interpret the response and instruct the gimbal accordingly */ int ServerLoop(void) { char buffer[MAX_CHARS]; int i; while(1) { ContactServer(buffer); pGimbal->m_NumWaypoints = parseServerResponse(buffer, pGimbal); pc.printf ("ISR Count: %08d, numwaypoints: %d\r\n", mgTick, pGimbal->m_NumWaypoints); enable.write(1); for (i=0; i< pGimbal->m_NumWaypoints; i++) { // Issue command to move to waypoint [i] pGimbal->RotateAbs(pGimbal->m_TourPoints[X_AXIS][i], pGimbal->m_TourPoints[Y_AXIS][i]); pGimbal->m_PointTemperature[i] = ReadMLX(); printf("Temperature at (%3.1f,%3.1f)=%3.1f\r\n", pGimbal->m_TourPoints[X_AXIS][i], pGimbal->m_TourPoints[Y_AXIS][i], pGimbal->m_PointTemperature[i]); } pGimbal->Home(); printf("Temperature at (0,0)=%3.1f\r\n", pGimbal->m_PointTemperature[i]); printf("Socket Closed\r\n"); enable.write(0); wait(8); } } /* * Execute a tour by stepping through 'i' way-points */ void Tour(void) { int i; enable.write(1); pc.printf("Performing manual tour...\r\n"); for (i=0; i<MAX_TOUR; i++) { pGimbal->TourPoint(i); pGimbal->m_PointTemperature[i] = ReadMLX(); printf("Temperature at (%3.1f,%3.1f)=%3.1f\r\n", pGimbal->m_TourPoints[X_AXIS][i], pGimbal->m_TourPoints[Y_AXIS][i], pGimbal->m_PointTemperature[i]); } enable.write(0); } void xStop(void) { pc.printf("Stop state: %02x\r\n", xHome.read()); } /* * Set the current x,y position as the Zero point for all x and y coordinates */ void Zero(void) { pGimbal->m_AbsoluteXAngle = 0.0; pGimbal->m_AbsoluteXPos = 0; pGimbal->m_AbsoluteYAngle = 0.0; pGimbal->m_AbsoluteYPos = 0; } /* * Rotate to absolute position x,y stored in the rotn structure, reference to home before moving */ void Rotate(ROTATION rotn) { float temperature; enable.write(1); pGimbal->Home(); pGimbal->RotateAbs(rotn.xAngle, rotn.yAngle); temperature = ReadMLX(); printf("%3.1f\r\nOK\r\n", temperature); enable.write(0); } /* * Rotate to absolute position x,y stored in the rotn structure without reference to home before moving */ void RotateNoHome(ROTATION rotn) { float temperature; enable.write(1); pGimbal->RotateAbs(rotn.xAngle, rotn.yAngle); temperature = ReadMLX(); printf("%3.1f\r\nOK\r\n", temperature); enable.write(0); } /* * Display the current MLX temperature value */ void Measure(void) { float temperature; temperature = ReadMLX(); printf("%3.1f\r\nOK\r\n", temperature); }