In the summer of 2022, I decided I wanted to apply my controls knowledge to a real system that I would create myself. I decided to create an inverted pendulum, constructed from aluminum extrusion, linear slide rails, and 3D printed parts, and controlled with a 24V DC Motor, an Arduino Mega, and two LiPo batteries.
The system required one actuator, a DC motor, which was attached to the left side of the setup via a 3D printed bracket. Two quadrature encoders were used, one for measuring the position of the gantry, which was attached on the right side of the setup via a 3D printed bracket, and one for measuring the angle of the pendulum, which was held on the gantry by 3D printed parts, shown to the right. The position-measuring encoder, motor, and gantry were connected by a timing belt such that the motor could drive the gantry and the encoder could measure the position. Lastly, an aluminum rod was connected to the other encoder with a 3D printed joint to act as the pendulum. The setup was attached to a table such that the pendulum could swing freely.
The 24V DC motor was driven with a BTS7960 motor driver, which was connected to two in-series 11.1V LiPo batteries. The quadrature encoders had both 1200 pulses per revolution, providing an accuracy of about .0052 radians. Limit switches were placed on both ends of the setup so that the position of the gantry could be calibrated on startup, and so that the program could be terminated when the gantry inevitably slammed into the side rail. All of these components were controlled with an Arduino Mega board.
Due to the lack of a spec sheet for the DC motor(cheap amazon motor!), parameter identification was performed to determine its stall torque and motor constant. This was done simply by disconnecting the gantry from the timing belt, providing step inputs to the motor of differing amplitudes, and measuring the response with the encoder. This data was curve fitted with an exponent to determine the model parameters.
With parametric identification complete, a full model of the system can be constructed in state space form. Friction on the gantry was deemed unnecessary for the model due to its difficulty to model. The state space model is shown on the left, as well as the transfer functions used for the traditional loop shaping control algorithm described next.
The first control algorithm developed for the system used the simple successive loop closure continuous-time loop shaping approach, in which one input is controlled by two separate discrete controllers which take the two encoder measurements as their input.
To upright the pendulum from its stable equilibrium point to its unstable equilibrium point, model predictive control was used. The regulation and terminal penalties were successively tuned to generate a sufficiently good trajectory that did not exceed the input limits or the position bounds, and nearly completely uprighted the pendulum.
It can be seen that the Model Predictive Control inputs did not come close to uprighting the real pendulum, unlike the simulation. This is mostly due to the unmodeled friction disturbances of the gantry and other modeling inconsistencies. Perturbations of the pendulum state must thus be corrected with perturbations along the control input. Optimal control can be applied by developing a constant feedback gain matrix(K) for the nominal uprighted state(LQR control), and then using the Differential Ricatti Equation to march this feedback gain matrix back in time along the nominal trajectory generated using MPC. This generates a LTV set of feedback gain matrices that can be applied to the system during the finite horizon phase of the control.