How to control a servo motor using a PID control with input from current sensor. I am not so proficient in arduino and in coding so can anyone please help me. I want to create a closed loop using pid for controlling servo with current sensor acs70331.
Have you looked at the PID library? Any library for the ACS70331?
I dont think there is any library for the current sensor. It just gives analog values(the same value of current shown in power supply.according to the value of current given by the current sensor the motor has to move and the position must be maintained using pid).
What have you done so far ?
Can you read the sensor and print the value returned to the Serial monitor ?
Can you convert the sensor value into a range that can be used to control the servo ?
Can you write the converted value to the servo ?
How are you powering the servo ?
I realise that the above questions do not relate to the use of a PID but we have no knowledge of your level of expertise
Have you installed the PID library and looked at the examples it contains ?
Just a heads-up… there’s a difference between a servo (self contained), and a servo motor - which is driven independently by a feedback loop.
I assume you’re talking about a self-contained RC style servo .
- Yes. I am able to read the values from the sensor and is able to print those values.
2.No. can you please give an idea on how to do that. At present how I obtained the value of current sensor from the servo is the by the code shown below.
for current sensor:
void setup() {
Serial.begin(9600); //Start Serial Monitor to display current read value on Serial monitor
}
void loop() {
unsigned int x=0;
float AcsValue=0.0,Samples=0.0,AvgAcs=0.0,AcsValueF=0.0;
for (int x = 0; x < 150; x++){ //Get 150 samples
AcsValue = analogRead(A0); //Read current sensor values
Samples = Samples + AcsValue; //Add samples together
delay (3); // let ADC settle before next sample 3ms
}
AvgAcs=Samples/150.0;//Taking Average of Samples
//((AvgAcs * (5.0 / 1024.0)) is converitng the read voltage in 0-5 volts
//2.5 is offset(I assumed that arduino is working on 5v so the viout at no current comes
//out to be 2.5 which is out offset. If your arduino is working on different voltage than
//you must change the offset according to the input voltage)
//0.185v(185mV) is rise in output voltage when 1A current flows at input
AcsValueF = -
(.259 - (AvgAcs * (5.0 / 1024.0)) )/0.8;
Serial.println(AcsValueF);//Print the read current on Serial monitor
delay(50);
}
Actually what i want is a code by which from the Analog value of the input sensor, using PID control I want to control the servo by its angle.
Its a RKI-1023. There is no inbuilt pid setup in it.
Please follow the advice given in the link below when posting code. Use code tags (the </> icon above the compose window) to make it easier to read and copy for examination
Why do you need PID for this?
the servo I am using doesn't have pid. I am using this servo for gripper. So in order for gripper to hold an object firmly it needs pid
Hi, @ajithdevan
Welcome to the forum.
Can you tell us your application please?
What are you ultimately trying to control?
We may be able to suggest other solutions if we know the scope of your project.
Thanks.. Tom..
I want to make a closed loop system using current sensor for a gripper. Since the gripper should neither hold so much force nor leave the object I need to use pid control. So I am looking for an arduino code by which from the analog input values of the current sensor to the arduino I can hold the angle for the servo. A particular value of current sensor is taken as set point. And if the current increases more than the set point the servo should move backwards and if the current value is less than the setpoint it should move forward. can u please help...
application is to grasp an object by a gripper
Hi,
So you want to control the "Pressure" of the grip?
Tom...
Yes... u are right
I don't see a need for PID here, most especially to start with. A simple feedback loop where you close the gripper a bit at a time measuring current as you go until it's at the set point should do it.
If necessary you can make the algorithm more clever.
PID would actually be a problem I think because you not want any overshoot at all if the object being gripped is fragile.
yes you are right... if you don't mind can you please help me in this coding. Can you please give me the code... I am bit confused on how to do it...
can you please give me the code if you dont mind. Thank you
Hi,
We will help with code, it is not a case of GIVING you code, but helping you develop it, that way you learn about your project.
Have you got code that makes the servo sweep?
You have code to read the current sensor, now write code to JUST make the servo sweep.
What servo do you have?
Can you post a link to specs/data?
Can you please post a circuit diagram?
How are you going to power your project?
Thanks. Tom...
#include <PID_v1.h>
#include <Servo.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,P_ON_M, DIRECT); //P_ON_M specifies that Proportional on Measurement be used//P_ON_E (Proportional on Error) is the default behavior
Servo servo_1; // servo controller (multiple can exist)
int servo_pin = 3; // PWM pin for servo control
int pos = 0; // servo starting position
void setup()
{
Serial.begin(9600);//start serial monitor to display current values on a serial monitor
servo_1.attach(servo_pin); // start servo control
servo_1.write(pos); // move servo to grasp object
Serial.println("Positioned to grasp");
//initialize the variables we're linked to
Input = analogRead(A0);
Setpoint = 0.68;
//turn the PID on
myPID.SetMode(AUTOMATIC);
}
void loop()
{
unsigned int x = 0;
Setpoint = 0.68;
float AcsValue = 0.0, Samples = 0.0, AvgAcs = 0.0, AcsValueF=0.0;
Input = analogRead(A0);
myPID.Compute();
//analogWrite(3,Output);
AcsValue = analogRead(A0);
Samples = Samples + AcsValue; //Add samples together
delay (3); // let ADC settle before next sample 3ms
AvgAcs=Samples/150.0;//Taking Average of Samples
AcsValueF = -
(.259 - (AvgAcs * (5.0 / 1024.0)) )/0.8;
Serial.println(AcsValueF);
delay(50);
if(Setpoint > Input)
{
//String in_char = 0;
//servo_1.write(in_char.toInt());
//servo_1.write(0);
analogWrite(3,OUTPUT);
analogWrite(3,HIGH);
}
else if(Setpoint < Input)
{
//String in_char = "90";
//servo_1.write(in_char.toInt());
// servo_1.write(90);
analogWrite(3,OUTPUT);
analogWrite(3,LOW);
}
}