-
• #2
LSM9DS1
Finally the board arrived a week later than expected. I also ordered an ESP32 board which required using a for profit shipping company instead of the post office for some reason. They shipped it from Colorado to Chicago and then mailed it to the suburbs.
The pony express would have been faster.Problems encountered when implementing the I2C interface:
LSM9DS1.prototype.xgReadBytes=function(subAddress,count){ var dest= new Uint8Array(count); // console.log("xgReadBytes ",this.xgAddress, subAddress|0x80, dest, count); var x=this.xgAddress; this.i2c.writeTo(x, subAddress|0x80); dest=this.i2c.readFrom(x, count); // for(var i=0;i<count;i++)console.log(dest[i]); return dest; }; LSM9DS1.prototype.mReadBytes=function(subAddress,count){ // console.log("mReadBytes ",this.mAddress, subAddress|0x80,count); var x=this.mAddress; var dest=new Uint8Array(count); this.i2c.writeTo(x, subAddress|0x80); dest=this.i2c.readFrom(x, count); // for(var i=0;i<count;i++)console.log(dest[i]); return dest; };
Notice the var x=this.address.
If this.address was used in the this.i2c.ReadFrom() function timeout errors occurred.
I tried to create a simplified version of the problem but have not succeeded in reproducing the error.
For reads of multiple bytes bit 7 of the sub-address is set to 1.LSM9DS1.prototype.readAccel=function(){ var temp=this.xgReadBytes(Regs.OUT_X_L_XL, 6); // Read 6 bytes, beginning at OUT_X_L_XL this.ax=this.twos_comp(temp[0],temp[1]); this.ay=this.twos_comp(temp[2],temp[3]); this.az=this.twos_comp(temp[4],temp[5]); /* this.ax = (temp[1] << 8) | temp[0]; // Store x-axis values into ax this.ay = (temp[3] << 8) | temp[2]; // Store y-axis values into ay this.az = (temp[5] << 8) | temp[4]; // Store z-axis values into az */ if (_autoCalc) { ax -= aBiasRaw[X_AXIS]; ay -= aBiasRaw[Y_AXIS]; az -= aBiasRaw[Z_AXIS]; } }; LSM9DS1.prototype.twos_comp=function(low,high){ var t=(high << 8) | low; return(t & 0x8000 ? t - 0x10000 : t); };
The values returned are in two’s compliment.
LSM9DS1.prototype.readTemp=function(){ //void LSM9DS1::readTemp(){ // We'll read two bytes from the temperature sensor into temp var temp=this.xgReadBytes(Regs.OUT_TEMP_L, 2); // Read 2 bytes, beginning at OUT_TEMP_L // console.log("TT= ",temp[0].toString(16),temp[1].toString(16)); this.temperature = temp[1];//(temp[1] << 8) | temp[0]; //temperature = ((int16_t)temp[1] << 8) | temp[0]; //https://gist.github.com/jimblom/08b333892ee383d6e443 //temperature = (((int16_t) temp[1] << 12) | temp[0] << 4 ) >> 4; // Temperature is a 12-bit signed integer //var t= (((temp[1]^0xf)<<12)|temp[0])>>4; //this.temperature=(t & 0x8000 ? t - 0x10000 : t); };
There is quite a bit of discussion on the web about reading the temperature.
Having tried various solutions, I’m still not sure it is working properly.
The file TestLSM9DS1_d.js is attached.
Some sample output:Acceleration -0.0087890625 -0.09417724609 1.02032470703 Gyro -810 294 75 Magnetometer 1379 1413 -2029 Temperature 246 Level -0.49353282241 -5.27352997140 heading 44.30230651281 Acceleration -0.01861572265 -0.09045410156 1.02691650390 Gyro -605 283 41 Magnetometer 1425 1387 -2030 Temperature 246 Level -1.03853188194 -5.03380446489 heading 45.77422016492 Acceleration 0.00439453125 -0.08666992187 1.02276611328 Gyro -429 -248 8 Magnetometer 1385 1459 -2064 Temperature 246 Level 0.24618193820 -4.84371267720 heading 43.50951784922 Acceleration -0.00036621093 -0.08117675781 1.03289794921 Gyro -501 21 -87 Magnetometer 1373 1453 -2027 Temperature 246 Level -0.02031404967 -4.49371112382 heading 43.37847185456
The readall function:
function readall(W){ W.readAccel(); W.readGyro(); W.readMag(); W.readTemp(); var pirate=180.0/Math.PI; console.log("Acceleration ",W.ax/16384,W.ay/16384,W.az/16384); console.log("Gyro ",W.gx,W.gy,W.gz); console.log("Magnetometer ",W.mx,W.my,W.mz); console.log("Temperature ",W.temperature); console.log("Level", pirate*Math.atan2(W.ax,W.az),pirate*Math.atan2(W.ay,W.az)); console.log("heading",pirate*Math.atan2(W.mx,W.my)); }//end readall
1 Attachment
-
• #3
Great - thanks for posting up!
Could your timeout error have been from doing something like:
doSomething(this.data); setTimeout(function() { doSomething(this.data); }, 100);
That's a common 'gotcha' in JS, since
this
doesn't stay the same inside asetTimeout
or interval. -
• #4
So far the Arduino code for the LSM9DS1 has been ported to Espruino, but to make it really useful it should be worked into module form.
There are a lot of knobs on the virtual control panel for this chip. In the previous version any changes to the knobs needed to be edited in the LSM9DS1.prototype.init function.
Today the code is modified so that the knobs are initialized to default values and an optional set of options can be supplied to the LSM9DS1.prototype.init function.
This is accomplished by changing the init function to the followingLSM9DS1.prototype.init=function(options){ var i,j; for (i=0; i<3; i++){ this.gBias[i] = 0; this.aBias[i] = 0; this.mBias[i] = 0; this.gBiasRaw[i] = 0; this.aBiasRaw[i] = 0; this.mBiasRaw[i] = 0; } //process and changes from options if(typeof options === "undefined" ) console.log("options undefined"); if(typeof options !== "undefined"){ console.log("options defined"); for(i in options){ //console.log(options); if(options.hasOwnProperty(i)){ for(j in this){//LSM9DS1){ // console.log(i,j);//,options[i],LSM9DS1[j]); if(j==i){ console.log(i,j,options[i],this[j]); this[j]=options[i]; } } } } } };
The optional options are outlined in the attached file options.js.
For example to change the acceleration sample rate from 6 to 5 :// accel sample rate can be 1-6 // 1 = 10 Hz 4 = 238 Hz // 2 = 50 Hz 5 = 476 Hz // 3 = 119 Hz 6 = 952 Hz accel_sampleRate: 6,
The code that calls the init function uses an option object containing only the options we wish to change.
function start(){ I2C3.setup({ scl :A8, sda: B4} ); var W=new LSM9DS1(I2C3); var myoptions={ //make changes to basic configuration here xgAddress: 0x6B, mAddress: 0x1e, test: 1, accel_sampleRate: 5, }; W.init(myoptions); //W.init(); console.log(W.begin()); var nn=setInterval(function () { readall(W); }, 200); }
The output of the substitutions made in the init function:
>options defined xgAddress xgAddress 107 107 mAddress mAddress 30 30 test test 1 0 accel_sampleRate accel_sampleRate 5 6
2 Attachments
-
• #5
This looks great - thanks! Looks like it could be ready to publish as a module soon? You could put
options.js
into the documentation file as a bit of code... -
• #6
Hi @Gordon. It’s tempting to go to module on this project but it’s not quite ready for that as yet. There are a number of functions that have yet to be translated. The most important one being the gyroscope calibration function. There are interrupt functions that would be difficult to use with the Sparkfun board but could be of use with the more expensive Adafruit board that brings forth the interrupt pins.
https://www.sparkfun.com/products/13944
https://www.adafruit.com/product/2021As to the topic of modules, I’m looking at a module within a module design for the final product.
The lowest level module uses a table to initialize the chip and functions to read the data.var xgstack= [ { "address": 107, "sub": 16, "data": 0 }, { "address": 107, "sub": 17, "data": 0 }, { "address": 107, "sub": 18, "data": 0 }, { "address": 107, "sub": 30, "data": 58 }, { "address": 107, "sub": 19, "data": 0 }, { "address": 107, "sub": 31, "data": 56 }, { "address": 107, "sub": 32, "data": 160 }, { "address": 107, "sub": 33, "data": 0 } ]; var mstack= [ { "address": 30, "sub": 32, "data": 28 }, { "address": 30, "sub": 33, "data": 0 }, { "address": 30, "sub": 34, "data": 0 }, { "address": 30, "sub": 35, "data": 12 }, { "address": 30, "sub": 36, "data": 0 } ]; LSM9DS1.prototype.run=function(){ var i; // To verify communication, we can read from the WHO_AM_I register //of each device. Store those in a variable so we can return them. var mTest = this.mReadByte(Mags.WHO_AM_I_M);// Read the gyro var xgTest = this.xgReadByte(Regs.WHO_AM_I_XG);//Read the accel/mag var whoAmICombined = (xgTest << 8) | mTest; console.log("who= ",whoAmICombined); if (whoAmICombined != ((WHO_AM_I_AG_RSP << 8) | WHO_AM_I_M_RSP)) return 0; for(i=0; i<this.xgstack.length;i++){ console.log(this.xgstack[i].address, this.xgstack[i].sub,this.xgstack[i].data); this.i2c.writeTo(this.xgstack[i].address, this.xgstack[i].sub,this.xgstack[i].data); } for(i=0; i<this.mstack.length;i++){ console.log(this.mstack[i].address, this.mstack[i].sub,this.mstack[i].data); this.i2c.writeTo(this.mstack[i].address, this.mstack[i].sub,this.mstack[i].data); } return whoAmICombined; };
See attached file: aTestLSM9DS1_a.js
At the next level of module, which invokes the first level module, the init function parses the options and the begin function populates the xgstack and mstack arrays.
This mod level module uses more memory resources but allows the tweaking of the options. Once the user is satisfied with the tweak, the stacks and some other variables are copied and pasted into a new program that uses only the first module. This will reduce the memory usage in a final program.
A similar approach seems possible for adding the calibration and interrupt functions.
A lowest level module example//TestM1.js 1 Dec 2016 function LSM9DS1() { } LSM9DS1.prototype.add=function(){ this.a=1; this.b=20; console.log(this.a+this.b); }; // Create an instance of LSM9DS1 exports.connect = function() { return new LSM9DS1(); };
A module one level up:
/TestM2.js 1 Dec 2016 exports.connect = function() { var x= require("testm1").connect(); x.d=98; x.sub= function() { console.log(this.a-this.b); }; return x; };
Invoke TestM1
//tryTestM1.js 1 Dec 2016 var ads =require("testm1").connect(); ads.add();
Invoke TestM2
//tryTestM2.js 1 Dec 2016 var ads =require("testm2").connect(); ads.add(); console.log(ads.d); ads.sub();
Some useful resource links on the topic of using IMU sensors:
https://www.intorobotics.com/accelerometer-gyroscope-and-imu-sensors-tutorials/
http://tutorial.cytron.com.my/2012/01/10/measuring-tilt-angle-with-gyro-and-accelerometer/
Kalman filter simulation
https://www.cs.utexas.edu/~teammco/misc/kalman_filter/
5 Attachments
-
• #7
LSM9DS1 4 Dec 2016
Some progress on the calibration functions has been made. There are some problems that need to be addressed.
The first item is the word calibration itself. The functions only address part of a full calibration, the zero point. The scale is not calibrated, but simply uses the advertised values from the data sheet.
The second item is the method used to determine the zero point. For this chip there are two different calibration functions. One calibrates the accelerometer/gyro and the other calibrates the magnetometer. Addressing the accelerometer/gyro function first.
The accelerometer/gyro calibration function for the LSM9DS1 chip makes use of the FIFO hardware. The function sets up the FIFO to read 32 samples each from the accelerometer and gyro, then it averages these values to find the zero offset. The accelerometer makes the assumption that the x-y plane is parallel to a level surface, and that the z-axis is on a plumb line. It doesn’t actually find a zero offset for the z-axis.
This can be corrected by doing the x-y calibration, reposition the chip so that either the x-z or y-z plane is level and finding the zero for the z-axis.
Of note is Figure 1 in the LSM9DS1 datasheet. Notice the dot on the chip is positioned differently for the magnetometer illustration. Also as drawn the axis directions are a left-hand coordinate system.
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
A bug was found in the previous code that froze the gyro readings. The gyro sample rate has been added to fix the bug.this.gyro_scale = 245; this.gyro_sampleRate = 6; this.gyro_bandwidth = 0;
Once calibrated using calls to the read accelerometer and read gyro functions with the FIFO produce an unreasonable variation in the at rest gyro readings. This variation is greatly reduced by using the FIFO in continuous mode, even limiting the FIFO to 2 samples. My hypothesis is that without the FIFO the values returned contain incomplete samples. To use the FIFO in continuous mode:
// fifoMode // FIFO_OFF = 0, FIFO_THS = 1, FIFO_CONT_TRIGGER = 3, //FIFO_OFF_TRIGGER = 4, FIFO_CONT = 5 W.enableFIFO(true); W.setFIFO(5,10); // ( fifoMode ,length<32)
The magnetometer calibration function acquires 128 readings and for each axis determines the maximum and minimum reading, and then averages these two values to produce the zero offset value for each axis. These values are stored on the chip using a call to the magOffset function.
I’m not sure if this method is of any value. I can imagine placing the chip inside a pair of A.C Helmholtz coils as one method. I finally performed a zero offset calibration manually.
I attached the chip to a cube. I placed the cube on a level non-magnetic surface (wood) with a wooden fence (think table saw) oriented North South. I zeroed the chip offsets using a call to the magOffset function. Then I collected six sets of data.- X-axis level and pointing North
- X-axis level and pointing South
- Y-axis level and pointing North
- Y-axis level and pointing South
- Z-axis level and pointing North
- Z-axis level and pointing South
Then I used a spreadsheet to find the maximum and minimum values in pairs of data sets and averaged them. For the X offset use sets 1 and 2, for Y sets 2 and 3 and finally for Z sets 5 and 6.
These offsets are then sent to the chip after initialization using the magOffset function.
If the chip is powered down the offset values are lost (volatile).
This procedure finally produced reasonable compass heading values when the x-y plane of the chip is level. Yet to address is the heading in 0 to 360 degrees instead of -180 to 180 degrees in the wrong direction. Also I hope to add the necessary rotation matrix math that gives the compass heading in any chip orientation.
Attached is the code as of today. I hope to incorporate changes that will reflect the issues discussed.
- X-axis level and pointing North
-
• #8
Problem posting the file.
I posted the wrong file and then removed it.
It wouldn't take the correct file.
When I did the post I got an error page.
It did post but no attached file.
Attached is the file
1 Attachment
-
• #9
Thanks! Yeah, calibrating is a real pain. I've even noticed with the Pucks that if you bring a magnet too close (<2cm from the case) then it can partially magnetise something on the Puck and you have to recalibrate!
For working out the heading, have you come across
Math.atan2
? It's amazingly helpful.I really quick hack would be something like this:
if (is_biggest(accel.x)) return sign(accel.x)*Math.atan2(mag.y, mag.z); if (is_biggest(accel.y)) return sign(accel.y)*Math.atan2(mag.z, mag.x); return sign(accel.z)*Math.atan2(mag.x, mag.y);
But I guess to do it properly you want to do it better than the nearest 90 degrees :)
-
• #10
That's a cool hack. What we call Q&D (quick and dirty).
Aran2 gives -180 to 180.
theta=atan2(z,x)
if(theta<0) theta+=360. Then theta ranges from 0 to 360
For the left handed axis on this chip theta= atan(-z/x)Using the accelerometer readings gx, gy, gz
theta = atan2(gz,gx), phi=atan2(gz,gy)
rotate around yaxis
x1=gx, y1=cos(theta)*gy-sin(theta)*gz, z1=sin(theta)*gy+cos(theta)*gz
the rotate around the xaxis
x2=cos(phi)*x1+sin(phi)*z1, y2=y1, z2=-sin(phi)*x1+cos(phi)*z1
At which point z2 should be -1. X2 and Y2 should be zero
If the rotations are them applied to the magnetometer readings the compass can be leveled.
Some gotchas:
May need a minus sign in the atan2(-a/b)
May need to rotate the opposite direction by changing the sign on the sin terms( +sin becomes -sin, and -sin becomes +sin)
I captured some data earlier this morning and did some of this in a spreadsheet. It looks like it works but I want to finish the mounting fixture and change the code to load the zero calibrations rather than recalibration on each run.X Y Z atan2(x/z) atan2(y/z)
Acceleration -0.000249863 0.003465652 1.000553131 -0.014308162 0.198456693
-
• #11
Tab made it post so I'll try again
X Y Z atan2(z,x) atan2(z,y) Acceleration -0.000249863 0.003465652 1.000553131 -0.014308162 0.198456693 sin(theta) cos(theta) sin(phi) cos(phi) -0.000249725 0.999999969 0.003463716 0.999994001 X1 Y1 Z1 X2 Y2 Z2 -0.000249863 0.003715515 1.000552234 0.003215767 0.003715515 1.000546232
Preview takes out the spaces that I tried to make the headings line up.
Better examples to follow. -
• #12
If you treat your stuff like code (with the three backticks) then you should be able to get it to appear a bit better (I changed it above).
I think it's just a typo, but you wrote
atan2(y/z)
, when you need eitheratan(y/z)
oratan2(y,z)
atan2
is clever, because12/34
and-12 / -34
should be different angles, but obviously evaluate to the same number.atan2
checks and makes sure that it outputs a value that represents all 360 degrees, and not just 180. -
• #13
NormalizeG.js
NormalizeG.wxm
6 Dec 2016
Attached are two files that use matrix rotations on an xyz vector to produce a vector where x1=0,y1=0,z1= - sqrt(x^2+y^2+z^3)
It’s still need some work as the matrix direction values depend on the vector quadrant.
This is likely the result of computerizing the trig and algebra.
The goal is to use the matrices and accelerometer readings to level the magnetometer readings and produce a compass heading.
The file with the wxm extension can be opened using the Maxima software.
This allows an analytic derivation as well as a numerical one.
http://maxima.sourceforge.net/
2 Attachments
-
• #14
Now working for all 8 quadrants.
On to doing the rotations for the magnetometer vector to do final proof of concept.
Then to see if pre-multiplying the matrices (using Maxima) and using simpler code will work.
Finally how well will it work with data from the chip?
Didn't use atan2. used the abs(atan) and then the sign of the original x,y values to set the matrix rotation direction and the z value to control if the final matrix is needed.
1 Attachment
-
• #15
I am trying to use LSM9DS1 with JavaScript. My setup is Sparkfun LSM9DS1 connected to Arduino, and then connected via Serial port to a laptop. I have node.js on a laptop. I tried Johnny-five, but it does not support LSM9DS1. Your code seems to be the only JavaScript code for that IMU.
Any advise on getting it to work on my current setup? -
• #16
Hi Eduard. The Sparkfun site has C code for Arduino. This JavaScript code is under development at the moment. I plan to post some revisions in a few days. Currently I'm using a Pico with Espruino. I have not tested it on other versions of hardware. It seems plausible that it would run on other hardware running Espruino that has I2C interface. Defining the I2C pins would be the first item on a list of things to get the code running on different hardware running Espruino.
I have zero experience with the Johnny-five system. -
• #17
Got it. So, to use your code as is, I'll need to get Espruino board instead of my Arduino one. Alternatively, I would need to adapt your code to somehow work on my laptop in Node.js environment. I guess something like SerialPort that would transfer raw data that Arduino board gets through I2C interface. And then apply your calculations to result from SerialPort.
I am very new to this and appreciate your help. -
• #18
@ClearMemory041063, could that be useful in Puck's using the built-in magnetometer?
I'm quite interested in such code to handle 'oscillations' around the heading on a bout in choppy sea... Of course, the device could be put in a gimbal device... but that's not what I'm looking for, though probably the most simple solution... and when running out of computing capacity the only solution... :(
-
• #19
Attached are two modules that implement an I2C interface with the LSM9DS1.
These modules should be placed in the modules directory of your WebIDE project.
The module slimLSM9DS1.js is tested by the program testslimLSM9DS1.js
The module calibrateLSM9DS1.js is tested by the program testcalibrateLSM9DS1.js and loads the slimLSM9DS1.js module as well. The test program performs the calibration that the Sparkfun code performed. Options to perform a more robust calibration are coded but not yet tested as this requires a menu system.
Several functions have been added to allow the scales, output data rate and filters to be changes on the accelerometer, gyro and magnetometer.
The calibrations in the attached code has not been performed on every scale of the three sensors. In the next development phase a menu program will allow a full calibration to be performed.
The moff, goff and aoff contain the zero offsets for each axis for each scale
The mres, gres and ares contain the scale factors for each axis for each scale
g=gyro, a= accelerometer, m= magnetometerthis.mScale=0;//0,1,2,3 index into mscale this.mscale=[ //the mres is the scale factor for each axis {scale:4,regvalue:0, mres:[0.000122,0.000122,0.000122], moff:[0,0,0] //zero offset in counts }, //// this.gScale=0;//0,1,2 index into gyroscale this.gyroscale=[ //the gres is the scale factor for each axis {scale:245,regvalue:0, gres:[245/32768.0,245/32768.0,245/32768.0], goff:[0,0,0] //zero offset }, //// this.aScale=0;//0,1,2,3 index into accelscale this.accelscale=[ //the ares is the scale factor for each axis {scale:2,regvalue:0, ares:[2/32768.0,2/32768.0,2/32768.0], aoff:[0,0,0] },
These structures along with autocalc variable determine the type of output. The following shows this for the accelerometer. Similar code is used for the magnetometer and gyro.
LSM9DS1.prototype.readAccel=function(){ var temp=this.xgReadBytes(Regs.OUT_X_L_XL, 6); var i; // Read 6 bytes, beginning at OUT_X_L_XL 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]; //this.aBiasRaw[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
4 Attachments
-
• #20
Hi @allObjects I hope to get back to the leveling code once I've got a calibrate IMU to work with.
I think it should exist as a separate object from the IMU code so it can be applied to other systems.
As to the viability on your boat, that remains to be seen.
Using the accelerometer to level the magnetometer readings is subject to accelerations such as experienced when turning, or an airplane in a banked turn.
Thanks for your interest. -
• #21
Some links:
https://en.wikipedia.org/wiki/I%C2%B2Chttp://johnny-five.io/news/introducing-i2c-component-backpacks/
https://github.com/sparkfun/SparkFun_LSM9DS1_Arduino_Library
The mreadbyte, xgreadbyte, mwritebyte, xgwritebyte, mreadbytes, and xgreadbyte functions using the I2C Wire class in Arduino are defined in the following:
https://github.com/sparkfun/SparkFun_LSM9DS1_Arduino_Library/blob/master/src/SparkFunLSM9DS1.cppLike I said, I know very little about the environment to which you want to port the code.
-
• #22
At this point the module slimLSM9DS1.js needs to be tested.
In order to do the testing the menutestSlimLSM9DS1.js has been written, with another program to test the calibration module to follow.
WARNING WARNING WARNING
The menu system redirects the USB port away from the console. Without a method to restore the USB-Console connection or reset a Pico you can brick the Pico if you save the menu program. As written the menu program provides three exits. Control-C, Menu option 9, and the pushbutton on the Pico. When you load the program it tells you to type startPGM(); in the left pane of the WebIDE. This is safe. Only save the program once you are convinced that all the exit methods work. This is especially true if you make modifications to the menu program.
Here is an example after the menu program is loaded, started and menu option 9 is selected.>In left pane type startPgm(); Use startPgm() first and make sure you can exit back to the console Once you are sure that a proper exit works then type save(); =undefined >startPgm(); =undefined -> LoopbackB Select option or use control-C to exit 0 Configure Gyro 1 Configure Accelerometer 2 Configure Magnetometer 3 Select Display Units 4 Read and Display Data 5 Show Calibration Structure 9 Exit <- USB >9 <- LoopbackB Exit -> USB
The code to use the pushbutton to reset the Pico is in nobrick.js
It does not redirect the USB port.//NoBrick.js // 15 Dec 2016 // //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(); }); function startPgm(){ var count=0; var nn=setInterval(function () { console.log(count); count++; if(count>1000)clearInterval(nn); }, 200); }//end startPgm 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();");
Here are some more menu screens.
-> LoopbackB Select option or use control-C to exit 0 Configure Gyro 1 Configure Accelerometer 2 Configure Magnetometer 3 Select Display Units 4 Read and Display Data 5 Show Calibration Structure 9 Exit <- USB >0 Configure Gyro Select option or use control-C to exit 0 Set Gyro Scale 1 Set Gyro Output Data Rate 8 Main Menu 9 Exit 0 Set Gyro Scale Select option or use control-C to exit Select Gyro Scale 0 for 245 deg/s 1 for 500 deg/s 2 for 2000 deg/s 8 Main Menu 9 Exit /////// use control-c to exit <- LoopbackB _____ _ | __|___ ___ ___ _ _|_|___ ___ | __|_ -| . | _| | | | | . | |_____|___| _|_| |___|_|_|_|___| |_| http://espruino.com 1v88 Copyright 2016 G.Williams >
Read and display data. Pressing the return key twice stops the collection and returns to the main menu. The average data is from a running average of 20 samples.
Select option or use control-C to exit 0 Configure Gyro 1 Configure Accelerometer 2 Configure Magnetometer 3 Select Display Units 4 Read and Display Data 5 Show Calibration Structure 9 Exit <- USB >4 Acceleration, -0.00655438823 , 0.01201211252 , 1.05891861454 Avg Acceleration, -0.00655438823 , 0.01201211252 , 1.05891861454 Gyro, -0.03014841387 , -0.77131702053 , 0.19415578534 Avg Gyro, -0.03014841387 , -0.77131702053 , 0.19415578534 Magnetometer, -0.006588 , 0.197274 , -0.217526 Avg Magnetometer -0.006588 , 0.197274 , -0.217526 Temperature 26.24 Level -0.35463914029 0.64992136537 heading 1.91269183128 avg heading 1.91269183128 > Select option or use control-C to exit 0 Configure Gyro 1 Configure Accelerometer 2 Configure Magnetometer 3 Select Display Units 4 Read and Display Data 5 Show Calibration Structure 9 Exit
3 Attachments
-
• #23
Updating the software.
The calibration menu system is now working after a rewrite of the module and additions to the menu program.
The calibrations are now stored in ROM page 99. To change this:
Look for: var CalPage=99; //ROM page where calibration is saved
savecal.js is used to write the calibration structure to the ROM, and should be the first program that you run to prime the data structure for the menu programs.
The modules should be copied to your local project module directory
slimLSM9DS1.js has not changed,
calibrateLSM9DS1.js has significantly changed. Callbacks are used and the calibration covers all the scales of the sensors-
BRICK CAUTIONS still apply to the menu programs. Be sure that the exits from these programs work before doing a save to a PICO as they redirect the USB port from the Console. Most important if you edit these programs!
AmenuCalSlimLSM9DS1.js will allow you to perform calibrations, save them to ROM, view the calibration values, change sensor scales and data rates and collect data. It uses the calibrateLSM9DS1.js module which loads the slimLSM9DS1.js module as well.
AtestmenuSlimLSM9DS1.js leaves out the calibration procedures and uses the slimLSM9DS1.js module.
The only outstanding issue are the accelerometer readings on the 16g scale.
The other scales move the one-g reading from axis to axis as the sensor is moved.
The 1-g on the 16g scale moves but the value is diminished on the X and Y axis for some reason
5 Attachments
-
• #24
For multi byte read, did you try enabling the IF_ADD_INC of CTRL_REG8.
I faced some issue with python i2c readList, but after setting the CTRL_REG8 properly i got it through the multi byte read.FIFO in continuous mode is 6 and not 5 as per the datasheet. There is no entry for 5.
-
• #25
Interesting, thanks.
April 1 my PC power supply emitted the magic smoke. I'm on a different one now and hoping that the a new PC power supply will fix the old one and lots of files will still be there. If not it's going to take a while to get most everything restored.
Then I will be able to try your fix.
TestLSM9DS1.js
21 Nov 2016
Using a Pico 1v88
I’m starting work on an I2C driver for the Sparkfun 9DoF Sensor Stick
https://www.sparkfun.com/products/13944
3-axis Magnetometer, Gyro and Accelerometer.
As a starting point I’ve downloaded the Arduino Library from
https://github.com/sparkfun/SparkFun_LSM9DS1_Arduino_Library
The board is scheduled to arrive tomorrow. The attached Espruino code has been derived from the Arduino library. TestLSM9DS1.js
A few functions related to the I2C have been stubbed until the board arrives and testing can begin. Additional functions beyond the basics have yet to be added.
Any suggestions on writing the stubbed I2C functions are welcome.
The current output of the stubbed code:
1 Attachment