Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
autocar/autocar.cpp@13:87cd0ae37e06, 2018-07-01 (annotated)
- Committer:
- cudaChen
- Date:
- Sun Jul 01 07:58:20 2018 +0000
- Revision:
- 13:87cd0ae37e06
- Parent:
- 12:e95ed962be7a
- Child:
- 14:28cae134a304
[add] create PID control feature (unfinished)
Who changed what in which revision?
| User | Revision | Line number | New contents of line | 
|---|---|---|---|
| cudaChen | 12:e95ed962be7a | 1 | #include "mbed.h" | 
| cudaChen | 12:e95ed962be7a | 2 | |
| cudaChen | 12:e95ed962be7a | 3 | #include "autocar.h" | 
| cudaChen | 12:e95ed962be7a | 4 | |
| cudaChen | 12:e95ed962be7a | 5 | DigitalOut M1_enable(D6); | 
| cudaChen | 12:e95ed962be7a | 6 | DigitalOut M2_enable(D5); | 
| cudaChen | 12:e95ed962be7a | 7 | DigitalOut M1_in1(D3); | 
| cudaChen | 12:e95ed962be7a | 8 | DigitalOut M1_in2(D2); | 
| cudaChen | 12:e95ed962be7a | 9 | DigitalOut M2_in3(D1); | 
| cudaChen | 12:e95ed962be7a | 10 | DigitalOut M2_in4(D0); | 
| cudaChen | 12:e95ed962be7a | 11 | const int MOTOR_M1 = 0; | 
| cudaChen | 12:e95ed962be7a | 12 | const int MOTOR_M2 = 1; | 
| cudaChen | 12:e95ed962be7a | 13 | const int DIR_FORWARD = 0; | 
| cudaChen | 12:e95ed962be7a | 14 | const int DIR_BACKWARD = 1; | 
| cudaChen | 12:e95ed962be7a | 15 | const int PWR_STOP = 0; | 
| cudaChen | 12:e95ed962be7a | 16 | |
| cudaChen | 12:e95ed962be7a | 17 | // used for IR sensors | 
| cudaChen | 12:e95ed962be7a | 18 | AnalogIn leftIR(A1); | 
| cudaChen | 12:e95ed962be7a | 19 | AnalogIn middleIR(A3); | 
| cudaChen | 12:e95ed962be7a | 20 | AnalogIn rightIR(A5); | 
| cudaChen | 13:87cd0ae37e06 | 21 | int left, middle, right; | 
| cudaChen | 13:87cd0ae37e06 | 22 | |
| cudaChen | 13:87cd0ae37e06 | 23 | // PID factors | 
| cudaChen | 13:87cd0ae37e06 | 24 | int interror = 0; | 
| cudaChen | 13:87cd0ae37e06 | 25 | int olderror = 0; | 
| cudaChen | 13:87cd0ae37e06 | 26 | int limit = 4096; // 12-bit ADC in STM32 | 
| cudaChen | 12:e95ed962be7a | 27 | |
| cudaChen | 12:e95ed962be7a | 28 | // used for output message via serial | 
| cudaChen | 12:e95ed962be7a | 29 | Serial pc(SERIAL_TX, SERIAL_RX); | 
| cudaChen | 12:e95ed962be7a | 30 | |
| cudaChen | 12:e95ed962be7a | 31 | long map(long x, long in_min, long in_max, long out_min, long out_max) | 
| cudaChen | 12:e95ed962be7a | 32 | { | 
| cudaChen | 12:e95ed962be7a | 33 | return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; | 
| cudaChen | 12:e95ed962be7a | 34 | } | 
| cudaChen | 12:e95ed962be7a | 35 | |
| cudaChen | 12:e95ed962be7a | 36 | void readIR(bool* left, bool* middle, bool* right, int threshold) | 
| cudaChen | 12:e95ed962be7a | 37 | { | 
| cudaChen | 12:e95ed962be7a | 38 | // not on track: > 500 | 
| cudaChen | 12:e95ed962be7a | 39 | // on track (black): < 500 | 
| cudaChen | 12:e95ed962be7a | 40 | *left = leftIR.read_u16() < threshold ? true : false; | 
| cudaChen | 12:e95ed962be7a | 41 | *middle = middleIR.read_u16() < threshold ? true : false; | 
| cudaChen | 12:e95ed962be7a | 42 | *right = rightIR.read_u16() < threshold ? true : false; | 
| cudaChen | 12:e95ed962be7a | 43 | } | 
| cudaChen | 12:e95ed962be7a | 44 | |
| cudaChen | 13:87cd0ae37e06 | 45 | int readIRValues() | 
| cudaChen | 13:87cd0ae37e06 | 46 | { | 
| cudaChen | 13:87cd0ae37e06 | 47 | left = leftIR.read_u16(); | 
| cudaChen | 13:87cd0ae37e06 | 48 | middle = middleIR.read_u16(); | 
| cudaChen | 13:87cd0ae37e06 | 49 | right = rightIR.read_u16(); | 
| cudaChen | 13:87cd0ae37e06 | 50 | |
| cudaChen | 13:87cd0ae37e06 | 51 | int ret = left * (-1) + middle * 0 + right * 1; | 
| cudaChen | 13:87cd0ae37e06 | 52 | |
| cudaChen | 13:87cd0ae37e06 | 53 | pc.printf("IR values: %d\r\n", ret); | 
| cudaChen | 13:87cd0ae37e06 | 54 | |
| cudaChen | 13:87cd0ae37e06 | 55 | return ret; | 
| cudaChen | 13:87cd0ae37e06 | 56 | } | 
| cudaChen | 13:87cd0ae37e06 | 57 | |
| cudaChen | 12:e95ed962be7a | 58 | // m: 0 => M1 1 => M2 | 
| cudaChen | 12:e95ed962be7a | 59 | // power 0~10 dir: 0=>正向 1=>反向 | 
| cudaChen | 12:e95ed962be7a | 60 | void DriveSingleMotor(int m, int speed, int dir) | 
| cudaChen | 12:e95ed962be7a | 61 | { | 
| cudaChen | 12:e95ed962be7a | 62 | /*int _speed = 0; | 
| cudaChen | 12:e95ed962be7a | 63 | |
| cudaChen | 12:e95ed962be7a | 64 | // 設定速度 | 
| cudaChen | 12:e95ed962be7a | 65 | if (speed>10) speed=10; | 
| cudaChen | 12:e95ed962be7a | 66 | _speed = map(speed, 1, 10, 100, 255); | 
| cudaChen | 12:e95ed962be7a | 67 | |
| cudaChen | 12:e95ed962be7a | 68 | if (speed<=0) { | 
| cudaChen | 12:e95ed962be7a | 69 | speed=0; | 
| cudaChen | 12:e95ed962be7a | 70 | _speed=0; | 
| cudaChen | 12:e95ed962be7a | 71 | } else | 
| cudaChen | 12:e95ed962be7a | 72 | _speed = map(speed, 1, 10, 100, 255);*/ | 
| cudaChen | 12:e95ed962be7a | 73 | |
| cudaChen | 12:e95ed962be7a | 74 | if (m == MOTOR_M1) { | 
| cudaChen | 12:e95ed962be7a | 75 | // 設定方向 | 
| cudaChen | 12:e95ed962be7a | 76 | if (speed == PWR_STOP) { | 
| cudaChen | 12:e95ed962be7a | 77 | M1_in1 = 0; | 
| cudaChen | 12:e95ed962be7a | 78 | M1_in2 = 0; | 
| cudaChen | 12:e95ed962be7a | 79 | } else if (dir == DIR_FORWARD) { | 
| cudaChen | 12:e95ed962be7a | 80 | // right wheel go forward | 
| cudaChen | 12:e95ed962be7a | 81 | M1_in1 = 1; | 
| cudaChen | 12:e95ed962be7a | 82 | M1_in2 = 0; | 
| cudaChen | 12:e95ed962be7a | 83 | } else { | 
| cudaChen | 12:e95ed962be7a | 84 | // right wheel go backward | 
| cudaChen | 12:e95ed962be7a | 85 | M1_in1 = 0; | 
| cudaChen | 12:e95ed962be7a | 86 | M1_in2 = 1; | 
| cudaChen | 12:e95ed962be7a | 87 | } | 
| cudaChen | 12:e95ed962be7a | 88 | //M1_enable.write_u16(_speed); // 驅動馬達 右輪 | 
| cudaChen | 12:e95ed962be7a | 89 | M1_enable.write(1); | 
| cudaChen | 12:e95ed962be7a | 90 | |
| cudaChen | 12:e95ed962be7a | 91 | } else if (m == MOTOR_M2) { | 
| cudaChen | 12:e95ed962be7a | 92 | // 設定方向 | 
| cudaChen | 12:e95ed962be7a | 93 | if (speed == PWR_STOP) { | 
| cudaChen | 12:e95ed962be7a | 94 | M2_in3 = 0; | 
| cudaChen | 12:e95ed962be7a | 95 | M2_in4 = 0; | 
| cudaChen | 12:e95ed962be7a | 96 | } else if (dir == DIR_FORWARD) { | 
| cudaChen | 12:e95ed962be7a | 97 | //左輪前進 | 
| cudaChen | 12:e95ed962be7a | 98 | M2_in3 = 1; | 
| cudaChen | 12:e95ed962be7a | 99 | M2_in4 = 0; | 
| cudaChen | 12:e95ed962be7a | 100 | } else { | 
| cudaChen | 12:e95ed962be7a | 101 | //左輪倒轉 | 
| cudaChen | 12:e95ed962be7a | 102 | M2_in3 = 0; | 
| cudaChen | 12:e95ed962be7a | 103 | M2_in4 = 1; | 
| cudaChen | 12:e95ed962be7a | 104 | } | 
| cudaChen | 12:e95ed962be7a | 105 | //M2_enable.write_u16(_speed); // 驅動馬達 左輪 | 
| cudaChen | 12:e95ed962be7a | 106 | M2_enable.write(1); | 
| cudaChen | 12:e95ed962be7a | 107 | } else { | 
| cudaChen | 12:e95ed962be7a | 108 | //M1_enable.write_u16(PWR_STOP); // right wheel | 
| cudaChen | 12:e95ed962be7a | 109 | //M2_enable.write_u16(PWR_STOP); // left wheel | 
| cudaChen | 12:e95ed962be7a | 110 | M1_enable.write(0); | 
| cudaChen | 12:e95ed962be7a | 111 | M2_enable.write(0); | 
| cudaChen | 12:e95ed962be7a | 112 | } | 
| cudaChen | 12:e95ed962be7a | 113 | } | 
| cudaChen | 12:e95ed962be7a | 114 | |
| cudaChen | 12:e95ed962be7a | 115 | void driveMotor(bool left, bool middle, bool right) | 
| cudaChen | 12:e95ed962be7a | 116 | { | 
| cudaChen | 12:e95ed962be7a | 117 | int status = left * 4 + middle * 2 + right; | 
| cudaChen | 12:e95ed962be7a | 118 | switch(status) { | 
| cudaChen | 12:e95ed962be7a | 119 | case 7: // go straight | 
| cudaChen | 12:e95ed962be7a | 120 | pc.printf("7. go straight\r\n"); | 
| cudaChen | 12:e95ed962be7a | 121 | forward(); | 
| cudaChen | 12:e95ed962be7a | 122 | break; | 
| cudaChen | 12:e95ed962be7a | 123 | case 6: // turn left | 
| cudaChen | 12:e95ed962be7a | 124 | pc.printf("6. turn left\r\n"); | 
| cudaChen | 12:e95ed962be7a | 125 | turnLeft(); | 
| cudaChen | 12:e95ed962be7a | 126 | break; | 
| cudaChen | 12:e95ed962be7a | 127 | case 5: // go straight | 
| cudaChen | 12:e95ed962be7a | 128 | pc.printf("5. go straight\r\n"); | 
| cudaChen | 12:e95ed962be7a | 129 | forward(); | 
| cudaChen | 12:e95ed962be7a | 130 | break; | 
| cudaChen | 12:e95ed962be7a | 131 | case 4: // turn left | 
| cudaChen | 12:e95ed962be7a | 132 | pc.printf("4. turn left\r\n"); | 
| cudaChen | 12:e95ed962be7a | 133 | turnLeft(); | 
| cudaChen | 12:e95ed962be7a | 134 | break; | 
| cudaChen | 12:e95ed962be7a | 135 | case 3: // turn right | 
| cudaChen | 12:e95ed962be7a | 136 | pc.printf("3. turn right\r\n"); | 
| cudaChen | 12:e95ed962be7a | 137 | turnRight(); | 
| cudaChen | 12:e95ed962be7a | 138 | break; | 
| cudaChen | 12:e95ed962be7a | 139 | case 2: // go straight | 
| cudaChen | 12:e95ed962be7a | 140 | pc.printf("2. go straight\r\n"); | 
| cudaChen | 12:e95ed962be7a | 141 | forward(); | 
| cudaChen | 12:e95ed962be7a | 142 | break; | 
| cudaChen | 12:e95ed962be7a | 143 | case 1: // turn right | 
| cudaChen | 12:e95ed962be7a | 144 | pc.printf("1. turn right\r\n"); | 
| cudaChen | 12:e95ed962be7a | 145 | turnRight(); | 
| cudaChen | 12:e95ed962be7a | 146 | break; | 
| cudaChen | 12:e95ed962be7a | 147 | case 0: // go straight | 
| cudaChen | 12:e95ed962be7a | 148 | pc.printf("0. go straight\r\n"); | 
| cudaChen | 12:e95ed962be7a | 149 | forward(); | 
| cudaChen | 12:e95ed962be7a | 150 | break; | 
| cudaChen | 12:e95ed962be7a | 151 | default: | 
| cudaChen | 12:e95ed962be7a | 152 | pc.printf("invalid\r\n"); | 
| cudaChen | 12:e95ed962be7a | 153 | break; | 
| cudaChen | 12:e95ed962be7a | 154 | } | 
| cudaChen | 12:e95ed962be7a | 155 | } | 
| cudaChen | 12:e95ed962be7a | 156 | |
| cudaChen | 13:87cd0ae37e06 | 157 | void driveMotorPID(int values, float Kp, float Ki, float Kd) | 
| cudaChen | 13:87cd0ae37e06 | 158 | { | 
| cudaChen | 13:87cd0ae37e06 | 159 | int error = values; // 'P' | 
| cudaChen | 13:87cd0ae37e06 | 160 | interror += error; | 
| cudaChen | 13:87cd0ae37e06 | 161 | int lasterror = error - olderror; | 
| cudaChen | 13:87cd0ae37e06 | 162 | olderror = error; // 注意olderror的順序 | 
| cudaChen | 13:87cd0ae37e06 | 163 | int power = error * Kp + interror * Ki + lasterror * Kd; | 
| cudaChen | 13:87cd0ae37e06 | 164 | /* error(P值)、interror(I值)、lasterror(D值)、olderror用來取D值的 */ | 
| cudaChen | 13:87cd0ae37e06 | 165 | |
| cudaChen | 13:87cd0ae37e06 | 166 | // limit PID output value (for 12-bit ADC in STM32) | 
| cudaChen | 13:87cd0ae37e06 | 167 | if(power > limit) { | 
| cudaChen | 13:87cd0ae37e06 | 168 | power = limit; | 
| cudaChen | 13:87cd0ae37e06 | 169 | } else if(power < -limit) { | 
| cudaChen | 13:87cd0ae37e06 | 170 | power = -limit; | 
| cudaChen | 13:87cd0ae37e06 | 171 | } | 
| cudaChen | 13:87cd0ae37e06 | 172 | |
| cudaChen | 13:87cd0ae37e06 | 173 | // control the direction of auto car | 
| cudaChen | 13:87cd0ae37e06 | 174 | if(power < -900) { | 
| cudaChen | 13:87cd0ae37e06 | 175 | turnLeft(); | 
| cudaChen | 13:87cd0ae37e06 | 176 | } else if (power > 900) { | 
| cudaChen | 13:87cd0ae37e06 | 177 | turnRight(); | 
| cudaChen | 13:87cd0ae37e06 | 178 | } else { | 
| cudaChen | 13:87cd0ae37e06 | 179 | forward(); | 
| cudaChen | 13:87cd0ae37e06 | 180 | } | 
| cudaChen | 13:87cd0ae37e06 | 181 | } | 
| cudaChen | 13:87cd0ae37e06 | 182 | |
| cudaChen | 12:e95ed962be7a | 183 | void init() | 
| cudaChen | 12:e95ed962be7a | 184 | { | 
| cudaChen | 12:e95ed962be7a | 185 | DriveSingleMotor(MOTOR_M1, PWR_STOP, DIR_FORWARD); | 
| cudaChen | 12:e95ed962be7a | 186 | DriveSingleMotor(MOTOR_M2, PWR_STOP, DIR_FORWARD); | 
| cudaChen | 12:e95ed962be7a | 187 | } | 
| cudaChen | 12:e95ed962be7a | 188 | |
| cudaChen | 12:e95ed962be7a | 189 | void forward() | 
| cudaChen | 12:e95ed962be7a | 190 | { | 
| cudaChen | 12:e95ed962be7a | 191 | DriveSingleMotor(MOTOR_M1, 2, DIR_FORWARD); | 
| cudaChen | 12:e95ed962be7a | 192 | DriveSingleMotor(MOTOR_M2, 2, DIR_FORWARD); | 
| cudaChen | 12:e95ed962be7a | 193 | } | 
| cudaChen | 12:e95ed962be7a | 194 | |
| cudaChen | 12:e95ed962be7a | 195 | void turnLeft() | 
| cudaChen | 12:e95ed962be7a | 196 | { | 
| cudaChen | 12:e95ed962be7a | 197 | DriveSingleMotor(MOTOR_M1, PWR_STOP, DIR_FORWARD); | 
| cudaChen | 12:e95ed962be7a | 198 | DriveSingleMotor(MOTOR_M2, 2, DIR_FORWARD); | 
| cudaChen | 12:e95ed962be7a | 199 | } | 
| cudaChen | 12:e95ed962be7a | 200 | |
| cudaChen | 12:e95ed962be7a | 201 | void turnRight() | 
| cudaChen | 12:e95ed962be7a | 202 | { | 
| cudaChen | 12:e95ed962be7a | 203 | DriveSingleMotor(MOTOR_M1, 2, DIR_FORWARD); | 
| cudaChen | 12:e95ed962be7a | 204 | DriveSingleMotor(MOTOR_M2, PWR_STOP, DIR_FORWARD); | 
| cudaChen | 12:e95ed962be7a | 205 | } |