Lu-Hsuan Chen
/
autocar_3sensor_mbed
An auto car with 3 IR sensors.
autocar/autocar.cpp@15:1d440beb24d3, 2018-07-05 (annotated)
- Committer:
- cudaChen
- Date:
- Thu Jul 05 09:33:33 2018 +0000
- Revision:
- 15:1d440beb24d3
- Parent:
- 14:28cae134a304
- Child:
- 18:d7509436e9ef
[add] add statements which user can define the pins they want to use
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 | const int MOTOR_M1 = 0; |
cudaChen | 12:e95ed962be7a | 6 | const int MOTOR_M2 = 1; |
cudaChen | 12:e95ed962be7a | 7 | const int DIR_FORWARD = 0; |
cudaChen | 12:e95ed962be7a | 8 | const int DIR_BACKWARD = 1; |
cudaChen | 12:e95ed962be7a | 9 | const int PWR_STOP = 0; |
cudaChen | 12:e95ed962be7a | 10 | |
cudaChen | 12:e95ed962be7a | 11 | // used for IR sensors |
cudaChen | 13:87cd0ae37e06 | 12 | int left, middle, right; |
cudaChen | 13:87cd0ae37e06 | 13 | |
cudaChen | 13:87cd0ae37e06 | 14 | // PID factors |
cudaChen | 13:87cd0ae37e06 | 15 | int interror = 0; |
cudaChen | 13:87cd0ae37e06 | 16 | int olderror = 0; |
cudaChen | 15:1d440beb24d3 | 17 | int limit = 4095; // 12-bit ADC in STM32 |
cudaChen | 12:e95ed962be7a | 18 | |
cudaChen | 12:e95ed962be7a | 19 | // used for output message via serial |
cudaChen | 12:e95ed962be7a | 20 | Serial pc(SERIAL_TX, SERIAL_RX); |
cudaChen | 12:e95ed962be7a | 21 | |
cudaChen | 12:e95ed962be7a | 22 | long map(long x, long in_min, long in_max, long out_min, long out_max) |
cudaChen | 12:e95ed962be7a | 23 | { |
cudaChen | 12:e95ed962be7a | 24 | return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; |
cudaChen | 12:e95ed962be7a | 25 | } |
cudaChen | 12:e95ed962be7a | 26 | |
cudaChen | 12:e95ed962be7a | 27 | void readIR(bool* left, bool* middle, bool* right, int threshold) |
cudaChen | 12:e95ed962be7a | 28 | { |
cudaChen | 12:e95ed962be7a | 29 | // not on track: > 500 |
cudaChen | 12:e95ed962be7a | 30 | // on track (black): < 500 |
cudaChen | 12:e95ed962be7a | 31 | *left = leftIR.read_u16() < threshold ? true : false; |
cudaChen | 12:e95ed962be7a | 32 | *middle = middleIR.read_u16() < threshold ? true : false; |
cudaChen | 12:e95ed962be7a | 33 | *right = rightIR.read_u16() < threshold ? true : false; |
cudaChen | 12:e95ed962be7a | 34 | } |
cudaChen | 12:e95ed962be7a | 35 | |
cudaChen | 13:87cd0ae37e06 | 36 | int readIRValues() |
cudaChen | 13:87cd0ae37e06 | 37 | { |
cudaChen | 13:87cd0ae37e06 | 38 | left = leftIR.read_u16(); |
cudaChen | 13:87cd0ae37e06 | 39 | middle = middleIR.read_u16(); |
cudaChen | 13:87cd0ae37e06 | 40 | right = rightIR.read_u16(); |
cudaChen | 13:87cd0ae37e06 | 41 | |
cudaChen | 13:87cd0ae37e06 | 42 | int ret = left * (-1) + middle * 0 + right * 1; |
cudaChen | 13:87cd0ae37e06 | 43 | |
cudaChen | 14:28cae134a304 | 44 | pc.printf("left middle right: %d %d %d\r\n", left, middle, right); |
cudaChen | 13:87cd0ae37e06 | 45 | pc.printf("IR values: %d\r\n", ret); |
cudaChen | 13:87cd0ae37e06 | 46 | |
cudaChen | 13:87cd0ae37e06 | 47 | return ret; |
cudaChen | 13:87cd0ae37e06 | 48 | } |
cudaChen | 13:87cd0ae37e06 | 49 | |
cudaChen | 12:e95ed962be7a | 50 | // m: 0 => M1 1 => M2 |
cudaChen | 12:e95ed962be7a | 51 | // power 0~10 dir: 0=>正向 1=>反向 |
cudaChen | 12:e95ed962be7a | 52 | void DriveSingleMotor(int m, int speed, int dir) |
cudaChen | 12:e95ed962be7a | 53 | { |
cudaChen | 12:e95ed962be7a | 54 | /*int _speed = 0; |
cudaChen | 12:e95ed962be7a | 55 | |
cudaChen | 12:e95ed962be7a | 56 | // 設定速度 |
cudaChen | 12:e95ed962be7a | 57 | if (speed>10) speed=10; |
cudaChen | 12:e95ed962be7a | 58 | _speed = map(speed, 1, 10, 100, 255); |
cudaChen | 12:e95ed962be7a | 59 | |
cudaChen | 12:e95ed962be7a | 60 | if (speed<=0) { |
cudaChen | 12:e95ed962be7a | 61 | speed=0; |
cudaChen | 12:e95ed962be7a | 62 | _speed=0; |
cudaChen | 12:e95ed962be7a | 63 | } else |
cudaChen | 12:e95ed962be7a | 64 | _speed = map(speed, 1, 10, 100, 255);*/ |
cudaChen | 12:e95ed962be7a | 65 | |
cudaChen | 12:e95ed962be7a | 66 | if (m == MOTOR_M1) { |
cudaChen | 12:e95ed962be7a | 67 | // 設定方向 |
cudaChen | 12:e95ed962be7a | 68 | if (speed == PWR_STOP) { |
cudaChen | 12:e95ed962be7a | 69 | M1_in1 = 0; |
cudaChen | 12:e95ed962be7a | 70 | M1_in2 = 0; |
cudaChen | 12:e95ed962be7a | 71 | } else if (dir == DIR_FORWARD) { |
cudaChen | 12:e95ed962be7a | 72 | // right wheel go forward |
cudaChen | 12:e95ed962be7a | 73 | M1_in1 = 1; |
cudaChen | 12:e95ed962be7a | 74 | M1_in2 = 0; |
cudaChen | 12:e95ed962be7a | 75 | } else { |
cudaChen | 12:e95ed962be7a | 76 | // right wheel go backward |
cudaChen | 12:e95ed962be7a | 77 | M1_in1 = 0; |
cudaChen | 12:e95ed962be7a | 78 | M1_in2 = 1; |
cudaChen | 12:e95ed962be7a | 79 | } |
cudaChen | 12:e95ed962be7a | 80 | //M1_enable.write_u16(_speed); // 驅動馬達 右輪 |
cudaChen | 12:e95ed962be7a | 81 | M1_enable.write(1); |
cudaChen | 12:e95ed962be7a | 82 | |
cudaChen | 12:e95ed962be7a | 83 | } else if (m == MOTOR_M2) { |
cudaChen | 12:e95ed962be7a | 84 | // 設定方向 |
cudaChen | 12:e95ed962be7a | 85 | if (speed == PWR_STOP) { |
cudaChen | 12:e95ed962be7a | 86 | M2_in3 = 0; |
cudaChen | 12:e95ed962be7a | 87 | M2_in4 = 0; |
cudaChen | 12:e95ed962be7a | 88 | } else if (dir == DIR_FORWARD) { |
cudaChen | 12:e95ed962be7a | 89 | //左輪前進 |
cudaChen | 12:e95ed962be7a | 90 | M2_in3 = 1; |
cudaChen | 12:e95ed962be7a | 91 | M2_in4 = 0; |
cudaChen | 12:e95ed962be7a | 92 | } else { |
cudaChen | 12:e95ed962be7a | 93 | //左輪倒轉 |
cudaChen | 12:e95ed962be7a | 94 | M2_in3 = 0; |
cudaChen | 12:e95ed962be7a | 95 | M2_in4 = 1; |
cudaChen | 12:e95ed962be7a | 96 | } |
cudaChen | 12:e95ed962be7a | 97 | //M2_enable.write_u16(_speed); // 驅動馬達 左輪 |
cudaChen | 12:e95ed962be7a | 98 | M2_enable.write(1); |
cudaChen | 12:e95ed962be7a | 99 | } else { |
cudaChen | 12:e95ed962be7a | 100 | //M1_enable.write_u16(PWR_STOP); // right wheel |
cudaChen | 12:e95ed962be7a | 101 | //M2_enable.write_u16(PWR_STOP); // left wheel |
cudaChen | 12:e95ed962be7a | 102 | M1_enable.write(0); |
cudaChen | 12:e95ed962be7a | 103 | M2_enable.write(0); |
cudaChen | 12:e95ed962be7a | 104 | } |
cudaChen | 12:e95ed962be7a | 105 | } |
cudaChen | 12:e95ed962be7a | 106 | |
cudaChen | 12:e95ed962be7a | 107 | void driveMotor(bool left, bool middle, bool right) |
cudaChen | 12:e95ed962be7a | 108 | { |
cudaChen | 12:e95ed962be7a | 109 | int status = left * 4 + middle * 2 + right; |
cudaChen | 12:e95ed962be7a | 110 | switch(status) { |
cudaChen | 12:e95ed962be7a | 111 | case 7: // go straight |
cudaChen | 12:e95ed962be7a | 112 | pc.printf("7. go straight\r\n"); |
cudaChen | 12:e95ed962be7a | 113 | forward(); |
cudaChen | 12:e95ed962be7a | 114 | break; |
cudaChen | 12:e95ed962be7a | 115 | case 6: // turn left |
cudaChen | 12:e95ed962be7a | 116 | pc.printf("6. turn left\r\n"); |
cudaChen | 12:e95ed962be7a | 117 | turnLeft(); |
cudaChen | 12:e95ed962be7a | 118 | break; |
cudaChen | 12:e95ed962be7a | 119 | case 5: // go straight |
cudaChen | 12:e95ed962be7a | 120 | pc.printf("5. go straight\r\n"); |
cudaChen | 12:e95ed962be7a | 121 | forward(); |
cudaChen | 12:e95ed962be7a | 122 | break; |
cudaChen | 12:e95ed962be7a | 123 | case 4: // turn left |
cudaChen | 12:e95ed962be7a | 124 | pc.printf("4. turn left\r\n"); |
cudaChen | 12:e95ed962be7a | 125 | turnLeft(); |
cudaChen | 12:e95ed962be7a | 126 | break; |
cudaChen | 12:e95ed962be7a | 127 | case 3: // turn right |
cudaChen | 12:e95ed962be7a | 128 | pc.printf("3. turn right\r\n"); |
cudaChen | 12:e95ed962be7a | 129 | turnRight(); |
cudaChen | 12:e95ed962be7a | 130 | break; |
cudaChen | 12:e95ed962be7a | 131 | case 2: // go straight |
cudaChen | 12:e95ed962be7a | 132 | pc.printf("2. go straight\r\n"); |
cudaChen | 12:e95ed962be7a | 133 | forward(); |
cudaChen | 12:e95ed962be7a | 134 | break; |
cudaChen | 12:e95ed962be7a | 135 | case 1: // turn right |
cudaChen | 12:e95ed962be7a | 136 | pc.printf("1. turn right\r\n"); |
cudaChen | 12:e95ed962be7a | 137 | turnRight(); |
cudaChen | 12:e95ed962be7a | 138 | break; |
cudaChen | 12:e95ed962be7a | 139 | case 0: // go straight |
cudaChen | 12:e95ed962be7a | 140 | pc.printf("0. go straight\r\n"); |
cudaChen | 12:e95ed962be7a | 141 | forward(); |
cudaChen | 12:e95ed962be7a | 142 | break; |
cudaChen | 12:e95ed962be7a | 143 | default: |
cudaChen | 12:e95ed962be7a | 144 | pc.printf("invalid\r\n"); |
cudaChen | 12:e95ed962be7a | 145 | break; |
cudaChen | 12:e95ed962be7a | 146 | } |
cudaChen | 12:e95ed962be7a | 147 | } |
cudaChen | 12:e95ed962be7a | 148 | |
cudaChen | 13:87cd0ae37e06 | 149 | void driveMotorPID(int values, float Kp, float Ki, float Kd) |
cudaChen | 13:87cd0ae37e06 | 150 | { |
cudaChen | 13:87cd0ae37e06 | 151 | int error = values; // 'P' |
cudaChen | 13:87cd0ae37e06 | 152 | interror += error; |
cudaChen | 13:87cd0ae37e06 | 153 | int lasterror = error - olderror; |
cudaChen | 13:87cd0ae37e06 | 154 | olderror = error; // 注意olderror的順序 |
cudaChen | 13:87cd0ae37e06 | 155 | int power = error * Kp + interror * Ki + lasterror * Kd; |
cudaChen | 13:87cd0ae37e06 | 156 | /* error(P值)、interror(I值)、lasterror(D值)、olderror用來取D值的 */ |
cudaChen | 13:87cd0ae37e06 | 157 | |
cudaChen | 13:87cd0ae37e06 | 158 | // limit PID output value (for 12-bit ADC in STM32) |
cudaChen | 13:87cd0ae37e06 | 159 | if(power > limit) { |
cudaChen | 13:87cd0ae37e06 | 160 | power = limit; |
cudaChen | 13:87cd0ae37e06 | 161 | } else if(power < -limit) { |
cudaChen | 13:87cd0ae37e06 | 162 | power = -limit; |
cudaChen | 13:87cd0ae37e06 | 163 | } |
cudaChen | 13:87cd0ae37e06 | 164 | |
cudaChen | 13:87cd0ae37e06 | 165 | // control the direction of auto car |
cudaChen | 13:87cd0ae37e06 | 166 | if(power < -900) { |
cudaChen | 13:87cd0ae37e06 | 167 | turnLeft(); |
cudaChen | 13:87cd0ae37e06 | 168 | } else if (power > 900) { |
cudaChen | 13:87cd0ae37e06 | 169 | turnRight(); |
cudaChen | 13:87cd0ae37e06 | 170 | } else { |
cudaChen | 13:87cd0ae37e06 | 171 | forward(); |
cudaChen | 13:87cd0ae37e06 | 172 | } |
cudaChen | 13:87cd0ae37e06 | 173 | } |
cudaChen | 13:87cd0ae37e06 | 174 | |
cudaChen | 12:e95ed962be7a | 175 | void init() |
cudaChen | 12:e95ed962be7a | 176 | { |
cudaChen | 12:e95ed962be7a | 177 | DriveSingleMotor(MOTOR_M1, PWR_STOP, DIR_FORWARD); |
cudaChen | 12:e95ed962be7a | 178 | DriveSingleMotor(MOTOR_M2, PWR_STOP, DIR_FORWARD); |
cudaChen | 12:e95ed962be7a | 179 | } |
cudaChen | 12:e95ed962be7a | 180 | |
cudaChen | 12:e95ed962be7a | 181 | void forward() |
cudaChen | 12:e95ed962be7a | 182 | { |
cudaChen | 12:e95ed962be7a | 183 | DriveSingleMotor(MOTOR_M1, 2, DIR_FORWARD); |
cudaChen | 12:e95ed962be7a | 184 | DriveSingleMotor(MOTOR_M2, 2, DIR_FORWARD); |
cudaChen | 12:e95ed962be7a | 185 | } |
cudaChen | 12:e95ed962be7a | 186 | |
cudaChen | 12:e95ed962be7a | 187 | void turnLeft() |
cudaChen | 12:e95ed962be7a | 188 | { |
cudaChen | 12:e95ed962be7a | 189 | DriveSingleMotor(MOTOR_M1, PWR_STOP, DIR_FORWARD); |
cudaChen | 12:e95ed962be7a | 190 | DriveSingleMotor(MOTOR_M2, 2, DIR_FORWARD); |
cudaChen | 12:e95ed962be7a | 191 | } |
cudaChen | 12:e95ed962be7a | 192 | |
cudaChen | 12:e95ed962be7a | 193 | void turnRight() |
cudaChen | 12:e95ed962be7a | 194 | { |
cudaChen | 12:e95ed962be7a | 195 | DriveSingleMotor(MOTOR_M1, 2, DIR_FORWARD); |
cudaChen | 12:e95ed962be7a | 196 | DriveSingleMotor(MOTOR_M2, PWR_STOP, DIR_FORWARD); |
cudaChen | 12:e95ed962be7a | 197 | } |