The subsystem design/basis for the final project

Dependencies:   mbed-rtos mbed-src pixylib

Committer:
balsamfir
Date:
Sun Mar 13 15:22:39 2016 +0000
Revision:
1:cc5636894b95
Parent:
0:80a37292f6b2
Child:
2:2bc519e14bae
Cleanup before change

Who changed what in which revision?

UserRevisionLine numberNew contents of line
balsamfir 1:cc5636894b95 1 // Description: combines the functionality of both the MotorControl program that controls a motor and the Pixy subsystem
JamesMacLean 0:80a37292f6b2 2 // to create a program that will control the robot
JamesMacLean 0:80a37292f6b2 3
JamesMacLean 0:80a37292f6b2 4 #include "rtos.h"
JamesMacLean 0:80a37292f6b2 5 #include "mbed.h"
JamesMacLean 0:80a37292f6b2 6 #include "Robot_Control.h"
JamesMacLean 0:80a37292f6b2 7 #include "Pixy.h"
JamesMacLean 0:80a37292f6b2 8
JamesMacLean 0:80a37292f6b2 9 #define MAX_BLOCKS 1
balsamfir 1:cc5636894b95 10 #define TARGET_DECIMAL 0x10 //the code of our target in decimal
JamesMacLean 0:80a37292f6b2 11
JamesMacLean 0:80a37292f6b2 12 //controls whether or not motors are a part of the program
JamesMacLean 0:80a37292f6b2 13 //for our test of the PIXY, they will not be
JamesMacLean 0:80a37292f6b2 14 #define MOTORS_ON 0
JamesMacLean 0:80a37292f6b2 15
JamesMacLean 0:80a37292f6b2 16 //steering inputs, may want to change to variables or something
JamesMacLean 0:80a37292f6b2 17 #define STEER_SETPOINT 160
JamesMacLean 0:80a37292f6b2 18 #define STEER_KP 1
JamesMacLean 0:80a37292f6b2 19 #define STEER_KI 0
JamesMacLean 0:80a37292f6b2 20 #define STEER_MAX 2147483648
JamesMacLean 0:80a37292f6b2 21
JamesMacLean 0:80a37292f6b2 22 //speed inputs
JamesMacLean 0:80a37292f6b2 23 #define HEIGHT_SETPOINT 160
JamesMacLean 0:80a37292f6b2 24 #define SPEED_KP 1
JamesMacLean 0:80a37292f6b2 25 #define SPEED_KI 0
JamesMacLean 0:80a37292f6b2 26 #define SPEED_MAX 2147483648
JamesMacLean 0:80a37292f6b2 27
JamesMacLean 0:80a37292f6b2 28 //shared variables between sensor thread and motor thread, protected by mutex
JamesMacLean 0:80a37292f6b2 29 float left_setpoint, right_setpoint;
JamesMacLean 0:80a37292f6b2 30
JamesMacLean 0:80a37292f6b2 31 //the setpoint mutex
JamesMacLean 0:80a37292f6b2 32 osMutexId setpoint_mutex;
JamesMacLean 0:80a37292f6b2 33 osMutexDef(setpoint_mutex);
JamesMacLean 0:80a37292f6b2 34
JamesMacLean 0:80a37292f6b2 35 //motorPI function variables
JamesMacLean 0:80a37292f6b2 36 float L_xState, R_xState; //the states for the left and right pi control loop (must have them outside of function to make them cumulative)
JamesMacLean 0:80a37292f6b2 37
JamesMacLean 0:80a37292f6b2 38 //PI function variables
JamesMacLean 0:80a37292f6b2 39 float steer_xState, speed_xState; //the states for the steering and speed pi control loop
JamesMacLean 0:80a37292f6b2 40
JamesMacLean 0:80a37292f6b2 41 //main()variables
JamesMacLean 0:80a37292f6b2 42 short idCode;
JamesMacLean 0:80a37292f6b2 43 char isMeasuring;
JamesMacLean 0:80a37292f6b2 44 char inKey;
JamesMacLean 0:80a37292f6b2 45 float pwmPeriod = 0.001;
JamesMacLean 0:80a37292f6b2 46
JamesMacLean 0:80a37292f6b2 47 //global variables
JamesMacLean 0:80a37292f6b2 48 float Kp, Ki; //kp and ki for motors
JamesMacLean 0:80a37292f6b2 49
JamesMacLean 0:80a37292f6b2 50 // Various debugging variables
JamesMacLean 0:80a37292f6b2 51 float vels[60], times[60], errs[60], xvals[60], uvals[60]; // Used to measure step response
JamesMacLean 0:80a37292f6b2 52 int x_global, height_global;
JamesMacLean 0:80a37292f6b2 53 float speed_global, steer_global;
JamesMacLean 0:80a37292f6b2 54
JamesMacLean 0:80a37292f6b2 55 // ******** Main Thread ********
JamesMacLean 0:80a37292f6b2 56 int main() { // This thread executes first upon reset or power-on.
JamesMacLean 0:80a37292f6b2 57
JamesMacLean 0:80a37292f6b2 58 if(MOTORS_ON){
JamesMacLean 0:80a37292f6b2 59 // left
JamesMacLean 0:80a37292f6b2 60 PWM0.period(pwmPeriod);
JamesMacLean 0:80a37292f6b2 61 PWM0.pulsewidth(0);
JamesMacLean 0:80a37292f6b2 62
JamesMacLean 0:80a37292f6b2 63 // right
JamesMacLean 0:80a37292f6b2 64 PWM1.period(pwmPeriod);
JamesMacLean 0:80a37292f6b2 65 PWM1.pulsewidth(0);
JamesMacLean 0:80a37292f6b2 66
JamesMacLean 0:80a37292f6b2 67 //mutex for the left and right motor setpoints
JamesMacLean 0:80a37292f6b2 68 setpoint_mutex = osMutexCreate(osMutex(setpoint_mutex));
JamesMacLean 0:80a37292f6b2 69 }
JamesMacLean 0:80a37292f6b2 70
JamesMacLean 0:80a37292f6b2 71 Bumper.rise(&ExtCollisionISR); // Attach the address of the interrupt handler to the rising edge of Bumper
JamesMacLean 0:80a37292f6b2 72
balsamfir 1:cc5636894b95 73 // Start execution of the threads: MotorControlThread,ExtCollisionThread, and SensorControlThread:
JamesMacLean 0:80a37292f6b2 74 SensorControl = osThreadCreate(osThread(SensorControlThread), NULL);
balsamfir 1:cc5636894b95 75 if(MOTORS_ON) MotorControl = osThreadCreate(osThread(MotorControlThread), NULL);
JamesMacLean 0:80a37292f6b2 76 ExtCollision = osThreadCreate(osThread(ExtCollisionThread), NULL);
JamesMacLean 0:80a37292f6b2 77
JamesMacLean 0:80a37292f6b2 78 // Start the watch dog timer and enable the watch dog interrupt
JamesMacLean 0:80a37292f6b2 79 osTimerId OneShot = osTimerCreate(osTimer(Wdtimer), osTimerOnce, (void *)0);
JamesMacLean 0:80a37292f6b2 80 led3=0; // Clear watch dog led3 status
JamesMacLean 0:80a37292f6b2 81
JamesMacLean 0:80a37292f6b2 82 if(MOTORS_ON){
JamesMacLean 0:80a37292f6b2 83 //SPI Section
JamesMacLean 0:80a37292f6b2 84 pc.printf("\n\rStarting SPI...");
JamesMacLean 0:80a37292f6b2 85 // Restart with a new SPI protocol.
JamesMacLean 0:80a37292f6b2 86 DE0.format(16,1); // 16 bit mode 1
JamesMacLean 0:80a37292f6b2 87 IoReset = 0;
JamesMacLean 0:80a37292f6b2 88 IoReset = 1;
JamesMacLean 0:80a37292f6b2 89 wait_us(10);
JamesMacLean 0:80a37292f6b2 90 IoReset = 0;
JamesMacLean 0:80a37292f6b2 91 SpiReset = 0;
JamesMacLean 0:80a37292f6b2 92 SpiReset = 1;
JamesMacLean 0:80a37292f6b2 93 wait_us(10);
JamesMacLean 0:80a37292f6b2 94 SpiReset = 0;
balsamfir 1:cc5636894b95 95 idCode = DE0.write(0x8004); // Read count/time for both motors
JamesMacLean 0:80a37292f6b2 96 pc.printf("\n\rDevice Id: %d", idCode);
JamesMacLean 0:80a37292f6b2 97
JamesMacLean 0:80a37292f6b2 98 // motor Kp and Ki
JamesMacLean 0:80a37292f6b2 99 Kp = 0.000120;
JamesMacLean 0:80a37292f6b2 100 Ki = 0.0000000001;
JamesMacLean 0:80a37292f6b2 101 }
JamesMacLean 0:80a37292f6b2 102
balsamfir 1:cc5636894b95 103 // Specify address of the ISRs and intervals in seconds between interrupts
balsamfir 1:cc5636894b95 104 // TODO: Optimize interrupt time for motor... Currently too fast
balsamfir 1:cc5636894b95 105 if(MOTORS_ON) MotorPeriodicInt.attach(&MotorControllerISR, .001);
balsamfir 1:cc5636894b95 106 SensorPeriodicInt.attach(&SensorControllerISR, .0167); //trigger sensor thread 60 times/sec
JamesMacLean 0:80a37292f6b2 107
JamesMacLean 0:80a37292f6b2 108 //isMeasuring = 1;
JamesMacLean 0:80a37292f6b2 109 //Setpoint = 6;
JamesMacLean 0:80a37292f6b2 110
JamesMacLean 0:80a37292f6b2 111 while (1) {
JamesMacLean 0:80a37292f6b2 112
JamesMacLean 0:80a37292f6b2 113 osTimerStart(OneShot, 2000); // Start or restart the watchdog timer interrupt and set to 2000ms.
JamesMacLean 0:80a37292f6b2 114
balsamfir 1:cc5636894b95 115 pc.printf("X Coordinate: %d, Steering: %d,", x_global, steer_global);
balsamfir 1:cc5636894b95 116 pc.printf("Height: %d, Speed: %d,", height_global, speed_global);
balsamfir 1:cc5636894b95 117 pc.printf(" L setpoint: %d, R setpoint: %d \n\r", left_setpoint, right_setpoint);
balsamfir 1:cc5636894b95 118
JamesMacLean 0:80a37292f6b2 119 /*
JamesMacLean 0:80a37292f6b2 120 if (!isMeasuring && (Setpoint!=0)) {
JamesMacLean 0:80a37292f6b2 121 pc.printf("\n\r-----------------------------------\n\r");
JamesMacLean 0:80a37292f6b2 122 printf("times (ms) \t vel (rads/s) \t error \t\t x value \t u value \n\r");
JamesMacLean 0:80a37292f6b2 123 for (i=0; i<60; i++) {
JamesMacLean 0:80a37292f6b2 124 printf("%f, \t %f, \t %f, \t %f, \t %f \n\r", times[i], vels[i], errs[i], xvals[i], uvals[i]);
JamesMacLean 0:80a37292f6b2 125 }
JamesMacLean 0:80a37292f6b2 126 pc.printf("\n\r-----------------------------------\n\r");
JamesMacLean 0:80a37292f6b2 127 Setpoint = 0;
JamesMacLean 0:80a37292f6b2 128 i = 0;
JamesMacLean 0:80a37292f6b2 129 }
JamesMacLean 0:80a37292f6b2 130 */
JamesMacLean 0:80a37292f6b2 131 Thread::wait(500); // Go to sleep for 500 ms
JamesMacLean 0:80a37292f6b2 132 }
JamesMacLean 0:80a37292f6b2 133 }
JamesMacLean 0:80a37292f6b2 134
JamesMacLean 0:80a37292f6b2 135 // ******** Control Thread ********
JamesMacLean 0:80a37292f6b2 136 void SensorControlThread(void const *argument) {
JamesMacLean 0:80a37292f6b2 137 float speed, steer;
JamesMacLean 0:80a37292f6b2 138 int x, count, height;
JamesMacLean 0:80a37292f6b2 139
JamesMacLean 0:80a37292f6b2 140 Pixy pixy(Pixy::SPI, p11, p12, p13);
JamesMacLean 0:80a37292f6b2 141
JamesMacLean 0:80a37292f6b2 142 while (1) {
JamesMacLean 0:80a37292f6b2 143 osSignalWait(SignalSensor, osWaitForever); //note: SignalSensor is just zero, waits for any signal dirrected at thread.
JamesMacLean 0:80a37292f6b2 144
JamesMacLean 0:80a37292f6b2 145 count = pixy.getBlocks(130); //get as many blocks as are available
JamesMacLean 0:80a37292f6b2 146
JamesMacLean 0:80a37292f6b2 147 //find the target block in all of the blocks that were sent
JamesMacLean 0:80a37292f6b2 148 for(x=0;x<count;x++){
balsamfir 1:cc5636894b95 149 if (pixy.blocks[x].signature == TARGET_DECIMAL) break;
JamesMacLean 0:80a37292f6b2 150 if (x==count) pc.printf("no target in frame");
JamesMacLean 0:80a37292f6b2 151 }
JamesMacLean 0:80a37292f6b2 152
JamesMacLean 0:80a37292f6b2 153 // if blocks were returned
JamesMacLean 0:80a37292f6b2 154 if (count){
JamesMacLean 0:80a37292f6b2 155
JamesMacLean 0:80a37292f6b2 156 //height = CalcHeight() //find the feedback from the pixy for the height
JamesMacLean 0:80a37292f6b2 157 height = pixy.blocks[(x-1)].height; //use this for now
JamesMacLean 0:80a37292f6b2 158
JamesMacLean 0:80a37292f6b2 159 steer = PI(0, STEER_SETPOINT, STEER_KP, STEER_KI, pixy.blocks[(x-1)].x, STEER_MAX); //the feedback for the steering is the x location of the target block
JamesMacLean 0:80a37292f6b2 160 speed = PI(1, HEIGHT_SETPOINT, SPEED_KP, SPEED_KI, height, SPEED_MAX);
JamesMacLean 0:80a37292f6b2 161
JamesMacLean 0:80a37292f6b2 162 if(!MOTORS_ON){
JamesMacLean 0:80a37292f6b2 163 x_global = pixy.blocks[x-1].x;
JamesMacLean 0:80a37292f6b2 164 height_global = height;
JamesMacLean 0:80a37292f6b2 165 steer_global = steer;
JamesMacLean 0:80a37292f6b2 166 speed_global = speed;
JamesMacLean 0:80a37292f6b2 167 }
JamesMacLean 0:80a37292f6b2 168
balsamfir 1:cc5636894b95 169 // give setpoints to MotorControlThread
JamesMacLean 0:80a37292f6b2 170 osMutexWait(setpoint_mutex, osWaitForever); //enter mutex
JamesMacLean 0:80a37292f6b2 171 left_setpoint = speed - steer;
JamesMacLean 0:80a37292f6b2 172 right_setpoint = speed + steer;
JamesMacLean 0:80a37292f6b2 173 osMutexRelease(setpoint_mutex); //exit mutex
JamesMacLean 0:80a37292f6b2 174 }
JamesMacLean 0:80a37292f6b2 175
JamesMacLean 0:80a37292f6b2 176 }
JamesMacLean 0:80a37292f6b2 177 }
JamesMacLean 0:80a37292f6b2 178
JamesMacLean 0:80a37292f6b2 179 // ******** Control Thread ********
balsamfir 1:cc5636894b95 180 void MotorControlThread(void const *argument) {
JamesMacLean 0:80a37292f6b2 181 short dP_L, dt_L, dP_R, dt_R;
JamesMacLean 0:80a37292f6b2 182 float uL,uR;
JamesMacLean 0:80a37292f6b2 183 float left_set,right_set;
JamesMacLean 0:80a37292f6b2 184
JamesMacLean 0:80a37292f6b2 185 while (1) {
JamesMacLean 0:80a37292f6b2 186 osSignalWait(SignalPi, osWaitForever); // Go to sleep until signal, SignalPi, is received. SignalPi is just zero lol, waits for any signal to thread
balsamfir 1:cc5636894b95 187 led2= !led2; // Alive status - led2 toggles each time MotorControlThread is signaled.
JamesMacLean 0:80a37292f6b2 188
JamesMacLean 0:80a37292f6b2 189 dP_L = DE0.write(0); // Read QEI-0 position register
JamesMacLean 0:80a37292f6b2 190 dt_L = DE0.write(0); // Read QEI-0 time register
JamesMacLean 0:80a37292f6b2 191 dP_R = DE0.write(0); // Read QEI-0 position register
JamesMacLean 0:80a37292f6b2 192 dt_R = DE0.write(0); // Read QEI-0 time register
JamesMacLean 0:80a37292f6b2 193
JamesMacLean 0:80a37292f6b2 194 osMutexWait(setpoint_mutex, osWaitForever);//enter mutex
JamesMacLean 0:80a37292f6b2 195 left_set= left_setpoint; //copy setpoint
JamesMacLean 0:80a37292f6b2 196 right_set= right_setpoint;
JamesMacLean 0:80a37292f6b2 197 osMutexRelease(setpoint_mutex);//exit mutex
JamesMacLean 0:80a37292f6b2 198
JamesMacLean 0:80a37292f6b2 199 uL = motorPI(0, left_set, Kp, Ki, dP_L, dt_L);
JamesMacLean 0:80a37292f6b2 200 uR = motorPI(1, right_set, Kp, Ki, dP_R, dt_R);
JamesMacLean 0:80a37292f6b2 201
JamesMacLean 0:80a37292f6b2 202 PWM0.pulsewidth(fabs(uL));
JamesMacLean 0:80a37292f6b2 203 PWM1.pulsewidth(fabs(uR));
JamesMacLean 0:80a37292f6b2 204 }
JamesMacLean 0:80a37292f6b2 205 }
JamesMacLean 0:80a37292f6b2 206
JamesMacLean 0:80a37292f6b2 207 // ******** Collision Thread ********
JamesMacLean 0:80a37292f6b2 208 void ExtCollisionThread(void const *argument) {
JamesMacLean 0:80a37292f6b2 209 while (1) {
JamesMacLean 0:80a37292f6b2 210 osSignalWait(SignalExtCollision, osWaitForever); // Go to sleep until signal, SignalExtCollision, is received
JamesMacLean 0:80a37292f6b2 211 led4 = 1;
JamesMacLean 0:80a37292f6b2 212 }
JamesMacLean 0:80a37292f6b2 213 }
JamesMacLean 0:80a37292f6b2 214
JamesMacLean 0:80a37292f6b2 215 // ******** Watchdog Interrupt Handler ********
balsamfir 1:cc5636894b95 216 // TODO: Shutdown system
JamesMacLean 0:80a37292f6b2 217 void Watchdog(void const *n) {
JamesMacLean 0:80a37292f6b2 218 led3=1; // led3 is activated when the watchdog timer times out
JamesMacLean 0:80a37292f6b2 219 }
JamesMacLean 0:80a37292f6b2 220
JamesMacLean 0:80a37292f6b2 221 // ******** Period Timer Interrupt Handler ********
balsamfir 1:cc5636894b95 222 void MotorControllerISR(void) {
balsamfir 1:cc5636894b95 223 osSignalSet(MotorControl,0x1); // Activate the signal, MotorControl, with each periodic timer interrupt.
JamesMacLean 0:80a37292f6b2 224 }
JamesMacLean 0:80a37292f6b2 225
JamesMacLean 0:80a37292f6b2 226 // ******** Period Timer Interrupt Handler ********
JamesMacLean 0:80a37292f6b2 227 void SensorControllerISR(void) {
JamesMacLean 0:80a37292f6b2 228 osSignalSet(SensorControl,0x1); // Activate the signal, SensorControl, with each periodic timer interrupt. (basically sends signal to id of thread)
JamesMacLean 0:80a37292f6b2 229 }
JamesMacLean 0:80a37292f6b2 230
JamesMacLean 0:80a37292f6b2 231 // ******** Collision Interrupt Handler ********
JamesMacLean 0:80a37292f6b2 232 void ExtCollisionISR(void) {
JamesMacLean 0:80a37292f6b2 233 osSignalSet(ExtCollision,0x1); // Activate the signal, ExtCollision, with each pexternal interrupt.
JamesMacLean 0:80a37292f6b2 234 }
JamesMacLean 0:80a37292f6b2 235
JamesMacLean 0:80a37292f6b2 236 // motorPI - motor pi control extacted from previous work
JamesMacLean 0:80a37292f6b2 237 // Input: 0 for Left motor, 1 for right motor
JamesMacLean 0:80a37292f6b2 238 // Output: pwm pulsewidth for corresponding motor
JamesMacLean 0:80a37292f6b2 239
JamesMacLean 0:80a37292f6b2 240 float motorPI(int RL_Motor, float Setpoint, float Kp, float Ki, short dP1, short dt1){
JamesMacLean 0:80a37292f6b2 241 int dP32, i;
JamesMacLean 0:80a37292f6b2 242 float angVel, e, u, xState;
JamesMacLean 0:80a37292f6b2 243
JamesMacLean 0:80a37292f6b2 244 if (dP1 & 0x00008000) {
JamesMacLean 0:80a37292f6b2 245 dP32 = dP1 | 0xFFFF0000;
JamesMacLean 0:80a37292f6b2 246 } else {
JamesMacLean 0:80a37292f6b2 247 dP32 = dP1;
JamesMacLean 0:80a37292f6b2 248 }
JamesMacLean 0:80a37292f6b2 249
JamesMacLean 0:80a37292f6b2 250 angVel = QE2RadsPerSec(dP32, dt1);
JamesMacLean 0:80a37292f6b2 251
JamesMacLean 0:80a37292f6b2 252 e = Setpoint - angVel;
JamesMacLean 0:80a37292f6b2 253
JamesMacLean 0:80a37292f6b2 254 RL_Motor ? xState = R_xState : xState = L_xState; //state is cumulative, select left or right state global variable
JamesMacLean 0:80a37292f6b2 255
JamesMacLean 0:80a37292f6b2 256 // Avoid integrator wind up
JamesMacLean 0:80a37292f6b2 257 if((u>=pwmPeriod)||(u<=-pwmPeriod)){
JamesMacLean 0:80a37292f6b2 258 //xState= xState; - turns off integrator when u maxed
JamesMacLean 0:80a37292f6b2 259 }else{
JamesMacLean 0:80a37292f6b2 260 xState = xState + e;
JamesMacLean 0:80a37292f6b2 261 }
JamesMacLean 0:80a37292f6b2 262
JamesMacLean 0:80a37292f6b2 263 RL_Motor ? R_xState = xState : L_xState = xState; //update state variable
JamesMacLean 0:80a37292f6b2 264
JamesMacLean 0:80a37292f6b2 265 u = Ki*xState + Kp*e;
JamesMacLean 0:80a37292f6b2 266
JamesMacLean 0:80a37292f6b2 267 // Set direction and pwm
JamesMacLean 0:80a37292f6b2 268 if (u >= 0) {
JamesMacLean 0:80a37292f6b2 269 RL_Motor ? DIR1 = 1 : DIR0 = 1;
JamesMacLean 0:80a37292f6b2 270 } else {
JamesMacLean 0:80a37292f6b2 271 RL_Motor ? DIR1 = 0 : DIR0 = 0;
JamesMacLean 0:80a37292f6b2 272 }
JamesMacLean 0:80a37292f6b2 273
JamesMacLean 0:80a37292f6b2 274 if (isMeasuring) {
JamesMacLean 0:80a37292f6b2 275 vels[i] = angVel;
JamesMacLean 0:80a37292f6b2 276 times[i] = i;
JamesMacLean 0:80a37292f6b2 277 errs[i] = e;
JamesMacLean 0:80a37292f6b2 278 xvals[i] = xState;
JamesMacLean 0:80a37292f6b2 279 uvals[i] = u;
JamesMacLean 0:80a37292f6b2 280 if (i>=59) {
JamesMacLean 0:80a37292f6b2 281 isMeasuring = 0;
JamesMacLean 0:80a37292f6b2 282 }
JamesMacLean 0:80a37292f6b2 283 i++;
JamesMacLean 0:80a37292f6b2 284 }
JamesMacLean 0:80a37292f6b2 285
JamesMacLean 0:80a37292f6b2 286 if (fabs(u) > pwmPeriod) u = pwmPeriod;
JamesMacLean 0:80a37292f6b2 287
JamesMacLean 0:80a37292f6b2 288 return u;
JamesMacLean 0:80a37292f6b2 289 }
JamesMacLean 0:80a37292f6b2 290
JamesMacLean 0:80a37292f6b2 291 // PI() - A generic PI controller function used by the sensor control thread
JamesMacLean 0:80a37292f6b2 292 // st_or_sp - 0 for steering, 1 for speed
JamesMacLean 0:80a37292f6b2 293 float PI(int st_or_sp, float setpoint, float Kp, float Ki, int feedback, float max_val){
JamesMacLean 0:80a37292f6b2 294 float e, xState, u;
JamesMacLean 0:80a37292f6b2 295
JamesMacLean 0:80a37292f6b2 296 e = setpoint - (float)feedback;
JamesMacLean 0:80a37292f6b2 297
JamesMacLean 0:80a37292f6b2 298 st_or_sp ? xState = speed_xState : xState = steer_xState;
JamesMacLean 0:80a37292f6b2 299
JamesMacLean 0:80a37292f6b2 300 // Avoid integrator wind up
JamesMacLean 0:80a37292f6b2 301 if((u>=max_val)||(u<=-max_val)){
JamesMacLean 0:80a37292f6b2 302 //xState= xState; - turns off integrator when u maxed
JamesMacLean 0:80a37292f6b2 303 }else{
JamesMacLean 0:80a37292f6b2 304 xState = xState + e;
JamesMacLean 0:80a37292f6b2 305 }
JamesMacLean 0:80a37292f6b2 306
JamesMacLean 0:80a37292f6b2 307 st_or_sp ? speed_xState = xState : steer_xState = xState; //update state variable
JamesMacLean 0:80a37292f6b2 308
JamesMacLean 0:80a37292f6b2 309 u = Ki*xState + Kp*e;
JamesMacLean 0:80a37292f6b2 310
JamesMacLean 0:80a37292f6b2 311 if (fabs(u) > max_val) u = max_val;
JamesMacLean 0:80a37292f6b2 312
JamesMacLean 0:80a37292f6b2 313 return u;
JamesMacLean 0:80a37292f6b2 314 }
JamesMacLean 0:80a37292f6b2 315
JamesMacLean 0:80a37292f6b2 316 float QE2RadsPerSec(int counts, int time) {
JamesMacLean 0:80a37292f6b2 317 return (counts*122.62)/time;
JamesMacLean 0:80a37292f6b2 318 }