Introduction
The
goal of this project was to build and implement an inverted pendulum
balancer, in the vertical two dimensional plane, using Proportional-Integral-Derivative
(PID) feedback control.
The
inverted pendulum balancer is a radio controlled car modified
by adding a plexiglass platform and an inverted pendulum with
free rotating pivot. The electrical component of the balancer
brings together computational hardware (Atmel Mega32 microcontroller),
an input angle sensor (US Digital Optical Shaft Encoder), and
an output motor driver (National Semiconductor LMD18200 H-Bridge)
onto a single board whose sole purpose is to autonomously control
the motion of the car in order to keep the pendulum from falling.
Motivated
by the School of Mechanical & Aerospace Engineering’s
Feedback Control Systems course at Cornell University, our desire
was to integrate the knowledge of stabilizing an unstable system
using feedback control (MAE478), the fast, flexible computing
power of microcontrollers (ECE476), and the use of real-world
engineering tools and budgetary constraints imposed on us by project
managers. The result was a simple, cheap, and fun device that
completed our desired goal.
High
Level Design
Our
motivation originated from Feedback Control Systems (MAE478),
a course that we are both currently enrolled in. We wanted to
attempt at a project where we could implement a feedback controller
with a microcontroller. The question was what to control. After
doing some research, we found a Stanford University EE281 project
by Geoffrey Bainbridge. This "Self-Balancing Robot"
project attempted to design a one-legged robot which balances
itself using a feedback control with Atmel Mega163 microcontroller.
Bainbridge attempted to balance a rod directly connected by two
wheels. He quickly added a third supporting wheel and pivot after
the two wheel design created unwanted rotational motion about
the vertical axis. In addition, Bainbridge used a tilt sensor
to measure the robot’s angle. However, the tilt sensor proved
to be inaccurate due to the combination of the robot’s horizontal
acceleration and the arm’s gravitational freefall.
The
basic structure of the feedback control system is shown below.
The angle sensor reading is subtracted from the reference angle
to produce the error. This error is used to calculate the motor
control parameters using the PID algorithm (discussed below).
The motor control is then sent to the device. We decided to keep
our feedback control system SISO (single-input single-output)
instead of MIMO (multi-input multi-output) for simplicity to help
with our black-box modeling. The reference angle is the only input
to the system, and the feedback control uses the error in angle
from the reference and calculates a motor output.
Our
limited mechanical engineering ability, along with the short timeframe
to complete the project, favored the use of a prefabricated car.
A four-wheeled vehicle would not experience the rotational motion
that Bainbridge encountered in his project. RadioShack’s
extensive selection of toy Radio Controlled cars made our selection
process very easy. Once a stable vehicle with fast response characteristics
was discovered and modified to hold an inverted pendulum, the
search turned to finding a reliable, high-resolution angle sensing
device. The two most viable choices were a MEMS accelerometer
or optical encoder. After initial testing, the analog accelerometer
could not perform as well as the digital encoder. Therefore, the
1024 cycles per revolution (CPR) optical shaft encoder from US
Digital became our angle sensor. This is a vast improvement over
the tilt sensor, as the encoder was not affected by the effects
of gravity or the car’s acceleration.
The
Atmel Mega32 microcontroller was used instead of the Mega163 due
to its superior speed, for external interrupt sampling of the
encoder data, and more versatile timer options. Initial black-box
testing of the car’s DC motor capabilities gave us a good
idea of the car’s performance. Different driving scenarios
were observed, including single-direction driving and oscillatory
motion. Upon finishing motor control, we moved on to testing the
sensor. The optical encoder’s input signals were quickly
converted to an error angle referenced from its initial count
value.
The
final design stage was the Proportional-Integral-Derivative (PID)
Controller to relate angle error to motor velocity and direction
(see equation below). The proportional term (A) applied a voltage
to the motor proportional to the error. This value affected the
cart’s response time; higher the proportional term, the
faster the car’s response at the expense of system stability.
The integral term (B) would correct any steady-state error that
would occur due to any sluggish response by the motor. Integral
control would give the motor a little extra “push”
to ensure correct tracking of the reference angle. However, a
higher integral control term would create oscillations that are
either unrecoverable or may throw the system to instability. Finally,
the derivative term (C) is used to smooth out changes in error
over time. This term can usually smooth out the oscillations in
the vehicle at the expense of slower response. Fine-tuning of
these three variables according to system behavior will allow
the car to balance the inverted pendulum.
Program
& Hardware Design
Hardware
Deisgn - The hardware required for the inverted pendulum
balancer can easily be separated into 2 subsystems: Mechanical
and Electrical.
Mechanical:
Our first priority was to quickly acquire a device capable of
forward and reverse motion, with quick transitions and fast acceleration.
Lacking the knowledge of mechanical cart design and the ability
to gear a motor correctly for sufficient torque to move the cart,
we quickly adopted the idea of using a radio controlled car as
our base. After testing various RC cars from RadioShack, we found
a car
that seemed to have the performance we required, along with a
sturdy base which would easily allow for a pendulum apparatus
to be installed.
The
vehicle’s DC motor was located in an easily accessible location
at the rear underside of the car. Six AA batteries were the manufacturer’s
defined power source; therefore, we knew our power supply would
have to supply at least 9 volts. The six AA’s were installed
with a break in the last contact of the battery holder and an
ammeter (DVM set to measure current) in series to measure the
current drawn by the device. With the car not under load (i.e.
not on the floor with the wheels in the air), the device drew
300 mA. We estimated that under load, the car would require at
least 600-800 mA to run with enough power. After rummaging through
many power supplies in the Phillips Hall Digital Lab, we found
a 12v 1500mA power supply from RadioShack, which would be more
than enough for our needs. It was later discovered that under
load and quick transition in motion, the device actually drew
approximately 900mA from the supply.
Upon
choosing our device, our next task was to build an inverted pendulum
on the car. A Plexiglas plate was used to create a platform on
which to attach the pendulum (see Image
9 ). This plate was secured to the car with 4 bolts at each
corner of the vehicle. At the center of the platform, two brackets
were placed with their inside angles touching each other, connected
by a ¼” screw, and used to create the pivot of the
pendulum (see Figure
3). Finally, a 38” rod (3/8” diameter) was screwed
into the center of the top bracket to create our pendulum. It
would seem strange to have a 38” rod above a 12” car.
The rod’s height, by design, however, acts in our favor,
as the larger moment of inertia (and higher center of mass) actually
slow down the rod’s initial movement. The added weight to
the vehicle would amplify the unwanted effects of the car’s
suspension system. Therefore, four elastic bands were placed around
the car in order to lock the shocks in a compressed position.
With
the pendulum sitting on the top bracket, and the screw acting
as a pivot, our next task was to be able to detect the angle and
direction of the pendulum’s tilt. Our first option was a
MEMS accelerometer from Analog Devices, ADXL202E. However, initial
tests proved that the accelerometer’s analog signal would
not provide us with the resolution that we required for angle
detection. The digital output of the leadless, surface mount ADXL202E
was disabled with the PCB that we used to mount it. Therefore,
we turned to the MAE department, where we were able to borrow
a 1024CPR (cycles per revolution) optical shaft encoder
from MAE478’s feedback lab.
Rather
than using the encoder’s shaft as the pivot, we decided
to use an approach that would put the least amount of stress on
the delicate piece of equipment. The encoder was placed in parallel
with the pendulum’s bracket. The height of the encoder’s
shaft was aligned with the pivot, effectively creating an imaginary
line from the pivot to the encoder’s shaft. Finally, a pin
was attached to the shaft of the encoder, with plastic tie-wraps,
and connected to the pendulum’s bracket. The bracket had
a 0.096” hole drilled above the pivot such that the pin
would fit tightly, without slipping; therefore, when the pendulum
moved, the encoder’s shaft rotated (See Figure
3, Image
3 and Image
4).
Electrical:
Once
the unstable pendulum was assembled and mounted on the car, an
electrical circuit had to be designed to accept information from
the optical encoder, process the information, and then control
the vehicle in forward and reverse motion. We did not need any
radio control circuitry or turning capabilities for our design;
therefore, the car’s motor lines were separated from the
rest of the manufacturer’s circuitry by clipping the wires
leading to the motor. Applying a potential to the motor leads
will cause the motor to spin in one direction, while reversing
the polarity on the leads will cause the DC motor to pin in the
opposite direction. To control the car’s forward and reverse
motion, we required a simple 4-switch device (See Figure
1) that would ensure protection against a short of the DC
supply, that is, switches 1 and 4 or 2 and 3 could never be closed
at the same time. To operate the motor in one direction, simply
close switches 1 and 3; for reverse operation, open switches 1
and 3 and close switches 2 and 4. To stop the motor completely,
simply open all switches.
Rather
than physically implementing each switch as a transistor, the
National Semiconductor LMD18200T H-Bridge was used. This convenient,
11-pin package accepts up to 55V supply voltage and can deliver
up to 3A of output current. The device contains the 4-switch setup
required for our motor control, along with protection diodes and
circuitry to ensure there is never a short from the supply to
ground. Upon connecting the supply (pin 6) and ground (pin 7),
only 3 inputs control the operation of the motor. A break bit
(pin 4) is used to effectively short the output terminals connected
to the motor. Without a potential difference across the motor
leads, the device does not operate. A high break bit implements
this feature; a low break bit will allow current to flow through
the motor. The direction of the motor is determined by the direction
bit (pin 3). When direction is high, output 1 (pin 2) will source
while output 2 (pin 10) will sink, and vice versa for a low direction
bit. Finally, the speed of the motor is determined by a pulse-width
modulated (PWM) signal at pin 5 of the H-Bridge. Speed is directly
proportional to the pulse width at this input; the higher the
duty cycle, the higher the speed of the motor. In addition, for
increased performance, 0.01 µF capacitors were placed from
each output to its corresponding bootstrap pin and a 100 µF
supply bypass capacitor (between motor supply and ground) to absorb
the recirculating currents of the inductive loads, as per manufacturer’s
recommendations. Without this 100 µF capacitor, the motor
behavior was very sluggish. The motor was connected to the H-Bridge
through a 2-pin header (See Figure
2, J3). Two more 2-pin headers were used for debugging purposes.
The first was placed in parallel to the 2-pin motor header(See
Figure 2, J2) such
that voltage across the motor could easily be measured. The second
header was placed in series between the H-bridge’s output
2 (pin 10) and the corresponding motor lead to measure current
going through the motor. Under normal operation, a jumper should
be placed across this header (See Figure
2, J1)
Once
the hardware to drive the motor was identified, we moved to creating
a stand-alone board such that all controls would be on the vehicle.
Using a 6” x 2-1/16” Perf Board, we began laying out
the necessary components for the Atmel Mega32 microcontroller
to run without the STK-500 development board. Our initial board
used a single 12V supply to provide power to both the MCU and
the motor. A Texas Instrument UA7805CKCS voltage regulator was
used to bring a regulated 5V to the MCU. A 0.1 µF capacitor
to ground was placed on each side of the regulator to block any
noise on the line from resetting the MCU. A 16 MHz crystal was
placed across XTAL1 (pin 13) and XTAL2 (pin 12), with a 27 pF
capacitor to ground at each pin. Finally, a 2x3 header was used
to allow for In-System Programming of the Mega32 (See Figure
2). The Vcc line in the ISP header was disabled. Connecting
the ISP’s 5V line, which brings in Vcc from the STK-500
during programming, to the MCU’s regulated Vcc line, which
comes directly from the 12V power supply, could lead to the two
supplies fighting each other if they were both on at the same
time. Therefore, we decided that the best option would be to disable
the ISP’s Vcc line, and always use our 12V supply line.
This, however, required the board to be powered externally when
programming. The MISO (ISP pin 1), SCK (ISP pin 3), MOSI (ISP
pin 4), ~Reset (ISP pin 5), and Ground (ISP pin 6) lines were
connected to the MCU’s pins 7, 8, 6, 9, and 11 respectively
to complete the In-System Programming setup. Finally, we dedicated
PORTD.4, D.5, and D.6 on the MCU as the 3 motor control signals;
Break, PWM, and Direction respectively.
Adding
the optical encoder to the circuit was the final step in the hardware
required to balance the pendulum. Output channels A and B from
the encoder (pins 3 and 5 respectively) were used to trigger external
interrupts on PORTD.2, D.3 respectively. The encoder was connected
to the circuit using a 1x5-pin header, which delivered +5V, ground,
and Channels A and B lines from the MCU to the encoder. (See Figure
2, J4) Turning on the power seemed the only thing stopping
our circuitry at this point.
Once
our software was ready to be tested, problems with the hardware
surfaced almost immediately; the most drastic being noise issues
orignating from the motor. Since only one power supply was used
(12V to the motor and regulated to 5V for the MCU), noise created
when the motor would change directions would travel down the ground
line and reset the MCU, which had an absolute maximum rating of
200mA DC current on Vcc and ground pins. Physically separating
the ground lines (but all leading to the same supply ground) did
not help. This was further seen when tested using the STK-500
and a separate H-Bridge on a prototype bread-board circuit. Since
noise kept resetting the MCU and the only line connecting the
STK-500 to the H-bridge was ground, an isolated ground scheme
had to be used. Therefore, we went from a single supply design
to two supplies, 5V to power the MCU and the encoder, and 12V
strictly to power the motor.
To
completely isolate the motor circuitry, which only consists of
the H-Bridge, from the MCU, three 4N35 opto-isolators are used
to detach the three MCU lines (break, PWM, and direction) from
their H-Bridge counterparts. This device uses an infared diode
to turn a phototransistor on and off. When current passes through
the diode, the transistor is essentially a closed switch, shorting
to ground in our application. When the photodiode is off, the
transistor is an open circuit and the output is high, 12V though
a 1 kOhm pull-up resistor. Since the 12V power supply is not regulated
and usually outputs around 14V, two LED’s in series were
placed between the 12V supply and the pull-up line to bring the
voltage to approximately 11V. This was done because of the H-Bridge’s
absolute maximum input rating of 12V on pins 3,4, and 5. The opto-isolator
is an inverting device, therefore, rather than inputting a signal
referenced to ground, we used 5V as the input and referenced it
to each of the three signals. Once the signals are inverted through
the opto-isolator’s transistor, the correct signals are
passed to the H-bridge, with exception that a logical high is
12V rather than 5V. Since the opto-isolators use phototransistors
that receive IR signals, there is no physical connection between
the MCU's circuitry to the H-bridge. Therefore, no noise from
the motor can go to the MCU.
Adding
the three opto-isolators made board layout very tight. Therefore,
only one power switch is used. The switch controls MCU power,
while 12V motor power is always connected. It is worthy to note
that if no input signals come in to the H-Bridge, the motors do
not run. Both power supplies are connected to the board with two-pin
headers. The complete separation of grounds between the motor
and MCU solved all noise issues, and allowed for high-speed motor
transitions without MCU reset.
Program
Design - There are three main functions in the final
controller code: sensor (encoder) input, PID control calculation,
and motor control output. The motor controller code (test_motor.c)
was written first. The DC motor is controlled via a H-Bridge and
three signals control the break (on/off), speed, and direction
of the motor. These signals were outputted from the pins on Port
D of the microcontroller to pins on the H-bridge. The speed of
the motor is controlled by a pulse-width-modulated (PWM) signal.
The current delivered to the motor is proportional to the pulse-width,
thus the percentage of duty-cycle period determines the speed
of the motor. Since we did not know at what frequency to output
the PWM signal and how sensitively the duty-cycle period would
affect the speed of the motor, we wanted to write a motor driver
code that could change both the PWM signal frequency and duty-cycle
period with ease. For this reason, we picked Port D of the microcontroller.
The OC1A (PD5) pin on port D can serve as an external output for
Timer 1's Output Compare mode. The "Fast PWM Mode" operation
on Timer 1 provides a high frequency PWM waveform generation.
The counter for Timer 1 is incremented from zero to TOP then restarts
from zero. The OC1A is set (pin is set high @ 5V) when the counter
reaches the TOP value. The OC1A is cleared (pin is set low @ 0V)
when there is a compare match between the counter and OCR1A register.
Thus, the TOP value of the counter (along with the clock prescaler
value) determines the frequency and the OCR1A register value determines
the duty-cycle period of the PWM signal being outputted (See Figure
4). In "Fast PWM Mode" of the 3 timers on Mega32,
only Timer 1 allowed to set the TOP value in ICR1 register instead
of fixed values. This allowed for variable frequency of PWM signal.
OCR1A and ICR1 registers are both 16-bit registers, thus the values
had to be set using two write operations, with the high byte always
written before the low byte. Two unsigned integer global varialbes,
motor_PWM_period and motor_PWM_duty were declared. The function
motor_updateDuty() set the high and low bytes of motor_PWM_duty
to OCR1AH and OCR1AL respectively. The function motor_updatePeriod()
set the high and low bytes of motor_PWM_period to ICR1H and ICR1L
respectively.
To
test the frequency and the duty-cycle period of the PWM signal
driving a DC motor, test code (void test_speed()) was written
which utilized the pushbuttons on the STK-500 development board.
Two buttons were defined to increase or decrease the value of
the ICR1 register, which in effect increased or decreased the
frequency of the PWM signal. Two buttons were defined to increase
or decrease the value of the OCR1A register, wihch in effect increased
or decreased the duty-cycle period of the PWM signal. When changing
these register values, the code had to check that the value of
OCR1A was less than the value of ICR1. If the OCR1A value became
larger than the ICR1 value, a compare match between the counter
and OCR1A would never happen because the Timer 1 counter would
reset to zero at ICR1 value. One button was defined to toggle
the direction signal and another button was defined to toggle
the break signal. Using this implementation, we found that setting
the ICR1 value to 300 is sufficient for controlling the motor.
This was equivalent to having 208.3Hz PWM signal ((16e6Hz/256)/300=208.3Hz).
Next,
we developed a function (void motor_controller()) in the motor
test code, where we planned to accpet the output of the PID controller.
The PID calculation would use the angle of the pendulum to calculate
the speed at which to drive the cart. The sign of the error would
determine the direction of the movement of the cart. The function,
motor_controller(), accepts the output of the PID calculation
and sets the speed (duty-cycle period), direction (sign of the
PID output), and duration of time for which to go at this speed.
After these parameters are set, the break is turned off (set low)
and waits until the timer runs out. When the timer runs out, the
break is turned on (set high) and the function ends. It is important
to note that the duration of timer determines the rate at which
the PID calculation is performed. After the function ends, the
code goes back to the PID calculation (see Figure
5) where error of the angle is used to calculate the new speed
and direction. Using this new function, we tested how quickly
the cart can oscillate. The test proved that the cart was capable
of changing directions fast enough, the character behavior that
we suspected that would be required to balance an unstable pendulum.
After
we decided that an optical encoder would be a better sensor for
measuring tilt than an accelerometer, we wrote the sensor controller
code. The encoder converts real-time shaft angle, speed, and direction
into two channel TTL square wave outputs with index pulse. The
resolution is 1024CPR (cycles per revolution), or 1024 cycles
per each 360 mechanical degrees of shaft rotation. The square
wave is outputted on both channels once per cycle. When the shaft
is rotating in a clockwise rotation, channel B leads channel A
by ¼ of cycle period, and when the shaft is rotating in
a counterclockwise rotation, channel A leads channel B by ¼
of cycle period. The index pulse also outputted once per cycle
when both channel A and channel B are low. (See Figure
6) By keeping track of which one of the two channels goes
high first, we can keep track of the rotation of the shaft. By
measuring the timing between rising/falling edges between Ch.
A and B square wave outputs, we can calculate the speed of the
shaft's rotation. We, however, do not care about the velocity
of the shaft's tilt so it was not calculated. On the other hand,
we do care about the angle of the shaft, which can be kept track
of by counting every cycle that the encoder outputs.
To
get the MCU to process all the data outputted from the encoder
turned out to be a tricky task. 1024 cycles per revolution translates
into 360/1024=0.35 mechanical degrees per cycle. For every 0.35
degrees, the encoder outputs two square waves and an index pulse.
The first attempt at trying to count each encoder cycle with the
MCU utilized the External Interrupt pin on Port D (D.2) connected
to the index pulse output of the encoder. The external interrupt
service routine was setup to be triggered on every falling edge
of the index output. According to the specifications of the encoder,
one of the channels would go high at most 300ns after the falling
edge of the index pulse. Since it takes approximately 35 cycles
to enter an ISR (~2e-6 or 2µs), the voltage on channel A
and B are checked at the beginning of the ISR. If one of the channels
is high and the other is low, we know the direction of the rotation
and can increment/decrement the counter accordingly. With this
implementation, the counter seemed to work well when rotated fast
but not slow in one direction and when rotated slow but not fast
in the other direction. This was probably due to the fact that
the ISR was triggered on a falling edge and that the channel's
levels were changing too fast compared to the ISR duration.
After
painful attempt at debugging this implementation, we decided to
try another implementation with two external interrupts (INT0/D.2
and INT1/D.3) connected to the two channel outputs of the encoder.
The external interrupt service routines were triggered on every
logical level change. During the ISR for Channel A, the 0th bit
of the global unsigned char variable sensor_channel would be toggled.
During the ISR for Channel B, the 1st bit of the sensor_channel
variable would be toggled. After each bit toggle in each ISR,
the value of the sensor_channel variable would be checked. If
the value of sensor_channel equaled 1 (0x01) in the ISR for Channel
A, it would imply Ch.A was leading Ch.B, thus counter-clockwise
rotation of the shaft. If the value of the sensor_channel equaled
2 (0x02) in the ISR for Channel B, it would imply Ch.B was leading
Ch.A, thus clockwise rotation of the shaft. For every cycle of
clockwise rotation, the counter variable, sensor_index, was incremented
by one and for every cycle of counter-clockwise rotation, the
sensor_index variable was decremented by one. This implementation
worked like a charm for various speed of rotation in both directions.
The sensor_index variable was declared as an unsigned char, because
we knew that once the pendulum was mounted on the car, the range
of the pendulum would be less than 90 degrees (1024/360*90=256).
The sensor_index was initialized at 128 so that the counter can
count up to 45 degrees in both directions.
Once
the sensor input and the motor output codes were tested independently,
the two logics were merged together and tested first without the
PID calculations (controller.c). This
code was used to drive the motor with manual rotation of the encoder
shaft. At reset of the program, the motor is not driven with any
voltage. When the shaft is rotated for more than 15 degrees in
one direction, the motor was driven in one direction. If the shaft
is brought back to the original position, the motor was stopped.
If the shaft was rotated for more than 15 degress in the other
direction, the motor was driven in the reverse direction. Using
this code, we assured that the the sensor input and motor output
logic were working together.
Implementing
the PID control calculation was pretty straight forward (balancer.c).
The proportional (kp), integral (ki), and drivative (kd) constants
were defined at the beginning of the code. It is worth noting
that the delta t values in the PID equation are absorbed into
these constants. In the pid_controller() function, the error of
the angle is calculated by taking the difference between the sensor_index
value and the init_sensor_index value. At reset of the program,
the sensor_index is initialized to the init_sensor_index value
and is constantly updated via external interrupts from the encoder.
This error, which can be positive or negative value, is then used
to calculate the prorportional, integral, and derivative terms.
The variables are cast to float for these calculations because
the constants could be decimal values. The three terms are added,
the sign of the sum determines the direction, and then its absolute
value is taken. This newly calculated value is the speed of the
motor, or the percent of duty-cycle period of PWM signal. This
value is checked against the max_motor_duty variable, and is changed
to its value if it exceeds the value. This is to ensure that the
duty-cycle period of the PWM signal never exceeds a predefined
threshold (at most 100 percent). The new calculated value is then
passed on to the motor_controller().
The
flow of code is diagramed in Figure
5. In order to prevent the car from moving at high speed in
one direction when the pendulum completely fell to one side, a
safety feature (safty_check()) was implemented at the end of each
PID calculation cycle. The safety_check function has two saftely
check features. The first feature checks the angle of the pendulum
tilt (sensor_index) and if it exceeds approximately 40 degrees
from the reference point, then we assume that the cart has no
chance of balancing the pendulum again and stops the motor operation.
The second feature checks if the cart moves above a predefined
speed (safety_speed) in one direction for a period of time (safety_timer).
This part of the safety feature is to ensure that the safety does
not solely rely on the angle reading of the pendulum from the
encoder. The pendulum can be initialized at any angle, so the
motor can be operating at high speed even if the MCU does not
register the angle of the pendulum as having fell to one side.
Results
of the Design
The
PID constants were determined through systematic trial and error.
Initially, the integral and derivative terms were set to zero
and the proportional term was gradually increased until the system
went unstable. Once we knew the maximum proportional term, we
added the derivative term to smooth the oscillation of the cart.
The integral term remained at zero because the oscillation caused
by the integral term caused the balancer to behave poorly.
We
run the balancer by starting off with the pendulum balanced. Setting
all initial conditions to zero allows the encoder to initialize
upon reset and create a reference angle. A light tap to the top
of the unstable pendulum is all that is required to start the
balancing process. The balancer quickly adjusts itself to recover
the error in the angle. The pendulum successfully completes 5-7
recovery periods on average before the motor/car characteristics
inhibit the quick response needed to recover the angle. The initial
balancing proves that the problem of the inverted pendulum balancer
can be solved, yet our mechanical limitations, namely poor motor/car
performance (gear train slippage and soft-wheel slippage with
the floor, which creates delay in the system as shown below),
keep us from the ultimate feat of infinite balance.
[Delay
block inidcated by e^(jwT) term]
As
long as one adheres to the setup procedures, anyone can operate
the inverted pendulum balancer. The procedure is as follows:
1)
Connect 5V and 12V power lines to correct pins on the circuit
board.
2)
With both power supplies off, balance the pendulum on the car.
3)
Turn on the 12V supply to power motor.
4)
Turn on the 5V supply to allow initialization of encoder.
5)
Gently tap the top of the pendulum in any direction.
See
a video of the inverted pendulum balance for ~8 seconds
The
device will not interfere with any other device in the room. The
only high-frequency device on the board is the 16 MHz crystal,
whose leads are short with capacitors to ground, to keep all noise
at a minimal. The RF circuitry of the RC car is disabled so as
to not interfere with anyone else’s circuitry, let alone
our own. Finally, the PWM signal is at such a low frequency (208.3
Hz) and passes through shielded cable such that it would not radiate
to interfere with anyone else’s circuit. Note: These frequencies
are not the same as those being transmitted by students with RF
projects. This virtually ensures no interference between projects.
The
metal rod used as a pendulum can create a dangerous situation
when placed on a moving vehicle. Therefore, we request that all
observers respect a 10’ safety zone. In addition, a software
safety feature is implemented to apply the break to the motor
if it travels in one direction for more than 2 seconds without
changing directions or if the MCU processes that the pendulum
has fallen more than 40 degrees.
What
We Would Do Differently Next Time
Assuming
the budget constraint is not removed, we would choose our car
more carefully, and base the decision not only on response but
also on mechanical design and stability (rocking, suspension,
etc). The pendulum would be reinforced such that movement would
be restricted to the vertical plane, with no rotational movement
in the pendulum, which causes excess pressure on the encoder and
possible erroneous sensor readings.
Our
entire design process revolved around what we had learned in MAE478.
Towards the end of the semester (and the end of the project),
the feedback course began moving from system analysis to controller
design and system modeling. Using techniques that we had learned
towards the end of the semester in the initial design phase (in
the middle of the semester) would have certainly created a more
robust and precise controller. The ability to model the mechanical
system, to use grey-box analysis (rather than black box analysis),
and apply bode plot and root locus design to create dominant poles
and zeros that make the system perform the way we want it to would
also have made for a more fulfilling design process, where more
knowledge between the two courses could be integrated. Finally,
the noise issue was dragged out for about 4 days while we tried
quick fixes to our original board. The minute this problem was
observed and the noise on the ground line viewed with the oscilloscope
(which showed very high noise spikes around 1V in amplitude),
the new board design (with isolated MCU and motor circuitry) should
have been adopted. This would have given us more time to fine-tune
the PID controller and maybe smooth out some mechanical bottlenecks
that prevented us from longer balancing time.
Conclusion
Throughout
the project, our one worry was that the car/motor’s response
was not good enough for our desired task; this was in fact true.
The car could not balance the pendulum indefinitely. Slippage,
originating in both the gear train and the soft tires (in contact
with the floor), would create a delay in our system that eventually
drove it to instability. The delay made it impossible for the
car to catch up, even though its velocity computations were correct.
However, while we could not balance the pendulum indefinitely,
the limited balancing achieved our main objective, which was to
balance the pendulum. The amount of time for which we balance
is out of our hand with our current budget, yet the prototype
clearly shows that the project can be done, albeit with quality
parts. We are confident that by using our circuit and logic on
a more sound mechanical setup and obviously adjusting PID parameters,
the system can achieve the ultimate feat of indefinite balance.
All
aspects of the design were our own. Of course ideas were taken
from MAE478’s feedback control labs, yet they were not implemented
in the same fashion. In addition, we did request outside help
from persons with a Mechanical Engineering background in our vehicle/pendulum
design. The code and circuit implementation of the design were
our own. We did not have time, however, to fabricate the stand-alone
board. Since we needed a prototype anyway, a perf board circuit
was made and after numerous hours of soldering and debugging the
two different circuits (single vs. dual power supplies), we decided
that time would be better allocated in fine-tuning the PID controller
rather than fabricating a board.
Despite
the short timeframe of ~1 month and the mechanical hurdles encountered,
we are pretty happy with the amount accomplished. The project
was a continuous learning process and it turned out to be one
of the most rewarding experiences at Cornell.
Code
of Ethics Checklist:
1. To accept responsibility in making engineering decisions
consistent with the safety, health, and welfare of the public,
and to disclose promptly factors that might endanger the public
or environment.
Our
inverted pendulum balancer can be a hazard to others standing
within the immediate vicinity of its path of motion. To that
end, we request that all observers maintain a 10’ safety
distance even with our 2 Sec. motor safety check, that is, if
the motor is rotating in the same direction for more than 2
seconds, or the pendlum reaches an angle greater than 40 degrees
from reference, a safety stop is executed.
2.
To avoid real or perceived conflicts of interest whenever
possible, and to disclose them to affected parties when they
do exist.
During
the Spring 2003 semester, another group attempted to balance
the inverted pendulum. While some may find it in our interest
to see our project succeed and out-perform theirs, our philosophy
was to help all groups with any questions they might have. Therefore,
we fully disclosed our method of angle detection to the other
group. We recommended to them that their potentiometer method
may not have enough resolution to detect an accurate angle error,
and that they may want to borrow an encoder from the MechE.
Dept.. In addition, we showed them how to isolate the motor
from the MCU with optoisolators.
3.
To be honest and realistic in stating claims or estimates
based on available data.
Our
original goal was “to build and implement an inverted
pendulum balancer, in the vertical two dimensional plane, using
PID control. Proportional-Integral-Derivative(PID) feedback
control will be implemented using a microcontroller, which will
sense a tilt of the pendulum and govern a motor to balance the
inverted pendulum.” (HW6 - Project Proposal)
There
was no claim of time-frame which the pendulum will balance.
We succeeded in balancing, yet could not achieve the ultimate
task of infinite balance due to the inferior motor/car.
4.
To reject bribery in all its forms.
There
was no bribery involved in our project. No person had anything
to gain by our successful completion of the inverted pendulum
balancer, nor did we have a motive to bribe any person as our
project worked and we were under budget.
5.
To improve the understanding of technology, its appropriate
application, and potential consequences.
Through
our website, we hope to have the ability to reach all those
interested in basic feedback control and practical engineering
using microcontrollers and various salvageable parts.
6.
To maintain and improve our technical competence and to
undertake technological tasks for other only if qualified by
training or experience, or after full disclosure of pertinent
limitations.
The
entire project was a learning process. Our technical competence
improved with every line of code written, every IC soldered.
From identifying the special features of the Atmel Mega32’s
PWM capabilities, to understanding how to isolate a noisy motor
from a sensitive MCU, we learned from each mistake made.
7.
To seek, accept, and offer honest criticism of technical
work, to acknowledge and correct errors, and to credit properly
the contributions of others.
Criticism
of our design was always welcome. Many people thought of different
ways to make our pendulum balance longer. Most ideas, however,
were contrary to all understanding of balancing an object easier.
Yet some criticisms were very helpful. For example, Prof. Land’s
help in isolating the motor from the MCU was probably the most
helpful step in moving from separate motor and encoder testing,
to motor, encoder, and MCU integration.
8.
To treat fairly all persons regardless of such factors as
race, religion, gender, disability, age, or national origin.
This project
shows that two people of different religion, disabilities, age,
and national origin, can work together to achieve a common goal.
9.
To avoid injuring others, their property, reputation, or
employment by false or malicious actions.
At
no time did we perform any malicious actions towards any group
in the ECE476 lab. This directly relates to the conflict of
interest code mentioned above. We did, however, encounter malicious
acts towards us, where someone (accidentally or purposefully)
knocked down our accelerometer with Op-Amp daughter board and
stepped on it. Luckily, we switched to the optical encoder and
did not need the accelerometer.
10.
To assist colleagues and co-workers in their professional
development and to support them in following this code of ethics.
As
mentioned above, any persons in the ECE476 lab that came to
us for help, be it with motor questions or stand-alone board
issues, received our help promptly and courteously.
Appendix
I: Program Listing
Motor
tester code: test_motor.c
Sensor
tester code: test_sensor.c | test_sensor2.c
Controller
code without PID: controller.c
Controller
code with PID: balancer.c
Appendix
II: Schematics
Figure
1: Simple
Motor Switch
Figure
2: Stand-alone
Board Schematic
Figure
3: Mechanical
set up of pendulum pivot and encoder
Figure
4: PWM output of
Timer 1
Figure
5: Code flow sequence
Figure
6: Encoder
channel output from usdigital.com
Image
1: Radioshack
Grinder Monster RC Truck from RadioShack.com
Image
2: US
Digital Optical Shaft Encoder S1 [one on left] from usdigital.com
Image
3: Pendulum
Pivot and Encoder Shaft #1
Image
4: Pendulum
Pivot and Encoder Shaft #2
Image
5: Stand-alone
board with one power supply
Image
6: Stand-alone
board with two power supplies #1
Image
7: Stand-alone
board with two power supplies #2
Image
8: Stand-along
board with two power supplies #3
Image
9: Inverted
Pendulum Balancer [cart/circuit/pivot]
Image
10: Inverted
Pendulum Balancer [overall picture]
Image
11: Inverted
Pendulum Balancer [mounted cirucuit]
Video:
Inverted Pendulum Balancer
[balances for ~8 seconds]
Appendix
III: Parts List
(1)
Atmel Mega32 Microcontroller [lab]
(1)
16 MHz Crystal [lab]
(1)
National Semiconductor LMD18200 H-Bridge [sampled]
(1)
Radioshack Grinder Monster RC Truck (Catalog #: 60-4311) [$11.97]
(1)
US Digital Optical Shaft Encoder (S1-1024-IB) [borrowed from MAE
dept.]
(3)
Optoisolators (4N35) [lab]
(1)
110V 60Hz AC to 12V DC transformer (1500mA max) [lab]
(1)
6"x2-1/16" PC Board [lab]
(1)
Mini slide switch [$0.35 from Jameco #204142]
(5)
.100" Straight Male Headers [$0.16 each from Jameco #108337]
(4)
Wire with 2 pin female connectors [$1.00 each from lab]
(X)
Various resistors, capacitors, and wires [lab]
(1)
7-3/4"x6"x1/4" Plexi glass [scrap]
(2)
L-shaped metal [scrap]
(1)
metal rod [scrap]
(4)
threaded rod [scrap]
(X)
Various screws and nuts [scrap]
TOTAL
COST: $17.12 < $25.00 Budget
Appendix
IV: Task List and Distribution
•
Mechanical assembly of pendulum on the cart - Eitan
•
Circuit layout and soldering - Eitan
•
Coding and documentation - Kenji
•
Testing and debugging - Eitan and Kenji
•
Project documentation - Eitan and Kenji
Special
Thanks to:
Mr.
Beny Sherer for help with mechanical assembly and various advice.
Mr.
Eryk Nice for lending us the encoder and helping us with PID control.
Professor
Bruce Land for all the advice and support.
All
our friends and family for putting up with our complaining.
All
the doubters for the extra motivation to proving you wrong. =)
Josh
for his box...
Appendix
V: Reference
Atmel
Mega32 Datasheet
National
Semiconductor H-Bridge Datasheet
US
Digital Optical Shaft Encoder Specs
Optoisolator
(4N35) Pinout
Stanford
Univ. EE281 Project: "Self-Balancing Robot" by Geoffrey
Bainbridge
|