PID DC motor control with POT feedback

I have seen lots of posts on PID, but cant find any with positional control via a Pot and feedback via another pot on the motor. Has anyone done this?

This is not a servo motor with built in controller , its just a DC motor (2 wire).

Basically I have a motor that needs to turn 0-180 (throttle body from a motorbike).

The motor has a simple potentiometer throttle valve position sensor for feedback.

The drive input to the arduino controller would be another pot (the throttle its self).

I know I will have to drive the motor via a FET or similar but wondered if anyone had a sketch using pots for control and feedback with the PID library?

The control logic would work based on the pot values, then modify the motor control signal.

Hmmmm another project with a lot of potential dangers ..worth avoiding IMO.

Most fly by wire systems use two potentiometers on the input , each checking the values of the other so faults can be detected . I’m unsure of the type of motor used on the throttle itself but it is fast and control is usually via an ECU which also has control over fuelling and ignition and is a very robust device with automotive rated parts , IP rating, fail safety systems designed to give an acceptable failure rate , etc

Wires falling off your throttle pot ground suddenly giving you full throttle could be exciting .

Working with fly by wire control "accidents" like loosing the GND or positive to the pot must be dectected. One alternative is that the pot never reaches the end positions. Then 0 or 1023 values, and their near values, are concidered as "alarm" and operation is returning to a safe state.

A few bits from google “ Throttle Pedal Assembly: The throttle pedal has two potentiometers attached to it, achieving the accuracy required from the pedal’s movement. The photograph on the right shows the throttle pedal assembly with the potentiometers attached to the side. The resistance ‘felt’ when the pedal is depressed is designed to give the same feel as a conventional throttle. The throttle pedal, in this instance, has 6 electrical connections.”

Actuators are usually servos themselves fed with a pwm signal to position them and also featuring a feedback pot signal as a check feedback signal to the ECU that the requested position has been reached .

Detected faults then give limp type functions - the ECU having control of ignition and fuel can take action if a fault is detected . Meanwhile you might have crashed

@kpg Can You get hold of documnentation of the motor and the pot and its use?

@hammy

In case of detected cable malfunction the entire operation should go inte a safe mode, shut down the operation "for good".

Thanks guys.

The motor and pot assembly are designed to go together. The motor is integral to the throttle bodies and the sensor (pot) is a unit fixed to the side of the throttle bodies that relays motor position, so a rugged OEM assembly.

The throttle input control (hand grip) is again designed to go with the bodies. I am not using the original units ECU because it isnt suitable for a 2 stroke so am making a full Speeduino ECU, unfortunately that cant do fly by wire throttle so I need a separate unit, hence the question.

I understand allowing for failed sensor issues (like close throttle now etc.) and initially just wanted help with a sketch to do some simulations.

Any points for a sketch starter? The PID examples dont help much I have seen.

Thanks

I would:

  • Use the PID library (PID_v1.h).
  • Set the Output limits to +/- 255.
  • Connect the two pots to give 0 to 1023 values on two analog input pins.
  • Use the throttle directly for Setpoint.
  • Use the feedback pot directly for Input.
  • For positive values of Output, set the motor direction to forward and the motor speed to Output.
  • For negative values of Output, set the motor direction to backward and the motor speed to -Output.
#include <PID_v1.h>


const byte THROTTLE_POT_PIN = A0;
const byte FEEDBACK_POT_PIN = A0;


//Define Variables we'll be connecting to
double Setpoint, Input, Output;


//Specify the links and initial tuning parameters
double Kp = 2, Ki = 5, Kd = 1;
PID ThrottlePID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);


void setup()
{
  //turn the PID on
  ThrottlePID.SetOutputLimits(-255, 255);
  ThrottlePID.SetMode(AUTOMATIC);
}


void loop()
{
  Setpoint = analogRead(THROTTLE_POT_PIN);
  Input = analogRead(FEEDBACK_POT_PIN);
  ThrottlePID.Compute();
  int speed = constrain((int)Output, -255, 255);
  if (speed >= 0)
  {
    MotorForward();
    MotorSpeed(speed);
  }
  else
  {
    MotorBackward();
    MotorSpeed(-speed);
  }
}


// Motor control left to whoever knows what motor controller is being used.
void MotorForward() {}
void MotorBackward() {}
void MotorSpeed(byte speed) {}

Thanks John,

void MotorForward() {} void MotorBackward() {} void MotorSpeed(byte speed) {}

As far as I understand the 'controller' will just be a PWM output of around 20ms frequency with a pulse width range from 1 - 2ms, dependent on input pot (throttle position). This will obviously have to drive a FET.

So I am not sure what the three routines you are quoting are other than increasing and decreasing the PWM duty cycle?

so can I just use ?

analogWrite(3,Output);

I don't know the library at all so I assume I must be missing something major??

Is a single FET enough? Then the motor will only run in one direction. To run in both directions I suggest a H-bridge. The motor speed comes from PWM as well.

kpg:
As far as I understand the ‘controller’ will just be a PWM output of around 20ms frequency with a pulse width range from 1 - 2ms, dependent on input pot (throttle position).

I don’t know the library at all so I assume I must be missing something major??

That’s weird. The output you describe is the output for a hobby servo. The Servo library will generate such a signal on up to 12 output pins.
In that case, change the Output range to 1000 to 2000 and send that directly to servo.writeMicroseconds().

#include <PID_v1.h>
#include <Servo.h>


const byte THROTTLE_POT_PIN = A0;
const byte FEEDBACK_POT_PIN = A1;
const byte CONTROL_OUTPUT_PIN = 4;


//Define Variables we'll be connecting to
double Setpoint, Input, Output;


//Specify the links and initial tuning parameters
double Kp = 2, Ki = 5, Kd = 1;
PID ThrottlePID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);


Servo Motor;


void setup()
{
  Motor.attach(CONTROL_OUTPUT_PIN);
  
  //turn the PID on
  ThrottlePID.SetOutputLimits(1000, 2000);
  ThrottlePID.SetMode(AUTOMATIC);
}


void loop()
{
  Setpoint = analogRead(THROTTLE_POT_PIN);
  Input = analogRead(FEEDBACK_POT_PIN);
  
  ThrottlePID.Compute();


  Motor.writeMicroseconds(Output);
}

John

I definitely do not want to drive a servo. My motor is just a 2 wire DC motor. I took the reference from the PID library example below and wrongly assumed that would provide the drive to the motor.

#include <PID_v1.h>

//Define Variables we'll be connecting to
double Setpoint, Input, Output;

//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT);

void setup()
{
  //initialize the variables we're linked to
  Input = analogRead(0);
  Setpoint = 100;

  //turn the PID on
  myPID.SetMode(AUTOMATIC);
}

void loop()
{
  Input = analogRead(0);
  myPID.Compute();
  analogWrite(3,Output);
}

So if this is really a servo driver or it needs an H bridge (thanks Railroader) then I will take a look at those.

I think what I am mis understanding is the connection between the PID output signal (hardware and software) and the 2 wire motor and how the software needs to drive it…

EDIT. OK, I think I have worked it out. I do need the H Bridge L298n controller to work with the PID library and motor.

So the bridge takes the PWM (speed) signal and two direction signals (backwards and forwards) and I need to assign pins for all three. So that leaves me with the question;

Are there any sketches around for ;
MotorForward() {}
void MotorBackward() {}
void MotorSpeed(byte speed) {}

Given that forwards and backwards will have to sense the control (throttle) pot movement and speed is the PWM signal generated from the same pot?

kpg:
EDIT. OK, I think I have worked it out. I do need the H Bridge L298n controller to work with the PID library and motor.

I think you are right.

kpg:
So that leaves me with the question; Are there any sketches around for:

MotorForward() {}

void MotorBackward() {}
void MotorSpeed(byte speed) {}

There are MANY examples and libraries for using every H-Bridge chip ever produced. Google can find a lot for you.

kpg:
Given that forwards and backwards will have to sense the control (throttle) pot movement and speed is the PWM signal generated from the same pot?

The Output from the PID contains both speed and direction information. The sign of the Output is the direction and the magnitude is the speed. The sketch breaks them apart since motor controllers generally control those two values separately. Some H-Bridge drivers use a single Direction signal. Some use two. Some use one of the direction pins for PWM and some use a separate “Enable” for PWM. Once you select a driver you should be able to use Google to find a library or an example of how to drive it.

So using a L298 which has a PWM input and a forwards and backwards control…

Does this make sense?

The only think I am unsure about is I dont think I have understood is …

void MotorSpeed(byte speed) {}

If I understand it this is the speed (pwm frequency). Do I just analogwrite a value to the pwm pin as in ?

#include <PID_v1.h>


const byte THROTTLE_POT_PIN = A0;
const byte FEEDBACK_POT_PIN = A1;
const int torquePin = 9; //PWM pin to motor driver
const int forwardsPin = 8; //Forwards enable pin to motor driver
const int backwardsPin = 7; //Backwards enable pin to motor driver

//Define Variables we'll be connecting to
double Setpoint, Input, Output;


//Specify the links and initial tuning parameters
double Kp = 2, Ki = 5, Kd = 1;
PID ThrottlePID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);


void setup()
{
  //turn the PID on
  ThrottlePID.SetOutputLimits(-255, 255);
  ThrottlePID.SetMode(AUTOMATIC);
  pinMode(torquePin, OUTPUT);
  pinMode(forwardsPin, OUTPUT);
  pinMode(backwardsPin, OUTPUT);
}


void loop()
{
  Setpoint = analogRead(THROTTLE_POT_PIN);
  Input = analogRead(FEEDBACK_POT_PIN);
  ThrottlePID.Compute();
  int speed = constrain((int)Output, -255, 255);
  if (speed >= 0)
  {
    MotorForward();
    MotorSpeed(speed);
  }
  else
  {
    MotorBackward();
    MotorSpeed(-speed);
  }
}

void MotorForward() {
  digitalWrite(forwardsPin, HIGH);
  digitalWrite(backwardsPin, LOW);
}
void MotorBackward() {
  digitalWrite(forwardsPin, LOW);
  digitalWrite(backwardsPin, HIGH);
}
void MotorSpeed(byte speed) {  
  analogWrite (speed, torquePin);
}

I feel this cant be right as I am not actually changing the duty cycle which controls speed?

If I understand it this is the speed (pwm frequency). 
Do I just analogwrite a value to the pwm pin as in ?

PWM is not about changing frequency. It is about changing the duty cycle, how much of the period is On and how much is Off. The frequency is constant. PWM stands for Pulse Width Modulation.

Using analogWrite is correct. Values used are from 0 to 255. Make sure that no underflow or overflow happends. Use analogWrite (torquePin, speed);

Railroader, yes sorry thanks. I reread my message and I know PWM frequency is fixed (well almost it can be changed) and duty cycle is adjustable which is what PWM does.

Last question hopefully......

The 298n H bridge just needs 5v or 0v on its enable to move the motor so why do I need to analogwrite the speed variable to that pin? Is it because the variable speed (which is a function of the PID libraries 'OUTPUT' in the sketch) is adjusted by the library?

No problem. Using the correct therminology is sometimes very important... I just took a short look at the data sheet of the 298n.

Consider the 298n as a two way switching transistor. When it receives an active pulse, it turns on. When it receives a not active pulse, it turns off. Direction input decides fwd or bwd. Pulse is the actual speed setting input having the PWM from the controller.

It has a logic part receiving the commands from the controller, and a "power part" that runs the motor. The controller is in charge, designing the pulsOn and pulseOff times.

Have You looked at this page: https://components101.com/modules/l293n-motor-driver-module

I think about the piece "L298 Module Features & Specifications:"

Hope this clearify things.

Good link......

So again the enable pins are the speed pins hence the PWM input. The the duty cycle in the sketch and PID library is controlled by the OUTPUT function which in turn is managed in the sketch by...

int speed = constrain((int)Output, -255, 255);

and the eventual write to the enable pin output....

void MotorSpeed(byte speed) {  
  analogWrite (torquePin,speed );
}

Quite correct. Just know that an integer handles the -32768 to +32767, but the PWM, in analogWrite,handles 0 - 255.
The sign, + or -, must be checked, directions decided and speed set to the absolute value. In C there is the function: newValue = ABS(rawValue). Make shure that the PID calculation returns values in the intervall -255 to + 255.

The 293 has several posibilities regarding powering the 5 volt logic. Read the data sheet and go for the setup that suits *Your needs the best. Look for "Brief about L298N Module"