DC motor position control with potentiometer

Dependents:   Ackermann steering baseControl_ackermannCar

Files at this revision

API Documentation at this revision

Comitter:
worasuchad
Date:
Wed Nov 07 16:51:16 2018 +0000
Commit message:
DC motor position control with potentiometer

Changed in this revision

LamborSteer.cpp Show annotated file Show diff for this revision Revisions of this file
LamborSteer.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r b20808175db0 LamborSteer.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LamborSteer.cpp	Wed Nov 07 16:51:16 2018 +0000
@@ -0,0 +1,183 @@
+#include "LamborSteer.h"
+#include "mbed.h"
+
+LamborSteer::LamborSteer(PinName _cw_pin, PinName _ccw_pin, PinName _enablerPin, PinName _sensor_pin, int _offset)
+: cw_pin(_cw_pin), ccw_pin(_ccw_pin), enabler_pin(_enablerPin), sensor_pin(_sensor_pin)
+{
+  if (s_index == MAX_SERVOS)
+  {
+    return;
+  }
+  
+  index = s_index;
+  
+  _m_servos[s_index++] = this;
+
+  tolerance = 15;
+  
+  /* New */
+  offset = _offset;
+  active = true;
+  
+  cw_pin = 0;
+  ccw_pin = 0;
+}
+
+// timer interrupt routine
+void LamborSteer::timer_int_routine()         
+{
+  for (int i = 0; i < s_index; i++)
+  {
+    if (_m_servos[i]->active)
+    {
+      _m_servos[i]->update();
+    }
+  }
+}
+
+
+void LamborSteer::detach()
+{
+  stop();
+  
+  active = false;
+}
+
+void LamborSteer::write(int degrees)
+{
+  // map degrees to potentiometer value
+  int pot_value = map(degrees, MIN_ANGLE, MAX_ANGLE, MIN_POT_VALUE, MAX_POT_VALUE);  
+
+  write_pot_value(pot_value);
+}
+
+void LamborSteer::update()
+{
+  int current_position = get_position();
+
+  // Guard servo's min and max bounds
+  if (current_position < MIN_POT_VALUE)
+  {
+    write(MIN_ANGLE);
+  }
+
+  if (current_position > MAX_POT_VALUE)
+  {
+    write(MAX_ANGLE);
+  }
+
+  // Gap between curent and wanted positions
+  int gap = abs(current_position - wanted_position);
+
+  // If gap is within tolerance then stop
+  if (gap < tolerance)
+  {
+    stop();
+
+    return;
+  }
+
+  // set speed according to gap remaining 
+  speed = 100;    //125
+
+  if (gap > 50)
+  {
+    speed = 100;  //165
+  }
+  if (gap > 75)
+  {
+    speed = 100;  //205
+  }
+  if (gap > 100)
+  {
+    speed = 100;  //255
+  }
+
+  // Determine direction
+  if (current_position < wanted_position)
+  {
+    run_cw();
+  }
+
+  if (current_position > wanted_position)
+  {
+    run_ccw();
+  }
+}
+
+servo_status LamborSteer::read()
+{
+  // Get current postion, wanted position and speed
+  servo_status current_status;
+  
+  int current_angle = map(get_position(), MIN_POT_VALUE, MAX_POT_VALUE, MIN_ANGLE, MAX_ANGLE);
+  int wanted_angle = map(wanted_position, MIN_POT_VALUE, MAX_POT_VALUE, MIN_ANGLE, MAX_ANGLE);
+
+  current_status.current_angle = current_angle;
+  current_status.wanted_angle = wanted_angle;
+  current_status.speed = speed;
+
+  return current_status;
+}
+
+/*************** Private stuff **************/
+
+void LamborSteer::write_pot_value(int value)
+{
+  // Constrain value to servo's min and max bounds
+  //int constrained_value = constrain(value, MIN_POT_VALUE + tolerance, MAX_POT_VALUE - tolerance);
+  if(value > MAX_POT_VALUE - tolerance)
+  {
+    constrained_value = MAX_POT_VALUE - tolerance;
+  }
+  else if(value < MIN_POT_VALUE + tolerance)
+  {
+    constrained_value = MIN_POT_VALUE + tolerance;  
+  }
+  else
+  {
+    constrained_value = value;   
+  }
+  // set destination
+  wanted_position = constrained_value;
+}
+
+// Run motor clockwise at current speed
+void LamborSteer::run_cw()
+{
+  cw_pin = 1;
+  ccw_pin = 0;
+
+  enabler_pin.write(speed / 255.0f);
+}
+
+// Run motor counter clockwise at current speed
+void LamborSteer::run_ccw()
+{
+  cw_pin = 0;
+  ccw_pin = 1;
+
+  enabler_pin.write(speed / 255.0f);
+}
+
+// Stop the motor, set speed to 0
+void LamborSteer::stop()
+{
+  cw_pin = 0;
+  ccw_pin = 0;
+  
+  enabler_pin.write(0);
+}
+
+// Get current offset potentiometer position
+int LamborSteer::get_position()
+{
+  return (sensor_pin.read()*1023) + offset;  // Read the analog input value (value from 0.0 to 1.0)
+                                             // And convert to 0 - 1023
+}
+
+// Mapping
+long LamborSteer::map(long x, long in_min, long in_max, long out_min, long out_max)
+{
+  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
+}
\ No newline at end of file
diff -r 000000000000 -r b20808175db0 LamborSteer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LamborSteer.h	Wed Nov 07 16:51:16 2018 +0000
@@ -0,0 +1,54 @@
+#ifndef LAMBORSTEER_H
+#define LAMBORSTEER_H
+
+#include "mbed.h"
+
+#define MAX_SERVOS 2
+#define MIN_POT_VALUE 10   
+#define MAX_POT_VALUE 1000  // 800
+#define MIN_ANGLE 10
+#define MAX_ANGLE 400       // 170
+
+typedef unsigned char uint8_t;
+
+typedef struct {
+    int wanted_angle;
+    int current_angle;
+    uint8_t speed;
+} servo_status;
+
+class LamborSteer
+{
+public:
+    LamborSteer(PinName _cw_pin, PinName _ccw_pin, PinName _enablerPin, PinName _sensor_pin, int _offset);
+    //void attach();
+    void timer_int_routine();  
+    void detach();
+    void write(int degrees);
+    void update();
+    servo_status read();
+
+    bool active;
+    int index;
+private:               
+    int offset;
+    uint8_t speed;
+    int wanted_position;
+    int tolerance;
+    int constrained_value;
+    
+    void write_pot_value(int degrees);
+    void run_cw();
+    void run_ccw();
+    void stop();
+    int get_position();
+    long map(long x, long in_min, long in_max, long out_min, long out_max);
+    DigitalOut cw_pin;
+    DigitalOut ccw_pin;
+    PwmOut enabler_pin;
+    AnalogIn sensor_pin;
+};
+
+static int s_index;                 // number of registered servo's
+static LamborSteer* _m_servos[2];   // array containing registered servo's
+#endif