PID Controller Example

From Neuron Robotics Wiki

Jump to: navigation, search

The DyIO has the capability to link inputs to outputs using an internal PID controller. This controller takes 2 steps to set up. First you need to define which channels and modes will be used by the PID group, and then you will need to configure the PID controller itself. You can enable asynchronous mode, which will allow the PID controller to notify the application of any event changes.

  • There are 8 PID groups available on the DyIO.


Special Case Direct Control and Reflexes

In this special case you can use an analogue input to directly control the position of a standard servo using the built in PID controller:

  • Configure the DyPID to use an analogue input and a servo output
  • Configure the PID gains to P<=.25 I=0 D=0. You can invert it or not, it depends on how you want the mapping to work
  • Set the Setpoint to 512 (half the range of the analogue input)

This sets up a proportional controller. If you attach a potentiometer to the input, and a position servo (not a velocity servo or motor like in the standard PID example), the servo will follow the input 1:1. Since the DyIO will store these configurations and load them at boot time, you can now run this simple control system without a controlling application. Now if you attach a button or switch to the analogue input (this will need a pull up resistor), you can have a button or switch moving a servo directly on the DyIO using the PID Controller. In the button case you can adjust the P gain to fine tune the throw of the servo when the button or switch is pressed/flipped. Uses for this might include:

  • Anamatronics and puppeteering
  • Halloween costumes
  • Quick action at a distance setups
  • "Reflex" mechanisms as a sub system to a robot. Using this for Line Tracking is a great application.

Sample Source Code

import com.neuronrobotics.sdk.dyio.DyIO;
import com.neuronrobotics.sdk.dyio.DyIOChannelMode;
import com.neuronrobotics.sdk.dyio.dypid.DyPIDConfiguration;
import com.neuronrobotics.sdk.pid.IPIDEventListener;
import com.neuronrobotics.sdk.pid.PIDConfiguration;
import com.neuronrobotics.sdk.pid.PIDEvent;
import com.neuronrobotics.sdk.ui.ConnectionDialog;

public class PID_test implements IPIDEventListener{
	
	public PID_test(){
		DyIO dyio=new DyIO();
		dyio.SetPrintModes(true, true);
		if (!ConnectionDialog.getBowlerDevice(dyio)){
			System.exit(0);
		}
		
		dyio.addPIDEventListener(this);
		DyPIDConfiguration dypid = new DyPIDConfiguration(	0,//PID group 0
															23,//Input channel number
															DyIOChannelMode.COUNT_IN_INT,//Input mode
															11,//Output Channel
															DyIOChannelMode.SERVO_OUT);//Output mode
		PIDConfiguration pid =new PIDConfiguration (	0,//PID group
															true,//enabled
															true,//inverted
															true,//Async
															1,// Kp
															0,// Ki
															0,//Kd
															//Latch values are only used with the Counter since analog is absolute and can not change its value
															37,//Value to load to the controller if the index pin is used. This value can be anything
															true,//Use the auto-load of a latched in value when using the index pin
															true);//Set the setpoint to the current location when index it reached
		
		//Setup the controller with the 2 configurations
		dyio.ConfigureDynamicPIDChannels(dypid);
		dyio.ConfigurePIDController(pid);
		
		//Set a single setpoint to the controler
		dyio.SetPIDSetPoint(	0,//Group 0
					500,//Tell the controller to go to position 500
					2.5);//Take 2.5 secoinds to get there
		ThreadUtil.wait(2500);//Wait for the controller to reach its destination
		//Now we will set up the channel wrapping object
		//No further configuration is needed since it was configured above
		PIDChannel chan0 = dyio.getPIDChannel(0);
		//Set a value to be cached by the channel and sent later
		chan0.setCachedTargetValue(-500);
		//Do something else
		ThreadUtil.wait(1000);
		//Now we can flush the entire PID controller
		//NOTE any other cached values will be sent to the device at the same time
		//This is a way of using co-ordinated motion for the PID system
		dyio.flushPIDChannels(2500);
		ThreadUtil.wait(2500);//Wait for the controller to reach its destination
		//This disables all of the PID loops running on the device at once
		dyio.killAllPidGroups();
	}
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try{
			new PID_test();
		}catch(Exception e){
			e.printStackTrace();
			System.err.println("Failed out!");
			System.exit(-1);
		}

	}
	@Override
	public void onPIDEvent(PIDEvent e) {
		System.out.println(e);
	}

}
Personal tools