Javascript PID Control

Posted on
  • Has anyone used this javascript PID controller code? Everything looks good but I can't figure out how to call it. Can someone point me in the right direction?

    I'm still trying to wrap my head around this 'prototype' concept in javascript. Yet to reach that ah ha moment!

  • I think you want to do:

    var p=new PID(...);

    (Also, I'm pretty sure the code won't work without a bit of work to port to the Espruino) .

  • Take a look to this node.js module. Its a simple solution.
    https://github.com/philmod/node-pid-contĀ­roller

  • I haven't tried it, but it should work with minor tweaks. I guess the first things to try would be:

    • copy+paste https://github.com/wilberforce/pid-contrĀ­oller/blob/master/lib/index.js into the right-hand pane.
    • Replace PID.prototype.millis with PID.prototype.millis = function() { return getTime()*1000;}
    • Just use it like in the example (without the require):

      var ctr = new PID(50, 66, 10,2,1, PID.DIRECT )
      ctr.setMode(ctr.AUTOMATIC);
      ctr.setTunings(10,2,1);
      ctr.setOutputLimits(0,100);
      ctr.setInput(temp); 
      

    If it works well, I guess we could add the module to Espruino?

    Have you done much work in other Object oriented languages? It's probably wrong but I tend to think of the prototype system as follows (and it works for me :) :

    function Foo() { ... } // the constructor (but also the name of the class)
    Foo.prototype // a list of the class methods and 'static' properties
    Foo.prototype.bar = function() { ... } // define one of the Class's methods
    Foo.prototype.baz = 42; // define a value that is shared between all instances of the class. In C++/Java this would be called 'static' 
    
    var a = new Foo(); // An object of class Foo
    var b = new Foo();
    
    a.x = "Test";
    console.log(b.x); // prints undefined - x wasn't in the prototype so is unique to the 'a' Object
    console.log(a.baz); // prints 42 - from the prototype
    a.baz = "Hello";
    console.log(b.baz); // prints 'Hello' - baz was in the prototype, so it's shared between instances of Foo
    
    Foo.prototype.hello = function() {
      console.log(this.x); // access the Object with 'this'
    }
    a.hello(); // prints "Test". In the 'hello' function, 'this' is the same value as 'a'.
    

    It all stems from some pretty simple rules in the interpreter. Each object is nothing more than a list of key/value pairs, and:

    When you say foo = new Foo(), it effectively just does foo = Foo(); foo.__proto__ = Foo.prototype.

    Then, if you access foo.bar:

    • foo is searched for something named bar. If that exists, it's returned.
    • Otherwise, if foo has a field named __proto__, that is searched for bar and it's returned if found
    • Otherwise, if we found __proto__ in the last step, see if there's a __proto__ inside that, and so on.
    • Or if nothing was found, simply return undefined (but if you're doing foo.bar= ..., it'll simply directly set bar on foo).

    So it's actually a really simple way of getting something like an Object Oriented language. I always find if I want to know what's going to happen, I can basically walk through the steps above.

    Does that help explain it at all?

  • @JumJum - I did find that one first, but I figured if we are going to have a module for the Espruino it had better have all the bells and whistles.
    This version from Rhys Williams is ported from Brett Beauregard's Arduino version which was pretty well documented on his blog a few years ago.

    @Gordon - No never really done any object oriented stuff, just simple bits and pieces. I seem to learn best by hacking away at other examples to understand whats going on. But I will definitely refer to your example.

    I had pretty much figured it out what you had with the PID code.

    The only issue may be when the value that is returned from getTime() rolls over.

    It appears to be working using a few simple tests (finger on thermistor) watch demand decrease, finger off thermistor watch demand increase.

  • Great! I did an example with a simple relay and really nasty control system. I'd love to see something similar with PWM and temperature sensing :)

    As far as the rollover, getTime() returns a double (which realistically will never roll over), and internally it's calculated from the RTC, which will only roll over after 136 years of continuous use - so I'm not sure it's such a big deal.

  • Just to say, that library is expecting the Arduino-style 'loop', so compute basically polls to see when it should do stuff. It'd be much better if it was re-written to use setInterval, with maybe a callback for when the output value changes.

  • Unfortunately I don't have the appropriate kit. Ideally the standard DIY reflow oven project would probably be a useful example.

    I do have an example project but its work in progress right now. I need to send the PCB gerbers off to SEEED. The only problem is when I open up the files I keep tweaking stuff ;)

    Yes I can't see anything being used for 136years so I think we are safe LOL.

    I am calling 'compute' from setInterval.

    setInterval (function() {
      p.setInput(temp);
      p.compute();
    }, 1000);
    
  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Javascript PID Control

Posted by Avatar for StuntMonkeh @StuntMonkeh

Actions