• A standard way to implement a feedback control system is the Proportional, Integral, Derivative (PID) control algorithm.
    Think of things to control and how different the control action can be.
    Driving a car. Use a compass module as the input and a motor to steer the wheels. As a driver you turn and hold the steering wheel until the new heading is achieved. Does a boat work the same way?
    When piloting an airplane you turn the yoke to tilt the plane over about 15 degrees and then neutralize the yoke. The plane will circle until you turn the yoke to level the plane. (I’m ignoring rudder action)
    When riding a bicycle or motorcycle, once in motion, the controls act opposite to that of a car. Turn right and the bike tilts to the left and you the bike turns left.
    So how to implement PID control?
    We need:

    1. An input sensor such as a compass module, a thermistor, a thermocouple, an accelerometer, a piezo-gyro etc.
    2. An output device that can be controlled using either a 0 to 3 Volt Voltage or a pulse width (servo motor).
    3. The PID algorithm implemented in Espruino.
      Using Google we find:
      https://en.wikipedia.org/wiki/PID_contro­ller
      The pseudocode from the link:

    previous_error = 0
    integral = 0
    start:
    error = setpoint - measured_value
    integral = integral + error*dt
    derivative = (error - previous_error)/dt
    output = Kp*error + Ki*integral + Kd*derivative
    previous_error = error
    wait(dt)
    goto start

    Suppose the setpoint is 0.5 and the measured value is 1.0. Then errpr= 0.5 – 1.0 = -0.5. Let dt = 1 second, then integral = 0.0 – 0.5 * 1 = -0.5 and derivative= (-0.5 -0.0 )/1 = -0.5.

    I think we have a problem since in an Espruino world analog inputs and outputs work between 0.0 and 1.0. I tried coding this and ran into this problem.
    Another link from a University course just seems to confuse the issue.
    http://www.cds.caltech.edu/~murray/cours­es/cds101/fa02/caltech/astrom-ch6.pdf
    I recall from a course taken many years ago that the PID algorithm can be expressed in a differential form so that the change in output is expressed as a function of the PID terms.
    doutput = P*sumof(error) + I *error + D*derivative,
    Where:
    P=Kp= the proportional gain,
    I=Ki= the integral gain, and
    D=Kd= the derivative gain.
    Maybe a math GURU can properly insert the dt values into the equation.

    First let’s setup a PID object:

    //The PID is an object that could be supplied as a stringified file or client
    //request using http. For development it is coded here.
    var PID={
      Dir:1,//direction +1 or -1
      P:0.1,//proportional gain
      I:0.1,//integral gain
      D:0.1,//derivative gain
      Fname:"PID.CSV" //a file to record results in CSV format on the SD card
    };
    
    

    The Dir field is used to reverse the control action.
    The Fname field is used to record a CSV file.
    Now implement an object to use the PIS information and extend it.

    //The constructor for PIDobj
    function PIDobj(pid,setpoint,input,output,interva­l){
      this.Interval=interval; //How often to apply algorithm
      this.Input=input; // a function that returns the process value
      this.Output=output; //a function that applies the output
      this.PID=pid; // a pointer to the PID object
      this.error=0;
      this.Setpoint=setpoint;
      this.integral=0;
      this.derivative=0;
      this.previous_error=0;
      this.id=0;
      this.out=0;
      this.N=0; // a counter for the CSV file
    }//end TimeObj
    
    //exports =PIDobj;
    
    

    Adding a method to setup and start the timer

    PIDobj.prototype.start = function() {
      this.N=0;
      var Q = E.openFile(this.PID.Fname, "w");
      Q.write("N,Error,Input,Output,Setpoint\r­");
      Q.close();
      if (this.id) return;
      this.id = setInterval( this.update.bind(this), this.Interval );
    };//end start
    
    

    Add a method to stop the timer

    PIDobj.prototype.stop=function(){
     if (this.id) {
      clearInterval(this.id);
      this.id = null;
      console.log(this.PID.Fname, "Finished");
      console.log(process.memory().usage);
     }//endif this.id
    };//end stop
    
    
About