Hello, I am beginner in arduino and our project is for the servo motor to move at an angle set by the potentiometer. Our teacher asked us to put PID with it. At first, without PID, it can already move to the desired angle but when we added the PID into the code, it starts to be chaotic and not then sometimes not move at all. Can someone help me with this? Thank you.
Welcome to the forum
Just an idea, but do you think it might help if you posted your code ?
This is without PID:
#include <Servo.h>
#include <SPI.h>
#include <SD.h>
#include <SoftwareSerial.h>
// Define the number of sensors and servos
const int numFlexSensors = 7;
const int numServos = 7;
// Define the flex sensor and servo pins
int masterFlexPins[numFlexSensors] = {A0, A1, A2, A3, A4, A5, A6};
int slaveFlexPins[numFlexSensors] = {A7, A8, A9, A10, A11, A12, A13};
int servoPins[numServos] = {2, 3, 4, 5, 6, 7, 8};
// Define the servo and flex sensor objects
Servo myservos[numServos];
int masterFlexValues[numFlexSensors];
int slaveFlexValues[numFlexSensors];
int servoAngles[numServos];
// Define the SD card and data file objects
File dataFile;
const int chipSelect = 10;
// Define the software serial object for Bluetooth communication
SoftwareSerial BTSerial(9, 11); // RX | TX
// Define the start and stop buttons
const int startButton = 12;
const int stopButton = 13;
// Define program variables
bool programRunning = false;
int numRepetitions = 0;
bool startButtonPressed = false;
bool stopButtonPressed = false;
void setup() {
// Initialize the serial port for debugging
Serial.begin(9600);
// Initialize the servo objects
for (int i = 0; i < numServos; i++) {
myservos[i].attach(servoPins[i]);
}
// Initialize the SD card
Serial.print("Initializing SD card...");
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
return;
}
Serial.println("card initialized.");
// Open the data file
dataFile = SD.open("data.txt", FILE_WRITE);
if (dataFile) {
Serial.println("Data file opened.");
} else {
Serial.println("Error opening data file.");
}
// Initialize the start and stop buttons
pinMode(startButton, INPUT_PULLUP);
pinMode(stopButton, INPUT_PULLUP);
// Initialize the Bluetooth serial communication
BTSerial.begin(9600);
Serial.println("Bluetooth serial communication initialized.");
}
void loop() {
// read the start and stop buttons
startButtonPressed = digitalRead(startButton) == LOW;
stopButtonPressed = digitalRead(stopButton) == LOW;
// if start button is pressed, start program
if (startButtonPressed) {
programRunning = true;
Serial.println("Program started.");
}
// if stop button is pressed, stop program
if (stopButtonPressed) {
programRunning = false;
Serial.println("Program stopped.");
}
// if program is running, move servo motors
if (programRunning) {
for (int i = 0; i < numServos; i++) {
servoAngles[i] = map(masterFlexValues[i], 0, 1023, 0, 180);
servoAngles[i] = constrain(servoAngles[i], 0, 181);
myservos[i].write(servoAngles[i]);
slaveFlexValues[i] = analogRead(slaveFlexPins[i]);
}
} else {
for (int i = 0; i < numServos; i++) {
myservos[i].write(0);
}
}
// save data to SD card every 5 repetitions
if (numRepetitions % 5 == 0 && numRepetitions != 0) {
dataFile.flush();
Serial.println("Data saved to SD card.");
}
// delay before next iteration
delay(10);
// increment the number of repetitions
numRepetitions++;
}
This works fine but when we add PID (we are following this one and change variables to the parameters we want to be manipulated which is angle: Simple motor control with EasyPID.h)
Sorry might be hard to explain and understand some things as I am new to this but would definitely love to learn. Thank you.
Also the motors we are using are: 5 MG996R, 1 FEETECH 35KG.cm Servo Motor, and 1 FEETECH 60KG.cm Servo Motor. Also using ArduinoMEGA for this one.
Post the sketch otherwise how do we know what you did ?
This is the code we are trying to do which is only for a couple of sensor and 1 motor first (not all 7, only 1)
int rflex = A3; // Reference flex
int encoder_flex = A2; // Position Feedback sensor
int val = 0; // reading of the rflex
int encoder_val =0; //reading of enc_flex
float kp = 0.2;
float ki = 0.00000 ;
float kd = 2.00;
float Theta, Theta_d;
int dt;
unsigned long t;
unsigned long t_prev = 0;
int val_prev =0;
float e, e_prev = 0, inte, inte_prev = 0;
void loop() {
val = analogRead(rflex); // Read V_out from Reference Pot
encoder_val =analogRead(encode_flex); // Read V_out from Feedback Pot
t = millis();
dt = (t - t_prev); // Time step
Theta = val; // Theta= Actual Angular Position of the Motor
Theta_d = encoder_val; // Theta_d= Desired Angular Position of the Motor
e = Theta_d - Theta; // Error
inte = inte_prev + (dt * (e + e_prev) / 2); // Integration of Error
V = kp * e + ki * inte + (kd * (e - e_prev) / dt) ; // Controlling Function
if (V > Vmax) {
V = Vmax;
inte = inte_prev;
}
if (V < Vmin) {
V = Vmin;
inte = inte_prev;
val_prev= val;
}
Serial.println(Theta_d); Serial.print(" \t");
Serial.print(Theta); Serial.print(" \t ");
t_prev = t;
inte_prev = inte;
e_prev = e;
delay(100);
}
Hi, @jinnya
Welcome to the forum.
What are you using for feedback of the servo position?
For the PID?
The servo's have their own internal feedback and PID!
What are the flex sensors for?
Can you please explain the application of your project?
Have you tried just PID on ONE SERVO in code ALL on its own?
Can we please have a circuit diagram?
An image of a hand drawn schematic will be fine, include ALL power supplies, component names and pin labels.
Thanks.. Tom..
PID to control a RC-servo does not work. The Servo already has a PID control loop built into it + a lot of other nice stuff that will get in your way if you superimpose a PID on top of it.
The sensors will be for each finger, the left hand is the master while the right hand is the slave. 5 flex sensors will be for command and 5 flex sensors will be used to monitor if the desired angle is met. The feedback will be coming from the flex sensors used to monitor the desired angle.
is it possible to add on a PID on top of the PID of the servo motor? if yes, how? a teacher told us to put one in it so we are currently confused. They also said that they should be able to check the closed loop feedback system in the code so we don't know how to properly implement it.
Hi, @jinnya
Have you understood that the servos have PID built into their own control system.
Adding another PID will not help performance.
What is your feedback for the PID?
Can we please have a circuit diagram?
An image of a hand drawn schematic will be fine, include ALL power supplies, component names and pin labels.
Thanks... Tom...
What did your teacher point out with PID?
Wild guess: "artificial hand" with 5 servos + 5 fingers controlled by "flex sensors" + glove.
yes
they told us to add PID for the control system and that the control system aka PID should be noticeable in the code
uhm what do you mean by what is your feedback for the PID? like the angle detected by the sensor? it is just direct connections like power supply to arduino to sensors and actuators. as for the servos, the one we are using are 5 MG996R, 1 FEETECH 35KG.cm Servo Motor, and 1 FEETECH 60KG.cm Servo Motor.
Hi,
Did your teacher write out the requirements of for your project?
Do you have a hardcopy?
Can you post exactly the instructions you were given?
Thanks.. Tom..
- Able to attain the set angle detected from the master sensor
- Error compensation with 10% tolerance for error, the slave sensor will be the feedback element
just that, we want for the gesture or movement from the slave to be 90% accurate with the master movement
Well, then just do exactly what's asked for. It's totally BS, but probaby your prof did not give a second thought on it. Use arduino PID library and just code it. Be prepared to observe oscillations with f=1hz that you cannot get rid of.
alternative: build a table "servo value" --> "resistance" when the unit is powerd on and then do a direct mapping without PID.
We did the 2nd one the mapping. Not sure with the 1st one but we did a PID library but there's nothing happening in there