For coursework of group 3 in SOFT564Z

Dependencies:   Motordriver ros_lib_kinetic

Committer:
Jonathan738
Date:
Sun Jan 05 15:42:22 2020 +0000
Revision:
12:82b8fe254222
Parent:
6:3872858b7844
Added working version of TOF code

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Jonathan738 4:8afc50a3e4ac 1 #include "mbed.h"
Jonathan738 0:3dfee562823a 2 #include "General.hpp"
Jonathan738 4:8afc50a3e4ac 3 #include "ros.h"
Jonathan738 4:8afc50a3e4ac 4 #include "rtos.h"
Jonathan738 4:8afc50a3e4ac 5 #include "ROS_Handler.hpp"
Jonathan738 4:8afc50a3e4ac 6 #include <motordriver.h>
Jonathan738 4:8afc50a3e4ac 7 #include "math.h"
Jonathan738 4:8afc50a3e4ac 8 #include "Motors.hpp"
Jonathan738 4:8afc50a3e4ac 9 #include "Battery_Monitor.hpp"
Jonathan738 4:8afc50a3e4ac 10 #include "Pins.h"
Jonathan738 0:3dfee562823a 11
Jonathan738 0:3dfee562823a 12 //Defines used for the encoder counting
Jonathan738 0:3dfee562823a 13 #define PREV_MASK 0x1 //Mask for the previous state in determining direction of rotation.
Jonathan738 0:3dfee562823a 14 #define CURR_MASK 0x2 //Mask for the current state in determining direction of rotation.
Jonathan738 0:3dfee562823a 15 #define INVALID 0x3 //XORing two states where both bits have changed.
Jonathan738 0:3dfee562823a 16
Jonathan738 0:3dfee562823a 17 Motor A(PB_13, PB_15, PC_6, 1); // pwm, fwd, rev, can brake
Jonathan738 0:3dfee562823a 18 Motor B(PB_4, PC_7, PA_15, 1); // pwm, fwd, rev, can brake
Jonathan738 0:3dfee562823a 19
Jonathan738 0:3dfee562823a 20 Serial pc(USBTX, USBRX);
Jonathan738 0:3dfee562823a 21
Jonathan738 0:3dfee562823a 22 InterruptIn encoderAchannel1(PB_12);
Jonathan738 0:3dfee562823a 23 InterruptIn encoderAchannel2(PA_4);
Jonathan738 0:3dfee562823a 24 InterruptIn encoderBchannel1(PB_5);
Jonathan738 0:3dfee562823a 25 InterruptIn encoderBchannel2(PB_3);
Jonathan738 0:3dfee562823a 26
Jonathan738 0:3dfee562823a 27 float radius = 3; //wheel radius in cm
Jonathan738 0:3dfee562823a 28 float bodyradius = 9.15; //radius of wheel centre from centre of bot, measured in vertical axis
Jonathan738 0:3dfee562823a 29 float benchmark = 3576; //number of encoder pulses per rotation of a wheel
Jonathan738 0:3dfee562823a 30 float pwm = -0.5; //the pwm constant that the wheels will use when moving
Jonathan738 0:3dfee562823a 31 float brakedist = 105; //the encoder target offset where the brakes will engage to prevent overshoot
Jonathan738 0:3dfee562823a 32 //^^ found using trial and error for a pwm value of 0.5 - will almost certainly vary if that is changed
Jonathan738 0:3dfee562823a 33
Jonathan738 0:3dfee562823a 34 volatile long acurrent = 0; //wheel A's current position in encoder counts
Jonathan738 0:3dfee562823a 35 int atarget = 0; //wheel A's current target position in encoder counts
Jonathan738 0:3dfee562823a 36 int aprevtarget = 0; //wheel A's previous target position in encoder counts
Jonathan738 0:3dfee562823a 37 float apwm = 0; //the pwm for wheel a, updated using the 'pwm' variable
Jonathan738 0:3dfee562823a 38 volatile int channelAstate1 = encoderAchannel1.read(); //read the encoder channels for motor A and record their states
Jonathan738 0:3dfee562823a 39 volatile int channelAstate2 = encoderAchannel2.read();
Jonathan738 0:3dfee562823a 40 int currentStateA = (channelAstate1 << 1) | (channelAstate2); //store a 2-bit state to track the current encoder readings
Jonathan738 0:3dfee562823a 41 int previousStateA = currentStateA;
Jonathan738 0:3dfee562823a 42 int nextmoveflagA = 1;
Jonathan738 0:3dfee562823a 43
Jonathan738 0:3dfee562823a 44 volatile long bcurrent = 0;
Jonathan738 0:3dfee562823a 45 int btarget = 0;
Jonathan738 0:3dfee562823a 46 int bprevtarget = 0;
Jonathan738 0:3dfee562823a 47 float bpwm = 0;
Jonathan738 0:3dfee562823a 48 volatile int channelBstate1 = encoderBchannel1.read();
Jonathan738 0:3dfee562823a 49 volatile int channelBstate2 = encoderBchannel2.read();
Jonathan738 0:3dfee562823a 50 int currentStateB = (channelBstate1 << 1) | (channelBstate2);
Jonathan738 0:3dfee562823a 51 int previousStateB = currentStateB;
Jonathan738 0:3dfee562823a 52 int nextmoveflagB = 1;
Jonathan738 0:3dfee562823a 53
Jonathan738 12:82b8fe254222 54 void initialize()
Jonathan738 12:82b8fe254222 55 {
Jonathan738 0:3dfee562823a 56 //every time a rising or falling edge is detected for the A or B channels, call the encoder counting interrupt for the respective wheel.
Jonathan738 0:3dfee562823a 57 //this corresponds to the counting program for the encoders for each wheel, given that quadrature encoding is used.
Jonathan738 0:3dfee562823a 58 encoderAchannel1.rise(&callbackA);
Jonathan738 0:3dfee562823a 59 encoderAchannel1.fall(&callbackA);
Jonathan738 0:3dfee562823a 60 encoderAchannel2.rise(&callbackA);
Jonathan738 0:3dfee562823a 61 encoderAchannel2.fall(&callbackA);
Jonathan738 0:3dfee562823a 62 encoderBchannel1.rise(&callbackB);
Jonathan738 0:3dfee562823a 63 encoderBchannel1.fall(&callbackB);
Jonathan738 0:3dfee562823a 64 encoderBchannel2.rise(&callbackB);
Jonathan738 0:3dfee562823a 65 encoderBchannel2.fall(&callbackB);
Jonathan738 0:3dfee562823a 66 //make sure the initial values for the encoders are all set correctly, and reflect their current real state.
Jonathan738 0:3dfee562823a 67 channelAstate1 = encoderAchannel1.read();
Jonathan738 0:3dfee562823a 68 channelAstate2 = encoderAchannel2.read();
Jonathan738 0:3dfee562823a 69 currentStateA = (channelAstate1 << 1) | (channelAstate2);
Jonathan738 0:3dfee562823a 70 previousStateA = currentStateA;
Jonathan738 0:3dfee562823a 71 channelBstate1 = encoderBchannel1.read();
Jonathan738 0:3dfee562823a 72 channelBstate2 = encoderBchannel2.read();
Jonathan738 0:3dfee562823a 73 currentStateB = (channelBstate1 << 1) | (channelBstate2);
Jonathan738 0:3dfee562823a 74 previousStateB = currentStateB;
Jonathan738 0:3dfee562823a 75 }
Jonathan738 0:3dfee562823a 76
Jonathan738 12:82b8fe254222 77 void callbackA()
Jonathan738 12:82b8fe254222 78 {
Jonathan738 0:3dfee562823a 79 ////////
Jonathan738 0:3dfee562823a 80 //insert the 'if X, carry out the rest of this code' debouncing check here, ensure the delay is minimal enough to avoid hindering 3576 measurements per rotation at max speed
Jonathan738 0:3dfee562823a 81 ////////
Jonathan738 12:82b8fe254222 82
Jonathan738 0:3dfee562823a 83 volatile int changeA = 0;
Jonathan738 0:3dfee562823a 84 channelAstate1 = encoderAchannel1.read();
Jonathan738 0:3dfee562823a 85 channelAstate2 = encoderAchannel2.read();
Jonathan738 0:3dfee562823a 86 currentStateA = (channelAstate1 << 1) | (channelAstate2);
Jonathan738 12:82b8fe254222 87
Jonathan738 0:3dfee562823a 88 if (((currentStateA ^ previousStateA) != INVALID) && (currentStateA != previousStateA)) {
Jonathan738 0:3dfee562823a 89 //2 bit state. Right hand bit of prev XOR left hand bit of current
Jonathan738 0:3dfee562823a 90 //gives 0 if clockwise rotation and 1 if counter clockwise rotation.
Jonathan738 0:3dfee562823a 91 changeA = (previousStateA & PREV_MASK) ^ ((currentStateA & CURR_MASK) >> 1);
Jonathan738 0:3dfee562823a 92 if (changeA == 0) {
Jonathan738 0:3dfee562823a 93 changeA = -1;
Jonathan738 0:3dfee562823a 94 }
Jonathan738 0:3dfee562823a 95 acurrent -= changeA;
Jonathan738 0:3dfee562823a 96 }
Jonathan738 0:3dfee562823a 97 previousStateA = currentStateA;
Jonathan738 0:3dfee562823a 98 //if the encoder signal is incremented or decremented to the target value, immediately hit the brakes for this wheel
Jonathan738 0:3dfee562823a 99 if(acurrent <= atarget + brakedist && acurrent >= atarget - brakedist) {
Jonathan738 0:3dfee562823a 100 A.stop(1);
Jonathan738 0:3dfee562823a 101 nextmoveflagA = 1;
Jonathan738 0:3dfee562823a 102 //amend the target of the wheels, to prevent buildup of error from stopping at target+-brakedist instead of exactly target
Jonathan738 0:3dfee562823a 103 atarget = acurrent;
Jonathan738 0:3dfee562823a 104 }
Jonathan738 0:3dfee562823a 105 }
Jonathan738 0:3dfee562823a 106
Jonathan738 12:82b8fe254222 107 void callbackB()
Jonathan738 12:82b8fe254222 108 {
Jonathan738 0:3dfee562823a 109 ////////
Jonathan738 0:3dfee562823a 110 //insert the 'if X, carry out the rest of this code' debouncing check here, ensure the delay is minimal enough to avoid hindering 3576 measurements per rotation at max speed
Jonathan738 0:3dfee562823a 111 ////////
Jonathan738 12:82b8fe254222 112
Jonathan738 0:3dfee562823a 113 //every time this function is called, increment or decrement the encoder count depending on which direction the relevant wheel is moving
Jonathan738 12:82b8fe254222 114
Jonathan738 0:3dfee562823a 115 volatile int changeB = 0;
Jonathan738 0:3dfee562823a 116 channelBstate1 = encoderBchannel1.read();
Jonathan738 0:3dfee562823a 117 channelBstate2 = encoderBchannel2.read();
Jonathan738 0:3dfee562823a 118 currentStateB = (channelBstate1 << 1) | (channelBstate2);
Jonathan738 12:82b8fe254222 119
Jonathan738 0:3dfee562823a 120 if (((currentStateB ^ previousStateB) != INVALID) && (currentStateB != previousStateB)) {
Jonathan738 0:3dfee562823a 121 //2 bit state. Right hand bit of prev XOR left hand bit of current
Jonathan738 0:3dfee562823a 122 //gives 0 if clockwise rotation and 1 if counter clockwise rotation.
Jonathan738 0:3dfee562823a 123 changeB = (previousStateB & PREV_MASK) ^ ((currentStateB & CURR_MASK) >> 1);
Jonathan738 0:3dfee562823a 124 if (changeB == 0) {
Jonathan738 0:3dfee562823a 125 changeB = -1;
Jonathan738 0:3dfee562823a 126 }
Jonathan738 0:3dfee562823a 127 bcurrent -= changeB;
Jonathan738 0:3dfee562823a 128 }
Jonathan738 0:3dfee562823a 129 previousStateB = currentStateB;
Jonathan738 0:3dfee562823a 130 //if the encoder signal is incremented or decremented to the target value, immediately hit the brakes for this wheel
Jonathan738 0:3dfee562823a 131 if(bcurrent <= btarget + brakedist && bcurrent >= btarget - brakedist) {
Jonathan738 0:3dfee562823a 132 B.stop(1);
Jonathan738 0:3dfee562823a 133 nextmoveflagB = 1;
Jonathan738 0:3dfee562823a 134 //amend the target of the wheels, to prevent buildup of error from stopping at target+-brakedist instead of exactly target
Jonathan738 0:3dfee562823a 135 btarget = bcurrent;
Jonathan738 0:3dfee562823a 136 }
Jonathan738 0:3dfee562823a 137 }
Jonathan738 0:3dfee562823a 138
Jonathan738 12:82b8fe254222 139 void move(const std_msgs::Int32& dinput)
Jonathan738 12:82b8fe254222 140 {
Jonathan738 0:3dfee562823a 141 if(nextmoveflagA == 1 && nextmoveflagB == 1) {
Jonathan738 0:3dfee562823a 142 //import the relevant ROS message and convert it to a usable encoder target
Jonathan738 0:3dfee562823a 143 float distance = dinput.data;
Jonathan738 0:3dfee562823a 144 float mtarget = distance/(2*3.142*radius)*benchmark;
Jonathan738 0:3dfee562823a 145 //set the encoder target as the interval for the wheels to move - must be an integer to match encoder readings
Jonathan738 0:3dfee562823a 146 atarget = ceil(mtarget + aprevtarget);
Jonathan738 0:3dfee562823a 147 btarget = ceil(mtarget + bprevtarget);
Jonathan738 0:3dfee562823a 148 //move the motors to their respective targets
Jonathan738 0:3dfee562823a 149 nextmoveflagA = 0;
Jonathan738 0:3dfee562823a 150 nextmoveflagB = 0;
Jonathan738 0:3dfee562823a 151 driveMotors();
Jonathan738 0:3dfee562823a 152 }
Jonathan738 0:3dfee562823a 153 }
Jonathan738 0:3dfee562823a 154
Jonathan738 12:82b8fe254222 155 void tempMove(float distance)
Jonathan738 12:82b8fe254222 156 {
Jonathan738 0:3dfee562823a 157 if(nextmoveflagA == 1 && nextmoveflagB == 1) {
Jonathan738 0:3dfee562823a 158 float mtarget = distance/(2*3.142*radius)*benchmark;
Jonathan738 0:3dfee562823a 159 atarget = ceil(mtarget + aprevtarget);
Jonathan738 0:3dfee562823a 160 btarget = ceil(mtarget + bprevtarget);
Jonathan738 0:3dfee562823a 161 pc.printf("Moving: A target is: %d B target is: %d M target is %f\n\r", atarget, btarget, mtarget);
Jonathan738 0:3dfee562823a 162 nextmoveflagA = 0;
Jonathan738 0:3dfee562823a 163 nextmoveflagB = 0;
Jonathan738 0:3dfee562823a 164 driveMotors();
Jonathan738 0:3dfee562823a 165 }
Jonathan738 0:3dfee562823a 166 }
Jonathan738 0:3dfee562823a 167
Jonathan738 12:82b8fe254222 168 void rotate(const std_msgs::Int32& rinput)
Jonathan738 12:82b8fe254222 169 {
Jonathan738 0:3dfee562823a 170 if(nextmoveflagA == 1 && nextmoveflagB == 1) {
Jonathan738 0:3dfee562823a 171 //import the relevant ROS message and convert it to usable encoder targets
Jonathan738 0:3dfee562823a 172 float degrees = rinput.data;
Jonathan738 0:3dfee562823a 173 float rtarget = (degrees/(360*3))*9.15*benchmark;
Jonathan738 0:3dfee562823a 174 //set the encoder targets as the intervals for the wheels to move - must be integers to match encoder readings
Jonathan738 0:3dfee562823a 175 atarget = ceil(rtarget + aprevtarget);
Jonathan738 0:3dfee562823a 176 btarget = ceil(-rtarget + bprevtarget);
Jonathan738 0:3dfee562823a 177 //move the motors to their respective targets
Jonathan738 0:3dfee562823a 178 nextmoveflagA = 0;
Jonathan738 0:3dfee562823a 179 nextmoveflagB = 0;
Jonathan738 0:3dfee562823a 180 driveMotors();
Jonathan738 0:3dfee562823a 181 }
Jonathan738 0:3dfee562823a 182 }
Jonathan738 0:3dfee562823a 183
Jonathan738 12:82b8fe254222 184 void tempRotate(float degrees)
Jonathan738 12:82b8fe254222 185 {
Jonathan738 0:3dfee562823a 186 if(nextmoveflagA == 1 && nextmoveflagB == 1) {
Jonathan738 0:3dfee562823a 187 float rtarget = (degrees/(360*3))*9.15*benchmark;
Jonathan738 0:3dfee562823a 188 atarget = ceil(rtarget + aprevtarget);
Jonathan738 0:3dfee562823a 189 btarget = ceil(-rtarget + bprevtarget);
Jonathan738 0:3dfee562823a 190 pc.printf("Rotating: A target is: %d B target is: %d R target is: %f\n\r", atarget, btarget, rtarget);
Jonathan738 0:3dfee562823a 191 nextmoveflagA = 0;
Jonathan738 0:3dfee562823a 192 nextmoveflagB = 0;
Jonathan738 0:3dfee562823a 193 driveMotors();
Jonathan738 0:3dfee562823a 194 }
Jonathan738 0:3dfee562823a 195 }
Jonathan738 0:3dfee562823a 196
Jonathan738 12:82b8fe254222 197 void driveMotors()
Jonathan738 12:82b8fe254222 198 {
Jonathan738 0:3dfee562823a 199 //depending on the direction the wheels have to move, set their pwms to either positive or negative so each motor moves correctly
Jonathan738 0:3dfee562823a 200 if(atarget > aprevtarget) {
Jonathan738 0:3dfee562823a 201 apwm = pwm;
Jonathan738 0:3dfee562823a 202 } else if(atarget < aprevtarget) {
Jonathan738 0:3dfee562823a 203 apwm = -pwm;
Jonathan738 0:3dfee562823a 204 } else if(atarget == aprevtarget) {
Jonathan738 0:3dfee562823a 205 apwm = 0;
Jonathan738 0:3dfee562823a 206 }
Jonathan738 0:3dfee562823a 207 if(btarget > bprevtarget) {
Jonathan738 0:3dfee562823a 208 bpwm = pwm;
Jonathan738 0:3dfee562823a 209 } else if(btarget < bprevtarget) {
Jonathan738 0:3dfee562823a 210 bpwm = -pwm;
Jonathan738 0:3dfee562823a 211 } else if(btarget == bprevtarget) {
Jonathan738 0:3dfee562823a 212 bpwm = 0;
Jonathan738 0:3dfee562823a 213 }
Jonathan738 0:3dfee562823a 214 //apply the pwm output to the motors
Jonathan738 0:3dfee562823a 215 pc.printf("Driving: A pwm is: %f B pwm is: %f\n\r", apwm, bpwm);
Jonathan738 0:3dfee562823a 216 A.speed(apwm);
Jonathan738 0:3dfee562823a 217 B.speed(bpwm);
Jonathan738 0:3dfee562823a 218 pc.printf("Driving: A target is: %d B target is: %d\n\r", atarget, btarget);
Jonathan738 0:3dfee562823a 219 pc.printf("Driving: A target was: %d B target was: %d\n\r", aprevtarget, bprevtarget);
firnenenrif 1:6a10e58b3d43 220 /**************************************************************************/
firnenenrif 1:6a10e58b3d43 221 //Note that this code prevents consecutive movement commands from being executed until the
firnenenrif 1:6a10e58b3d43 222 //previous one is done, but has the downside of keeping the thread busy during movement.
firnenenrif 1:6a10e58b3d43 223 //Feel free to replace it with a different method of waiting, if you want.
Jonathan738 0:3dfee562823a 224 while(nextmoveflagA == 0 || nextmoveflagB == 0) {
Jonathan738 0:3dfee562823a 225 wait_ms(500);
Jonathan738 0:3dfee562823a 226 }
firnenenrif 1:6a10e58b3d43 227 /**************************************************************************/
Jonathan738 0:3dfee562823a 228 //update the recordings of the previous command's movement targets
Jonathan738 0:3dfee562823a 229 aprevtarget = atarget;
Jonathan738 0:3dfee562823a 230 bprevtarget = btarget;
Jonathan738 3:7da9888ac8dc 231 }
Jonathan738 12:82b8fe254222 232