Import an other JS file in modules directory.

Posted on
  • Hello,

    I'm trying to build my application as OOP, that's why I have parted all classes in different files. I have placed those files in modules directory.

    Example ;

    modules/connectionClass.js

    var connectionClass=function(){
        getVars=function(){
            return {social_id:Math.floor((Math.random() * 4)),text:zeroFill(Math.floor((Math.rando­m() * 10) + 1),6)}
        };
    }
    

    modules/helper.js

    function zeroFill( number, width )
    {
        width -= number.toString().length;
        if ( width > 0 )
        {
            return new Array( width + (/\./.test( number ) ? 2 : 1) ).join( '0' ) + number;
        }
        return number + ""; // always return a string
    }
    

    projects/main.js

    require('connectionClass');
    
    var connection=new connectionClass();
    

    But at the line var connection=... I'm getting this error

    Uncaught Error: Field or method does not already exist, and can't
    create it on undefined at line x col y

    What I am doing wrong?

  • Hi. You're doing this with the 'projects' option in the Web IDE?

    The first thing I think might be an issue is that modules aren't just simple files that are 'included'. You've got to define 'exports'.

    For instance:

    mymodule.js:

    exports.foo = function() {
      console.log("Hello");
    };
    

    main.js:

    var mymodule = require("mymodule");
    mymodule.foo();
    
  • Yes, I'm doing it with projects options in Web IDE.

    How to import a class that gets parameters on construction like this :

    modules/stepper.js

    var stepperClass = function (p1, p2, p3, p4) {
        var step = 0;
        var steps = [0b0001, 0b0011, 0b0010, 0b0110, 0b0100, 0b1100, 0b1000, 0b1001];
        var stepperPins = [p4, p3, p2, p1];
        this.writeStep = function () {
            step++;
            digitalWrite(stepperPins, steps[step % steps.length]);
        };
        this.stop = function () {
            digitalWrite(stepperPins[0], LOW);
            digitalWrite(stepperPins[1], LOW);
            digitalWrite(stepperPins[2], LOW);
            digitalWrite(stepperPins[3], LOW);
        };
        this.doStep = function (cnt) {
            for (i = 0; i < cnt; i++) {
                x = 0;
                while (x < 10) x++;
                this.writeStep();
            }
            this.stop();
        };
    };
    
  • The way we usually do it in modules is:

    // your other stuff
    
    exports.connect = function (p1,p2,p3,p4) {
      return new stepperClass(p1,p2,p3,p4);
    }
    

    then:

    var stepper = require("stepper").connect(...);
    

    There's a template on the website here that you might find handy.

  • never mind ;-)

  • Modules and OOP are not necessarily tied together... if you want to have just one stepper in your system, you do not need to go for a class, module works just fine. If you though want to have multiples, the code has to undergo some changes in order to take advantage of the OOP ideas... AND the abilities of ESPRUINO Javascript implementation.

    You can start exactly the way @Gordon suggests - and you can even nicely test it in the IDE. Put your code plus the 3-liner from @Gordon into the file stepper.js and save it in the modules folder of your project sandbox folder.

    In your runtime code you can then get a stepper the way @Gordon shoes in the one-liner.

    stepper.doStep(512); will then give you one turn on the drive shaft.

    Do you intend to have more than one stepper in your setup?

  • Yes, I'm going to use 7 steppers in my project. It is not only about steppers, OOP is easiest way to build application for me.

    By taking advantage @Gordon's code I have build my OOP like this; The way below is easy to read and understand the code for me.

    modules/stepperClass.js

    exports.stepperClass = function (p1, p2, p3, p4) {
        var step = 0;
        var steps = [0b0001, 0b0011, 0b0010, 0b0110, 0b0100, 0b1100, 0b1000, 0b1001];
        var stepperPins = [p4, p3, p2, p1];
    
        this.writeStep = function () {
            step++;
            digitalWrite(stepperPins, steps[step % steps.length]);
        };
    
        this.stop = function () {
            digitalWrite(stepperPins[0], LOW);
            digitalWrite(stepperPins[1], LOW);
            digitalWrite(stepperPins[2], LOW);
            digitalWrite(stepperPins[3], LOW);
        };
    
        this.doStep = function (cnt) {
            for (i = 0; i < cnt; i++) {
                x = 0;
                while (x < 10) x++;//delay a little bit
                this.writeStep();
            }
            this.stop();
        };
    
    

    projects/main.js

    var stepperClass=require('stepperClass').ste­pperClass;
    
    stepper1=new stepperClass(A1,A2,A3,A4);
    stepper2=new stepperClass(B1,B2,B3,B4);
    stepper3=new stepperClass(C1,C2,C3,C4);
    
    stepper1.doStep(100);
    ....
    ....
    ....
    
  • ;-) somehow, I expected your response... but did not want to make further comment before this had been cleared.

    I make you now some suggestions that take more advantage of oo and Espruino. Furthermore, you have to know that the odd 'steps' are not stable steps: when hit stop - apply 0 to all pins - at any of these, the motor will either move forward to next even 'step' or ' back to previous even 'step'. If you want to use 'stop' state (all pins 0 / off), you best compensate that internally by making for one external step two internal steps. Since you (may) expose (and use) .stop() you have to make sure that you always make an extra internal step (in the current direction) when stop hit's at an odd internal step.

    First, use Javascript's 'idea' of oo by using prototype and -second, use Espruino's support for setInterval (or setTimeout). Using prototype saves you memory. Using intervals (or timeouts) makes it possible that more than one stepper can move at one time... (your current piece of code hogs the process until all steps are done). - Times are in milliseconds [ms].

    // Stepper module - 2-phases 5-leads stepper
    
    // define 'static parts' - same for each instance
    var steps = [0b0001, 0b0011, 0b0010, 0b0110, 0b0100, 0b1100, 0b1000, 0b1001];
    var stop = 0b0000;
    var defaultIntervalTime = 10;
    var minimalIntervalTime = 4;
    
    // Class / state - constructor (with pins, intervalTime) - defines state of the individual instances
    var Stepper = function(p1,p2,p3,p4,intervalTime) {
      this.pins = [p1,p2,p3,p4];
      this.intervalTime = defaultIntervalTime;
      this.intervalTime = this._getIntervalTime(intervalTime);
      this.interval = null;
      this.stepsToGo = 0;
      this.st = 0;
    };
    
    // .connect()-style constructor (for convenience) with same parms as default contructor)
    Stepper.connect = function(p1,p2,p3,p4,intervalTime) {
      return new Stepper(p1,p2,p3,p4,intervalTime);
    };
    
    // temp stepper prototype - used 'to stick behavior' to instances
    var p = Stepper.prototype;
      
    // instance methods - defines behavior common to and reused by all the instances
    p._step = function() {
      digitalWrite(this.pins,steps[this.st = ++this.st % 8]);
      if (--this.stepsToGo < 1) { this.stop(); }
    };
    
    p.step = function(stepsToGo,intervalTime) {
      this.stepsToGo = stepsToGo * 2; 
      this.intervalTime = this._getIntervalTime(intervalTime);
      var _this = this;
      this.interval = setInterval(function(){
        _this._step(); }, this.intervalTime);
    };
    
    p.stop = function() {
      if (this.interval) { 
        clearInterval(this.interval);
        this.interval = null;
      } 
      if (this.st % 2) {
        digitalWrite(this.pins,steps[this.st = ++this.st % 8]);
        --this.stepsToGo;
      }
      digitalWrite(this.pins, stop);
    };
    
    // return a valid interval time
    p._getIntervalTime = function(intervalTime) {
      var t = ( (isNaN(intervalTime) || (intervalTime < minimalIntervalTime))
             ? this.intervalTime : intervalTime );
      return t;
    };
    
    export = Stepper;
    

    To use this Stepper class you write:

    var Stepper = require("Stepper");
    var stepper1 = new Stepper(A0,A1,A2,A3); // takes default stepping interval of 10[ms]
    var stepper2 = new Stepper(A4,A5,A6,A7,20); // takes 20[ms] as stepping interval
    stepper1.step(256); // 256 steps = full circle with your stepper, 
                          // takes 5120[ms]  (512 (internal) steps * 10[ms] = 5120[ms] = 5.12 seconds)
    stepper2.step(128); // half circle in same time
    

    Note that the code executed at every interval - this is the method ._step() - has to be as short as possible.

    Regarding naming, this may be a helpful rule-of-thumb:

    • Uppercase beginning, camel-cased names are classes names (you can then avoid Class suffix)
    • lowercase beginning, camel-cased names are methods and variable names
    • _beginning, camel-cased names are for 'private' things only 'knowlegable'/tightly coupled code code should use (even though privacy is not (easy) enforceable in JavaScript)
  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Import an other JS file in modules directory.

Posted by Avatar for fobus @fobus

Actions