Hi Guys,
Currently I am working on a PID control based system that will allow my robot to self balance. However, I am having some issues and I am relatively new to Arduino, let alone coding. The current list of parts I am using include:
- Tamaya Double Gear Box with 2 DC Motors from Polulu
- Tamaya Wheel set from Polulu
- AXDL203EB - Dual-Axis Accelometer
- Arduino Uno
- Adafruit Motorshield V2
The main issue I am having is getting my robot to balance and whether or not my coding is correct in this case. I have read a lot in regards to Brett's PID library, Kas' robots, Instructables, and the fourm, but I am still confused on why it doesn't balance. I have encased all my components within a grey box mounted on the side of my robot, which makes its sorta heavy on one side..., but I think my coding may be the real issue? I have attached the code below for anyone who is interested in helping me with this project.
I also tried using the PID library to attempt this, but I ran into a few problems in regards to setting the read speed and the output limits. I tried using the functions but it wouldn't let me do so in my code and gave me an error code.
/********************************************************
* PID Basic Example
* Reading analog input 0 to control analog PWM output 3
********************************************************/
#include <PID_v1.h>
#include <Wire.h> //define wire library
#include <Adafruit_MotorShield.h> //define adafruit motorshield library
//Define Variables we'll be connecting to
double Setpoint, Input, Output;
//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint,1,0,0, DIRECT);
//Specifiy Motor Control Parameters
Adafruit_MotorShield AFMS = Adafruit_MotorShield(); //Define the motorshield as an object
Adafruit_DCMotor *myMotor = AFMS.getMotor (1); //Define motor 1
Adafruit_DCMotor *myMotor2 = AFMS.getMotor (2); //Define motor 2
///Bias Parameters
float Vb = 0;
int sampleNum = 500;
void setup()
{
Serial.begin(115200);
//////////////////// Motor Controller ///////////////////
//turn motorcontroller on
AFMS.begin(); //Turn on the motorshield
myMotor->setSpeed(0);
myMotor2->setSpeed(0);
///////////////////////// PID ///////////////////////
//initialize the variables we're linked to
Input = analogRead(0);
Setpoint = 0;
//turn the PID on
myPID.SetMode(AUTOMATIC);
SetOutputLimits (-255,255);
SetSampleTime (10);
/////////////////////// Vb (Counts) ///////////////////////////
//500 samples of readings Vb
for(int n=0;n<sampleNum;n++)
{
float Accel_X = analogRead(A0);
Vb += Accel_X;
}
Vb = Vb/sampleNum;
delay(1000);
}
void loop()
{
Input = analogRead(0);
Input = Input - Vb;
Input = Input * 0.00488758553;
Input = Input / 0.0159;
myPID.Compute();
float wer = analogRead(0);
if ( Output > 0)
{
myMotor->setSpeed(abs(Output));
myMotor2->setSpeed(abs(Output));
myMotor->run(BACKWARD);
myMotor2->run(BACKWARD);
}
else if (Output < 0)
{
myMotor->setSpeed(abs(Output));
myMotor2->setSpeed(abs(Output));
myMotor->run(FORWARD);
myMotor2->run(FORWARD);
}
}
Balancing_Attempt_5.ino (9.19 KB)
Try putting "myPID." before the name "SetOutputLimits" so it knows which PID you are talking about. Same for "SetSampleTime".
You can leave this part out:
Input = Input * 0.00488758553;
Input = Input / 0.0159;
The PID will work just as well on the un-scaled values.
One problem that I see is that your motors probably won't start to move until the PWM value (Output) goes high enough. I mean, there is some minimum value of PWM to get the motor to move at all so you might need to a bit of "bias".
Adding the myPID. in front of the code worked, however I am not quite sure what you mean by the motor bias. How exactly would i implement in this bias especially if the motors are already given the command to run up to its maximum 255 PWM?
As an update my PID doesn't run anymore... after i changed the settings and I am not quite sure why it dose this
What exactly do you mean by "doesn't run anymore"?
SegwayRobo:
As an update my PID doesn't run anymore... after i changed the settings and I am not quite sure why it dose this
If you want help with that: Show your sketch and describe what it does different from what you thought you told it to do.
So the code is using a PID controller in order to make the robot self balance. I am currently using an ADXL-203EB accelometer as my sensor and DC motors from a Tamiya Double Gearbox kit. My understand of code is that it will take the sensor readings and convert it into an angle and take 0 as the setpoint. The PID would then attempt to control the motors to get the sensor readings back to 0 and output a PWM between -255, 255 to control the motors. The negative -255 would represent a backwards movement and 255 forward, note that in the code this is reversed on motor commands because the polarity of the motors were switched. However, when I run this code it does nothing...
/********************************************************
* PID Basic Example
* Reading analog input 0 to control analog PWM output 3
********************************************************/
#include <PID_v1.h>
#include <Wire.h> //define wire library
#include <Adafruit_MotorShield.h> //define adafruit motorshield library
//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,7, DIRECT);
//Specifiy Motor Control Parameters
Adafruit_MotorShield AFMS = Adafruit_MotorShield(); //Define the motorshield as an object
Adafruit_DCMotor *myMotor = AFMS.getMotor (1); //Define motor 1
Adafruit_DCMotor *myMotor2 = AFMS.getMotor (2); //Define motor 2
///Bias Parameters
float Vb = 0;
int sampleNum = 500;
void setup()
{
Serial.begin(115200);
//////////////////// Motor Controller ///////////////////
//turn motorcontroller on
AFMS.begin(); //Turn on the motorshield
myMotor->setSpeed(0);
myMotor2->setSpeed(0);
///////////////////////// PID ///////////////////////
//initialize the variables we're linked to
Input = analogRead(0);
Setpoint = 0;
//turn the PID on
myPID.SetMode(AUTOMATIC);
myPID. SetOutputLimits (-255,255);
myPID. SetSampleTime (10);
/////////////////////// Vb (Counts) ///////////////////////////
//500 samples of readings Vb
for(int n=0;n<sampleNum;n++)
{
float Accel_X = analogRead(A0);
Vb += Accel_X;
}
Vb = Vb/sampleNum;
delay(1000);
}
void loop()
{
Input = analogRead(0);
Input = Input - Vb;
myPID.Compute();
Serial.print(Output);
if ( Output > 0)
{
myMotor->setSpeed(abs(Output));
myMotor2->setSpeed(abs(Output));
myMotor->run(BACKWARD);
myMotor2->run(BACKWARD);
}
else if (Output < 0)
{
myMotor->setSpeed(abs(Output));
myMotor2->setSpeed(abs(Output));
myMotor->run(FORWARD);
myMotor2->run(FORWARD);
}
}