PM2_Lib

Dependencies:   LSM9DS1 RangeFinder FastPWM

Revision:
8:6b747ad59ff5
Child:
9:583dbd17e0ba
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PositionController.cpp	Mon Apr 19 15:54:15 2021 +0000
@@ -0,0 +1,130 @@
+#include "PositionController.h"
+
+using namespace std;
+
+const float PositionController::TS = 0.001f;                       // period of 1 ms
+const float PositionController::LOWPASS_FILTER_FREQUENCY = 100.0f; // given in [rad/s]
+const float PositionController::MIN_DUTY_CYCLE = 0.0f;             // minimum duty-cycle
+const float PositionController::MAX_DUTY_CYCLE = 1.0f;             // maximum duty-cycle
+
+PositionController::PositionController(float counts_per_turn, float kn, float max_voltage, FastPWM& pwm, EncoderCounter& encoderCounter) : pwm(pwm), encoderCounter(encoderCounter), thread(osPriorityHigh, 4096)
+{
+    this->counts_per_turn = counts_per_turn;
+    this->kn = kn;
+    this->kp = 0.1f;
+    this->max_voltage = max_voltage;
+    this->max_speed   = kn*max_voltage;
+    this->p  = 1300.0f;
+
+    // Initialisieren der PWM Ausgaenge
+    pwm.period(0.00005); // PWM Periode von 50 us
+    pwm.write(0.5);      // Duty-Cycle von 50%
+
+    // Initialisieren von lokalen Variabeln
+    previousValueCounter = encoderCounter.read();
+    speedFilter.setPeriod(TS);
+    speedFilter.setFrequency(LOWPASS_FILTER_FREQUENCY);
+    desiredSpeed = 0.0f;
+    actualSpeed = 0.0f;
+    float initialRotation = (float)encoderCounter.read()/counts_per_turn;
+    this->initialRotation = initialRotation;
+    actualRotation  = initialRotation;
+    desiredRotation = initialRotation;
+
+    // Starten des periodischen Tasks
+    thread.start(callback(this, &PositionController::run));
+    ticker.attach(callback(this, &PositionController::sendThreadFlag), TS);
+}
+
+PositionController::PositionController(float counts_per_turn, float kn, float kp, float p, float max_voltage, FastPWM& pwm, EncoderCounter& encoderCounter) : pwm(pwm), encoderCounter(encoderCounter), thread(osPriorityHigh, 4096)
+{
+    this->counts_per_turn = counts_per_turn;
+    this->kn = kn;
+    this->kp = kp;
+    this->max_voltage = max_voltage;
+    this->max_speed   = kn*max_voltage;
+    this->p  = p;
+
+    // Initialisieren der PWM Ausgaenge
+    pwm.period(0.00005); // PWM Periode von 50 us
+    pwm.write(0.5);      // Duty-Cycle von 50%
+
+    // Initialisieren von lokalen Variabeln
+    previousValueCounter = encoderCounter.read();
+    speedFilter.setPeriod(TS);
+    speedFilter.setFrequency(LOWPASS_FILTER_FREQUENCY);
+    desiredSpeed = 0.0f;
+    actualSpeed  = 0.0f;
+    float initialRotation = (float)encoderCounter.read()/counts_per_turn;
+    this->initialRotation = initialRotation;
+    actualRotation  = initialRotation;
+    desiredRotation = initialRotation;
+
+    // Starten des periodischen Tasks
+    thread.start(callback(this, &PositionController::run));
+    ticker.attach(callback(this, &PositionController::sendThreadFlag), TS);
+}
+
+PositionController::~PositionController()
+{
+    ticker.detach(); // Stoppt den periodischen Task
+}
+
+float PositionController::getSpeedRPM()
+{
+    return actualSpeed;
+}
+
+float PositionController::getSpeedRPS()
+{
+    return actualSpeed/60.0f;
+}
+
+void PositionController::setDesiredRotation(float desiredRotation)
+{
+    this->desiredRotation = initialRotation + desiredRotation;
+}
+
+void PositionController::setDesiredRotation(float desiredRotation, float maxSpeedRPS)
+{
+    this->max_speed = maxSpeedRPS*60.0f;
+    this->desiredRotation = initialRotation + desiredRotation;
+}
+
+float PositionController::getRotation()
+{
+    return actualRotation - initialRotation;
+}
+
+void PositionController::run()
+{
+    while(true) {
+
+        // wait for the periodic signal
+        ThisThread::flags_wait_any(threadFlag);
+
+        // calculate actual speed of motors in [rpm]
+        short valueCounter = encoderCounter.read();
+        short countsInPastPeriod = valueCounter - previousValueCounter;
+        previousValueCounter = valueCounter;
+        actualSpeed = speedFilter.filter((float)countsInPastPeriod/counts_per_turn/TS*60.0f);
+        actualRotation = actualRotation + actualSpeed/60.0f*TS;
+
+        // calculate motor phase voltages
+        desiredSpeed  = p*(desiredRotation - actualRotation);
+        if (desiredSpeed < -max_speed) desiredSpeed = -max_speed;
+        else if (desiredSpeed > max_speed) desiredSpeed = max_speed;
+        float voltage = kp*(desiredSpeed - actualSpeed) + desiredSpeed/kn;
+        // calculate, limit and set duty cycles
+        float dutyCycle = 0.5f + 0.5f*voltage/max_voltage;
+        if (dutyCycle < MIN_DUTY_CYCLE) dutyCycle = MIN_DUTY_CYCLE;
+        else if (dutyCycle > MAX_DUTY_CYCLE) dutyCycle = MAX_DUTY_CYCLE;
+        pwm.write(static_cast<double>(dutyCycle));
+
+    }
+}
+
+void PositionController::sendThreadFlag()
+{
+    thread.flags_set(threadFlag);
+}
\ No newline at end of file