diff --git a/devices/AmenuCalSlimLSM9DS1.js b/devices/AmenuCalSlimLSM9DS1.js new file mode 100644 index 000000000..c5bb41af7 --- /dev/null +++ b/devices/AmenuCalSlimLSM9DS1.js @@ -0,0 +1,765 @@ +//AmenuCalSlimLSM9DS1.js +//21 Dec 2016 +/* Copyright (c) 2016 Joe McCarty. See the file LICENSE for copying permission. */ + +var CalPage=99; //ROM page where calibration is saved +////////////////////////////////////////////////////////////// +// CAUTION CAUTION CAUTION///// +////////////////////////////////////////////////////////////// + +//How not to brick a PICO when reassigning the console +// away from the USB port to do menu programs + +//Setup the button to light the LED and reset the Pico +//Always include this code when a save() and oninit() functions are // used. +setWatch(function(e) { + digitalWrite(LED1, e.state); + USB.setConsole(); + reset(); +}, BTN, { repeat: true }); + + +E.on('init', function() { + console.log("Hello"); + startPgm(); +}); + +//input cmd from terminal,send it to parsecmd() +USB.on('data', function (data) { + var i; + sst+=data; +// look for control c in input stream + if(sst.indexOf(String.fromCharCode(3))>-1){ + USB.setConsole(); + reset(); + }// console.log("control C seen"); + USB.print(data); + if(sst.length>-1) + if(sst.charAt(sst.length-1)==="\r")selectparser(); +// if(sst.charAt(0)==="\r")selectparser(); +}); + +//Espruino replies here +LoopbackA.on('data',function(data){ + USB.print(data); //sending data to terminal +}); + + +console.log("In left pane type startPgm();"); +console.log("Use startPgm() first and make sure you can exit back to the console"); +console.log("Once you are sure that a proper exit works then type save();"); + + +var menulevel=0; +function startPgm(){ +setTimeout(function () { + start(); + LoopbackB.setConsole(); + mainmenu(); +}, 1000); +}//end startPgm + +var sst=""; + +function selectparser(){ + switch(menulevel){ + case 0: + parsemainmenu(); + break; + case 1: + parsegyromenu(); + break; + case 2: + parseaccelmenu(); + break; + case 3: + parsemagmenu(); + break; + case 4: + parsegyroscalemenu(); + break; + case 5: + parseaccelscalemenu(); + break; + case 6: + parsemagscalemenu(); + break; + case 7: + parsegyroODRmenu(); + break; + case 8: + parseaccelODRmenu(); + break; + case 9: + parsemagODRmenu(); + break; + case 10://return exits read and displaydata + sst=""; + clearInterval(nn); + mainmenu(); + break; + case 11://select display units + parsedisplaymenu(); + break; + case 12://magnetometer calstep 0 + W.calMag(0,function(){ + USB.print("Point X-axis South and press return\n\r"); + sst=""; + menulevel=13; + }); + break; + case 13://magnetometer calstep 1 + W.calMag(1,function(){ + USB.print("Point Y-axis North and press return\n\r"); + sst=""; + menulevel=14; + }); + break; + case 14://magnetometer calstep 2 + W.calMag(2,function(){ + USB.print("Point Y-axis South and press return\n\r"); + sst=""; + menulevel=15; + }); + break; + case 15://magnetometer calstep 3 + W.calMag(3,function(){ + USB.print("Point Z-axis North and press return\n\r"); + sst=""; + menulevel=16; + }); + break; + case 16://magnetometer calstep 4 + W.calMag(4,function(){ + USB.print("Point Z-axis South and press return\n\r"); + sst=""; + menulevel=17; + }); + break; + case 17://magnetometer calstep ` + W.calMag(5,function(){ + mainmenu(); + }); + break; + }//end switch +} + +function mheader(){ + USB.print("\n\rSelect option or use control-C to exit\n\r"); +} + +function mainmenu(){ + sst=""; + menulevel=0; + mheader(); + USB.print("0 Configure Gyro\n\r"); + USB.print("1 Configure Accelerometer\n\r"); + USB.print("2 Configure Magnetometer\n\r"); + USB.print("3 Select Display Units\n\r"); + USB.print("4 Read and Display Data\n\r"); + USB.print("5 Show Calibration Structure\n\r"); + USB.print("6 Calibrate Gyro and Accelerometer\n\r"); + USB.print("7 Calibrate Magnetometer\n\r"); + USB.print("8 Save calibrations to ROM\n\r"); + USB.print("E Exit\n\r"); +} + +var count=0;var nn; +function parsemainmenu(){ +USB.print("\n\r"); + switch(this.sst.charAt(0)){ + case "0"://Configure Gyro + USB.print("Configure Gyro\n\r"); + gyromenu(); + break; + case "1"://Configure Accelerometer + USB.print("Configure Accelerometer\n\r"); + accelmenu(); + break; + case "2"://Configure Magnetometer + USB.print("Configure Magnetometer\n\r"); + magmenu(); + break; + case "3"://select display units + USB.print("Select Display Units\n\r"); + displaymenu(); + break; + case "4"://read and display data + menulevel=10;sst=""; + readall(W); + nn=setInterval(function () { + readall(W); + count++; + if(count>1000)clearInterval(nn); + }, 200); + break; + case "5"://show calibration structure + USB.print("Magnetometer Scale "+W.mScale+"\n\r"); + USB.print(JSON.stringify(W.mscale)+"\n\r"); + USB.print("Gyro Scale "+W.gScale+"\n\r"); + USB.print(JSON.stringify(W.gyroscale)+"\n\r"); + USB.print("Acceleration Scale "+W.aScale+"\n\r"); + USB.print(JSON.stringify(W.accelscale)+"\n\r\n\r"); + mainmenu(); + break; + case "6"://calibrate the gyro and accelerometer +//do all scales 0..4 + W.calibrate(W.autoCalc,0,0,function(){ + W.calibrate(W.autoCalc,0,1,function(){ + W.calibrate(W.autoCalc,0,2,function(){ + W.calibrate(W.autoCalc,0,3,function(){ + });//3 + });//2 + });//1 + mainmenu(); + });//0 +// mainmenu(); + break; + case "7"://calibrate magnetometer + USB.print("Point X-axis North and press return\n\r"); + menulevel=12;sst=""; + break; + case "8"://save calibrations to ROM + USB.print("Saving calibration to ROM\n\r"); + var mag=JSON.stringify(W.mscale)+';'+JSON.stringify(W.gyroscale)+';'+ + JSON.stringify(W.accelscale); + var f = new (require("FlashEEPROM"))(); + f.write(CalPage, mag); + mainmenu(); + break; + case"E"://Exit + USB.setConsole(); + LoopbackA.print("USB.setConsole();\n\r"); + USB.print("Exit\n\r"); + break; + default: + mainmenu(); + break; + }//end switch sst +}//end parsemainmenu + +function displaymenu(){ + sst=""; + menulevel=11; + mheader(); + USB.print("0 Raw count\n\r"); + USB.print("1 Raw-Offset\n\r"); + USB.print("2 Engineering Units\n\r"); + USB.print("8 Main Menu\n\r"); + USB.print("E Exit\n\r"); +} + +function parsedisplaymenu(){ +USB.print("\n\r"); + switch(this.sst.charAt(0)){ + case "0"://Raw count + USB.print("Raw Count\n\r"); + W.autoCalc=0; + mainmenu(); + break; + case "1"://Rawcount-offset + USB.print("Raw Count - Offset\n\r"); + W.autoCalc=1; + mainmenu(); + break; + case "2"://Engineering Units + USB.print("Engineering Units\n\r"); + W.autoCalc=2; + mainmenu(); + break; + case "8"://Main Menu + USB.print("Return to Main Menu\n\r"); + mainmenu(); + break; + case"E"://Exit + USB.setConsole(); + LoopbackA.print("USB.setConsole();\n\r"); + USB.print("Exit\n\r"); + break; + default: + displaymenu(); + break; + }//end switch sst +} + +function gyromenu(){ + sst=""; + menulevel=1; + mheader(); + USB.print("0 Set Gyro Scale\n\r"); + USB.print("1 Set Gyro Output Data Rate\n\r"); +// USB.print("2 Set Gyro Filter\n\r"); + USB.print("8 Main Menu\n\r"); + USB.print("E Exit\n\r"); +} + +function parsegyromenu(){ +USB.print("\n\r"); + switch(this.sst.charAt(0)){ + case "0"://Set Gyro Scale + USB.print("Set Gyro Scale\n\r"); + gyroscalemenu(); + break; + case "1"://Set Gyro Output Data Rate + USB.print("Set Gyro Output Data Rate\n\r"); + gyroODRmenu(); + break; + case "8"://Main Menu + USB.print("Return to Main Menu\n\r"); + mainmenu(); + break; + case"E"://Exit + USB.setConsole(); + LoopbackA.print("USB.setConsole();\n\r"); + USB.print("Exit\n\r"); + break; + default: + gyromenu(); + break; + }//end switch sst +}//end parsegyromenu + +function accelmenu(){ + sst=""; + menulevel=2; + mheader(); + USB.print("0 Set Accelerometer Scale\n\r"); + USB.print("1 Set Accelerometer Output Data Rate\n\r"); + USB.print("8 Main Menu\n\r"); + USB.print("E Exit\n\r"); +} + +function parseaccelmenu(){ +USB.print("\n\r"); + switch(this.sst.charAt(0)){ + case "0"://Set accel Scale + USB.print("Set Accelerometer Scale\n\r"); + accelscalemenu(); + break; + case "1"://Set accel Output Data Rate + USB.print("Set Accelerometer Output Data Rate\n\r"); + accelODRmenu(); + break; + case "8"://Main Menu + USB.print("Return to Main Menu\n\r"); + mainmenu(); + break; + case"E"://Exit + USB.setConsole(); + LoopbackA.print("USB.setConsole();\n\r"); + USB.print("Exit\n\r"); + break; + default: + accelmenu(); + break; + }//end switch sst +}//end parseaccelmenu + +function magmenu(){ + sst=""; + menulevel=3; + mheader(); + USB.print("0 Set Magnetometer Scale\n\r"); + USB.print("1 Set Magnetometer Output Data Rate\n\r"); + USB.print("8 Main Menu\n\r"); + USB.print("E Exit\n\r"); +} + +function parsemagmenu(){ +USB.print("\n\r"); + switch(this.sst.charAt(0)){ + case "0"://Set mag Scale + USB.print("Set Magnetometer Scale\n\r"); + magscalemenu(); + break; + case "1"://Set mag Output Data Rate + USB.print("Set Magnetometer Output Data Rate\n\r"); + magODRmenu(); + break; + case "8"://Main Menu + USB.print("Return to Main Menu\n\r"); + mainmenu(); + break; + case"E"://Exit + USB.setConsole(); + LoopbackA.print("USB.setConsole();\n\r"); + USB.print("Exit\n\r"); + break; + default: + magmenu(); + break; + }//end switch sst +}//end parsemagmenu + + +///////////////////////// + +function gyroscalemenu(){ + sst=""; + menulevel=4; + mheader(); + USB.print("Select Gyro Scale\n\r"); + USB.print("0 for 245 deg/s\n\r"); + USB.print("1 for 500 deg/s\n\r"); + USB.print("2 for 2000 deg/s\n\r"); + USB.print("8 Main Menu\n\r"); + USB.print("E Exit\n\r"); +} + +function parsegyroscalemenu(){ +USB.print("\n\r"); + switch(this.sst.charAt(0)){ + case "0"://Set gyro Scale 245 + case "1":///Set gyro Scale 500 + case "2"://Set gyro Scale 2000r + USB.print("Set Gyro Scale\n\r"); + W.setGyroScale(Number(this.sst.charAt(0))); + gyromenu(); + break; + case "8"://Main Menu + USB.print("Return to Main Menu\n\r"); + mainmenu(); + break; + case"E"://Exit + USB.setConsole(); + LoopbackA.print("USB.setConsole();\n\r"); + USB.print("Exit\n\r"); + break; + default: + gyroscalemenu(); + break; + }//end switch sst +}//end parsegyroscalemenu + +function accelscalemenu(){ + sst=""; + menulevel=5; + mheader(); + USB.print("Select Accelerometer Scale\n\r"); + USB.print("0 for 2 g\n\r"); + USB.print("1 for 4 g\n\r"); + USB.print("2 for 8 g\n\r"); + USB.print("3 for 16 g\n\r"); + USB.print("8 Main Menu\n\r"); + USB.print("E Exit\n\r"); +} + +function parseaccelscalemenu(){ +USB.print("\n\r"); + switch(this.sst.charAt(0)){ + case "0"://Set accel Scale 2g + case "1"://Set accel Scale 4g + case "2"://Set accel Scale 8g + case "3"://Set accel Scale 16g + USB.print("Set Accelerometer Scale\n\r"); + W.setAccelScale(Number(this.sst.charAt(0))); + accelmenu(); + break; + case "8"://Main Menu + USB.print("Return to Main Menu\n\r"); + mainmenu(); + break; + case"E"://Exit + USB.setConsole(); + LoopbackA.print("USB.setConsole();\n\r"); + USB.print("Exit\n\r"); + break; + default: + accelscalemenu(); + break; + }//end switch sst +}//end parseaccelscalemenu + +function magscalemenu(){ + sst=""; + menulevel=6; + mheader(); + USB.print("Select Magnetometer Scale\n\r"); + USB.print("0 for 4 Gauss\n\r"); + USB.print("1 for 8 Gauss\n\r"); + USB.print("2 for 12 Gauss\n\r"); + USB.print("3 for 16 Gauss\n\r"); + USB.print("8 Main Menu\n\r"); + USB.print("E Exit\n\r"); +} + +function parsemagscalemenu(){ +USB.print("\n\r"); + switch(this.sst.charAt(0)){ + case "0"://Set mag Scale 4 Gauss + case "1"://Set mag Scale 8 Gauss + case "2"://Set magl Scale 12 Gauss + case "3"://Set mag Scale 16 Gauss + USB.print("Set Accelerometer Scale\n\r"); + W.setMagScale(Number(this.sst.charAt(0))); + magmenu(); + break; + case "8"://Main Menu + USB.print("Return to Main Menu\n\r"); + mainmenu(); + break; + case"E"://Exit + USB.setConsole(); + LoopbackA.print("USB.setConsole();\n\r"); + USB.print("Exit\n\r"); + break; + default: + magscalemenu(); + break; + }//end switch sst +}//end parsemagscalemenu + +function gyroODRmenu(){ + sst=""; + menulevel=7; + mheader(); + USB.print("Select Gyro Output Data Rate\n\r"); +// USB.print("0 for off\n\r"); + USB.print("1 for 14.9 Hz\n\r"); + USB.print("2 for 59.5 Hz\n\r"); + USB.print("3 for 119 Hz\n\r"); + USB.print("4 for 238 Hz\n\r"); + USB.print("5 for 476 Hz\n\r"); + USB.print("6 for 952 Hz\n\r"); + USB.print("8 Main Menu\n\r"); + USB.print("E Exit\n\r"); +} + +function parsegyroODRmenu(){ +USB.print("\n\r"); + switch(this.sst.charAt(0)){ +// case "0"://Set gyroODR off + case "1"://Set gyroODR 14.9 Hz + case "2"://Set gyroODR 59.5 Hz + case "3"://Set gyroODR 119 Hz + case "4"://Set gyroODR 238 Hz + case "5"://Set gyroODR 476 Hz + case "6"://Set gyroODR 952 Hz + USB.print("Set Gyro Output Data Rate\n\r"); + W.setGyroODR(Number(this.sst.charAt(0))); + gyromenu(); + break; + case "8"://Main Menu + USB.print("Return to Main Menu\n\r"); + mainmenu(); + break; + case"E"://Exit + USB.setConsole(); + LoopbackA.print("USB.setConsole();\n\r"); + USB.print("Exit\n\r"); + break; + default: + gyroODRmenu(); + break; + }//end switch sst +}//end parsegyroODRmenu + +function accelODRmenu(){ //(accelerometer only mode) + sst=""; + menulevel=8; + mheader(); + USB.print("Select Accelerometer Output Data Rate\n\r"); +// USB.print("0 for off\n\r"); + USB.print("1 for 10 Hz\n\r"); + USB.print("2 for 50 Hz\n\r"); + USB.print("3 for 119 Hz\n\r"); + USB.print("4 for 238 Hz\n\r"); + USB.print("5 for 476 Hz\n\r"); + USB.print("6 for 952 Hz\n\r"); + USB.print("8 Main Menu\n\r"); + USB.print("E Exit\n\r"); +} + +function parseaccelODRmenu(){ +USB.print("\n\r"); + switch(this.sst.charAt(0)){ +// case "0"://Set accelODR off + case "1"://Set accelODR 10 Hz + case "2"://Set accelODR 50 Hz + case "3"://Set accelODR 119 Hz + case "4"://Set accelODR 238 Hz + case "5"://Set accelODR 476 Hz + case "6"://Set accelODR 952 Hz + USB.print("Set Accelerometer Output Data Rate\n\r"); + W.setAccelODR(Number(this.sst.charAt(0))); + accelmenu(); + break; + case "8"://Main Menu + USB.print("Return to Main Menu\n\r"); + mainmenu(); + break; + case"E"://Exit + USB.setConsole(); + LoopbackA.print("USB.setConsole();\n\r"); + USB.print("Exit\n\r"); + break; + default: + accelODRmenu(); + break; + }//end switch sst +}//endparsemagODRmenu + +function magODRmenu(){ //(accelerometer only mode) + sst=""; + menulevel=9; + mheader(); + USB.print("Select Magnetometer Output Data Rate\n\r"); + USB.print("0 for 0.625 Hz\n\r"); + USB.print("1 for 1.25 Hz\n\r"); + USB.print("2 for 2.5 Hz\n\r"); + USB.print("3 for 5 Hz\n\r"); + USB.print("4 for 10 Hz\n\r"); + USB.print("5 for 20 Hz\n\r"); + USB.print("6 for 40 Hz\n\r"); + USB.print("7 for 80 Hz\n\r"); + USB.print("8 Main Menu\n\r"); + USB.print("E Exit\n\r"); +} + +function parsemagODRmenu(){ +USB.print("\n\r"); + switch(this.sst.charAt(0)){ + case "0"://Set magODR 0.625 Hz + case "1"://Set magODR 1.25 Hz + case "2"://Set magODR 2.5 Hz + case "3"://Set magODR 5 Hz + case "4"://Set magODR 10 Hz + case "5"://Set magODR 206 Hz + case "6"://Set magODR 40 Hz + case "7"://Set magODR 80 Hz + USB.print("Set Accelerometer Output Data Rate\n\r"); + W.setMagODR(Number(this.sst.charAt(0))); + magmenu(); + break; + case "8"://Main Menu + USB.print("Return to Main Menu\n\r"); + mainmenu(); + break; + case"E"://Exit + USB.setConsole(); + LoopbackA.print("USB.setConsole();\n\r"); + USB.print("Exit\n\r"); + break; + default: + magODRmenu(); + break; + }//end switch sst +}//end parsemagODRmenu + +/* +W.setGyroBandwidth(0);// 0..3 see table 46 +// +//setGyroHPfilter=function(onoff,cutoff) +W.setGyroHPfilter(1,7); //cutoff 0 to 15 +*/ + +////////////////////////////////////////////////////// +var AC=new xyzAvg(20);var ac=[0,0,0]; +var GY=new xyzAvg(20);var gy=[0,0,0]; +var MA=new xyzAvg(20);var ma=[0,0,0]; +function readall(W){ +W.readAccel(); +ac=AC.getAvg(W.a); +W.readGyro(); +gy=GY.getAvg(W.g); +W.readMag(); +ma=MA.getAvg(W.m); +W.readTemp(); +var pirate=180.0/Math.PI; + +console.log("Acceleration, ",W.a[0],',',W.a[1],',',W.a[2]); +console.log("Avg Acceleration, ",ac[0],',',ac[1],',',ac[2]); +console.log("Gyro, ",W.g[0],',',W.g[1],',',W.g[2]); +console.log("Avg Gyro, ",gy[0],',',gy[1],',',gy[2]); +console.log("Magnetometer, ",W.m[0],',',W.m[1],',',W.m[2]); +console.log("Avg Magnetometer ",ma[0],',',ma[1],',',ma[2]); + +console.log("Temperature ",W.temperature/10); +console.log("Level", pirate*Math.atan2(W.a[0],W.a[2]),pirate*Math.atan2(W.a[1],W.a[2])); +var heading; // if level +heading=pirate*Math.atan2(-W.m[0],W.m[1]); +if(heading <0) heading+=360; +console.log("heading",heading); +heading=pirate*Math.atan2(-ma[0],ma[1]); +if(heading <0) heading+=360; +console.log("avg heading",heading); +}//end readall + +//Configuration +//The I2C pins that the LSM9D01 is connected to +//PICO I2C pins +//IC1 sda=B7 scl=B6 +//IC1 sda=B9 scl=B8 shim pins +//IC3 sda=B4 scl=A8 +//IC2 sda=B3 scl=B10 +var W; +function start(){ +// console.log("start"); + I2C3.setup({ scl :A8, sda: B4} ); +//console.log(I2C3); +var xgAddress= 0x6B;// Would be 0x1C if SDO_M is LOW +var mAddress= 0x1e;// Would be 0x6A if SDO_AG is LOW +var f = new (require("FlashEEPROM"))(); +require("slimLSM9DS1"); +W=require("calibrateLSM9DS1").connect(I2C3,xgAddress,mAddress); +W.run();//Get it started +// +//load the zero offsets obtained from calibration program +//load the zero offsets obtained from calibration program +var arr; +var mmmag=f.read(CalPage); +if (mmmag === undefined) { + console.log("No calibration found"); +} else { + console.log("Calibration is defined"); + var mmag=E.toString(mmmag); + arr = mmag.split(";"); +W.mscale=JSON.parse(arr[0]); +W.gyroscale=JSON.parse(arr[1]); +W.accelscale=JSON.parse(arr[2]); +} +//use magnetometer offset in program not the ones on the chip +W.magOffset(0,0); +W.magOffset(1,0); +W.magOffset(2,0); + + W.enableFIFO(true); + W.setFIFO(5,10); //FIFO_THS=1,len + +//use autoCalc to control display values +W.autoCalc=2;//0=raw,1=raw-offset,2=calibrated +}//end start + +///// running average functions +//Ravg.js +//15 Dec 2016 +//running averagearr + +function Ravg(n){ + this.N=n; + this.avg=0.0; + this.flag=true; +} + +Ravg.prototype.getAvg=function(data){ + if(this.flag){ + this.avg=data; + this.flag=false; + }else{ + this.avg=(this.avg*(this.N-1)+data)/this.N; + }//end else + return this.avg; +}; + +function xyzAvg(n){ + this.vect=[new Ravg(n),new Ravg(n),new Ravg(n)]; +} + +xyzAvg.prototype.getAvg=function(data){ + var Rvalue=[0,0,0]; + var i; + for(i=0;i<3;i++)Rvalue[i]=this.vect[i].getAvg(data[i]); + return Rvalue; +}; + +////////////////////////////////////////////////////////////////// diff --git a/devices/AtestmenuSlimLSM9DS1.js b/devices/AtestmenuSlimLSM9DS1.js new file mode 100644 index 000000000..6162d44b0 --- /dev/null +++ b/devices/AtestmenuSlimLSM9DS1.js @@ -0,0 +1,694 @@ +//AtestmenuSlimLSM9DS1.js +//21 Dec 2016 +/* Copyright (c) 2016 Joe McCarty. See the file LICENSE for copying permission. */ + +var CalPage=99; //ROM page where calibration is saved +////////////////////////////////////////////////////////////// +// CAUTION CAUTION CAUTION///// +////////////////////////////////////////////////////////////// + +//How not to brick a PICO when reassigning the console +// away from the USB port to do menu programs + +//Setup the button to light the LED and reset the Pico +//Always include this code when a save() and oninit() functions are // used. +setWatch(function(e) { + digitalWrite(LED1, e.state); + USB.setConsole(); + reset(); +}, BTN, { repeat: true }); + + +E.on('init', function() { + console.log("Hello"); + startPgm(); +}); + +//input cmd from terminal,send it to parsecmd() +USB.on('data', function (data) { + var i; + sst+=data; +// look for control c in input stream + if(sst.indexOf(String.fromCharCode(3))>-1){ + USB.setConsole(); + reset(); + }// console.log("control C seen"); + USB.print(data); + if(sst.length>-1) + if(sst.charAt(sst.length-1)==="\r")selectparser(); +// if(sst.charAt(0)==="\r")selectparser(); +}); + +//Espruino replies here +LoopbackA.on('data',function(data){ + USB.print(data); //sending data to terminal +}); + + +console.log("In left pane type startPgm();"); +console.log("Use startPgm() first and make sure you can exit back to the console"); +console.log("Once you are sure that a proper exit works then type save();"); + + +var menulevel=0; +function startPgm(){ +setTimeout(function () { + start(); + LoopbackB.setConsole(); + mainmenu(); +}, 1000); +}//end startPgm + +var sst=""; + +function selectparser(){ + switch(menulevel){ + case 0: + parsemainmenu(); + break; + case 1: + parsegyromenu(); + break; + case 2: + parseaccelmenu(); + break; + case 3: + parsemagmenu(); + break; + case 4: + parsegyroscalemenu(); + break; + case 5: + parseaccelscalemenu(); + break; + case 6: + parsemagscalemenu(); + break; + case 7: + parsegyroODRmenu(); + break; + case 8: + parseaccelODRmenu(); + break; + case 9: + parsemagODRmenu(); + break; + case 10://return exits read and displaydata + sst=""; + clearInterval(nn); + mainmenu(); + break; + case 11://select display units + parsedisplaymenu(); + break; + }//end switch +} + +function mheader(){ + USB.print("\n\rSelect option or use control-C to exit\n\r"); +} + +function mainmenu(){ + sst=""; + menulevel=0; + mheader(); + USB.print("0 Configure Gyro\n\r"); + USB.print("1 Configure Accelerometer\n\r"); + USB.print("2 Configure Magnetometer\n\r"); + USB.print("3 Select Display Units\n\r"); + USB.print("4 Read and Display Data\n\r"); + USB.print("5 Show Calibration Structure\n\r"); + USB.print("E Exit\n\r"); +} + +var count=0;var nn; +function parsemainmenu(){ +USB.print("\n\r"); + switch(this.sst.charAt(0)){ + case "0"://Configure Gyro + USB.print("Configure Gyro\n\r"); + gyromenu(); + break; + case "1"://Configure Accelerometer + USB.print("Configure Accelerometer\n\r"); + accelmenu(); + break; + case "2"://Configure Magnetometer + USB.print("Configure Magnetometer\n\r"); + magmenu(); + break; + case "3"://select display units + USB.print("Select Display Units\n\r"); + displaymenu(); + break; + case "4"://read and display data + menulevel=10;sst=""; + readall(W); + nn=setInterval(function () { + readall(W); + count++; + if(count>1000)clearInterval(nn); + }, 200); + break; + case "5"://show calibration structure + USB.print("Magnetometer Scale "+W.mScale+"\n\r"); + USB.print(JSON.stringify(W.mscale)+"\n\r"); + USB.print("Gyro Scale "+W.gScale+"\n\r"); + USB.print(JSON.stringify(W.gyroscale)+"\n\r"); + USB.print("Acceleration Scale "+W.aScale+"\n\r"); + USB.print(JSON.stringify(W.accelscale)+"\n\r\n\r"); + mainmenu(); + break; + case"E"://Exit + USB.setConsole(); + LoopbackA.print("USB.setConsole();\n\r"); + USB.print("Exit\n\r"); + break; + default: + mainmenu(); + break; + }//end switch sst +}//end parsemainmenu + +function displaymenu(){ + sst=""; + menulevel=11; + mheader(); + USB.print("0 Raw count\n\r"); + USB.print("1 Raw-Offset\n\r"); + USB.print("2 Engineering Units\n\r"); + USB.print("8 Main Menu\n\r"); + USB.print("E Exit\n\r"); +} + +function parsedisplaymenu(){ +USB.print("\n\r"); + switch(this.sst.charAt(0)){ + case "0"://Raw count + USB.print("Raw Count\n\r"); + W.autoCalc=0; + mainmenu(); + break; + case "1"://Rawcount-offset + USB.print("Raw Count - Offset\n\r"); + W.autoCalc=1; + mainmenu(); + break; + case "2"://Engineering Units + USB.print("Engineering Units\n\r"); + W.autoCalc=2; + mainmenu(); + break; + case "8"://Main Menu + USB.print("Return to Main Menu\n\r"); + mainmenu(); + break; + case"E"://Exit + USB.setConsole(); + LoopbackA.print("USB.setConsole();\n\r"); + USB.print("Exit\n\r"); + break; + default: + displaymenu(); + break; + }//end switch sst +} + +function gyromenu(){ + sst=""; + menulevel=1; + mheader(); + USB.print("0 Set Gyro Scale\n\r"); + USB.print("1 Set Gyro Output Data Rate\n\r"); +// USB.print("2 Set Gyro Filter\n\r"); + USB.print("8 Main Menu\n\r"); + USB.print("E Exit\n\r"); +} + +function parsegyromenu(){ +USB.print("\n\r"); + switch(this.sst.charAt(0)){ + case "0"://Set Gyro Scale + USB.print("Set Gyro Scale\n\r"); + gyroscalemenu(); + break; + case "1"://Set Gyro Output Data Rate + USB.print("Set Gyro Output Data Rate\n\r"); + gyroODRmenu(); + break; + case "8"://Main Menu + USB.print("Return to Main Menu\n\r"); + mainmenu(); + break; + case"E"://Exit + USB.setConsole(); + LoopbackA.print("USB.setConsole();\n\r"); + USB.print("Exit\n\r"); + break; + default: + gyromenu(); + break; + }//end switch sst +}//end parsegyromenu + +function accelmenu(){ + sst=""; + menulevel=2; + mheader(); + USB.print("0 Set Accelerometer Scale\n\r"); + USB.print("1 Set Accelerometer Output Data Rate\n\r"); + USB.print("8 Main Menu\n\r"); + USB.print("E Exit\n\r"); +} + +function parseaccelmenu(){ +USB.print("\n\r"); + switch(this.sst.charAt(0)){ + case "0"://Set accel Scale + USB.print("Set Accelerometer Scale\n\r"); + accelscalemenu(); + break; + case "1"://Set accel Output Data Rate + USB.print("Set Accelerometer Output Data Rate\n\r"); + accelODRmenu(); + break; + case "8"://Main Menu + USB.print("Return to Main Menu\n\r"); + mainmenu(); + break; + case"E"://Exit + USB.setConsole(); + LoopbackA.print("USB.setConsole();\n\r"); + USB.print("Exit\n\r"); + break; + default: + accelmenu(); + break; + }//end switch sst +}//end parseaccelmenu + +function magmenu(){ + sst=""; + menulevel=3; + mheader(); + USB.print("0 Set Magnetometer Scale\n\r"); + USB.print("1 Set Magnetometer Output Data Rate\n\r"); + USB.print("8 Main Menu\n\r"); + USB.print("E Exit\n\r"); +} + +function parsemagmenu(){ +USB.print("\n\r"); + switch(this.sst.charAt(0)){ + case "0"://Set mag Scale + USB.print("Set Magnetometer Scale\n\r"); + magscalemenu(); + break; + case "1"://Set mag Output Data Rate + USB.print("Set Magnetometer Output Data Rate\n\r"); + magODRmenu(); + break; + case "8"://Main Menu + USB.print("Return to Main Menu\n\r"); + mainmenu(); + break; + case"E"://Exit + USB.setConsole(); + LoopbackA.print("USB.setConsole();\n\r"); + USB.print("Exit\n\r"); + break; + default: + magmenu(); + break; + }//end switch sst +}//end parsemagmenu + + +///////////////////////// + +function gyroscalemenu(){ + sst=""; + menulevel=4; + mheader(); + USB.print("Select Gyro Scale\n\r"); + USB.print("0 for 245 deg/s\n\r"); + USB.print("1 for 500 deg/s\n\r"); + USB.print("2 for 2000 deg/s\n\r"); + USB.print("8 Main Menu\n\r"); + USB.print("E Exit\n\r"); +} + +function parsegyroscalemenu(){ +USB.print("\n\r"); + switch(this.sst.charAt(0)){ + case "0"://Set gyro Scale 245 + case "1":///Set gyro Scale 500 + case "2"://Set gyro Scale 2000r + USB.print("Set Gyro Scale\n\r"); + W.setGyroScale(Number(this.sst.charAt(0))); + gyromenu(); + break; + case "8"://Main Menu + USB.print("Return to Main Menu\n\r"); + mainmenu(); + break; + case"E"://Exit + USB.setConsole(); + LoopbackA.print("USB.setConsole();\n\r"); + USB.print("Exit\n\r"); + break; + default: + gyroscalemenu(); + break; + }//end switch sst +}//end parsegyroscalemenu + +function accelscalemenu(){ + sst=""; + menulevel=5; + mheader(); + USB.print("Select Accelerometer Scale\n\r"); + USB.print("0 for 2 g\n\r"); + USB.print("1 for 4 g\n\r"); + USB.print("2 for 8 g\n\r"); + USB.print("3 for 16 g\n\r"); + USB.print("8 Main Menu\n\r"); + USB.print("E Exit\n\r"); +} + +function parseaccelscalemenu(){ +USB.print("\n\r"); + switch(this.sst.charAt(0)){ + case "0"://Set accel Scale 2g + case "1"://Set accel Scale 4g + case "2"://Set accel Scale 8g + case "3"://Set accel Scale 16g + USB.print("Set Accelerometer Scale\n\r"); + W.setAccelScale(Number(this.sst.charAt(0))); + accelmenu(); + break; + case "8"://Main Menu + USB.print("Return to Main Menu\n\r"); + mainmenu(); + break; + case"E"://Exit + USB.setConsole(); + LoopbackA.print("USB.setConsole();\n\r"); + USB.print("Exit\n\r"); + break; + default: + accelscalemenu(); + break; + }//end switch sst +}//end parseaccelscalemenu + +function magscalemenu(){ + sst=""; + menulevel=6; + mheader(); + USB.print("Select Magnetometer Scale\n\r"); + USB.print("0 for 4 Gauss\n\r"); + USB.print("1 for 8 Gauss\n\r"); + USB.print("2 for 12 Gauss\n\r"); + USB.print("3 for 16 Gauss\n\r"); + USB.print("8 Main Menu\n\r"); + USB.print("E Exit\n\r"); +} + +function parsemagscalemenu(){ +USB.print("\n\r"); + switch(this.sst.charAt(0)){ + case "0"://Set mag Scale 4 Gauss + case "1"://Set mag Scale 8 Gauss + case "2"://Set magl Scale 12 Gauss + case "3"://Set mag Scale 16 Gauss + USB.print("Set Accelerometer Scale\n\r"); + W.setMagScale(Number(this.sst.charAt(0))); + magmenu(); + break; + case "8"://Main Menu + USB.print("Return to Main Menu\n\r"); + mainmenu(); + break; + case"E"://Exit + USB.setConsole(); + LoopbackA.print("USB.setConsole();\n\r"); + USB.print("Exit\n\r"); + break; + default: + magscalemenu(); + break; + }//end switch sst +}//end parsemagscalemenu + +function gyroODRmenu(){ + sst=""; + menulevel=7; + mheader(); + USB.print("Select Gyro Output Data Rate\n\r"); +// USB.print("0 for off\n\r"); + USB.print("1 for 14.9 Hz\n\r"); + USB.print("2 for 59.5 Hz\n\r"); + USB.print("3 for 119 Hz\n\r"); + USB.print("4 for 238 Hz\n\r"); + USB.print("5 for 476 Hz\n\r"); + USB.print("6 for 952 Hz\n\r"); + USB.print("8 Main Menu\n\r"); + USB.print("E Exit\n\r"); +} + +function parsegyroODRmenu(){ +USB.print("\n\r"); + switch(this.sst.charAt(0)){ +// case "0"://Set gyroODR off + case "1"://Set gyroODR 14.9 Hz + case "2"://Set gyroODR 59.5 Hz + case "3"://Set gyroODR 119 Hz + case "4"://Set gyroODR 238 Hz + case "5"://Set gyroODR 476 Hz + case "6"://Set gyroODR 952 Hz + USB.print("Set Gyro Output Data Rate\n\r"); + W.setGyroODR(Number(this.sst.charAt(0))); + gyromenu(); + break; + case "8"://Main Menu + USB.print("Return to Main Menu\n\r"); + mainmenu(); + break; + case"E"://Exit + USB.setConsole(); + LoopbackA.print("USB.setConsole();\n\r"); + USB.print("Exit\n\r"); + break; + default: + gyroODRmenu(); + break; + }//end switch sst +}//end parsegyroODRmenu + +function accelODRmenu(){ //(accelerometer only mode) + sst=""; + menulevel=8; + mheader(); + USB.print("Select Accelerometer Output Data Rate\n\r"); +// USB.print("0 for off\n\r"); + USB.print("1 for 10 Hz\n\r"); + USB.print("2 for 50 Hz\n\r"); + USB.print("3 for 119 Hz\n\r"); + USB.print("4 for 238 Hz\n\r"); + USB.print("5 for 476 Hz\n\r"); + USB.print("6 for 952 Hz\n\r"); + USB.print("8 Main Menu\n\r"); + USB.print("E Exit\n\r"); +} + +function parseaccelODRmenu(){ +USB.print("\n\r"); + switch(this.sst.charAt(0)){ +// case "0"://Set accelODR off + case "1"://Set accelODR 10 Hz + case "2"://Set accelODR 50 Hz + case "3"://Set accelODR 119 Hz + case "4"://Set accelODR 238 Hz + case "5"://Set accelODR 476 Hz + case "6"://Set accelODR 952 Hz + USB.print("Set Accelerometer Output Data Rate\n\r"); + W.setAccelODR(Number(this.sst.charAt(0))); + accelmenu(); + break; + case "8"://Main Menu + USB.print("Return to Main Menu\n\r"); + mainmenu(); + break; + case"E"://Exit + USB.setConsole(); + LoopbackA.print("USB.setConsole();\n\r"); + USB.print("Exit\n\r"); + break; + default: + accelODRmenu(); + break; + }//end switch sst +}//endparsemagODRmenu + +function magODRmenu(){ //(accelerometer only mode) + sst=""; + menulevel=9; + mheader(); + USB.print("Select Magnetometer Output Data Rate\n\r"); + USB.print("0 for 0.625 Hz\n\r"); + USB.print("1 for 1.25 Hz\n\r"); + USB.print("2 for 2.5 Hz\n\r"); + USB.print("3 for 5 Hz\n\r"); + USB.print("4 for 10 Hz\n\r"); + USB.print("5 for 20 Hz\n\r"); + USB.print("6 for 40 Hz\n\r"); + USB.print("7 for 80 Hz\n\r"); + USB.print("8 Main Menu\n\r"); + USB.print("E Exit\n\r"); +} + +function parsemagODRmenu(){ +USB.print("\n\r"); + switch(this.sst.charAt(0)){ + case "0"://Set magODR 0.625 Hz + case "1"://Set magODR 1.25 Hz + case "2"://Set magODR 2.5 Hz + case "3"://Set magODR 5 Hz + case "4"://Set magODR 10 Hz + case "5"://Set magODR 206 Hz + case "6"://Set magODR 40 Hz + case "7"://Set magODR 80 Hz + USB.print("Set Accelerometer Output Data Rate\n\r"); + W.setMagODR(Number(this.sst.charAt(0))); + magmenu(); + break; + case "8"://Main Menu + USB.print("Return to Main Menu\n\r"); + mainmenu(); + break; + case"E"://Exit + USB.setConsole(); + LoopbackA.print("USB.setConsole();\n\r"); + USB.print("Exit\n\r"); + break; + default: + magODRmenu(); + break; + }//end switch sst +}//end parsemagODRmenu + +/* +W.setGyroBandwidth(0);// 0..3 see table 46 +// +//setGyroHPfilter=function(onoff,cutoff) +W.setGyroHPfilter(1,7); //cutoff 0 to 15 +*/ + +////////////////////////////////////////////////////// +var AC=new xyzAvg(20);var ac=[0,0,0]; +var GY=new xyzAvg(20);var gy=[0,0,0]; +var MA=new xyzAvg(20);var ma=[0,0,0]; +function readall(W){ +W.readAccel(); +ac=AC.getAvg(W.a); +W.readGyro(); +gy=GY.getAvg(W.g); +W.readMag(); +ma=MA.getAvg(W.m); +W.readTemp(); +var pirate=180.0/Math.PI; + +console.log("Acceleration, ",W.a[0],',',W.a[1],',',W.a[2]); +console.log("Avg Acceleration, ",ac[0],',',ac[1],',',ac[2]); +console.log("Gyro, ",W.g[0],',',W.g[1],',',W.g[2]); +console.log("Avg Gyro, ",gy[0],',',gy[1],',',gy[2]); +console.log("Magnetometer, ",W.m[0],',',W.m[1],',',W.m[2]); +console.log("Avg Magnetometer ",ma[0],',',ma[1],',',ma[2]); + +console.log("Temperature ",W.temperature/10); +console.log("Level", pirate*Math.atan2(W.a[0],W.a[2]),pirate*Math.atan2(W.a[1],W.a[2])); +var heading; // if level +heading=pirate*Math.atan2(-W.m[0],W.m[1]); +if(heading <0) heading+=360; +console.log("heading",heading); +heading=pirate*Math.atan2(-ma[0],ma[1]); +if(heading <0) heading+=360; +console.log("avg heading",heading); +}//end readall + +//Configuration +//The I2C pins that the LSM9D01 is connected to +//PICO I2C pins +//IC1 sda=B7 scl=B6 +//IC1 sda=B9 scl=B8 shim pins +//IC3 sda=B4 scl=A8 +//IC2 sda=B3 scl=B10 +var W; +function start(){ +// console.log("start"); + I2C3.setup({ scl :A8, sda: B4} ); +//console.log(I2C3); +var xgAddress= 0x6B;// Would be 0x1C if SDO_M is LOW +var mAddress= 0x1e;// Would be 0x6A if SDO_AG is LOW + W =require("slimLSM9DS1").connect(I2C3,xgAddress,mAddress); +W.run();//Get it started +// +//load the zero offsets obtained from calibration program +var f = new (require("FlashEEPROM"))(); +var arr; +var mmmag=f.read(CalPage); +if (mmmag === undefined) { + console.log("No calibration found"); +} else { + console.log("Calibration is defined"); + var mmag=E.toString(mmmag); + arr = mmag.split(";"); +W.mscale=JSON.parse(arr[0]); +W.gyroscale=JSON.parse(arr[1]); +W.accelscale=JSON.parse(arr[2]); +} +//use magnetometer offset in program not the ones on the chip +W.magOffset(0,0); +W.magOffset(1,0); +W.magOffset(2,0); + + W.enableFIFO(true); + W.setFIFO(5,10); //FIFO_THS=1,len + +//use autoCalc to control display values +W.autoCalc=2;//0=raw,1=raw-offset,2=calibrated +}//end start + +///// running average functions +//Ravg.js +//15 Dec 2016 +//running averagearr + +function Ravg(n){ + this.N=n; + this.avg=0.0; + this.flag=true; +} + +Ravg.prototype.getAvg=function(data){ + if(this.flag){ + this.avg=data; + this.flag=false; + }else{ + this.avg=(this.avg*(this.N-1)+data)/this.N; + }//end else + return this.avg; +}; + +function xyzAvg(n){ + this.vect=[new Ravg(n),new Ravg(n),new Ravg(n)]; +} + +xyzAvg.prototype.getAvg=function(data){ + var Rvalue=[0,0,0]; + var i; + for(i=0;i<3;i++)Rvalue[i]=this.vect[i].getAvg(data[i]); + return Rvalue; +}; + diff --git a/devices/LSM9Ds1.md b/devices/LSM9Ds1.md new file mode 100644 index 000000000..af2787f87 --- /dev/null +++ b/devices/LSM9Ds1.md @@ -0,0 +1,217 @@ +# Two Modules for LSM9DS1, +## thinLSM9DS1.js and calibrateLSM9DS1.js + + +* KEYWORDS: Module,IMU,I2C,Gyro,Accelerometer,Magnetometer + +### LSM9DS1 Description +* 3 acceleration, 3 angular rate and, 3 magnetic field channels +* ±2/ ±4/ ±8/ ±16 g linear acceleration full scale +* ±4/ ±8/ ±12/ ±16 gauss magnetic full scale +* ±245/ ±500/ ±2000 dps angular rate full scale +* 16-bit data output +* SPI / I2C serial interfaces +* Analog supply voltage 1.9 V to 3.6 V +* Die Temperature +* Sources:.. + + [LSM9DS1 at Sparkfun](https://www.sparkfun.com/products/13944) + + [LSM9DS1 at Adafruit](https://www.adafruit.com/products/2021) + + +* [LSM9DS1 Datasheet](http://www.st.com/content/ccc/resource/technical/document/datasheet/1e/3f/2a/d6/25/eb/48/46/DM00103319.pdf/files/DM00103319.pdf/jcr:content/translations/en.DM00103319.pdf) + +Note that figure 1 of the datasheet is a bit confusing. Note the dot on the picture of the chip for each axis. + +### Module Overview +The module calibrateLSM9DS1.js adds calibration functions to the +module thinLSM9DS1.js +The program savecal.js can be used to alter values in the calibration stucture save in ROM. +The program AmenucalslimLSM9DS1.js should be used first to establish the zero offsets for each sensor, axis and scale. +The program AmenutestSlimLSM9DS1.js is similar but omits the calibration functions and menus. +These programs and modules were created and tested using the Sparkfun breakout board. + +### Connecting the LSM9DS1 to a Pico using I2C + +#### You can wire this up as follows: + +| Device Pin | Espruino | +| ---------- | -------- | +| 1 (GND) | GND | +| 2 (VCC) | 3.3 | +| 3 (SDA) | B4 | +| 4 (SCLT)| A8 | + +#### Software Configuration +1. The program savecal.js is used to write the calibaration structure to ROM on the Pico. It uses the module FlashEEPROM.js and writes the sturcture to a ROM page defined by: var CalPage=99; The CalPage can be edited if needed +2. The programs AmenucalslimLSM9DS1.js and +AmenutestSlimLSM9DS1.js can be configured to use a different CalPage, I2C, and pins for the SCL and SDA. The I2C interface bus for the LSM9DS1 uses two different bus addresses. The xgAddress for the gyro and accelerometer defaults to 0x6B. The mAddress for the magnetometer defaults to 0x1E. The Sparkfun part uses these default addresses, but can be modified to use the alternatives of 0x1C and 0x6A. +3. The program savecal.js can be used to write the calibration structure to ROM. The AmenucalslimLSM9DS1.js will also create the structure when the calibration save option is selected. Savecal.js may be used to adjust the scale factors for each axis manually. +4. Calibration (sets zero offsets for sensors) + + 1. Load and run the AmenucalslimLSM9DS1.js program + 2. Place the LSM9DS1 board on a level surface (X and Y axis level), and select the Calibrate Gyro and Accelerometer option. + 3. To calibrate the magnetometer, I found it useful to tape the device to a wooden cube and use a wooden fence to ensure that the device points North and South as different axis are pointed for calibration. The menu option Calibrate Magnetometer will call out six steps starting with pointing the X-axis North. + 4. Save the calibrations by selecting menu option Save calibrations to ROM. + 5. The menu option Read and Display Data will do that until the return key is pressed. + +5. Some caution is needed with these menu programs. They make use of the USB port on the Pico. This disconnects the Espruino console from the USB port and can BRICK the Pico if a proper exit that restores the connection. The programs as written provide three exit paths: the Pico pushbutton, a control-C, and "E" in the menus. If you edit these programs please confirm that the exit methods work before performing a save() to save the program to ROM. When loaded the left WebIDE pane will ask you to startPgm() or save(). Use the startPgm() option until you are satified that the exits work. + + +#### How to use these modules: +calibrateLSM9DS1.js requires thinLSM9DS1.js + +``` +require("slimLSM9DS1"); +W=require("calibrateLSM9DS1").connect(I2C3,xgAddress,mAddress); +W.run();//Get it started +``` +Both menu programs, and savecal.js also require FlashEEPROM + +``` +var CalPage=99; //ROM page where calibration is saved + +//Configuration +//The I2C pins that the LSM9D01 is connected to +//PICO I2C pins +//IC1 sda=B7 scl=B6 +//IC1 sda=B9 scl=B8 shim pins +//IC3 sda=B4 scl=A8 +//IC2 sda=B3 scl=B10 +var W; +function start(){ +// console.log("start"); + I2C3.setup({ scl :A8, sda: B4} ); +//console.log(I2C3); +var xgAddress= 0x6B;// Would be 0x1C if SDO_M is LOW +var mAddress= 0x1e;// Would be 0x6A if SDO_AG is LOW + W =require("slimLSM9DS1").connect(I2C3,xgAddress,mAddress); +W.run();//Get it started +// +//load the zero offsets obtained from calibration program +var f = new (require("FlashEEPROM"))(); +var arr; +var mmmag=f.read(CalPage); +if (mmmag === undefined) { + console.log("No calibration found"); +} else { + console.log("Calibration is defined"); + var mmag=E.toString(mmmag); + arr = mmag.split(";"); +W.mscale=JSON.parse(arr[0]); +W.gyroscale=JSON.parse(arr[1]); +W.accelscale=JSON.parse(arr[2]); +} +//use magnetometer offset in program not the ones on the chip +W.magOffset(0,0); +W.magOffset(1,0); +W.magOffset(2,0); +// once the run() function has executed the scale and output data rate (ODR) can be +// changed using +W.setGyroScale(1);//0,1,2 +W.setAccelScale(1);//0,1,2,3 +W.setMagScale(1);//0,1,2,3 +//use autoCalc to control display values +W.autoCalc=2;//0=raw,1=raw-offset,2=calibrated +W.setGyroODR(6);//0,1,2,3,4,5,6 +W.setAccelODR(6);//0,1,2,3,4,5,6 +W.setMagODR(7);//0,1,2,3,4,5,6,7 +// can put readall in a loop +W.readall(W); +}//end start + +function readall(W){ +W.readAccel(); +W.readGyro(); +W.readMag();ma=MA.getAvg(W.m); +W.readTemp(); + +console.log("Acceleration, ",W.a[0],',',W.a[1],',',W.a[2]); +console.log("Gyro, ",W.g[0],',',W.g[1],',',W.g[2]); +console.log("Magnetometer, ",W.m[0],',',W.m[1],',',W.m[2]); +console.log("Avg Magnetometer ",ma[0],',',ma[1],',',ma[2]); +console.log("Temperature ",W.temperature/10); +var pirate=180.0/Math.PI; +console.log("Level", pirate*Math.atan2(W.a[0],W.a[2]),pirate*Math.atan2(W.a[1],W.a[2])); +var heading; // if level +heading=pirate*Math.atan2(-W.m[0],W.m[1]); +if(heading <0) heading+=360; +console.log("heading",heading); +}//end readall + +function startPgm(){ +setTimeout(function () { + start(); +(); +}, 1000); +}//end startPgm +startPgm(); +``` + +#### The Calibration Structures: +The scale: element is the sensor scale. +The regvalue: element is used to write to the device and should not be modified. +The res: element is used to convert counts to engineering units for each axis of the sensor in X, Y, and Z order. +The off: element is the zero offset for each axis of the sensor + +``` +/** 'mScale indexes mscale, used to select magnetometer scale' */ +this.mScale=0; +this.mscale=[ + {scale:4,regvalue:0, + mres:[0.000122,0.000122,0.000122], + moff:[0,0,0] //zero offset in counts + }, + {scale:8,regvalue:32, + mres:[0.000244,0.000244,0.000244], + moff:[0,0,0] + }, + {scale:12,regvalue:64, + mres:[0.000366,0.000366,0.000366], + moff:[0,0,0] + }, + {scale:16,regvalue:96, + mres:[0.000488,0.000488,0.000488], + moff:[0,0,0] + }, +]; + +/** 'gScale indexes gyroscale, used to select gyroscope scale' */ + this.gScale=0; + this.gyroscale=[ + {scale:245,regvalue:0, + gres:[245/32768.0,245/32768.0,245/32768.0], + goff:[0,0,0] //zero offset + }, + {scale:500,regvalue:8, + gres:[500/32768.0,500/32768.0,500/32768.0], + goff:[0,0,0] + }, + {scale:2000,regvalue:0x18, + gres:[2000/32768.0,2000/32768.0,2000/32768.0], + goff:[0,0,0] + }, +]; + +/** 'aScale indexes accelscale, used to select accelerometer scale' */ +this.aScale=0; +this.accelscale=[ + {scale:2,regvalue:0, + ares:[2/32768.0,2/32768.0,2/32768.0], + aoff:[0,0,0] + }, + {scale:4,regvalue:16, + ares:[4/32768.0,4/32768.0,4/32768.0], + aoff:[0,0,0] + }, + {scale:8,regvalue:24, + ares:[8/32768.0,8/32768.0,8/32768.0], + aoff:[0,0,0] + }, + {scale:16,regvalue:8, + ares:[16/32768.0,16/32768.0,16/32768.0], + aoff:[0,0,0] + }, +]; +``` \ No newline at end of file diff --git a/devices/calibrateLSM9DS1.js b/devices/calibrateLSM9DS1.js new file mode 100644 index 000000000..aa31beec4 --- /dev/null +++ b/devices/calibrateLSM9DS1.js @@ -0,0 +1,112 @@ +/* Copyright (c) 2016 Joe McCarty. See the file LICENSE for copying permission. */ +/* +This module provides I2C connection to a LSM9DS1 IMU +The prefix calibrate indicates that the calibration functions are added to the slimLSM9DS1.js.*/ +//calibrateLSM9DS1.js as a module +//19 Dec2016 +// requires slimLSM9DS1.js +// 13 dec 2016 +//////////////////////////////////////// +/*Private */ +var Regs={ + FIFO_SRC: (0x2F), +}; + var Avg=[0,0,0,0]; + +/** This is 'exported' so it can be used with `require('calibrateLSM9dS1.js').connect(i2c,xgAddress,mAddress)` */ +exports.connect = function(i2c,xgAddress,mAddress) { + var Q=require("slimLSM9DS1").connect(i2c,xgAddress,mAddress); + +/**'calibrate(autocalc,mode,cscale,callback) calibrates the accelerometer and gyro'*/ + +Q.calibrate=function(autocalc,mode,cscale,callback){ + var data= new Uint8Array(6); + var samples=0; + var ii,i; + var aBiasRawTemp=[0,0,0]; + var gBiasRawTemp=[0,0,0]; + var saveascale=this.aScale; + var savegscale=this.gScale; + aBiasRawTemp[0]=0;aBiasRawTemp[1]=0;aBiasRawTemp[2]=0; + gBiasRawTemp[0]=0;gBiasRawTemp[1]=0;gBiasRawTemp[2]=0; + this.setAccelScale(cscale); + if(cscale<3)this.setGyroScale(cscale); + aBiasRawTemp[0]=0;aBiasRawTemp[1]=0;aBiasRawTemp[2]=0; + gBiasRawTemp[0]=0;gBiasRawTemp[1]=0;gBiasRawTemp[2]=0; + this.autoCalc = 0; + this.enableFIFO(false); + this.enableFIFO(true); + this.setFIFO(0, 0); + this.enableFIFO(false); + this.enableFIFO(true); + this.setFIFO(1, 0x1F); + while (samples < 0x1F){ + samples = (this.xgReadByte(Regs.FIFO_SRC) & 0x3F); + }//end while + for(ii = 0; ii < samples ; ii++){ + // Read the gyro data stored in the FIFO + this.readGyro(); + for(i=0;i<3;i++)gBiasRawTemp[i] += this.g[i]; + this.readAccel(); + for(i=0;i<2;i++)aBiasRawTemp[i] += this.a[i]; +if(!mode)aBiasRawTemp[2]+=this.a[2] - 1.0/this.accelscale[this.aScale].ares[2]; +else aBiasRawTemp[2]+=this.a[2]; + // Assumes sensor facing up! + }//next ii + for (ii = 0; ii < 3; ii++){ +this.gyroscale[this.gScale].goff[ii]= gBiasRawTemp[ii]/ samples; +this.accelscale[this.aScale].aoff[ii]= aBiasRawTemp[ii] / samples; + }//nextii + this.enableFIFO(false); + this.setFIFO(0, 0x00);//FIFO_OFF=0 + this.autoCalc = autocalc; + this.setAccelScale(saveascale); + this.setGyroScale(savegscale); + callback(); +};//end calibrate + +/**'avgMag(scale,N,callback) takes N magnetometer readings calculate the average for the magnetometer scale'*/ +Q.avgMag=function(scale,N,callback){ + var saveMagscale=this.mScale; + var saveAutocalc=this.autoCalc; + this.setMagScale(scale); + this.autoCalc=0; + this.setMagODR(7); + this.readMag(); + var avg=[0,0,0]; + var i,j; + for(i=0;i0){ +for(i=0;i<4;i++)W.mscale[i].moff[Math.floor(step/2)]=Avg[i]/2; +}//endif + callback(); + }); + }); + }); + }); +};//end calMag + + return Q; +}; diff --git a/devices/savecal.js b/devices/savecal.js new file mode 100644 index 000000000..2cf0e3f20 --- /dev/null +++ b/devices/savecal.js @@ -0,0 +1,22 @@ +//savecal.js +//19 dec 2016 +//Write calibrations to ROM +//for LSM9DS1 +var CalPage=99; //ROM page where calibration is saved + +var mag='[{"scale":4,"regvalue":0,"mres":[0.000122,0.000122,0.000122],"moff":[2015.3,-756.5,1002.4]},{"scale":8,"regvalue":32,"mres":[0.000244,0.000244,0.000244],"moff":[1025.2,-371.7,485.1]},{"scale":12,"regvalue":64,"mres":[0.000366,0.000366,0.000366],"moff":[686.2,-231,311.95]},{"scale":16,"regvalue":96,"mres":[0.000488,0.000488,0.000488],"moff":[521.9,-168.4,228.1]}]'; + +var gyro='[{"scale":245,"regvalue":0,"gres":[0.00747680664,0.00747680664,0.00747680664],"goff":[-607.19354838709,139.51612903225,-89.25806451612]},{"scale":500,"regvalue":8,"gres":[0.01525878906,0.01525878906,0.01525878906],"goff":[-328.21875,88.3125,-15.21875]},{"scale":2000,"regvalue":24,"gres":[0.06103515625,0.06103515625,0.06103515625],"goff":[-62.29032258064,40.48387096774,11.32258064516]}]'; + +var accel='[{"scale":2,"regvalue":0,"ares":[0.00006103515,0.00006103515,0.00006103515],"aoff":[-756.3125,-617,618.625]},{"scale":4,"regvalue":16,"ares":[0.00012207031,0.00012207031,0.00012207031],"aoff":[-434.53125,-267.84375,270.34375]},{"scale":8,"regvalue":24,"ares":[0.00024414062,0.00024414062,0.00024414062],"aoff":[-202.93548387096,-133.64516129032,135.38709677419]},{"scale":16,"regvalue":8,"ares":[0.00048828125,0.00048828125,0.00048828125],"aoff":[-62.77419354838,-35.61290322580,-646.35483870967]}]'; + +mag=mag+';'+gyro+';'+accel; +var f = new (require("FlashEEPROM"))(); +f.write(CalPage, mag); +var mmag=E.toString(f.read(CalPage)); +var arr = mmag.split(";"); + +console.log(arr[0]); +console.log(arr[1]); +console.log(arr[2]); + diff --git a/devices/slimLSM9DS1.js b/devices/slimLSM9DS1.js new file mode 100644 index 000000000..ca6ed0cbb --- /dev/null +++ b/devices/slimLSM9DS1.js @@ -0,0 +1,408 @@ +/* Copyright (c) 2016 Joe McCarty. See the file LICENSE for copying permission. */ +/* +This module provides I2C connection to a LSM9DS1 IMU +The prefix slim indicates that the zero calibration and interrupt functions are omitted. These functions may be added using a different module +*/ + +//slimLSM9DS1.js as a module +//13 Dec2016 +//////////////////////////////////////// +/*Private */ +var WHO_AM_I_AG_RSP=0x68; +var WHO_AM_I_M_RSP=0x3D; +var Mags={ + WHO_AM_I_M: 0x0F, + OFFSET_X_REG_L_M: 0x05, + OFFSET_X_REG_H_M: 0x06, + OUT_X_L_M: 0x28, + CTRL_REG1_M:0x20, + CTRL_REG2_M:0x21, + STATUS_REG_M:0x27, +}; + +var Regs={ +WHO_AM_I_XG:(0x0F), + CTRL_REG9:(0x23), + FIFO_CTRL:(0x2E), + OUT_TEMP_L:(0x15), + OUT_X_L_G:(0x18), + OUT_X_L_XL:(0x28), + CTRL_REG1_G:(0x10), + CTRL_REG3_G:(0x12), + CTRL_REG6_XL:(0x20), + STATUS_REG_1:(0x27), +}; + +/** 'creates an instance of LSM9DS1*/ +function LSM9DS1(i2c,xgAddress,mAddress) { + this.i2c = i2c; + this.xgAddress= xgAddress; + this.mAddress= mAddress; +this.xgstack=[ + { "sub": 16, "data": 192 }, + { "sub": 17, "data": 0 }, + { "sub": 18, "data": 0 }, + { "sub": 30, "data": 58 }, + { "sub": 19, "data": 0 }, + { "sub": 31, "data": 56 }, + { "sub": 32, "data": 192 }, + { "sub": 33, "data": 0 } + ]; +this.mstack=[ + { "sub": 32, "data": 28 }, + { "sub": 33, "data": 0 }, + { "sub": 34, "data": 0 }, + { "sub": 35, "data": 12 }, + { "sub": 36, "data": 0 } + ]; +/** 'mScale indexes mscale, used to select magnetometer scale' */ +this.mScale=0; +this.mscale=[ + {scale:4,regvalue:0, + mres:[0.000122,0.000122,0.000122], + moff:[0,0,0] //zero offset in counts + }, + {scale:8,regvalue:32, + mres:[0.000244,0.000244,0.000244], + moff:[0,0,0] + }, + {scale:12,regvalue:64, + mres:[0.000366,0.000366,0.000366], + moff:[0,0,0] + }, + {scale:16,regvalue:96, + mres:[0.000488,0.000488,0.000488], + moff:[0,0,0] + }, +]; + +/** 'gScale indexes gyroscale, used to select gyroscope scale' */ + this.gScale=0; + this.gyroscale=[ + {scale:245,regvalue:0, + gres:[245/32768.0,245/32768.0,245/32768.0], + goff:[0,0,0] //zero offset + }, + {scale:500,regvalue:8, + gres:[500/32768.0,500/32768.0,500/32768.0], + goff:[0,0,0] + }, + {scale:2000,regvalue:0x18, + gres:[2000/32768.0,2000/32768.0,2000/32768.0], + goff:[0,0,0] + }, +]; + +/** 'aScale indexes accelscale, used to select accelerometer scale' */ +this.aScale=0; +this.accelscale=[ + {scale:2,regvalue:0, + ares:[2/32768.0,2/32768.0,2/32768.0], + aoff:[0,0,0] + }, + {scale:4,regvalue:16, + ares:[4/32768.0,4/32768.0,4/32768.0], + aoff:[0,0,0] + }, + {scale:8,regvalue:24, + ares:[8/32768.0,8/32768.0,8/32768.0], + aoff:[0,0,0] + }, + {scale:16,regvalue:8, + ares:[16/32768.0,16/32768.0,16/32768.0], + aoff:[0,0,0] + }, +]; + +/** 'a g m where readings are stored' */ + this.g=[0,0,0]; + this.a=[0,0,0]; + this.m=[0,0,0]; + this.temperature=0; +/** 'autoCalc determine output units 0=raw,1=raw-offset,2=calibrated' */ + this.autoCalc = 0; +} +/** 'run() initializes the LSM9DS1' */ +LSM9DS1.prototype.run=function(){ + var i; +var mTest = this.mReadByte(Mags.WHO_AM_I_M); +var xgTest = this.xgReadByte(Regs.WHO_AM_I_XG); +var whoAmICombined = (xgTest << 8) | mTest; +if (whoAmICombined != ((WHO_AM_I_AG_RSP << 8) | WHO_AM_I_M_RSP)) + return 0;//callback(0); + for(i=0; i 2)return 0; + var msb, lsb; + msb = (offset & 0xFF00) >> 8; + lsb = offset & 0x00FF; + this.mWriteByte(Mags.OFFSET_X_REG_L_M + (2 * axis), lsb); + this.mWriteByte(Mags.OFFSET_X_REG_H_M + (2 * axis), msb); +};//end magOffset + +/** 'public' constants here */ +LSM9DS1.prototype.mWriteByte=function(subAddress,data){ + //console.log("mWriteByte ",this.mAddress, subAddress, data); + var x=this.mAddress; + this.i2c.writeTo(x, subAddress,data); + return 0; +};//end mWriteByte + +/** 'public' constants here */ +LSM9DS1.prototype.enableFIFO=function(enable){ + var temp = this.xgReadByte(Regs.CTRL_REG9); + if (enable) temp |= (1<<1); + else temp &= ~(1<<1); + this.xgWriteByte(Regs.CTRL_REG9, temp); +};//end enableFIFO + +/** 'xgWriteByte(subAddress,data) Write data byte to gyro/accelerometer at subAddress' */ +LSM9DS1.prototype.xgWriteByte=function(subAddress,data){ + var x=this.xgAddress; + this.i2c.writeTo(x, subAddress,data); +};//end xgWriteByte + +/** 'setFIFO(fifoMode,fifoThs) Sets fifo mode and length' */ +LSM9DS1.prototype.setFIFO=function(fifoMode,fifoThs){ + var threshold = fifoThs <= 0x1F ? fifoThs : 0x1F; + this.xgWriteByte(Regs.FIFO_CTRL, ((fifoMode & 0x7) << 5) | (threshold & 0x1F)); +};//end setFIFO + +/** 'readAccel() reads X,Y,Z accelerometer values'*/ +LSM9DS1.prototype.readAccel=function(){ + var temp=this.xgReadBytes(Regs.OUT_X_L_XL, 6); + var i; + this.a[0]=this.twos_comp(temp[0],temp[1]); + this.a[1]=this.twos_comp(temp[2],temp[3]); + this.a[2]=this.twos_comp(temp[4],temp[5]); + if (this.autoCalc>0){ + for(i=0;i<3;i++) + this.a[i] -= this.accelscale[this.aScale].aoff[i]; + }//endif + if (this.autoCalc>1){ + for(i=0;i<3;i++) + this.a[i]=this.a[i]*this.accelscale[this.aScale].ares[i]; + }//endif +};//end readAccel + +/** 'xgReadBytes(subAddress,count) read count bytes from gyro/accelerometer at subAddress'*/ +LSM9DS1.prototype.xgReadBytes=function(subAddress,count){ + var dest= new Uint8Array(count); + var x=this.xgAddress; + this.i2c.writeTo(x, subAddress|0x80); + dest=this.i2c.readFrom(x, count); + return dest; +};//end xgReadBytes + +/** 'prototype.twos_comp(low,high) converts low and high bytes'*/ +LSM9DS1.prototype.twos_comp=function(low,high){ + var t=(high << 8) | low; + return(t & 0x8000 ? t - 0x10000 : t); +};//end twos_comp + +/** 'readGyro() get data reading from the Gyro' */ +LSM9DS1.prototype.readGyro=function(){ + var temp= this.xgReadBytes(Regs.OUT_X_L_G,6); + var i; + this.g[0]=this.twos_comp(temp[0],temp[1]); + this.g[1]=this.twos_comp(temp[2],temp[3]); + this.g[2]=this.twos_comp(temp[4],temp[5]); + if (this.autoCalc>0){ + for(i=0;i<3;i++) + this.g[i] -=this.gyroscale[this.gScale].goff[i]; + }//endif + if (this.autoCalc>1){ + for(i=0;i<3;i++) + this.g[i]=this.g[i]*this.gyroscale[this.gScale].gres[i]; + }//endif +};//end readGyro + +/** 'readMag() get data reading from the magnetometer'*/ +LSM9DS1.prototype.readMag=function(){ + var temp=this.mReadBytes(Mags.OUT_X_L_M, 6); + var i; + this.m[0]=this.twos_comp(temp[0],temp[1]); + this.m[1]=this.twos_comp(temp[2],temp[3]); + this.m[2]=this.twos_comp(temp[4],temp[5]); + if (this.autoCalc>0){ + for(i=0;i<3;i++) + this.m[i] -=this.mscale[this.mScale].moff[i]; + }//endif + if (this.autoCalc>1){ + for(i=0;i<3;i++) + this.m[i]=this.m[i]*this.mscale[this.mScale].mres[i]; + }//endif +};//end readMag + +/** 'mReadBytes(subAddress,count) read count bytes from magnetometer at subAddress'*/ +LSM9DS1.prototype.mReadBytes=function(subAddress,count){ + var x=this.mAddress; + var dest=new Uint8Array(count); + this.i2c.writeTo(x, subAddress|0x80); + dest=this.i2c.readFrom(x, count); + return dest; +};//end mReadBytes + +/** 'readTemp() read the chip temperature C' */ +LSM9DS1.prototype.readTemp=function(){ + var temp=this.xgReadBytes(Regs.OUT_TEMP_L, 2); + this.temperature=this.twos_comp(temp[1]<<4,(temp[0]&0xf)<<4); + this.temperature=this.temperature/15; +};//end readTemp + +/** 'setGyroScale(gScl) gScl 0 for 245, 1 for 500, 2 for 2000' */ +LSM9DS1.prototype.setGyroScale=function(gScl){ + if(gScl<0)return "Bad Gyro Scale selection"; + if(gScl>2)return "Bad Gyro Scale selection"; + var ctrl1RegValue = this.xgReadByte(Regs.CTRL_REG1_G); + ctrl1RegValue &= 0xE7; + ctrl1RegValue |= this.gyroscale[gScl].regvalue; + this.xgWriteByte(Regs.CTRL_REG1_G, ctrl1RegValue); + this.gScale=gScl; + return this.gyroscale[gScl].scale; +};//end setGyroScale + +/** 'setGyroBandwidth(bw) 0..3' */ +LSM9DS1.prototype.setGyroBandwidth=function(bw){ + if(bw<0)return "Bad Gyro Bandwidth selection"; + if(bw>3)return "Bad Gyro Bandwidth selection"; + var temp = this.xgReadByte(Regs.CTRL_REG1_G); + temp &= 0xFC; + temp |= bw; + this.xgWriteByte(Regs.CTRL_REG1_G, temp); + return bw; +};//end setGyroBandwidth + +/** 'setGyroHPfilter(onoff,cutoff) 0/1, 0..31'*/ +LSM9DS1.prototype.setGyroHPfilter=function(onoff,cutoff){ + if(cutoff<0)return "Bad Gyro cutoff selection"; + if(cutoff>31)return "Bad Gyro cutoff selection"; + var temp = this.xgReadByte(Regs.CTRL_REG3_G); + temp &= 0xB0; + temp |= cutoff; + onoff&=1;onoff=onoff<<6; + temp|=onoff; + this.xgWriteByte(Regs.CTRL_REG3_G, temp); + return cutoff; +};//end setGyroHPfilter + +/** 'public' constants here */ +LSM9DS1.prototype.setAccelScale=function(aScl){ + if(aScl<0)return "Bad Acceleration Scale selection"; + if(aScl>3)return "Bad Acceleration Scale selection"; + var tempRegValue = this.xgReadByte(Regs.CTRL_REG6_XL); + // Mask out accel scale bits: + tempRegValue &= 0xE7; + tempRegValue |= this.accelscale[aScl].regvalue; + this.xgWriteByte(Regs.CTRL_REG6_XL, tempRegValue); + this.aScale=aScl; + return this.accelscale[aScl].scale; +};//end setAccelScale + +/** 'setMagScale(mScl) 0..3' */ +LSM9DS1.prototype.setMagScale=function(mScl){ + if(mScl<0)return "Bad Magnetometer Scale selection"; + if(mScl>3)return "Bad Magnetometer Scale selection"; + var temp = this.mReadByte(Mags.CTRL_REG2_M); + temp &= 0xFF^(0x3 << 5); + temp |= this.mscale[mScl].regvalue; + this.mWriteByte(Mags.CTRL_REG2_M, temp); + this.mScale=mScl; + return this.mscale[mScl].scale; +};//end setMagScale + +/** 'Bool=magAvailable()' */ +LSM9DS1.prototype.magAvailable=function(){ + var status; + status = this.mReadByte(Mags.STATUS_REG_M); + return (status & 8)>>3; +};//end magAvailable + +/** 'Bool=accelAvailable()' */ +LSM9DS1.prototype.accelAvailable=function(){ + var status = this.xgReadByte(Regs.STATUS_REG_1); + return (status & (1<<0)); +};//end accelAvailable + +/** 'Bool=gyroAvailable()' */ +LSM9DS1.prototype.gyroAvailable=function(){ + var status = this.xgReadByte(Regs.STATUS_REG_1); + return ((status & (1<<1)) >> 1); +};//end gyroAvailable + +/** 'Bool=tempAvailable()' */ +LSM9DS1.prototype.tempAvailable=function(){ + var status = this.xgReadByte(Regs.STATUS_REG_1); + return ((status & (1<<2)) >> 2); +};//end tempAvailable + +/** 'setGyroODR(gRate)' */ +LSM9DS1.prototype.setGyroODR=function(gRate){ + if ((gRate & 0x07) !== 0){ + var temp = this.xgReadByte(Regs.CTRL_REG1_G); + temp &= 0xFF^(0x7 << 5); + temp |= (gRate & 0x07) << 5; + this.gyro_sampleRate= gRate & 0x07; + this.xgWriteByte(Regs.CTRL_REG1_G, temp); + }//endif +};//end setGyroODR + + +/** 'setAccelODR(aRate)' */ +LSM9DS1.prototype.setAccelODR=function(aRate){ + if ((aRate & 0x07) !== 0){ + var temp = this.xgReadByte(Regs.CTRL_REG6_XL); + temp &= 0x1F; + temp |= ((aRate & 0x07) << 5); + this.accel_sampleRate = aRate & 0x07; + this.xgWriteByte(Regs.CTRL_REG6_XL, temp); + }//endif +};//end setAccelODR + +/** 'setMagODR(mRate)' */ +LSM9DS1.prototype.setMagODR=function(mRate){ + var temp = this.mReadByte(Mags.CTRL_REG1_M); + temp &= 0xFF^(0x7 << 2); + temp |= ((mRate & 0x07) << 2); + this.mag_sampleRate = mRate & 0x07; + this.mWriteByte(Mags.CTRL_REG1_M, temp); +};//end setMagODR + +/** This is 'exported' so it can be used with `require('slimLSM9dS1.js').connect(i2c,xgAddress,mAddress)` */ +// Create an instance of LSM9DS1 +exports.connect = function(i2c,xgAddress,mAddress) { + return new LSM9DS1(i2c,xgAddress,mAddress); +}; + +