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.
main.cpp
- Committer:
- benkatz
- Date:
- 2013-06-28
- Revision:
- 2:89bb6272869b
- Parent:
- 1:30696e4d196b
- Child:
- 3:cae0b305d54c
File content as of revision 2:89bb6272869b:
//Ben Katz, 2013
#include "QEI.h"
#include "PID.h"
#define pi 3.14159265358979323846
Serial pc(USBTX, USBRX);
//Use X4 encoding.
QEI wheel(p16, p17, NC, 1200, QEI::X4_ENCODING); //(encoder channel 1, encoder channel 2, index (n/a here), counts per revolution, mode (X4, X2))
DigitalOut EncoderVcc (p18); //Encoder VCC pin. Alternatively, just connect these to the mbed's vout and gnd, but tihs can make wiring easier
DigitalOut EncoderGnd(p19); //Encoder ground pin
PwmOut Motor1(p21); //Ouput pin to h-bridge 1
PwmOut Motor2 (p22); //Output pin to h-bridge 2
AnalogIn Current (p20); //Current sense pin
int steps_per_rev = 1200; //Encoder CPR * gearbox ratio
Timer timer;
float pulsesToRadians(float pulses) //Encoder steps to revolutions of output shaft in radians
{
return ((pulses/steps_per_rev)*(2*pi));
}
float pulsesToDegrees(float pulses) //Encoder steps to revolutions of output shaft in degrees
{
return ((pulses/steps_per_rev)*360);
}
void signal_to_hbridge( float signal) //Input of -1 means full reverse, 1 means full forward
{ //An input of magnitude > 1 gets reduced to 1 (or -1) by the pwm.write() function
if (signal < 0) {
Motor1.write(0);
Motor2.write(signal * -1);
} else if (signal > 0) {
Motor1.write(signal);
Motor2.write(0);
} else {
Motor1.write(0);
Motor2.write(0);
}
}
void pulse_motor(float pulse_time, float pulse_interval) //Usefull for testing peak torque.
//pulse_time = motor on time. pulse_interval = motor off time
{
timer.start();
while (timer.read() < pulse_time){
Motor1.write(1);
Motor2.write(0);
//Prints current draw to PC
printf("%F", (Current.read())*3.3*4/.525); //Arithmetic converts the analog input to Amps
printf("\n"); //(0-3.3V input) * (voltage divider muiltiplier) / (.525 V/A)
}
timer.stop();
timer.reset();
wait(pulse_time);
Motor1.write(0);
Motor2.write(0);
wait(pulse_interval);
}
int main()
{
EncoderVcc.write(1); //Encoder VCC and GND attached to digital output pins to make wiring easier
EncoderGnd.write(0);
Motor1.period(.00005); //Set PWM frequency. MC33926 h-bridge limited 20 kHz (.00005 seconds)
Motor2.period(.00005);
PIDController controller(180, 0.05, 3, 0); //(desired position, P gain, D gain, I gain)
/*
Insert servo control loop below
*/
while(1) {
signal_to_hbridge(controller.Update());
}
}
PIDController::PIDController(float desired_position, float p_gain, float d_gain, float i_gain)
{
kp = p_gain;
kd = d_gain;
ki = i_gain;
error = 0;
old_error = 0;
goal_position = desired_position;
}
float PIDController::Update(void) //This function is called to set the desired position of the servo
{
wait(.0004); //This delay allows enough time to register a position difference between cycles.
//Without the delay, velocity is read as 0, so there is no D feedback.
//The delay can be decreased when adding more servos, as the computation time becomes more significant.
float desired_position = this->goal_position; //All value are stored in the PIDController object created, and can be changed at any time
float p_gain = this->kp;
float d_gain = this->kd;
float i_gain = this->ki;
float currentPosition = pulsesToDegrees(wheel.getPulses()); //Change pulsesToDegrees() to pulsesToRadians() if you would prefer to use radians
this->error = (currentPosition - desired_position);
this->integral_error += this->error;
float command = p_gain*(this->error) + d_gain*(this->error - this->old_error) + i_gain*(this->integral_error);
this->old_error = error;
return command;
}