Decoupled position and current control working.

Dependencies:   QEI mbed-src

Revision:
2:89bb6272869b
Parent:
1:30696e4d196b
Child:
3:cae0b305d54c
diff -r 30696e4d196b -r 89bb6272869b main.cpp
--- a/main.cpp	Wed Aug 11 09:15:10 2010 +0000
+++ b/main.cpp	Fri Jun 28 19:03:06 2013 +0000
@@ -1,16 +1,127 @@
+//Ben Katz, 2013
+
 #include "QEI.h"
+#include "PID.h"
+
+#define pi  3.14159265358979323846
+
 
 Serial pc(USBTX, USBRX);
 //Use X4 encoding.
-//QEI wheel(p29, p30, NC, 624, QEI::X4_ENCODING);
-//Use X2 encoding by default.
-QEI wheel (p29, p30, NC, 624);
+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);
+    }
+}
 
-int main() {
+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);
+}
+
+
 
-    while(1){
-        wait(0.1);
-        pc.printf("Pulses is: %i\n", wheel.getPulses());
+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;
+
+}