The subsystem design/basis for the final project
Dependencies: mbed-rtos mbed-src pixylib
robot.cpp
- Committer:
- balsamfir
- Date:
- 2016-03-14
- Revision:
- 3:dfb6733ae397
- Parent:
- 2:2bc519e14bae
- Child:
- 4:01252f56e0e5
File content as of revision 3:dfb6733ae397:
#include "robot.h" #include "global.h" // Global Definitions // ---------------------------------------------------------------- #define MAX_BLOCKS 1 #define TARGET_DECIMAL 10 #define PWM_PERIOD 0.001 #define MOTOR_KP 0.000120 #define MOTOR_KI 0.0000000001 #define X_SETPOINT 160 #define STEERING_KP 0.01 #define STEERING_KI 0.005 #define HEIGHT_SETPOINT 100 #define SPEED_KP 0.01 #define SPEED_KI 0.01 #define SPEED_MAX 10 // Interrupt and thread control 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 xTracked, heightTracked; float speed, steering; // PI internal variables (TODO: move to object) float steeringIntegral, speedIntegral; float leftMotorIntegral, rightMotorIntegral; // Functions // ---------------------------------------------------------------- void AutoTrack() { leftPwm.period(PWM_PERIOD); leftPwm.pulsewidth(0); rightPwm.period(PWM_PERIOD); rightPwm.pulsewidth(0); pixy.setSerialOutput(&pc); 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 osTimerId 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", deSpi.write(0x8004)); // Read count & time for both motors // Specify periodic ISRs and their intervals in seconds // TODO: Optimize interrupt time for motor... Currently too fast motorPeriodicInt.attach(&MotorISR, .001); sensorPeriodicInt.attach(&NavigationISR, 0.1); //trigger sensor thread 60 times/sec while (1) { osTimerStart(oneShotId, 2000); // Start or restart the watchdog timer interrupt and set to 2000ms. pc.printf("X Coordinate: %d, Height: %d \r\n", xTracked, heightTracked); pc.printf("Speed Set: %f, Steering Set: %f \r\n", speed, steering); pc.printf("Speed Int: %f, Steering Int: %f \r\n", speedIntegral, steeringIntegral); pc.printf("Left Motor Set: %f, Right Motor Set: %f \n\r\r\n", leftMotor, rightMotor); Thread::wait(500); // Go to sleep for 500 ms } } void ManualControl(void) { } void PixySubsystem(void) { } // Threads // ---------------------------------------------------------------- void NavigationThread(void const *argument) { int count; 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)) { heightTracked = pixy.blocks[0].height; //use this for now xTracked = pixy.blocks[0].x; PI(HEIGHT_SETPOINT-heightTracked, &speed, &speedIntegral, SPEED_KP, SPEED_KI, SPEED_MAX); PI(X_SETPOINT-xTracked, &steering, &steeringIntegral, STEERING_KP, STEERING_KI, 2*SPEED_MAX); // Give setpoints to MotorThread // Do not update speeds if already turning as fast as possible osMutexWait(motorMutex, osWaitForever); leftMotor = speed - steering; rightMotor = speed + steering; osMutexRelease(motorMutex); } } } void MotorThread(void const *argument) { float leftSet, rightSet, angVel; short dP, dt; float uL, uR; 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); PI(leftSet-angVel, &uL, &leftMotorIntegral, MOTOR_KP, MOTOR_KI, PWM_PERIOD); // Run PI control on right motor dP = deSpi.write(0); dt = deSpi.write(0); angVel = QE2RadsPerSec(dP, dt); PI(rightSet-angVel, &uR, &rightMotorIntegral, MOTOR_KP, MOTOR_KI, PWM_PERIOD); // Output new PWM and direction (motors have opposite orientations) if (uL >= 0) leftDir = 1; else leftDir = 0; if (uR >= 0) rightDir = 0; else rightDir = 1; leftPwm.pulsewidth(fabs(uL)); rightPwm.pulsewidth(fabs(uR)); } } // 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 }