Real-Time Systems

Laboratory 1: Control of the Ball and Beam Process

2019 Version


Preparatory Exercise

In order to be allowed to do this laboratory, you must be able to show a working solution to the The Ball and Beam Control exercise from Exercise 3.


Introduction

Your task is to write a Java program that controls the physical ball and beam process. The Java program should consist of two parts:

The main difference between the new Regul class and the one used in Exercise 3 is that the GUIs for the inner PI controller and the outer PID controller are now implemented by OpCom rather than by internal GUI classes.

A predefined ReferenceGenerator class is used to provide the reference signal. This class has its own GUI. From the GUI you can decide to either use a squarewave signal as the reference or to manually set the reference using a JSlider.


OpCom

The public interface of OpCom is the following:

  // Constructor. Note: Different from Exercise 4.
  public OpCom(int plotterPriority);
  
  // Passes in a reference to Regul. Called from Main.
  public void setRegul(Regul r);

  // Build up the GUI. Called from Main.
  public void initializeGUI();

  // Starts the plotting within OpCom. Called from Main.
  public void start();

  // Insert a new DoublePoint containing the current time (x) and 
  // control signal (y) into a PlotterPanel in OpCom.
  // The documentation for DoublePoint can be found here.
  public void putControlDataPoint(DoublePoint dp);
  
  // Inserts a new PlotData containing the current time, reference and
  // measured value into a PlotterPanel in OpCom.
  public void putMeasurementDataPoint(PlotData pd);

The control modes are represented as

  public static final int OFF = 0;
  public static final int BEAM = 1;
  public static final int BALL = 2;

PlotData

The PlotData class looks as follows:

  public class PlotData implements Cloneable {
    double ref, y;
    double x; // holds the current time

    public Object clone() {
      try {
        return super.clone();
      } catch (Exception e) {
        return null;
      }
    }
  }

Regul

The Regul class should contain one PI controller for the inner loop and one PID controller for the outer loop. Use a single thread for the execution of both the controllers in the same way as in the exercise. Regul receives its reference signal by calling the getRef() method of the ReferenceGenerator.

The controller should use the cascade structure according to the figure below. The code should be written so that the delay between the sampling of the measurement signals and the generation of the control signal is minimized.

Cascaded Controller Tracking

Regul should run in one out of three different modes: BEAM, BALL, and OFF. In the mode OFF the control signal (u) = 0 should be sent out. The regul thread should still be executing. In each loop, the regul thread should call putControlDataPoint() and putMeasurementDataPoint() in OpCom. If the mode is OFF the signals sent to OpCom, (y, yref and u) should all have the value 0.

A major difference compared with the exercise is that you now use real analog IO classes rather than the classes that communicate with the virtual process. The following code example shows how to use these classes:

  import se.lth.control.realtime.*;
  
  class IODemo {
    public static void main(String[] args) {
      AnalogIn yChan;
      AnalogOut uChan;
      double y;
      try {
        uChan = new AnalogOut(1);
        yChan = new AnalogIn(1);
      } catch (Exception e) {
        System.out.println(e);
        return;
      }
      
      try {
        uChan.set(0.0);
      } catch (Exception e) {
        System.out.println(e);
      }
      
      try {
        y = yChan.get();
      } catch (Exception e) {
        System.out.println(e);
      }
    }
  }

A difference compared to Exercise 3 is that the reference signal now is plotted by the GUI rather than by the virtual simulator. Hence, the reference signal should no longer be output using an analog output. Instead, the reference signal should be sent to OpCom by calling putMeasurementDataPoint().

Regul Public Interface

The Regul class should have the following public methods:

  // Constructor
  public Regul(int priority);
  
  // Passes in a reference to OpCom. Called from Main.
  public void setOpCom(OpCom o);
  
  // Passes in a reference to ReferenceGenerator. Called from Main.
  public void setRefGen(ReferenceGenerator r);
  
  // Starts the regul thread. Called from Main.
  public void start();

  // Set the parameters of the inner PI controller (inner controller).
  // The PIParameters class is the same as in Exercise 3.
  // Not synchronized, the synchronization is handled by PI.
  public void setInnerParameters(PIParameters p);

  // Returns the current parameters in the inner loop.
  // Only called during OpCom GUI initialization.
  // Not synchronized, the synchronization is handled by PI.
  public PIParameters getInnerParameters();

  // Set the parameters of the outer PID controller (outer controller).
  // The PIDParameters class is the same as in Exercise 3.
  // Not synchronized, the synchronization is handled by PID.
  public void setOuterParameters(PIDParameters p);

  // Returns the current parameters in the outer loop.
  // Only called during OpCom GUI initialization.
  // Not synchronized, the synchronization is handled by PID.
  public PIDParameters getOuterParameters();

  // Set the controller in OFF mode.
  // Use an internal monitor class to store the current control mode.
  public void setOFFMode();

  // Set the controller in BEAM control mode.
  // Use an internal monitor class to store the current control mode.
  public void setBEAMMode();

  // Set the controller in BALL control mode.
  // Use an internal monitor class to store the current control mode.
  public void setBALLMode();

  // Returns the initial control mode.
  public int getMode();

  // Called from OpCom when the Stop button has been pressed,
  // before the system is shut down.
  public synchronized void shutDown();

PI and PID

Use your PI and PID classes from Exercise 3 with the following extensions:

  // PI
  
  // Sets the I-part of the controller to 0.
  // For example needed when changing controller mode.
  public synchronized void reset();
  
  // Returns the current PIParameters.
  public synchronized PIParameters getParameters();
  
  
  
  // PID
  
  // Sets the I-part and D-part of the controller to 0.
  // For example needed when changing controller mode.
  public synchronized void reset();

  // Returns the current PIDParameters.
  public synchronized PIDParameters getParameters();

Main

The following Main class should be used.

  import javax.swing.*;

  public class Main { 
    public static void main(String[] argv) { 

      final int regulPriority = 8; 
      final int refGenPriority = 6; 
      final int plotterPriority = 7; 

      ReferenceGenerator refgen = new ReferenceGenerator(refGenPriority); 
      Regul regul = new Regul(regulPriority); 
      final  OpCom opcom = new OpCom(plotterPriority); 

      regul.setOpCom(opcom); 
      regul.setRefGen(refgen);
 
      opcom.setRegul(regul); 

      Runnable initializeGUI = new Runnable(){
	public void run(){
          opcom.initializeGUI();
          opcom.start();
	}
      };
      try{
        SwingUtilities.invokeAndWait(initializeGUI);
      }catch(Exception e){
        return;
      }

      refgen.start(); 
      regul.start(); 
    } 
  }

Structure Diagram

The design can be summarized in the figure below. The notation introduced in the Buttons exercise is used.

Module Overview

NOTE: In the diagram, the PI and PID classes are drawn as if they are inner classes of Regul but it is probably easier to keep them as ordinary, "top-level", classes.


Process Interface

The output signals from the process (angle and position) are voltages in the interval [-10, 10]. The angle measurement should be connected to AI 0 on and the position signal to AI 1.

The input signal to the process (the control signal) is a voltage in the interval [-10, 10]. The control signal should be connected to AO 0.

Since we only have four physical processes you will have to share these among the groups.


  1. Update your PI and PID classes using the modified interface.
  2. Implement Regul based on your BeamRegul and BeamAndBallRegul classes from Exercise 3. It should use external IO instead of the simulator IO. Make sure that it sends plot data to OpCom in the correct way. You may download and use Regul.java as a starting point.

To be able to build you need the following classes:

Make sure that:
  1. The I/O delay, that is the delay between sampling of the measurement signals and the generation of the control signal, is minimized.
  2. The lock times aren't longer than necessary.
  3. The outer loop tracking is in accordance with the structure figure above.
  1. Test your program against the real ball and beam process.


Time-Optimal Feedforward Generator

In the next part you will extend the previous control-structure with a time-optimal feedforward generator. You have already been provided all the necessary classes for this, and will only have to do some minor changes in order to make it work. Before moving on, you should recall the lecture slides from Lecture 10.

Below you can see a block diagram for the new control structure. To change your current control-structure into this, you will need to call two new methods from the reference generator in order to get the feedforward terms: referenceGenerator.getPhiff() and referenceGenerator.getUff(). You should also recall from the lecture that when using the feedforward generator you will need to use gamma=1 when computing the D-term in the PID-controller. Therefore, in PID.java you will have to change D = ad*D - bd*(y - yOld) to D = ad*D + bd*(e - eOld) (NOTE the plus-sign!)

Feedforward Block Diagram

  1. Update the Regul.java to use the new feedforward signals
  2. Update PID.java to use gamma = 1:
    D = ad*D - bd*(y - yOld) should be changed into
    D = ad*D + bd*(e - eOld)
  3. Compile and test the new system using time-optimal feedforward generator. Remember to switch the reference generator into "Time-optimal mode". Do you see any difference?