Pages: [1] 2   Go Down
Author Topic: Pendulum Balance Robot  (Read 2578 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey guys, Its my first post,  so be nice  smiley

For a project I am supposed to create an Inverted pendulum balancing robot, controlled by PID via arduino.

I am using a Mega2560 with the motor shield, and an optical encoder, however I am struggling a little with the code, I dont think I'm too far away, but unfortunately when uploading, nothing happens. I was wondering if anyone could point me where the problem may be? Most of it is assembly of Library codes (Note: I have the encocer, stepper and PID libraries installed, so its not that)

Code:
#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;
const int m = 0;
const int newPosition = 0;
Stepper myStepper(STEPS, dirA, dirB);
Encoder myEnc(20, 21);
PID myPID(newPosition, m, 0, 1, 20, 100, 1);
void setup() {
  myStepper.setSpeed(90);
  Serial.begin(9600);
  Serial.println("Basic Encoder Test:");
}

long oldPosition  = -999;

void loop() {
  myEnc.write(-180);
  long newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    Serial.println(newPosition);

  }
  myPID.Compute();
  myStepper.step(m);
  Serial.println(m);
  delay (1);

}

Currently when the code is ran,  nothig happens, I have tested the stepper motor components in another sketch and then work,  but even when assigning a number for the step (say 200) in this sketch,  the stepper does not move.

Since a picture speaks a thousand words, I have included one below



Thanks for your help, Yew


Moderator edit: Quote tags swapped for code tags
« Last Edit: March 13, 2013, 07:44:26 am by AWOL » Logged

Queens, New York
Offline Offline
Faraday Member
**
Karma: 101
Posts: 3644
"Of all the things I've ever lost, I miss my mind the most" -Ozzy Osbourne
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Nothing happens at all? What about the serial monitor, does that at least give you "Basic Encoder Test:" ?
Do you ever get a print out for Serial.println(newPosition) ?
When does "m" ever change?
Logged

Created Libraries:
TFT_Extension, OneWireKeypad, SerialServo, (UPD)WiiClassicController, VWID

Johannesburg. UTC+2
Online Online
Faraday Member
**
Karma: 99
Posts: 4407
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Currently when the code is ran,  nothig happens

Do you mean that literally?- not even the serial write from setup()?

Edit.... seems HM and I on the same track here...
Logged

The Elders of the Internet know who I am
I'm on LinkedIn: http://www.linkedin.com/in/jimbrownza

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Nothing happens at all? What about the serial monitor, does that at least give you "Basic Encoder Test:" ?
Do you ever get a print out for Serial.println(newPosition) ?
When does "m" ever change?

by 'nothing happens'  I mean there is no movement from the motor, and serial.println Gives a page of 0's, I'm unsure how to measure m, however. (as I'm still a beginner to arduino. smiley-grin
Logged

Johannesburg. UTC+2
Online Online
Faraday Member
**
Karma: 99
Posts: 4407
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Gives a page of 0's

It will, it never changes in that code

Quote
I'm unsure how to measure m

What is m in the first place?
Logged

The Elders of the Internet know who I am
I'm on LinkedIn: http://www.linkedin.com/in/jimbrownza

Queens, New York
Offline Offline
Faraday Member
**
Karma: 101
Posts: 3644
"Of all the things I've ever lost, I miss my mind the most" -Ozzy Osbourne
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The only way for this "Serial.println(newPosition);" to change is if the stepper moves, and the only way the stepper is going to move is if "m" changes. Stepper does not move equals no change in encoder, so your result will ALWAYS be 0.

Change "m" first.
Logged

Created Libraries:
TFT_Extension, OneWireKeypad, SerialServo, (UPD)WiiClassicController, VWID

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Quote
I'm unsure how to measure m

What is m in the first place?

In this code it is the output from the PID,


If I where to '//' out the later serial prints, I should be able to read the optical encoder output right (in this case, 'newPosition')  and It would show the written value,  plus any changes due to the encoder rotation,  correct? However currently it gives;
 
Quote
Basic Encoder Test:
-180

However, since this is a single value,  that doesnt not change with time or rotation,  it suggests something is wrong with the read, or the connections.  the encoder has channels A and B plugged into slots 20 and 21, I have changed the code to include the lines, 'int chanA = 20' and the same for channel B,   the names on myEnc have been altered correspondingly. Unfortunately the Basic encoder test still returns the same written result.

On the bright side,  I seem to be starting to think through this slightly more methodically smiley-grin

EDIT:  If I change 'myStepper.step(m)' to a value of 500, the motor does not move, however the same code in another sketch does...
« Last Edit: March 13, 2013, 09:15:11 am by Yewzorz » Logged

Queens, New York
Offline Offline
Faraday Member
**
Karma: 101
Posts: 3644
"Of all the things I've ever lost, I miss my mind the most" -Ozzy Osbourne
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ok then look at this.
Quote
const int m = 0;
This should NOT be a constant because you want m to change. And in order to change m, it should be getting the value from "myPID.Compute();"

So it should be,
Code:
m = myPID.Compute();

Added:
Where are these ever setup or used?
const int pwmA = 3;
const int pwmB = 11;
const int brakeA = 9;
const int brakeB = 8;

Does your code even know it has a stepper wired to the arduino?
« Last Edit: March 13, 2013, 10:23:03 am by HazardsMind » Logged

Created Libraries:
TFT_Extension, OneWireKeypad, SerialServo, (UPD)WiiClassicController, VWID

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ok then look at this.
Quote
const int m = 0;
This should NOT be a constant because you want m to change. And in order to change m, it should be getting the value from "myPID.Compute();"

So it should be,
Code:
m = myPID.Compute();

I thought something was wrong with that, however using 'int m - myPID.Compute();'  I get an error saying the myPID is not declared in scope,  if I put it before this,  or 'm' is not declared if I put it afterwards.   If i just use 'int m = 0' it says something about 'invalid conversion from 'int' or 'double*'

Logged

Queens, New York
Offline Offline
Faraday Member
**
Karma: 101
Posts: 3644
"Of all the things I've ever lost, I miss my mind the most" -Ozzy Osbourne
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think it would be best to start over and do tests to see if it works, and again after each additional code.
Logged

Created Libraries:
TFT_Extension, OneWireKeypad, SerialServo, (UPD)WiiClassicController, VWID

Offline Offline
Full Member
***
Karma: 5
Posts: 181
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Syntax

PID(&Input, &Output, &Setpoint, Kp, Ki, Kd, Direction)
Parameters

Input: The variable we're trying to control (double)
Output: The variable that will be adjusted by the pid (double)
Setpoint: The value we want to Input to maintain (double)
Kp, Ki, Kd: Tuning Parameters. these affect how the pid will chage the output. (double>=0)
Direction: Either DIRECT or REVERSE. determines which direction the output will move when faced with a given error. DIRECT is most common.
http://playground.arduino.cc//Code/PIDLibraryConstructor
m needs to be a double to work correctly with the PID library
you can cast it to an int for your stepper motor like this if you want
Code:
myStepper.step((int)m);
« Last Edit: March 13, 2013, 10:30:28 am by laadams85 » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think it would be best to start over and do tests to see if it works, and again after each additional code.

Okay,  i have gone back and and sorted out the stepper motor, this code was a second attempt,  and the bits you mentioned I had forgotten to copy over. So now the motor will now step if commanded.

I'm still struggling to input a 'double*' however,  I guess the code ' double int = (something) '  is used,  but I am unsure what to put as the something. I guess a similar thing will happen for the variable 'newPosition'?  to give a variable that has the double format required by the PID? (and hopefully fixing the encoder reader in the process)
Logged

Offline Offline
Full Member
***
Karma: 5
Posts: 181
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
long newPosition = myEnc.read();
Don't do this it will re-define newPosition which will no longer be associated with your PID.

Code:
double m = 0;
double newPosition = 0;
PID myPID(&newPosition, &m, 0.0, 1.0, 20.0, 100.0, DIRECT);
void loop(){
  newPosition = (double)myEnc.read();
}
You may not have to explicitly cast myEnc.read(), but I'm a little rusty on my automatic casts.
« Last Edit: March 13, 2013, 11:13:10 am by laadams85 » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks, The PID isnt throwing up any more errors smiley-grin

I've looked with an oscilloscope,  and the encoder changes its values when rotated in manner that I would expect,  however unfortunately no change its still not showing in the serial monitor, with it sticking at the initial value (now -512) lke this:

Quote
-512.00
Basic Encoder Test
-ÿ-512.00
-512.00
-512.00
-512.00
-512.00

I'm not sure what the Y'' is,  here is the most recent code for good measure.


Code:
#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;
int chanA = 20;
int chanB = 21;
Stepper myStepper(STEPS, dirA, dirB);
Encoder myEnc(chanA, chanB);
PID myPID(&newPosition, &m, 0, 1, 20, 100, DIRECT);
void setup() {
  myStepper.setSpeed(90);
  Serial.begin(9600);
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() {
  myEnc.write(-512);
  newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
    }

Serial.println(newPosition);
     
 
  myPID.Compute();
  myStepper.step(int(m));
  //Serial.println(m);
  delay (1);

}


Thanks a lot for help everyone, every post puts me one step closer to  an  automatic breakfast machine smiley-grin




(edited to fix broken quote '}' )
Logged

Queens, New York
Offline Offline
Faraday Member
**
Karma: 101
Posts: 3644
"Of all the things I've ever lost, I miss my mind the most" -Ozzy Osbourne
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Try this, comment out "myEnc.write(-512);" and spin the encoder, does it give out readings. Whats happening is, your telling the encoder to be set to a value, and then without any actual movement, its reading back that same value.
Logged

Created Libraries:
TFT_Extension, OneWireKeypad, SerialServo, (UPD)WiiClassicController, VWID

Pages: [1] 2   Go Up
Jump to: