Control for RenBuggy

Dependencies:   PID PinDetect mbed

Files at this revision

API Documentation at this revision

Comitter:
salatron
Date:
Tue Mar 04 13:31:17 2014 +0000
Child:
1:8a2a7adb3c5d
Commit message:
Version1
; RenBuggy with PID controll

Changed in this revision

PID.lib Show annotated file Show diff for this revision Revisions of this file
PinDetect.lib Show annotated file Show diff for this revision Revisions of this file
RenBuggy_PID.cpp Show annotated file Show diff for this revision Revisions of this file
RenBuggy_PID.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PID.lib	Tue Mar 04 13:31:17 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/aberk/code/PID/#6e12a3e5af19
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PinDetect.lib	Tue Mar 04 13:31:17 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/AjK/code/PinDetect/#cb3afc45028b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RenBuggy_PID.cpp	Tue Mar 04 13:31:17 2014 +0000
@@ -0,0 +1,293 @@
+/*******************************************************************************
+* RenBED PID Motor Control for RenBuggy                                        *
+* Copyright (c) 2014 Sally Brown                                               *
+*                                                                              *
+* Permission is hereby granted, free of charge, to any person obtaining a copy *
+* of this software and associated documentation files (the "Software"), to deal*
+* in the Software without restriction, including without limitation the rights *
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell    *
+* copies of the Software, and to permit persons to whom the Software is        *
+* furnished to do so, subject to the following conditions:                     *
+*                                                                              *
+* The above copyright notice and this permission notice shall be included in   *
+* all copies or substantial portions of the Software.                          *
+*                                                                              *
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR   *
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,     *
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  *
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER       *
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,*
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN    *
+* THE SOFTWARE.                                                                *
+*                                                                              *
+* PID_Controller.cpp                                                           *
+*                                                                              *
+*******************************************************************************/
+
+#ifndef _PIDCONTROLLER_C
+#define _PIDCONTROLLER_C
+
+#include "RenBuggy_PID.h"
+
+PID_Controller::PID_Controller
+(
+    PinName motorL,
+    PinName motorR,
+    PinName brakeL,
+    PinName brakeR,
+    PinName sensorL,
+    PinName sensorR
+) :
+    m_controllerL(1.0, 0.0, 0.0, RATE),  //Kc, Ti, Td, interval
+    m_controllerR(1.0, 0.0, 0.0, RATE),
+    m_motorL(motorL),
+    m_motorR(motorR),
+    m_brakeL(brakeL),
+    m_brakeR(brakeR),
+    m_senseL(sensorL),
+    m_senseR(sensorR),
+    m_numberStrips(16),                           //Default to 16 stripes
+    m_wheelCircumference(16.96),                  //Default to 16.96
+    m_stripesL(0),                                //Initialise the number of stripes to 0.
+    m_stripesR(0),
+    m_turnLeft(false),
+    m_turnRight(false),    
+    m_fProportionLeft(0.0),
+    m_fProportionRight(0.0),        
+    m_iProportionLeft(0),
+    m_iProportionRight(0)
+{  
+    m_senseL.setSampleFrequency(1000);
+    m_senseR.setSampleFrequency(1000); //If this is playing up, consider changing this to 1001?
+    
+    //It's 5 samples before it recognises it's held on.
+    m_senseL.setSamplesTillHeld(5);
+    m_senseR.setSamplesTillHeld(5);
+    
+    //Only when it's been held high and then goes low will it increment the number of counts.
+    m_senseL.attach_deasserted_held(this, &PID_Controller::countL);
+    m_senseR.attach_deasserted_held(this, &PID_Controller::countR);
+    
+    setUpControllers();
+}
+
+void PID_Controller::SetUpConstants(int numberStripes, float wheelCircumference)
+{
+    m_numberStrips = numberStripes;
+    m_wheelCircumference = wheelCircumference;
+}
+
+void PID_Controller::Forwards(int CountsForward)
+{
+    m_turnRight = false;
+    m_turnLeft = false;
+    
+    CountsForward = CountsForward * (m_numberStrips/m_wheelCircumference);
+    
+    m_rate.attach(this, &PID_Controller::doSomePID, RATE); //Attach the counter if it hasn't gone too far. Then hopefully just sit in a loop.
+    
+    m_stripesL = m_stripesR = 0;
+    m_brakeR = m_brakeL = 0;
+    
+    m_fProportionLeft = m_fProportionRight = 1.0;
+    
+    while ((m_brakeR == 0) || (m_brakeL == 0)) 
+    {
+        if (CountsForward < m_stripesL)
+        {
+            m_motorL = 0.0;
+            m_brakeL = 1;
+        }
+        if (CountsForward < m_stripesR)
+        {
+            m_motorR = 0.0;
+            m_brakeR = 1;
+            if (CountsForward < m_stripesL)
+            {
+                m_rate.detach();
+            }
+        }
+    }
+    return;
+}
+
+void PID_Controller::Left(int AngleLeft, int RadiusLeft)
+{
+    m_turnRight = false; //Turning left, NOT turning right
+    m_turnLeft = true;
+    
+    m_rate.attach(this, &PID_Controller::doSomePID, RATE);
+    
+    m_brakeR = m_brakeL = 0; //Turning off the brakes is often quite fun.
+    m_stripesL = m_stripesR = 0;
+    
+    float m_fDistanceL = (2*pi*(RadiusLeft - 6.5))*(m_numberStrips/m_wheelCircumference)/(360/AngleLeft); 
+    float m_fDistanceR = (2*pi*(RadiusLeft + 6.5))*(m_numberStrips/m_wheelCircumference)/(360/AngleLeft); //gives the length of the arc over which the wheel will travel, and translates that into a number of wheel stripes
+    
+    int iDistanceL = (int) m_fDistanceL; //Cast the distance into an int
+    int iDistanceR = (int) m_fDistanceR;
+    
+    int LeftWheelDist = iDistanceL; //Set the distance the left wheel travels
+    int RightWheelDist = iDistanceR; //Set the distance the right wheel travels
+    
+    float myfloatL = (float)LeftWheelDist/(float)RightWheelDist;
+    m_iProportionLeft = floor(myfloatL); 
+    m_fProportionLeft = myfloatL;
+    
+    float myfloatR = (float)RightWheelDist/LeftWheelDist; //When turning right, you only use the left wheel's proportion
+    m_iProportionRight = ceil(myfloatR);
+    m_fProportionRight = myfloatR;
+
+    while ((m_brakeR == 0))
+    {
+        if (LeftWheelDist <= m_stripesL) //If the left motor has gone far enough
+        {
+            m_motorL = 0.0;   //Stop the motor
+            m_brakeL = 1;     //Apply the brakes
+        }
+        if (RightWheelDist <= m_stripesR)
+        {
+            m_motorR = 0.0;
+            m_brakeR = 1;
+            if (LeftWheelDist <= m_stripesL)
+            {
+                m_rate.detach();
+            }
+        }
+    }
+} 
+
+void PID_Controller::Right(int AngleRight, int RadiusRight)
+{
+    m_turnRight = true;
+    m_turnLeft = false;
+    
+    m_rate.attach(this, &PID_Controller::doSomePID, RATE);
+    
+    m_brakeR = m_brakeL = 0; //Turning off the brakes is often quite fun.    
+    m_stripesL = m_stripesR = 0;
+    
+    float m_fDistanceL = (2*pi*(RadiusRight + 6.5))*(m_numberStrips/m_wheelCircumference)/(360/AngleRight); //Forcing it to an int beforehand didn't work. It twitches instead of going argh no, but it still doesn't really work.
+    float m_fDistanceR = (2*pi*(RadiusRight - 6.5))*(m_numberStrips/m_wheelCircumference)/(360/AngleRight);
+    
+    int iDistanceL = (int) m_fDistanceL; 
+    int iDistanceR = (int) m_fDistanceR;
+    
+    int LeftWheelDist = iDistanceL;  //Formula for the length of an arc, divided by circumference, multiplied by 16 stripes. 
+    int RightWheelDist = iDistanceR; //This give a distance, after which it will stop moving. These lines are causing problems... 
+    
+    float myfloatL = (float)LeftWheelDist/(float)RightWheelDist;
+    m_iProportionLeft = (int) ceil(myfloatL);
+    m_fProportionLeft = myfloatL;
+    
+    float myfloatR = (float)RightWheelDist/(float)LeftWheelDist;
+    m_iProportionRight = (int) floor(myfloatR);
+
+    while ((m_brakeL == 0))
+    {
+        if (LeftWheelDist <= m_stripesL) //If the left motor has gone far enough
+        {
+            m_motorL = 0.0;   //Stop the motor
+            m_brakeL = 1;     //Apply the brakes
+        }
+        if (RightWheelDist <= m_stripesR)
+        {
+            m_motorR = 0.0;
+            m_brakeR = 1;
+            if (LeftWheelDist <= m_stripesL)
+            {
+                m_rate.detach();
+            }
+        }
+    }
+} 
+
+void PID_Controller::doSomePID()
+{
+    PIDLeft();
+    PIDRight();
+}
+
+void PID_Controller::PIDLeft()
+{
+    float fSPL = 0.0;
+    int SPL = 0;
+    
+    if(m_turnLeft)
+    {
+        fSPL = m_stripesR / m_fProportionRight;
+        SPL = (int) fSPL;
+    }
+    else if(m_turnRight)
+    {
+        fSPL = m_stripesR * m_fProportionLeft;
+        SPL = (int) fSPL;
+    }
+    else
+    {
+        SPL = m_stripesR;
+    }
+
+    m_controllerL.setProcessValue(m_stripesL); 
+    
+    m_motorL = (m_controllerL.compute()); //PWM output * some speed proportion. May slow it down or speed it up.*/
+    
+    m_controllerL.setSetPoint(SPL);
+}
+
+void PID_Controller::PIDRight()
+{
+    float fSPR = 0.0;
+    int SPR = 0;
+    
+    if(m_turnRight) //If you're turning right, the left wheel goes further, so use xProportionLeft
+    {
+        fSPR = m_stripesL / m_fProportionLeft;
+        SPR = (int) fSPR;
+    }
+    else if(m_turnLeft) //If you're turning left, the right wheel goes further, so use xProportionRight
+    {
+        fSPR = m_stripesL * m_fProportionRight;
+        SPR = (int) fSPR;
+    }
+    else
+    {
+        SPR = m_stripesL;
+    }
+    
+    m_controllerR.setProcessValue(m_stripesR); //Set the process value (what it IS).
+    
+    m_motorR = (m_controllerR.compute()); //Calculate the PWM duty cycle
+    
+    m_controllerR.setSetPoint(SPR); //SPR = set point right. this sets the set point (what it SHOULD BE).
+}
+
+void PID_Controller::countL() 
+{
+    m_stripesL++;
+}
+
+void PID_Controller::countR() 
+{
+    m_stripesR++;
+}
+
+void PID_Controller::setUpControllers()
+{
+    //m_controllerL = PID(1.0, 0.0, 0.0, RATE);  //Kc, Ti, Td, interval
+    //m_controllerR = PID(1.0, 0.0, 0.0, RATE);
+
+    m_controllerL.setInputLimits(0.0, 200);
+    m_controllerR.setInputLimits(0.0, 200);
+    //Pwm output from 0.0 to 1.0 (PWM duty cycle %)
+    m_controllerL.setOutputLimits(0.0, 1.0);
+    m_controllerR.setOutputLimits(0.0, 1.0);
+    //If there's a bias. FULL SPEED AHEAD. I don't know why this works but it does.
+    m_controllerL.setBias(1.0);
+    m_controllerR.setBias(1.0);
+    //Set it to auto mode.
+    m_controllerL.setMode(AUTO_MODE);
+    m_controllerR.setMode(AUTO_MODE);    
+}
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RenBuggy_PID.h	Tue Mar 04 13:31:17 2014 +0000
@@ -0,0 +1,89 @@
+/*******************************************************************************
+* RenBED PID Motor Control for RenBuggy                                        *
+* Copyright (c) 2014 Sally Brown                                               *
+*                                                                              *
+* Permission is hereby granted, free of charge, to any person obtaining a copy *
+* of this software and associated documentation files (the "Software"), to deal*
+* in the Software without restriction, including without limitation the rights *
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell    *
+* copies of the Software, and to permit persons to whom the Software is        *
+* furnished to do so, subject to the following conditions:                     *
+*                                                                              *
+* The above copyright notice and this permission notice shall be included in   *
+* all copies or substantial portions of the Software.                          *
+*                                                                              *
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR   *
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,     *
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  *
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER       *
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,*
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN    *
+* THE SOFTWARE.                                                                *
+*                                                                              *
+* PID_Controller.h                                                             *
+*                                                                              *
+*******************************************************************************/
+
+#ifndef _PIDCONTROLLER_H
+#define _PIDCONTROLLER_H
+
+#include "mbed.h"
+#include "PID.h"
+#include "PinDetect.h"
+
+#define pi      3.1416
+#define RATE    0.001
+
+class PID_Controller
+{
+    public:
+        PID_Controller(PinName motorL, PinName motorR, PinName brakeL, PinName brakeR, PinName sensorL, PinName sensorR);
+    
+        void SetUpConstants(int numberStripes, float wheelCircumference);
+        
+        void Forwards(int countsForward);
+        void Left(int angleLeft, int radiusLeft);
+        void Right(int angleRight, int radiusRight);
+        
+    private:
+    
+        void doSomePID();
+        void PIDLeft();
+        void PIDRight();
+        
+        void countL();
+        void countR();
+        
+        void setUpControllers();
+        
+        PID     m_controllerL;  //Kc, Ti, Td, interval
+        PID     m_controllerR;
+        
+        PwmOut  m_motorL;
+        PwmOut  m_motorR;
+        
+        DigitalOut m_brakeL;
+        DigitalOut m_brakeR;
+        
+        PinDetect   m_senseL;     //Left encoder. Pin detect type is the debouncing.
+        PinDetect   m_senseR; 
+
+        Ticker  m_rate;
+        
+        int     m_numberStrips;
+        float   m_wheelCircumference;
+
+        int     m_stripesL;
+        int     m_stripesR;
+        
+        bool    m_turnLeft;
+        bool    m_turnRight;
+        
+        float   m_fProportionLeft;
+        float   m_fProportionRight;
+        
+        int     m_iProportionLeft;
+        int     m_iProportionRight;
+};
+
+#endif    // _PIDCONTROLLER_H
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Mar 04 13:31:17 2014 +0000
@@ -0,0 +1,12 @@
+
+#include "RenBuggy_PID.h"
+
+int main()
+{
+    PID_Controller pid(p25, p10, p8, p7, p9, p21);
+    pid.Forwards(20);
+    pid.Left(90, 45);
+    pid.Forwards(20);
+    pid.Right(90,45);
+    pid.Forwards(20);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Tue Mar 04 13:31:17 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/8e73be2a2ac1
\ No newline at end of file