Publishing for Biomimetics.

Dependencies:   CRC MODDMA MODSERIAL MPU6050IMU PID QEI mbed-rtos mbed-src

Revision:
0:8cfa73bb68e4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/control.cpp	Tue May 31 17:04:59 2016 +0000
@@ -0,0 +1,97 @@
+#include "control.h"
+
+Control::Control(
+    PinName left_mot_0_pin, PinName left_mot_1_pin, 
+    PinName right_mot_0_pin, PinName right_mot_1_pin, 
+    Sensors *sensors, uint32_t tick_per_rev,
+    float kP, float kI, float kD, float period, float velocity_max,
+    float pid_dead_band
+  ) :
+    sensors_(sensors),
+    control_timer_(&Control::control_helper,osTimerPeriodic,this),
+    pid_dead_band_(pid_dead_band)
+  {
+
+  motors_[MOTOR_LEFT][0] = new PwmOut(left_mot_0_pin);
+  motors_[MOTOR_LEFT][1] = new PwmOut(left_mot_1_pin);
+  motors_[MOTOR_RIGHT][0] = new PwmOut(right_mot_0_pin);
+  motors_[MOTOR_RIGHT][1] = new PwmOut(right_mot_1_pin);
+  
+  // For the LPC1768, all PWM channels are on the same timer, so setting one
+  // period sets them all
+  motors_[MOTOR_LEFT][0]->period_us(50);
+
+  tick_to_angular_velocity_ = 2.0 * 3.14159265358979323846 / (float)(tick_per_rev * period);
+  
+  pid_init(MOTOR_LEFT,kP,kI,kD,period,velocity_max);
+  pid_init(MOTOR_RIGHT,kP,kI,kD,period,velocity_max);
+
+  control_timer_.start(period*1000);
+
+  last_positions_[MOTOR_LEFT] = 0;
+  last_positions_[MOTOR_RIGHT] = 0;
+}
+
+void Control::set_setpoints(float left, float right) {
+  pids_[MOTOR_LEFT]->setSetPoint(left);
+  pids_[MOTOR_RIGHT]->setSetPoint(right);
+}
+
+void Control::fill_pid_packet(packet_t* pkt) {
+  pkt->header.type = PKT_TYPE_PID;
+  pkt->header.length = sizeof(header_t) + sizeof(pid_data_t) + 1;
+  pid_data_t* pid_data = (pid_data_t*)pkt->data_crc;
+  pid_data->vel[MOTOR_LEFT] = velocities_[MOTOR_LEFT];
+  pid_data->vel[MOTOR_RIGHT] = velocities_[MOTOR_RIGHT];
+  pid_data->pwm[MOTOR_LEFT] = pwms_[MOTOR_LEFT];
+  pid_data->pwm[MOTOR_RIGHT] = pwms_[MOTOR_RIGHT];
+}
+
+void Control::fill_sensor_packet(packet_t* pkt) {
+  pkt->header.type = PKT_TYPE_SENSOR;
+  pkt->header.length = sizeof(header_t) + sizeof(sensor_data_t) + 1;
+  sensor_data_t* sensor_data = (sensor_data_t*)pkt->data_crc;
+  sensor_data->velocity[MOTOR_LEFT] = velocities_[MOTOR_LEFT];
+  sensor_data->velocity[MOTOR_RIGHT] = velocities_[MOTOR_RIGHT];
+}
+
+void Control::set_motor_pwm(int motor, float value) {
+  if (value >= 0.0) {
+    motors_[motor][0]->write(value);
+    motors_[motor][1]->write(0.0);
+  } else {
+    motors_[motor][0]->write(0.0);
+    motors_[motor][1]->write(-value);
+  }
+}
+
+void Control::pid_init(int motor, float kP, float kI, float kD, float period, float velocity_max) {
+  pids_[motor] = new PID(kP,kI,kD,period);
+  pids_[motor]->setInputLimits(-velocity_max, velocity_max);
+  pids_[motor]->setOutputLimits(-1.0,1.0);
+  pids_[motor]->setBias(0.0);
+  pids_[motor]->setSetPoint(0.0);
+}
+
+void Control::control_helper(const void* p) {
+  Control* instance = (Control*)p;
+  instance->control_update();
+}
+
+void Control::control_update(void) {
+  float positions[2];
+  
+  sensors_->get_angles(positions);
+
+  for (uint32_t i=0; i<2; i++) {
+    velocities_[i] = tick_to_angular_velocity_ * (positions[i] - last_positions_[i]);
+    last_positions_[i] = positions[i];
+    pids_[i]->setProcessValue(velocities_[i]);
+    pwms_[i] = pids_[i]->compute();
+    if (fabs(pwms_[i]) < pid_dead_band_)
+      pwms_[i] = 0.0;
+  }
+
+  set_motor_pwm(MOTOR_LEFT, pwms_[MOTOR_LEFT]);
+  set_motor_pwm(MOTOR_RIGHT, pwms_[MOTOR_RIGHT]);
+}
\ No newline at end of file