PID Function with pLtouch 101g using Android

The following example project the want to show in this post talks about an example of Pid Control with Android.

Particullary will be explained how to use the PID function for controlling heat using pLtouch 101g  .

There are two default Pid functions:
The first function PID has analog Input 1 attached to Analog Output 1
The first function PID has analog Input 2 attached to Analog Output 2

In this case the PID mode the we are going to use is for heating and we will use function PID1; so that when heat drops it will encrease ServoControl based on a Set Point Updatable from the touch Screen.

For this we are going to need:

- pLtouch  101g
- heat sensor mod. pt100
- converter pt100 to 0..20 mA
- modular ServoControl 0..10 V
- 24 VDC poewr supply

Let’s get into practice:


For acquirng the heat, we use a normal probe mod. PT100.

Because pLtouch 101g has 4 power inputs, we use a converter capable of converting the heat in a signal of current with a range between 0 … 20 mA. We link the converter Output at the first analog inpu of pltouch 101g, with its own clamp VA0 ( maggiori dettagli ).
The Pid function will Lead the exit, in this case, a modular ServoControl with input 0…10 V so we link the first Output in tension of pLtouch 101g, at the Actuator like from scheme.
In case you have Actuator or ServoControls with comand in current linked like from the description of our wiki page.

Feed pLtocuch 101g at 24Vdc with removable camps on the back of the case.

That made, we open Eclipse IDE.
Suppose that we already created an Android project, otherwise please read our blog, import and using Pltouch Library (Read our article about it). It serves to implement to your Activity our interface PltouchListener. Thanks to that you can put your code inside of the callback onLogicExecution, like for example:

public class MainActivity extends Activity implements PlTouchListener, OnClickListener {

	private PltouchManager pManager;
	private TextView analog1,analog1_mA;
	private TextView analog2,analog2_mA;
        private Button btnonPID1;
	public EditText SetPid1,SetOut;
	private int index;
        public double z = 0;
	public double m =0;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		pManager = new PltouchManager(this);
		pManager.setDebug(true);
		pManager.initialize();
		pManager.addListener(this);

         };

The code inserted inside our callback onLogicExecution will be executed sequentially, an infinite amout of time inipendently from all the rest. One important thing to know is that Everty call inside the method will be executed in a different thread from that of the UI: This implies that if you want to update a a graphical widget inside onLogicExecution, you must to use a call like in the following example:

@Override
	public void onLogicExecution() {
		Log.d("Pltouch", "on logic execution");

		runOnUiThread(new Runnable() {

			@Override
			public void run() {
			TextView ValueResult = (TextView)findViewById(R.id.textView1);
			ProgressBar progressBar = (ProgressBar)findViewById (R.id.progressBar1);
			final EditText SetPointPID1 = (EditText) findViewById(R.id.editTxtPID1);

			Switch sw1,sw2;
			sw1 = (Switch) findViewById(R.id.switch00);

			sw1.setOnClickListener(new OnClickListener() {
				@Override
				public void onClick(View v) {
					boolean isChecked = ((Switch) v).isChecked();
					boolean value = (isChecked) ? true : false;

					try {
						pManager.setPidStatus(1, value); // start PID
						} catch (ConnectException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						} catch (IndexOutOfBounds e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				});

				try {
					z = pManager.analogRead(1);  //read analog input 1
					double x = Math.floor(z);
					m = x/100;                   //transform into temperature

				} catch (IndexOutOfBounds e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (ConnectionError e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

				ValueResult.setText(String.valueOf(m)); //I represent on screen

	SetPointPID1.setOnEditorActionListener(new OnEditorActionListener() {
	              public boolean onEditorAction1(TextView arg0,
	                      int actionId, KeyEvent arg2) {
	                    // TODO Auto-generated method stub
	                  if (actionId == EditorInfo.IME_ACTION_NEXT) {
	                  }
	                  return false;
	              }
		          @Override
			public boolean onEditorAction(TextView v, int actionId,
					KeyEvent event) {
				if (SetPointPID1.getText().toString().equals("")) {

				}else{
					int setpointPid1 =Integer.parseInt( SetPointPID1.getText().toString());
					try {
						pManager.setPidSetPoint(1, setpointPid1); // write set point
					} catch (ConnectException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (IndexOutOfBounds e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}

				return false;
			}

	          });
	}

I deliberatly choosen to not focalize interface Design aspect, but on the most tecnical aspects of the project. Can be you, reader, that you can with your fantasy the best interface responding to your needs.
Let’s go into code detail:


- Set direction of the function, constants Kp-Ki-Kd and the sampling speed
- We read the analog input and we show it to he Monitor
- we Set the Set Point
- We active the PID function

We set Kp-Ki-Kd constants and the sampling speed:

We use function from Library: pManager.setPidParameters(function,direction,kp,ki,kd,ts);

This parameters can be instantied at App startup or you can call it in any moment. In our case we have a button that calls the function from Library.

From this instruction we set :
function: corrisponds to wich function we use ( in this case function 1)
direction: corrisponds to the direction of the Output
There are two possibilities :
-DigitalValues.HIGH
-DigitalValues.LOW
(in our example we want to warm so that we use DigitalValues.Low; at Heat decreasing it encrease Output)
kp : proportional constant ( 5 in this case)
ki : integral constant ( 14 in this case)
kd: derived constant ( 4 in this case )
ts: Sampling time in ms ( 100 in this case )

We read analog input and we show it on screen:

We read analog input 1 putting it on the variable z so that we can convert it in heat and show at video.

z= pManager.analogRead(1);

LIke you see, simply call the Library pManager.analogRead And assign reference to Analog Input.

Like from picture :
1 = First input analog clamp VA0

Now we show to screen the value this way:

double x = Math.floor(z);
m = x/100;

ValueResult.setText(String.valueOf(m));

We set Set Point with PID function:

Insert an editText named editTxtPID1 and with a simple control in case the field it’s not empty we the Library pManager and we set the value on Set Point like that :
( warning: passed value is 12 bit with 0-4096 scale)

if (SetPointPID1.getText().toString().equals("")) {
  // campo vuoto non faccio niente
}else{
  int setpointPid1 =Integer.parseInt( SetPointPID1.getText().toString());
try {
  pManager.setPidSetPoint(1, setpointPid1);
    } catch (ConnectException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IndexOutOfBounds e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

Now we can activate the PID function and we obtain the modulation for the ServoControl based on heat.
We use a simple switch, so that at changin stat it has value from 0 to 1.
Even in this case, we can call the Library this way:

pManager.setPidStatus(function, value);

where the first field is the relative function ( like in our function example 1) and the second to the start / stop of the same function.