One big fixed period control loop
Dependencies: FastAnalogIn MODSERIAL PID QEI RPCInterface Servo mbed-rtos mbed telemetry PinDetect
Fork of Everything by
Diff: main.cpp
- Revision:
- 17:bf6192a361ab
- Parent:
- 16:3ab3c4670f4f
--- a/main.cpp Tue Apr 12 02:03:50 2016 +0000 +++ b/main.cpp Thu Apr 14 00:45:14 2016 +0000 @@ -11,6 +11,8 @@ // ========= // Telemetry // ========= +//DigitalOut test(PTD1); + MODSERIAL telemetry_serial(PTC4, PTC3); // TX, RX //MODSERIAL telemetry_serial(USBTX, USBRX); telemetry::MbedHal telemetry_hal(telemetry_serial); // Hardware Abstraction Layer @@ -26,9 +28,11 @@ Timer t; Timer t_tele; Ticker control_interrupt; -int t_cam = 0; +int t_cam1 = 0; +int t_cam2 = 0; int t_steer = 0; int t_vel = 0; +int t_down = 0; float interrupt_T = 0.015; bool ctrl_flag = false; @@ -37,15 +41,12 @@ // Communication // ============= char comm_cmd; // Command -char comm_in[8]; // Input +char comm_in[5]; // Input Serial bt(USBTX, USBRX); // USB connection //Serial bt(PTC4, PTC3); // BlueSMiRF connection void communication(void const *args); // Communications -//void Kmill(Arguments *input, Reply *output); -//RPCFunction rpc_Kmill(&Kmill, "Kmill"); - // ===== // Motor // ===== @@ -60,6 +61,7 @@ const int ppr = 389; // Pulses per revolution const float c = 0.20106; // Wheel circumference int prev_pulses = 0; // Previous pulse count +int prev_pulse_counts[5] = {0}; int curr_pulses = 0; // Current pulse count float velocity = 0; // Velocity QEI qei(PTD3, PTD2, NC, ppr, QEI::X4_ENCODING); // Quadrature encoder @@ -67,19 +69,19 @@ // ======== // Velocity // ======== -float Kmp = 8.0; // Proportional factor -float Kmi = 0; // Integral factor -float Kmd = 0; // Derivative factor -float motor_interval = 0.01; // Sampling interval -float prev_vels[10]; -float ref_v = 0.8; // Reference velocity -PID motor_ctrl(Kmp, Kmi, Kmd, interrupt_T); // Motor controller +float Kmp = 36.0; // Proportional factor +float Kmi = 1; // Integral factor +float Kmd = 0; // Derivative factor +float interval = 0.01; // Sampling interval +float ref_v = 0.5; // Reference velocity +int vel_count = 1; +PID motor_ctrl(Kmp, Kmi, Kmd, interrupt_T); // Motor controller // ===== // Servo // ===== float angle = 88; // Angle -float Ksp = 1.0; // Steering proportion +float Ksp = 1; // Steering proportion float Ksi = 0; float Ksd = 0; PID servo_ctrl(Ksp, Ksi, Ksd, interrupt_T); @@ -89,7 +91,7 @@ // Camera // ====== int t_int = 10000; // Exposure time -const int T_INT_MAX = interrupt_T * 1000000 - 1000; // Maximum exposure time +const int T_INT_MAX = interrupt_T * 1000000 - 2000; // Maximum exposure time const int T_INT_MIN = 35; // Minimum exposure time int img[108] = {0}; // Image data DigitalOut clk(PTD5); // Clock pin @@ -113,19 +115,18 @@ // Functions // ================ - -void Kmillswitch(MODSERIAL_IRQ_INFO *q) { +void killswitch(MODSERIAL_IRQ_INFO *q) { MODSERIAL *serial = q->serial; if (serial->rxGetLastChar() == 'k') { e_stop = true; motor = 1.0; } if (serial->rxGetLastChar() == '+') { - ref_v = ref_v + 0.05; + ref_v = ref_v + 0.2; motor_ctrl.setSetPoint(ref_v); } if (serial->rxGetLastChar() == '-') { - ref_v = ref_v - 0.05; + ref_v = ref_v - 0.2; motor_ctrl.setSetPoint(ref_v); } } @@ -133,7 +134,7 @@ // Communications //void communication(void const *args) { // telemetry_serial.baud(115200); -// telemetry_serial.attach(&Kmillswitch, MODSERIAL::RxIrq); +// telemetry_serial.attach(&killswitch, MODSERIAL::RxIrq); // telemetry_obj.transmit_header(); // while (true) { // tele_time_ms = t_tele.read_ms(); @@ -156,9 +157,7 @@ bt.printf(" [5] Change Ksp\r\n"); bt.printf(" [6] Change reference velocity\r\n"); bt.printf(" [7] EMERGENCY STOP\r\n"); -// bt.printf(" [8] Timing\r\n"); - bt.printf(" [8] duty += 0.05\r\n"); - bt.printf(" [9] duty -= 0.05\r\n"); + bt.printf(" [8] Timing\r\n"); comm_cmd = bt.getc(); while (comm_cmd != 'q') { switch(atoi(&comm_cmd)){ @@ -169,8 +168,8 @@ bt.printf("Servo angle: %f, Track center: %d, t_int: %d\r\n", angle, center, t_int); break; case 2: - bt.printf("Current: %f, New (8 digits): ", Kmp); - for (int i = 0; i < 8; i++) { + bt.printf("Current: %f, New (5 digits): ", Kmp); + for (int i = 0; i < 5; i++) { comm_in[i] = bt.getc(); bt.putc(comm_in[i]); } @@ -180,8 +179,8 @@ comm_cmd = 'q'; break; case 3: - bt.printf("Current: %f, New (8 digits): ", Kmi); - for (int i = 0; i < 8; i++) { + bt.printf("Current: %f, New (5 digits): ", Kmi); + for (int i = 0; i < 5; i++) { comm_in[i] = bt.getc(); bt.putc(comm_in[i]); } @@ -191,8 +190,8 @@ comm_cmd = 'q'; break; case 4: - bt.printf("Current: %f, New (8 digits): ", Kmd); - for (int i = 0; i < 8; i++) { + bt.printf("Current: %f, New (5 digits): ", Kmd); + for (int i = 0; i < 5; i++) { comm_in[i] = bt.getc(); bt.putc(comm_in[i]); } @@ -202,8 +201,8 @@ comm_cmd = 'q'; break; case 5: - bt.printf("Current: %f, New (8 digits): ", Ksp); - for (int i = 0; i < 8; i++) { + bt.printf("Current: %f, New (5 digits): ", Ksp); + for (int i = 0; i < 5; i++) { comm_in[i] = bt.getc(); bt.putc(comm_in[i]); } @@ -212,8 +211,8 @@ comm_cmd = 'q'; break; case 6: - bt.printf("Current: %f, New (8 digits): ", ref_v); - for (int i = 0; i < 8; i++) { + bt.printf("Current: %f, New (5 digits): ", ref_v); + for (int i = 0; i < 5; i++) { comm_in[i] = bt.getc(); bt.putc(comm_in[i]); } @@ -223,25 +222,12 @@ comm_cmd = 'q'; break; case 7: -// e_stop = true; - motor = 1.0; + e_stop = true; bt.printf("STOPPED\r\n"); comm_cmd = 'q'; break; -// case 8: -// bt.printf("Exposure: %dus, Camera Read: %dus, Steering: %dus, Velocity: %dus, Total: %dus\r\n", t_int, t_cam-t_int, t_steer, t_vel, t_cam+t_steer+t_vel); -// break; case 8: - motor_duty = motor_duty + 0.05; - motor = 1.0 - motor_duty; - bt.printf("%f\r\n", motor_duty); - comm_cmd = 'q'; - break; - case 9: - motor_duty = motor_duty - 0.05; - motor = 1.0 - motor_duty; - bt.printf("%f\r\n", motor_duty); - comm_cmd = 'q'; + bt.printf("Read 1: %dus, Exposure: %dus, Read 2: %dus, Steering: %dus, Velocity: %dus, Down: %dus, Total: %dus\r\n", t_cam1, t_int, t_cam2, t_steer, t_vel, t_down, t_cam1+t_int+t_cam2+t_steer+t_vel+t_down); break; } if (bt.readable()) { @@ -253,7 +239,8 @@ void control() { // Image capture - // t.reset(); + t_down = t.read_us(); + t.reset(); // Dummy read PTD->PCOR = (0x01 << 5); @@ -265,6 +252,7 @@ PTD->PCOR = (0x01 << 5); PTD->PSOR = (0x01 << 5); } + t_cam1 = t.read_us(); // Expose wait_us(t_int); @@ -275,6 +263,7 @@ PTD->PSOR = (0x01 << 5); PTD->PCOR = (0x01); + t.reset(); for (int i = 0; i < 128; i++) { PTD->PCOR = (0x01 << 5); if (i > 9 && i < 118) { @@ -284,58 +273,66 @@ PTD->PSOR = (0x01 << 5); } - // t_cam = t.read_us(); + t_cam2 = t.read_us(); // Steering control - // t.reset(); + t.reset(); // Detect peak edges j = 0; for (int i = 0; i < 108 && j < 5; i++) { - if (img[i] > 45000) { + if (img[i] > max * 0.65) { left[j] = i; - while (img[i] > 45000 && i < 108) { - i = i + 1; + while (img[i] > max * 0.65) { + if (i < 107) { + i = i + 1; + } else { + j = j - 1; + break; + } } - right[j] = i; + if (i < 107) { + right[j] = i; + } j = j + 1; } } - // Calculate peak centers - for (int i = 0; i < j; i++) { - centers[i] = (left[i] + right[i] + 20) / 2; - } - // Assign scores - for (int i = 0; i < j; i++) { - scores[i] = 8 / (right[i] - left[i]) + img[centers[i]] / 65536 + 5 / abs(centers[i] - prev_center); - } - - // Choose most likely center - best_score_idx = 0; - for (int i = 0; i < j; i++) { - if (scores[i] > scores[best_score_idx]) { - best_score_idx = i; + if (j > 0) { + // Calculate peak centers + for (int i = 0; i < j; i++) { + centers[i] = (left[i] + right[i] + 20) / 2; + } + + // Assign scores + for (int i = 0; i < j; i++) { + scores[i] = 4 / (right[i] - left[i]) + img[centers[i]] / 65536 + 16 / abs(centers[i] - prev_center); } + + // Choose most likely center + best_score_idx = 0; + for (int i = 0; i < j; i++) { + if (scores[i] > scores[best_score_idx]) { + best_score_idx = i; + } + } + prev_center = center; + center = centers[best_score_idx]; + tele_center = center; + + angle = 88 + (64 - center) * 0.9; + if (angle > 113) { + angle = 113; + } + if (angle < 63) { + angle = 63; + } + // servo_ctrl.setProcessValue(center); + // angle = 88 + servo_ctrl.compute(); + // servo = floor(angle / 180 * 100 + 0.5) / 100; + servo = angle / 180; } - prev_center = center; - center = centers[best_score_idx]; - tele_center = center; - - // Set servo angle - // angle = 88 + (55 - center) * Ksp; - // if (angle > 113) { - // angle = 113; - // } - // if (angle < 63) { - // angle = 63; - // } - // servo = angle / 180; - - servo_ctrl.setProcessValue(center); - angle = 88 + servo_ctrl.compute(); - servo = angle / 180; // AGC max = -1; @@ -358,49 +355,43 @@ } tele_exposure = t_int; - // t_steer = t.read_us(); + t_steer = t.read_us(); + + // wait_us(8000 - t.read_us()); + + -// // Velocity control -// // t.reset(); -// if (!e_stop) { -// curr_pulses = qei.getPulses(); -// //for (int i = 0; i < 9; i++) { -//// prev_vels[i] = prev_vels[i+1]; -//// } -//// prev_vels[9] = (curr_pulses - prev_pulses) / t.read() / ppr * c; -//// t.reset(); -//// if (prev_vels[9] < 0) { -//// prev_vels[9] = 0; -//// } -//// if (prev_vels[0] < 0) { -//// velocity = prev_vels[9]; -//// } else { -//// velocity = 0; -//// for (int i = 0; i < 10; i++) { -//// velocity = velocity + prev_vels[i]; -//// velocity = velocity / 10; -//// } -//// } -// velocity = (curr_pulses - prev_pulses) / interrupt_T / ppr * c; -// if (velocity < 0) { -// velocity = 0; -// } -//// velocity = (curr_pulses - prev_pulses) / t.read() / ppr * c; -// t.reset(); -// tele_velocity = velocity; -// prev_pulses = curr_pulses; -// motor_ctrl.setProcessValue(velocity); -// motor_duty = motor_ctrl.compute(); -// motor = 1.0 - motor_duty; -// tele_pwm = motor_duty; -// } else { -// motor = 1.0; -// } -// // t_vel = t.read_us(); -// ctrl_flag = false; + // Velocity control + t.reset(); + if (!e_stop) { + curr_pulses = qei.getPulses(); + if (vel_count < 6) { + velocity = curr_pulses / interrupt_T / vel_count / ppr * c; + prev_pulse_counts[vel_count - 1] = curr_pulses; + vel_count = vel_count + 1; + } else { + velocity = (curr_pulses - prev_pulse_counts[0]) / interrupt_T / 5 / ppr * c; + for (int i = 0; i < 4; i++) { + prev_pulse_counts[i] = prev_pulse_counts[i+1]; + } + prev_pulse_counts[4] = curr_pulses; + } + tele_velocity = velocity; + motor_ctrl.setProcessValue(velocity); + motor_duty = motor_ctrl.compute(); + motor = 1.0 - motor_duty; + tele_pwm = motor_duty; + } else { + motor = 1.0; + } + t_vel = t.read_us(); + t.reset(); + ctrl_flag = false; +// test = 0; } -void set_control_flag() { +void set_ctrl_flag() { +// test = 1; ctrl_flag = true; } @@ -413,17 +404,13 @@ tele_center.set_limits(0, 128); tele_pwm.set_limits(0.0, 1.0); - for (int i = 0; i < 10; i++) { - prev_vels[i] = -1; - } - // Initialize motor motor.period_us(motor_T); motor = 1.0 - motor_duty; // Initialize motor controller motor_ctrl.setInputLimits(0.0, 10.0); - motor_ctrl.setOutputLimits(0.0, 0.75); + motor_ctrl.setOutputLimits(0.0, 0.5); motor_ctrl.setSetPoint(ref_v); motor_ctrl.setBias(0.0); motor_ctrl.setMode(1); @@ -436,18 +423,19 @@ servo_ctrl.setInputLimits(10, 117); servo_ctrl.setOutputLimits(-25, 25); servo_ctrl.setSetPoint(63.5); - servo_ctrl.setBias(0.0); + servo_ctrl.setBias(0); servo_ctrl.setMode(1); // Initialize communications thread - Thread communication_thread(communication); - - control_interrupt.attach(control, interrupt_T); -// control_interrupt.attach(set_control_flag, interrupt_T); +// Thread communication_thread(communication); + + // control_interrupt.attach(control, interrupt_T); + // Thread::wait(osWaitForever); + control_interrupt.attach(set_ctrl_flag, interrupt_T); while (true) { -// if (ctrl_flag) { -// control(); -// } + if (ctrl_flag) { + control(); + } } } \ No newline at end of file