• **A Object to Calibrate and Scale Analog Inputs to Engineering Units( In three installments)
    Part 3:
    **
    Let’s add two fields to the calibration file, name and units.

    var AnalogReadObj1={
      calibrations:[
        {name:"Inlet",units:"psig",pin:'A0',slope:10.0,Intercept:5.0},
        {name:"Outlet",units:"psig",pin:'A1',slope:50.0,Intercept:-25.0},
        {name:"Motor",units:"Amps",pin:'A2',slope:1.0,Intercept:0.0},
        {name:"Supply",units:"Volts",pin:'A3',slope:1.0,Intercept:0.0},
        {name:"Flow",units:"Liters/minute",pin:'A4',slope:1.0,Intercept:0.0}
      ]
    };//end AnalogReadObj1
    
    function saveCalibration(calibration) {
      var Q;
      var sss=JSON.stringify(calibration);
     if (Q===undefined) {
      Q = E.openFile("Mycalibrations.cal", "w");
      Q.write(sss);
      Q.close();
      Q = undefined;
     }//endif
    }//end doLog
    
    saveCalibration(AnalogReadObj1); 
    console.log(require("fs").readFileSync("Mycalibrations.cal"));
    
    

    The left screen:

    >echo(0);
    {"calibrations":[{"name":"Inlet","units":"psig","pin":"A0","slope":10,"Intercept":5},
    {"name":"Outlet","units":"psig","pin":"A1","slope":50,"Intercept":-25},
    {"name":"Motor","units":"Amps","pin":"A2","slope":1,"Intercept":0},
    {"name":"Supply","units":"Volts","pin":"A3","slope":1,"Intercept":0},
    {"name":"Flow","units":"Liters/minute","pin":"A4","slope":1,"Intercept":0}]}
    =undefined
    > 
    
    

    The code that knits the two objects together and implements a two point calibration.
    The calibration is save to the calibration file on the SD card followed by the reading of the calibrated analog inputs in engineering units (EU).
    Button 1 on the Espruino board is used to step through the steps. Entering A= selects the channel to calibrate. During the calibration entering B= is used to set the EU values needed for calibration. If A=-1 exits calibration, and proceeds to reading the analog inputs after each press of button1.

    var sss=(require("fs").readFileSync("Mycalibrations.cal")); 
    //console.log(sss);
    
    //The constructor for AnalogReadObj
    function AnalogReadObj(ARO){
      this.A=JSON.parse(ARO);
    }//end AnalogReadObj
    //Methods for AnalogReadObj
    
    AnalogReadObj.prototype.saveCalibration=function() {
      var Q;
      var sss=JSON.stringify(this.A);
      console.log("Saving calibrations");
      console.log(this.A);
     if (Q===undefined) {
      Q = E.openFile("Mycalibrations.cal", "w");
      Q.write(sss);
      Q.close();
      Q = undefined;
     }//endif
    };//saveCalibration
    
    
    AnalogReadObj.prototype.SanalogRead=function(Arg){
        for(var i=0;i in this.A.calibrations;i++){
    //      console.log(i,Arg,this.A.calibrations[i].pin);
         if(Arg===this.A.calibrations[i].pin){
      return( analogRead(Arg)*this.A.calibrations[i].slope+this.A.calibrations[i].Intercept);
         }//endif
        }//next i
        return -99;
    };//end SanalogRead
    
    AnalogReadObj.prototype.getName=function(Arg){
        for(var i=0;i in this.A.calibrations;i++){
    //      console.log(i,Arg,this.A.calibrations[i].pin);
         if(Arg===this.A.calibrations[i].pin){
          return( this.A.calibrations[i].name);
         }//endif
        }//next i
        return -99;
    };//end SanalogRead
    
    AnalogReadObj.prototype.getUnits=function(Arg){
        for(var i=0;i in this.A.calibrations;i++){
    //      console.log(i,Arg,this.A.calibrations[i].pin);
         if(Arg===this.A.calibrations[i].pin){
          return( this.A.calibrations[i].units);
         }//endif
        }//next i
        return -99;
    };//end SanalogRead
    
    AnalogReadObj.prototype.SetAnalog=function(Arg){
        for(var i=0;i in this.A.calibrations;i++)
         pinMode(this.A.calibrations[i].pin, 'analog');
    };//end SetAnalog
    //end methods for AnalogReadObj
    
    //The constructor for LinRegObj
    function LinRegObj(a,nn){
      this.Sx=0;
      this.Sy=0;
      this.Sxy=0;
      this.Sxx=0;
      this.Syy=0;
      this.N=0;
      this.A=a;
      this.NN=nn;
      this.slope=0;
      this.intercept=0;
    }//end LinRegObj
    //Methods for LinRegObj
    LinRegObj.prototype.TakeData=function(y){
    //LinRegObj.prototype.TakeData=function(x,y){
      for(i=0;i<this.NN;i++){
        var x=analogRead(this.A.pin);
        this.Sx+=x;
        this.Sy+=y;
        this.Sxy+=(x*y);
        this.Sxx+=(x*x);
        this.Syy+=(y*y);
        this.N++;
      }//next i
    };//endTakeData
    
    LinRegObj.prototype.Calculate=function(){
     this.slope=(this.N*this.Sxy-this.Sx*this.Sy)/
       (this.N*this.Sxx - this.Sx*this.Sx);
     this.intercept=this.Sy/this.N-(this.slope*this.Sx)/this.N;
     this.A.slope=this.slope;
     this.A.Intercept=this.intercept;
    };//end Calculate
    
    LinRegObj.prototype.ListChannels=function(T){
      for(var i=0;i in T;i++){
        console.log(i,","+T[i].name+","+T[i].units);
      }//next i
    };//end List Channels
    //end LinRegObj methods
    var A=0;//used to select channel -1 exits calibration sequence
    var B=0;//used to input EU values during calibration
    
    //create an instance of AnalogReadObject using the string data contained in 
    //the variable sss
    var ScaledAR=new AnalogReadObj(sss);
    //console.log(ScaledAR.calibrations);
    // setup the pins for analog
    ScaledAR.SetAnalog();
    //test example calculation
    var Q=new LinRegObj(ScaledAR.A.calibrations[0],5);// 5 samples to take
    //SelectChannel();
    console.log("Press button on Espruino board to start");
    var state=10;
    
    function doButton(){
      if (digitalRead(BTN1) === 1){
        switch (state){
          case 10:
           Q.ListChannels(ScaledAR.A.calibrations);
           console.log(' ');
           console.log("Select channel by number");
           console.log("Type A=<number>; in left pane");
           console.log("Type A=-1; in the left pane to exit calibrations");
           console.log("Then press button on Espruino board");
           console.log(' ');
           state=20;
          break;
    
          case 20:
           if(A<0){
            console.log("Exit");
            ScaledAR.saveCalibration();
            state=200;
            return;
           }
           if(A in ScaledAR.A.calibrations){
            console.log("Calibrating ",ScaledAR.A.calibrations[A].name);
            console.log("Apply low value (0.0) input to sensor");
            console.log("Enter the engineering units (EU) by typing in left pane");
            console.log("B=<EU>;");
            console.log("Then press button on the Espruino board");
           }//endif A in Q
           state=30;
          break;
    
          case 30:
           Q.TakeData(B);
           console.log("Calibrating ",ScaledAR.A.calibrations[A].name);
           console.log("Apply high value (80% FS) input to sensor");
           console.log("Enter the engineering units (EU) by typing in left pane");
           console.log("B=<EU>;");
           console.log("Then press button on the Espruino board");
           state=40;
          break;
    
          case 40:
           Q.TakeData(B);
           Q.Calculate();
           console.log("Calibrating ",ScaledAR.A.calibrations[A].name);
           console.log("Slope= ",Q.slope);
           console.log("Intercept= ",Q.intercept);
           console.log("Press button on the Espruino board");
           state=10;
          break;
          case 200:
           console.log(' ');
           // Now do a scaled read of pin A0
           console.log(ScaledAR.getName('A0')," A0= ",ScaledAR.SanalogRead('A0').toFixed(2)+" ",ScaledAR.getUnits('A0'));
           // Now do a scaled read of pin A1
           console.log(ScaledAR.getName('A1')," A1= ",ScaledAR.SanalogRead('A1').toFixed(2)+" ",ScaledAR.getUnits('A1'));
           // Now do a scaled read of pin A2
           console.log(ScaledAR.getName('A2')," A2= ",ScaledAR.SanalogRead('A2').toFixed(2)+" ",ScaledAR.getUnits('A2'));
           // Now do a scaled read of pin A3
           console.log(ScaledAR.getName('A3')," A3= ",ScaledAR.SanalogRead('A3').toFixed(2)+" ",ScaledAR.getUnits('A3'));
           // Now do a scaled read of pin A4
           console.log(ScaledAR.getName('A4')," A4= ",ScaledAR.SanalogRead('A4').toFixed(2)+" ",ScaledAR.getUnits('A4'));
           console.log("Press button on Espruino board");
          return;
    
          default:
        }//end switch
      }//end BTN1
    }//end doButton
    
    setWatch(doButton, BTN1, true);
    
    

    The left pane view:

    Press button on Espruino board to start
    =undefined
    0 ,Inlet,psig
    1 ,Outlet,psig
    2 ,Motor,Amps
    3 ,Supply,Volts
    4 ,Flow,Liters/minute
     
    Select channel by number
    Type A=<number>; in left pane
    Type A=-1; in the left pane to exit calibrations
    Then press button on Espruino board
     A=0;
    Calibrating  Inlet
    Apply low value (0.0) input to sensor
    Enter the engineering units (EU) by typing in left pane
    B=<EU>;
    Then press button on the Espruino board
    >B=0;
    =0
    Calibrating  Inlet
    Apply high value (80% FS) input to sensor
    Enter the engineering units (EU) by typing in left pane
    B=<EU>;
    Then press button on the Espruino board
    >B=80;
    =80
    Calibrating  Inlet
    Slope=  100.13897386465
    Intercept=  -0.03419722673
    Press button on the Espruino board
    0 ,Inlet,psig
    1 ,Outlet,psig
    2 ,Motor,Amps
    3 ,Supply,Volts
    4 ,Flow,Liters/minute
    Xxxxxxxxxxxxxxxxxxxx
    A=-1; exits the calibration sequence.
    Xxxxxxxxxx
    >A=-1
    =-1
    Exit
    Saving calibrations
    {
      "calibrations": [
        {
          "name": "Inlet",
          "units": "psig",
          "pin": "A0",
          "slope": 100.13897386465, "Intercept": -0.03419722673 },
        {
          "name": "Outlet",
          "units": "psig",
          "pin": "A1",
          "slope": 50, "Intercept": -25 },
        {
          "name": "Motor",
          "units": "Amps",
          "pin": "A2",
          "slope": 1, "Intercept": 0 },
        {
          "name": "Supply",
          "units": "Volts",
          "pin": "A3",
          "slope": 1, "Intercept": 0 },
        {
          "name": "Flow",
          "units": "Liters/minute",
          "pin": "A4",
          "slope": 1, "Intercept": 0 }
       ]
     }
     
    Inlet  A0=  79.94  psig
    Outlet  A1=  12.00  psig
    Motor  A2=  0.72  Amps
    Supply  A3=  0.69  Volts
    Flow  A4=  0.82  Liters/minute
    Press button on Espruino board
    
    

    Testing was performed using five 1k resistors wired in series. One end connects to GND and the other end to +3.3V pins. A wire from the analog input pin can then be connected to connections along the resistor chain.


    2 Attachments

About