Go Down

Topic: Pendulum Balance Robot (Read 9196 times) previous topic - next topic


I'm pretty sure you need to use an interrupt
attach the encoder to pins 2 and 4
Code: [Select]
Encoder encoder(2, 4);

        void setup() {
            attachInterrupt(0, doEncoder, CHANGE);
            Serial.begin (9600);

        void loop(){
            // do some stuff here - the joy of interrupts is that they take care of themselves

        void doEncoder(){
            Serial.println( encoder.getPosition() );


It looks like you are using a different encoder library.  Seems to be several out there.  Just try using the encoder on different interrupt pins.


Mar 13, 2013, 06:17 pm Last Edit: Mar 13, 2013, 06:19 pm by laadams85 Reason: 1
Also try putting this bit in the setup
Code: [Select]
You may be setting the encoder faster than the interrupt can update, also you won't get far from -512 as it is incremental and you are basically resetting it during the loop.

edit: and why -512 and not 0


Mar 18, 2013, 04:57 pm Last Edit: Mar 18, 2013, 05:05 pm by Yewzorz Reason: 1
Hey guys,  I have disabled the line setting the encoder at -512,  and now the encoder reads the value correctly.  :D Unfortunately the motor isnt working,  the output from the PID is still constant , despite the Position changing

Any thoughts,  I think its the PID causing the issues now,  as the encoder reads correctly,  and motor moves when an step is put in to it.

heres the code
Code: [Select]
#include <PID_v1.h>
#include <Encoder.h>
#include <Stepper.h>
const int pwmA = 3;
const int pwmB = 11;
const int brakeA = 9;
const int brakeB = 8;
const int dirA = 12;
const int dirB = 13;
const int STEPS = 200;
double m = 0;
double newPosition  = 0;
double Position = 0;
int chanA = 20;
int chanB = 21;
Stepper myStepper(STEPS, dirA, dirB);
Encoder myEnc(chanA, chanB);
PID myPID(&Position, &m, 0, 1, 20, 100, DIRECT);
void setup() {
pinMode (pwmA, OUTPUT);
 digitalWrite(pwmA, HIGH);
 pinMode(pwmB, OUTPUT);
 digitalWrite(pwmB, HIGH);
 pinMode(brakeA, OUTPUT);
 digitalWrite(brakeA, LOW);
 pinMode(brakeB, OUTPUT);
 digitalWrite(brakeB, LOW);

long oldPosition  = -999;
void loop() {
 newPosition = myEnc.read();
 if (newPosition != oldPosition) {
   oldPosition = newPosition;
   Position = ((newPosition/11.37)+180);
   if (Position > 180) {
   Position = Position -360;
   if (Position < -180) {
   Position = Position +360;


Just for referance,  the  PID wants the motor to move 536 steps no matter the actual location, I'm not sure why.


I'm glad that you got the encoder to work properly.  To get the PID to work you are going to have to tune the PID.  There are several ways to do this, but I'll borrow from wikipedia for the easiest way.
-Set the I and D terms to zero.
-Increase the P term until the system oscillates.
Then set your values based on the table found here
I would also suggest printing out the double value of m as well as the integer value of m.  Maybe it is changing but not enough to make a difference.
Code: [Select]


Hi everyone,  unfortuantely I'm still having no luck,  the PID output it still remaining constant. I have tried normalising the position data between 0-1, however that has not given a response. Changing the P value has no effect on the output,  neither does changing the position. Has anyone got any thoughts on what might not be working?


Is the PID on?

//turn the PID on

My GitHub:


tobo bolta hai - "sab galat hai ye BC"


Is it even feasible to control an inverse pendulum using a PID regulator reliably? I mean, it depends on the length of the said pendulum, but from what I recall, it's usually better to use a state feeback with observer. Hmmmmm although Maybe a lead regulator or a PD one would suffice. This being said, you'd probably need a really fast feedback loop, so I would treat the loop code as speed critical.

Go Up