The subsystem design/basis for the final project
Dependencies: mbed-rtos mbed-src pixylib
robot.cpp
- Committer:
- balsamfir
- Date:
- 2016-03-26
- Revision:
- 15:caa5a93a31d7
- Parent:
- 14:2d609d465f00
- Child:
- 16:73db7ef2deb6
File content as of revision 15:caa5a93a31d7:
#include "robot.h" #include "global.h" // Global Definitions // ---------------------------------------------------------------- // Function prototypes // ---------------------------------------------------------------- void MotorISR(void); void NavigationISR(void); void CollisionISR(void); void WatchdogISR(void const *n); void MotorThread(void const *argument); void NavigationThread(void const *argument); void UpdateGains(char key, float *increment); void ShutDown(void); // Interrupt and thread control osTimerId oneShotId; osThreadId motorId, navigationId, wdtId; osThreadDef(MotorThread, osPriorityRealtime, DEFAULT_STACK_SIZE); osThreadDef(NavigationThread, osPriorityAboveNormal, DEFAULT_STACK_SIZE); osTimerDef(Wdtimer, WatchdogISR); int32_t motorSignal, navigationSignal; Ticker motorPeriodicInt; Ticker sensorPeriodicInt; // Mutex to protect left and right motor setpoints osMutexId motorMutex; osMutexDef(motorMutex); // Set points and display variables float leftMotor, rightMotor; int x, height; float speed, steering; // Functions // ---------------------------------------------------------------- void InitRobot(void) { leftPwm.period(PWM_PERIOD); leftPwm.pulsewidth(0); rightPwm.period(PWM_PERIOD); rightPwm.pulsewidth(0); motorMutex = osMutexCreate(osMutex(motorMutex)); bumper.rise(&CollisionISR); // Attach interrupt handler to rising edge of Bumper // Start execution of the threads MotorThread, and NavigationThread: navigationId = osThreadCreate(osThread(NavigationThread), NULL); motorId = osThreadCreate(osThread(MotorThread), NULL); // Start the watch dog timer and enable the watch dog interrupt oneShotId = osTimerCreate(osTimer(Wdtimer), osTimerOnce, (void *)0); led3 = 0; // Clear watch dog led3 status //SPI Initialization pc.printf("\n\rStarting SPI..."); deSpi.format(16,1); // 16 bit mode 1 ioReset = 0; ioReset = 1; wait_us(10); ioReset = 0; spiReset = 0; spiReset = 1; wait_us(10); spiReset = 0; pc.printf("\n\rDevice Id: %d \r\n", deSpi.write(0x8004)); // Read count & time for both motors } void AutoTrack(void) { char key; motorPeriodicInt.attach(&MotorISR, MOTOR_PERIOD); sensorPeriodicInt.attach(&NavigationISR, NAVIGATION_PERIOD); while (1) { osTimerStart(oneShotId, 2000); // Start or restart the watchdog timer interrupt and set to 2000ms. if (pc.readable()) { key = pc.getc(); if (key == 'q') { ShutDown(); return; } } pc.printf("X Coordinate: %d, Height: %d \r\n", x, height); pc.printf("Speed Set: %f, Steering Set: %f \r\n", speed, steering); pc.printf("Left Motor Set: %f, Right Motor Set: %f \n\r\r\n\r\n", leftMotor, rightMotor); Thread::wait(500); // Go to sleep for 500 ms } } void ManualControl(void) { char key; motorPeriodicInt.attach(&MotorISR, MOTOR_PERIOD); while (1) { osTimerStart(oneShotId, 2000); // Start or restart the watchdog timer interrupt and set to 2000ms. if (pc.readable()) { key = flushBuffer(); if (key == 'q') ShutDown(); if (key == 'w') { speed++; } else if (key == 's') { speed--; } else if (speed != 0) { speed = (speed < 0) ? speed++ : speed--; } if (key == 'a') { steering++; } else if (key == 'd') { steering--; } else if (steering != 0) { steering = (steering < 0) ? steering++ : steering--; } } else if (speed != 0) { speed = (speed < 0) ? speed++ : speed--; } else if (steering != 0) { steering = (steering < 0) ? steering++ : steering--; } if (speed > SPEED_MAX) speed = SPEED_MAX ; else if (speed < -SPEED_MAX) speed = -SPEED_MAX ; if (steering > SPEED_MAX) steering = SPEED_MAX ; else if (steering < -SPEED_MAX) steering = -SPEED_MAX ; osMutexWait(motorMutex, osWaitForever); leftMotor = speed - steering; rightMotor = speed + steering; osMutexRelease(motorMutex); Thread::wait(10); // Go to sleep for 100 ms } } void Tunning(void) { char key; float increment = 1; motorPeriodicInt.attach(&MotorISR, MOTOR_PERIOD); sensorPeriodicInt.attach(&NavigationISR, NAVIGATION_PERIOD); while (1) { osTimerStart(oneShotId, 2000); // Start or restart the watchdog timer interrupt and set to 2000ms. if (pc.readable()) { key = pc.getc(); if (key == 'q') { ShutDown(); return; } UpdateGains(key, &increment); pc.printf("Increment \t %f \r\n", increment); pc.printf("Motor \t KP: %f, KI: %f \r\n", leftMotorPI.kP, leftMotorPI.kI); pc.printf("Steering \t KP: %f, KI: %f \r\n", xPI.kP, xPI.kI); pc.printf("Speed \t KP: %f, KI: %f \r\n\r\n\r\n", heightPI.kP, heightPI.kI); } Thread::wait(500); // Go to sleep for 500 ms } } void ShutDown(void) { motorPeriodicInt.detach(); sensorPeriodicInt.detach(); osThreadTerminate(navigationId); osThreadTerminate(motorId); leftPwm.pulsewidth(0); rightPwm.pulsewidth(0); } // Threads // ---------------------------------------------------------------- void NavigationThread(void const *argument) { int count; int missingCount; while (1) { osSignalWait(navigationSignal, osWaitForever); // Go to sleep until navigation signal is set high by ISR count = pixy.getBlocks(1); // If target returned if (count && (pixy.blocks[0].signature == TARGET_DECIMAL)) { missingCount = 0; height = pixy.blocks[0].height; //use this for now x = pixy.blocks[0].x; speed = heightPI.Run(HEIGHT_SETPOINT-height, SPEED_MAX); steering = xPI.Run(X_SETPOINT-x, SPEED_MAX); // Give setpoints to MotorThread osMutexWait(motorMutex, osWaitForever); if (speed >= 0) { leftMotor = speed - steering; rightMotor = speed + steering; } else { leftMotor = speed - steering; rightMotor = speed + steering; } osMutexRelease(motorMutex); } else { // When the robot can't see the target spin in last known direction if (missingCount >= 30) { osMutexWait(motorMutex, osWaitForever); leftMotor = (leftMotor > rightMotor)? SPEED_MAX/3 : -SPEED_MAX/3; rightMotor = (rightMotor > leftMotor)? SPEED_MAX/3 : -SPEED_MAX/3; osMutexRelease(motorMutex); } else { missingCount++; } } } } void MotorThread(void const *argument) { float leftSet, rightSet, angVel; float timeOnLeft, timeOnRight; short dP, dt; while (1) { osSignalWait(motorSignal, osWaitForever); // Go to sleep until motor signal is set high by ISR led2= !led2; // Alive status - led2 toggles each time MotorControlThread is signaled. // Get setpoints from navigation osMutexWait(motorMutex, osWaitForever); leftSet = leftMotor; rightSet = rightMotor; osMutexRelease(motorMutex); // Run PI control on left motor dP = deSpi.write(0); dt = deSpi.write(0); angVel = QE2RadsPerSec(dP, dt); timeOnLeft = leftMotorPI.Run(leftSet-angVel, PWM_PERIOD); // Run PI control on right motor dP = deSpi.write(0); dt = deSpi.write(0); angVel = -QE2RadsPerSec(dP, dt); // motors have opposite orientations timeOnRight = rightMotorPI.Run(rightSet-angVel, PWM_PERIOD); // // Output new PWM and direction if (timeOnLeft >= 0) leftDir = 1; else leftDir = 0; if (timeOnRight >= 0) rightDir = 0; else rightDir = 1; leftPwm.pulsewidth(fabs(timeOnLeft)); rightPwm.pulsewidth(fabs(timeOnRight)); } } // Interrupt Service Routines // ---------------------------------------------------------------- // TODO: Shutdown system void WatchdogISR(void const *n) { led3=1; // Activated when the watchdog timer times out } void MotorISR(void) { osSignalSet(motorId,0x1); // Activate the signal, MotorControl, with each periodic timer interrupt } void NavigationISR(void) { osSignalSet(navigationId,0x1); // Activate the signal, SensorControl, with each periodic timer interrupt } // TODO: Shutdown system void CollisionISR(void) { led4 = 1; // Activated on collision } // Nasty case function to update gain values void UpdateGains(char key, float *increment) { switch(key) { case 'e': leftMotorPI.kP = leftMotorPI.kP + *increment; break; case 'd': leftMotorPI.kP = leftMotorPI.kP - *increment; break; case 'r': leftMotorPI.kI = leftMotorPI.kI + *increment; break; case 'f': leftMotorPI.kI = leftMotorPI.kI - *increment; break; case 't': xPI.kP = xPI.kP + *increment; break; case 'g': xPI.kP = xPI.kP - *increment; break; case 'y': xPI.kI = xPI.kI + *increment; break; case 'h': xPI.kI = xPI.kI - *increment; break; case 'u': heightPI.kP = heightPI.kP + *increment; break; case 'j': heightPI.kP = heightPI.kP - *increment; break; case 'i': heightPI.kI = heightPI.kI + *increment; break; case 'k': heightPI.kI = heightPI.kI - *increment; break; case 'o': *increment = *increment * 10; break; case 'l': *increment = *increment / 10; break; } }