This project was the culmination of my Control Applications course (MTE 484). The objective was to design a controller for an inherently unstable "Ball and Beam" system where a motor tilts a beam to roll a ball to a specific position. Unlike simple PID implementations, this project required using Input-Output Parametrization (IOP) to mathematically model the plant and place poles for precise stability. It was a rigorous exercise in system identification, MATLAB simulation, and real-time C++ implementation on an Arduino to handle non-linear physical constraints.
Stabilize a steel ball on a beam and track step inputs (0.1m to 0.25m).
Achieve a 2% settling time of <= 8.5, overshoot <= 45%, steady state tracking error <= 4%.
Design a discrete-time controller using Input-Output Parametrization (IOP).
Implemented a Cascade Control Architecture (Inner/Outer loop) to separate motor angle control from ball position control.
Utilized multi-rate sampling (10ms for inner motor loop, 300ms for outer ball loop) to balance system dynamics with controller feasibility.
Developed a bisected motor scaling algorithm to compensate for physical beam warping and non-linearities.
Achieved a 2% settling time of 4.05 seconds (beating the 8.5 second requirement).
Achieved 0% overshoot (significantly lower than the 45% limit).
Achieved steady state tracking error of 1.4% (requirement was <=4%).
Before designing the controller, we had to mathematically model the physical plant. The system is comprised of a DC motor driving a lever arm, which tilts the beam. This was modeled as a cascade of transfer functions: the motor dynamics (K1, Τ), and the beam kinematics (K2, K3).
We determined these parameters experimentally by analyzing step responses. For example, K3 (the relationship between beam angle and ball acceleration) was found by recording the ball's position over time at fixed angles and taking the second derivative of the best-fit curves. This resulted in a discrete plant model that could be imported into MATLAB for controller design.
Position Plots for The Ball on the Beam at Angles (A) 0.2 radians (B) -0.2 radians (C) 0.4 radians and (D) -0.4 radians
System Block Diagram
In this project, we utilized a dual-loop strategy. The Inner Loop controls the DC motor gear angle, while the Outer Loop calculates the required beam angle to move the ball. The controllers were first designed and validated in MATLAB, then validated in Simulink before being implemented on the Arduino.
Inner Loop (Motor Control): The inner loop required a fast sampling time (10ms) to maintain stability of the motor. We designed a controller using pole placement to ensure that the motor tracked the desired angle. A saturator was implemented in the loop to ensure that the +/-6V voltage limits wouldn't be exceeded.
Outer Loop (Ball Control): The outer loop operates at a slower frequency (300ms). This loop measures the ball's position, compares it to the target, and outputs a reference angle for the inner loop to track. Using MATLAB, we generated a controller that met the settling time and overshoot constraints.
When designing our controllers in MATLAB, we tightened the specifications beyond what was required. This was done as we expected to encounter issues in the real-world that weren't present in simulation. As this made finding feasible controllers more difficult, we designed a MATLAB script to brute-force pole placement. Our script iterated over all possible pole positions within the open unit disk, given our specifications and sampling time.
Step response, Control effort (both for cascaded Simulink controller)
Simulink Model of System
The control logic was implemented in C++ on an Arduino UNO R4. The mult-rate sampling (10ms vs 300ms) was handled by using the Interrupt Service Routine (ISR) as a global clock to trigger flags. This ensured that the inner and outer loops fired at their respective frequencies without bloating the ISR.
The controller transfer function coefficients calculated in MATLAB were exported to the Arduino code with maximum precision (15 decimal places) to prevent rounding errors. To discretize the controller, the transfer function was manipulated to solve for the current control input, which was then fed further into the system. In addition to this, to handle sensor noise in the output graph, a 10-unit moving average filter on the ball position ADC readings was implemented.
Non-Linear Beam Warping: During testing, we discovered a steady-state error where the ball would settle towards the center regardless of the target. This was found to be caused by a physical bend in the steel beam.
Solution: We implemented a bisected scaling method. We virtually split the beam at 0.145m and calculated different linear scaling coefficients (the slope and offset of the equation that converted the ADC value to meters) for the left and right sides. Through this, the steady state bias was eliminated.
Controller Step Response Without Scaling or Anti-Stiction Block Implemented
Ball Stiction: For small error adjustments, the calculated beam angle was often too shallow to overcome the static friction (stiction) of the ball, causing it to stop short of the target.
Solution: We implemented an anti-stiction block that utilizes a small proportional gain multiplied by the outer loop error to supplement the reference angle. This allows the ball to overcome stiction without destablizing the system.
The final controller was highly effective. During real-world testing, the controller reached steady state within 4.05 seconds with zero overshoot. With the scaling and stiction modifications applied, the controller easily tracked the step inputs from 0.1m to 0.25m while satisfying all design requirements.
Final Controller Output with All Modifications Applied and 10-unit Moving Average