Forum Rule: Always post complete source code & details to reproduce any issue!
Page 1 of 2 1 2 LastLast
Results 1 to 25 of 38

Thread: MPU9250 Add-On for Teensy 3.6

  1. #1
    Senior Member onehorse's Avatar
    Join Date
    Apr 2014
    Location
    Danville, California
    Posts
    920

    MPU9250 Add-On for Teensy 3.6

    I finally got around to designing and testing a MPU9250+MS5637 add-on for Teensy 3.6. It was a challenge to design a board with a 2 x 5 pattern of pads rather than the 2 x 6 pattern available on the Teensy 3.1/2. I kept the board two layers since I wanted to take advantage of the 0.8-mm-thick pcb option available at OSH Park for easier mounting. I used low-temperature solder paste and a hot air gun to assemble and solder the board to the Teensy 3.6. The board looks like this:

    Click image for larger version. 

Name:	Teensy3.6Addon_1.jpg 
Views:	155 
Size:	67.3 KB 
ID:	8903

    and when mounted onto the Teensy 3.6 it looks like this:

    Click image for larger version. 

Name:	Teensy3.6_ADDON_2.jpg 
Views:	229 
Size:	104.4 KB 
ID:	8904

    I verified the ADO address pin and the interrupt work as expected. I designed the board to use I2C only even though it would be possible (but challenging on a small 2-layer board like this) to wire it for SPI instead. I2C at 400 kHz is plenty fast for anything I would do with these sensors. A simple sketch configures the sensors, reads the data, performs the Madgwick (or Mahony) sensor fusion and outputs everything to the serial monitor.

    At 72 MHz I was getting a 5 kHz fusion rate with the open-source Madgwick filter. The fusion rate is dominated by either the magnetometer polling every loop cycle (no mag interrupt on the MPU9250) or the pressure sensor, I am not sure why it isn't faster. More interestingly for me is the current usage, which came in at about 41 mA. I am interested in very low power applications of such sensor fusion engines and I have been working with the STM32L4 to get there:

    Click image for larger version. 

Name:	Butterfly_Ladybug_3.jpg 
Views:	95 
Size:	140.5 KB 
ID:	8905

    here in two new formats. A Teensy 3.2-sized version using the STM32L433 we call Butterfly and a 0.6" x 1.1" board using the STM32L432 we call Ladybug. The STM32L4 runs the Madgwick filter with a similar MPU9250+BME280 add-on (on the Dragonfly board) at about the same speed but uses ~16 mA at 72 MHz to do so. The STM32L4 has a rich variety of low power modes and we are working out the API for the Arduino core to access them. The goal is to be able to use the STM32L4 to manage sensors, GPS, wifi and/or BLE and keep the average power usage well below 1 mA to allow months-long operation with a small LiPo battery. This is very challenging with the STM32L4, and nigh on impossible with the Teensy 3.6.
    Last edited by onehorse; 11-27-2016 at 05:28 AM.

  2. #2
    Senior Member onehorse's Avatar
    Join Date
    Apr 2014
    Location
    Danville, California
    Posts
    920
    I was polling the magnetometer outside of the accel/gyro interrupt-driven portion of the loop which means I was reading the mag status register each time through the loop which is really dumb and wasteful. Here is the better way to do it:

    Code:
     // If intPin goes high, all data registers have new data
       if(newData == true) {  // On interrupt, read data
         newData = false;  // reset newData flag
    //  if (readByte(MPU9250_ADDRESS, INT_STATUS) & 0x01) {  // check if data ready interrupt
        readAccelData(accelCount);  // Read the x/y/z adc values
     
        // Now we'll calculate the accleration value into actual g's
        ax = (float)accelCount[0]*aRes - accelBias[0];  // get actual g value, this depends on scale being set
        ay = (float)accelCount[1]*aRes - accelBias[1];   
        az = (float)accelCount[2]*aRes - accelBias[2];  
       
        readGyroData(gyroCount);  // Read the x/y/z adc values
    
        // Calculate the gyro value into actual degrees per second
        gx = (float)gyroCount[0]*gRes;  // get actual gyro value, this depends on scale being set
        gy = (float)gyroCount[1]*gRes;  
        gz = (float)gyroCount[2]*gRes;   
    
        // Poll for new mag data
        newMagData = (readByte(AK8963_ADDRESS, AK8963_ST1) & 0x01);
        if(newMagData == true) { // wait for magnetometer data ready bit to be set
    
        readMagData(magCount);  // Read the x/y/z adc values
        
        // Calculate the magnetometer values in milliGauss
        // Include factory calibration per data sheet and user environmental corrections
        mx = (float)magCount[0]*mRes*magCalibration[0] - magBias[0];  // get actual magnetometer value, this depends on scale being set
        my = (float)magCount[1]*mRes*magCalibration[1] - magBias[1];  
        mz = (float)magCount[2]*mRes*magCalibration[2] - magBias[2];  
        mx *= magScale[0];
        my *= magScale[1];
        mz *= magScale[2]; 
        }
    }
    Of course, I would prefer an interrupt on mag data ready but there is none on the MPU9250 (I've encouraged Invensense to add one on the successor due out next year).

    With this change I recover the much faster fusion rates I had measured and reported before. Now we can take another look at fusion rates verses current draw for the above devices:

    Click image for larger version. 

Name:	MadwickCurrent.png 
Views:	93 
Size:	49.7 KB 
ID:	8921 Click image for larger version. 

Name:	MadwickRate.png 
Views:	101 
Size:	46.7 KB 
ID:	8919

    You can see that the fusion rates and current draw scale approximately linearly with CPU speed for all devices and that the current is highest for the Teensy 3.6 and lowest for the Butterfly STM32L433. Part of the reason for the slightly lower current for Butterfly compared to Dragonfly is the fact that Butterfly does not have a 16 MHz crystal.

    In all cases, the fusion rate is way more than it needs to be. Ideally, one would like to run this kind of steepest-descent-like fusion algorithm at a rate ~5 - 10 times that of the data rate in order to reach convergence before the next new data sample arrives. This means for a 200 Hz accel/gyro rate like we are using here a Madgwick rate of no more than 2 kHz is sufficient.

    I took advantage of the WFI command available for the Teensy 3.6 and simply invoked it after the loop counter exceeded 10 in the sketch, this pegs the fusion rate at about 10 times the average data rate (the mag is sampled at 100 Hz) and results in a measured fusion rate of 1.7 kHz more or less independent of CPU speed, just about right, while the current draw is significantly reduced. I added the equivalent STM32.sleep(); after ten loop counts and succeeded in significantly reducing the Butterfly current draw (by 33% at 72 MHz!) while maintaining the same ~1.7 kHz Madgwick fusion rate; it is power management methods like this that will be required to get the average usage down below 1 mA.
    Last edited by onehorse; 11-27-2016 at 08:51 PM.

  3. #3
    Senior Member manitou's Avatar
    Join Date
    Jan 2013
    Posts
    1,156
    In one of your earlier optimized dragonfly mpu9250 sketches, you simply read the magnetometer data each time you had newData. So avoiding the mag status check would save you about 120us of I2C time every other iteration or so, but assumes the magnetometer always returns "good" data.

    EDIT: Never mind.

    looking more closely, the dragonfly sketch after reading 8 bytes of mag data does test for "data ready" before incorporating the raw mag data. And the optimized dragonfly sketch is using DMA for the I2C transfers so there is no lost time for I2C data transfers.

    for the T3.6 it is probably is faster to read a 1-byte status, and only read the raw data if status says it's ready.
    Last edited by manitou; 12-01-2016 at 07:31 PM.

  4. #4
    Senior Member onehorse's Avatar
    Join Date
    Apr 2014
    Location
    Danville, California
    Posts
    920
    Well, I've been struggling with how best (most efficiently) to read the mag data and on this iteration (I guess I should have posted the entire sketch) I removed the data ready test from the mag data read function (I still check for overlfow) and I am relying only on the data ready read in the main loop. I am trying to minimize reads of mag registers while getting the proper data when ready. This would be so much easier with a proper AK8963C interrupt exposed.

    I thought about having a counter and reading the mag data automatically every other MPU6500 data ready interrupt. But probably the best way and the way Invensense intended is to treat the AK8963C as a slave 0 device, have the MPU9250 ASIC read all of the data into the FIFO and then when the mag data is ready read all of the sensors in a single burst read. This is what their DMP does, but this is also why the DMP is limited to 100 Hz quaternion update rates. So there is no perfect solution (except a mag interrupt!).

    The other thing I used to do and probably still should is burst read the accel and gyro (and temperature, tucked between them) data and parse the single array into accelerations and rotations. This would save a fair amount of time in I2C transactions for both MCUs and is the righter way to do it without the 100 Hz limitation on the data rate a la Invensense.

  5. #5
    Is the mag data ready in a consistent fixed time- in all conditions? if you did a test loop of if(Ready) and plotted the time between Ready and saw it to be max of X_ms you could perhaps use an "elapsedMillis ReadMag" to limit the read?

    Then let your loop run getting other data without checking or waiting until "(ReadMag >= X_ms).

    I assume Mag calc does continuous update cycle, and doesn't wait until a Read to start the next sample - but only stores one Ready sample - so probably set ReadMag = 0; first thing inside if{}. This would read perhaps slower than ready - but not take any bus polling time.

  6. #6
    Moderator KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    3,077
    Looks pretty cool. Are they up on Tindie yet?

    Might be a good addition to my Robot controller board. Was planning on using BNO055...

  7. #7
    Senior Member onehorse's Avatar
    Join Date
    Apr 2014
    Location
    Danville, California
    Posts
    920
    Just for completeness I ran the same tests at 1 MHz I2C clock speed and got about a 10% increase in fusion rate, but I discovered something not quite right about the way I was handling the Madgwick fusion iteration. I think this is more correct:

    Code:
    void loop()
    {  
       // If intPin goes high, all data registers have new data
       if(newData == true) {  // On interrupt, read data
         newData = false;  // reset newData flag
         readMPU9250Data(MPU9250Data); // INT cleared on any read
       
        // Now we'll calculate the accleration value into actual g's
         ax = (float)MPU9250Data[0]*aRes - accelBias[0];  // get actual g value, this depends on scale being set
         ay = (float)MPU9250Data[1]*aRes - accelBias[1];   
         az = (float)MPU9250Data[2]*aRes - accelBias[2];  
    
        // Calculate the gyro value into actual degrees per second
         gx = (float)MPU9250Data[4]*gRes;  // get actual gyro value, this depends on scale being set
         gy = (float)MPU9250Data[5]*gRes;  
         gz = (float)MPU9250Data[6]*gRes; 
      
        newMagData = (readByte(AK8963_ADDRESS, AK8963_ST1) & 0x01);
        if(newMagData == true) { // wait for magnetometer data ready bit to be set
          readMagData(magCount);  // Read the x/y/z adc values
      
        // Calculate the magnetometer values in milliGauss
        // Include factory calibration per data sheet and user environmental corrections
          mx = (float)magCount[0]*mRes*magCalibration[0] - magBias[0];  // get actual magnetometer value, this depends on scale being set
          my = (float)magCount[1]*mRes*magCalibration[1] - magBias[1];  
          mz = (float)magCount[2]*mRes*magCalibration[2] - magBias[2];  
          mx *= magScale[0];
          my *= magScale[1];
          mz *= magScale[2]; 
        }
    
        for(uint8_t i = 0; i < 5; i++) { // iterate a fixed number of times per data read cycle
        Now = micros();
        deltat = ((Now - lastUpdate)/1000000.0f); // set integration time by time elapsed since last filter update
        lastUpdate = Now;
    
        sum += deltat; // sum for averaging filter update rate
        sumCount++;
    
        MadgwickQuaternionUpdate(-ax, ay, az, gx*pi/180.0f, -gy*pi/180.0f, -gz*pi/180.0f,  my,  -mx, mz);
        }
     } 
       
        STM32.sleep(); //then sleep
    
        ''''
    
           serial output etc
    
    } // end loop
    and the correspinding WFI command for the Teensy 3.6. This behaves as I expect, meaning as the number of iterations changes the average fusion rate changes, allowing one to simply choose the fusion rate to suit the processor, etc. Before I was not doing the fusion 10 times every data cycle like I thought. Now it works as it should, and the average power increases a bit since the iterations are being done every data cycle now.

    OK, I haven't put the Teensy 3.6 shields on Tindie yet since I just made them to test how they worked but if there is enough demand I suppose I could offer them for sale. It is convenient to have a motion/pressure sensor on the MCU, especially with the thin 0.8-mm pcb available from OSH Park. It blends in really well and makes use of otherwise not very usable pin pads.
    Last edited by onehorse; 12-02-2016 at 06:45 PM.

  8. #8
    @onehorse : Which of your current Teensy 3.2 MPU9250 versions does this unit match with hardware and fusion features? I have interest of course and a T_3.6 on hand that might inspire me to get back to it.

    RE post #5:: If I understood your prior postings you wouldn't care if you didn't get mag data with each accel data read? If it wasn't fresh when other data was you could iterate with the prior calculated mag data and new accel data and still improve your approximation [ since waiting means you accel data ages ]? If so then the elapsedMillis[Micros] gating of the readMagData() would keep you from stalling as often or so long. You could do a few timed reads in setup() to calibrate to the current system speed and get the limit value. Or - on the fly - you could measure the wait and increase the gating time upwards and still end up processing more accel samples.

  9. #9
    Senior Member onehorse's Avatar
    Join Date
    Apr 2014
    Location
    Danville, California
    Posts
    920
    Which of your current Teensy 3.2 MPU9250 versions does this unit match with hardware and fusion features?
    Not sure what you mean. The Teensy 3.6 add-on board doesn't match anything really, being a new design specifically for the Teensy 3.6 pin pad arrangement, which is quite different from the Teensy 3.1/2. The devices are the same though and almost any Teensy 3.1 program designed to operate these sensors will work with the Teensy 3.6 after some small changes. Is this what you mean?

    The mag data is read on average half as often as the accel/gyro data but there is no way to guarantee it is exacly half. The best one can do here is check the new data ready status register. Best is if the mag had an exposed interrupt, but it doesn't. The way the program is designed the fusion is iterated with the last mag data fresh or no, so there is a ~5 ms latency error of a sort in the fusion result. I don't expect this to be a problem for most applications, and it is even reasonable to run the mag at 8 Hz to save power and since the mag data is corrective to the gyro, like the accel data is, the overall result might not suffer too badly for slow human motions, but will be badly off for a fast flying robot.

  10. #10
    Yes - 'match with hardware and fusion features' - understood as noted the fit is custom to T_3.6 lower pads since the T_3.2 pads became T_3.6 pins.
    I wondered if feature <set> is like "Ultimate Sensor Fusion Solution" or "MPU9250 Teensy 3.X add-on shields".

    If mag data comes on a fixed clock then watching an elapsedMillis could adapt to whatever speed it is seen to return data - and skip 1 or two full waits with a test making best use of the faster returning accel data.
    Last edited by defragster; 12-03-2016 at 07:55 AM.

  11. #11
    Don't know if this will compile - on Teensy with elapsedM's it should limit attempts to read mag data with just a watch on the time. Checking the time should be faster than asking if Mag data ready each pass. I added what should be usable DEBUG printing each 10 seconds of Mag Data read Freq reading and what the current wait time is between checking for data ready. If that wait expires and Mag data isn't ready - 10 us is added to the wait for next time so it will home in on the right value if data is ready in a fixed time. Existing code should show in green with added code in black.

    Code:
    elapsedMillis DEBUG_ReadMag = 60005;
    uint32_t DEBUG_ReadMagCNT 0;
    elapsedMicros ReadMag;
    uint32_t waitReadMag 1000; // Not sure of expected Mag read freq - at 1000 this would allow 1000 Hz :: it should be 10000 if it is 100 Hz
    
    void loop()
    {
      // If intPin goes high, all data registers have new data
      if (newData == true) { // On interrupt, read data
        newData = false;  // reset newData flag
        readMPU9250Data(MPU9250Data); // INT cleared on any read
    
        // Now we'll calculate the accleration value into actual g's
        ax = (float)MPU9250Data[0] * aRes - accelBias[0]; // get actual g value, this depends on scale being set
        ay = (float)MPU9250Data[1] * aRes - accelBias[1];
        az = (float)MPU9250Data[2] * aRes - accelBias[2];
    
        // Calculate the gyro value into actual degrees per second
        gx = (float)MPU9250Data[4] * gRes; // get actual gyro value, this depends on scale being set
        gy = (float)MPU9250Data[5] * gRes;
        gz = (float)MPU9250Data[6] * gRes;
    
        if ( ReadMag > waitReadMag ) {
          newMagData = (readByte(AK8963_ADDRESS, AK8963_ST1) & 0x01);
          ReadMag = 0;
          if (newMagData == true) { // DEBUG
            DEBUG_ReadMagCNT++;
            if ( DEBUG_ReadMag > 10000 ) {
              Serial.print( "\nReadMag info:: DEBUG_ReadMagCNT/sec =" );
              Serial.print( DEBUG_ReadMagCNT/10 );
              Serial.print( "__ waitReadMag =" );
              Serial.println( waitReadMag );
              DEBUG_ReadMagCNT = 0;
              DEBUG_ReadMag = 0;
            } // DEBUG
          }
          if (newMagData == true) { // wait for magnetometer data ready bit to be set
            readMagData(magCount);  // Read the x/y/z adc values
    
            // Calculate the magnetometer values in milliGauss
            // Include factory calibration per data sheet and user environmental corrections
            mx = (float)magCount[0] * mRes * magCalibration[0] - magBias[0]; // get actual magnetometer value, this depends on scale being set
            my = (float)magCount[1] * mRes * magCalibration[1] - magBias[1];
            mz = (float)magCount[2] * mRes * magCalibration[2] - magBias[2];
            mx *= magScale[0];
            my *= magScale[1];
            mz *= magScale[2];
          }
          else { //  Adjust wait upwards - tried too soon :: 10 added is arbitrary start value
            waitReadMag += 10;
            ReadMag = 0;
          }
        }
      }
    Last edited by defragster; 12-10-2016 at 08:32 PM.

  12. #12
    Hi Kris

    I have a question that is maybe silly - so be it. The MPU9250 provides filtering for accel and gyro data, but as I understand not for the AK8963. The AK8963 does according the block diagram no filtering on its own. As much as I understand the mag values go unfiltered into the Madgwick or Mahony computations. Is there a reason why it is ok this way ?

    Are you updating the files on github anytime soon ?

    It would also be VERY helpful if you would specify what axis orientation and units for the values passed over to the quaternion.ino are expected. Seems I am not the only one who is struggling with it (see github). Especially the stuff with shifting axes and rotation is for me not clear. I admit I am not a math genius and some 40 years ago did not really pay attention to vector geometry. At the moment - I just just don't get it. But the values I get are ok.

    regards Andi

  13. #13
    Senior Member onehorse's Avatar
    Join Date
    Apr 2014
    Location
    Danville, California
    Posts
    920
    No filtering on the mag. You can do so on the host.

    I update the sketches when I find errors but they are not canned programs right for every application so use at your own risk.

    The Madgwick function expects:

    Madgwick(Naccel, Eaccel, Daccel, Ngyro, Egyro, Dgyro, Nmag, Emag, Dmag);

    where accel and mag units are arbitrary (since they are normalized in the function) and gyro is in radians/sec, and these will depend on the axis you choose for North. In the MPU9250, for example, the accel/gyro z-axis is usually up while the max z-axis is usually down so the Madwick function would look like:

    Madgwick(Naccel, Eaccel, -Az, Ngyro, Egyro, -Gz, Nmag, Emag, Mz);

    You will have to figure out the other entries by determining which axes are pointing North and which are pointing East, etc.

  14. #14
    Senior Member ninja2's Avatar
    Join Date
    Aug 2016
    Location
    Adelaide, Australia
    Posts
    149
    I think it is up on tindie

    very neat add-on.

    I assume it will also work on T3.5?

    Shipping to Australia is often expensive, do you have a distributor over here?

  15. #15
    Hi Kris

    thank you for your answer. Since I am putting things together at the moment, a feedback will follow later.

    I hope I may ask three other questions :

    - Madwick uses deltat, is this microseconds/1000000, fraction of a second ?
    - assume a sensor update rate out of the MPU9250 of 200Hz :
    - is a "call-rate" of the MadgwickQuaternionUpdate 10 times higher sufficient or should it be even higher ?
    - given the max update rate of the AK8963 of 100 hz - am I right that the mag raw data is refreshed only every second data read out of the MPU9250 ?
    Readout in my case is driven by interrupt and I make a readout of all values at the same time (acc, gyro, mag, temp).
    - acc and gyro are filtered by DPLF and therefore get some timelag (up to 66ms). How does this match with the mag data ? Is it possible that
    readout mag data is SOMETIMES "fresher" than data out of the DPLF ? Maybe this question is utterly academic but I am just curious.

    best regards

    Andi
    Last edited by hw999; 12-05-2016 at 07:46 PM.

  16. #16
    Senior Member
    Join Date
    Jun 2014
    Posts
    243
    I had my go at this too and added a temp sensor. Going to build a few soon.
    Not yet sure if the 0201 parts were a mistake or not


  17. #17
    Senior Member ninja2's Avatar
    Join Date
    Aug 2016
    Location
    Adelaide, Australia
    Posts
    149
    nice work fyod. is the metal component a pressure sensor ?

    I see you've labelled with the X and Y axes directions for the Accel/Gyro. Maybe you know already, but aware that Invense in their wisdom mounts the magnetometer with different alignment. It has with X + Y swapped and +Z is down (up for Accel/Gyro). See the attachment, from the datasheet page 38 figures 4 & 5.
    Click image for larger version. 

Name:	Axes - MPU9250.jpg 
Views:	48 
Size:	40.4 KB 
ID:	9045
    Last edited by ninja2; 12-07-2016 at 06:40 AM.

  18. #18
    Senior Member
    Join Date
    Jul 2014
    Posts
    1,457
    Quote Originally Posted by onehorse View Post

    Click image for larger version. 

Name:	Teensy3.6_ADDON_2.jpg 
Views:	229 
Size:	104.4 KB 
ID:	8904
    I'm curious how the compass will react to uSD card access (currents)? Any tests done?
    Last edited by WMXZ; 12-07-2016 at 08:33 AM.

  19. #19
    Hi wmxz

    just a thougt : why are the guys at ardupilot etc. moving the mags as far away from anything as possible ? As much as I understand after following these RC-comunities for a few years the mag measurement needs to be as far away from anything else as possible to give results that do not stress the fusion-algorithm. However - it matters what you really need. I am NOT an expert in this whole matter, its not only a matter of data collection, but something more. It is colleting data, processing the data and getting a result. In between there is the weird "calibration". Kris developed a routine that provides data that is fed into later computations. It's mandatory that you follow this step - it simply puts all later computations on a "healthy" track. It is maybe not perfect - but its a good point to begin with.
    I did not review his calibration coding in detail - but it helped a lot. From purely nonsense my readout went to meaningful after calibribation..

    To make it short : build up your project, calibrate and see the results. Calibrate many times. The results most of the times differ quite a lot. You get an eye on it. If you REALLY need reliable mag data, then in my opinon you have to look for another solution with a mag separate far away from stuff that might disturb it.

    To come back at your question : I am interested in this as well, but given mag readouts I have seen, there are other questions lingering. Mine are unstable like hell (lots of noise)

    brg hw999
    Last edited by hw999; 12-08-2016 at 09:37 PM.

  20. #20
    The PJRC PROTO shield has calibration to remove the local effects of the system from the measurements: prop_shield.html

    The reason and things that affect it aren't noted there. In using this graphic calibration tool you can see when it nears active components outside the system - cell phone - or the processor in a watch - and the like.

    I saw WMXZ with a question to that - being so close to the processor and PCB power/ground planes/circuitry - wondering if it would have a dynamic effect in use - that would be different from the calibration operation - and my wondering if the metal PCB planes might blind the sensor? And specifically WMXZ asked: does the immediately over head SDIO card operation which uses 'high' current affect the readings outside the calibration.

    As for RC guys :: If you can't calibrate as installed - then you probablyneed to keep it as close to any factory calibrated setting clear of local disturbances to the magnetic field/sensor.

  21. #21
    Senior Member onehorse's Avatar
    Join Date
    Apr 2014
    Location
    Danville, California
    Posts
    920
    Well there are several parts to answering this question.

    Firstly, for any application whether near transient fields or no, good calibration of all sensors is essential to get the best performance from sensor fusion of any kind. With good calibration, especially for the mag and accel, one can expect to get four degree heading accuracy from the Madwick algorithm if the sensors are up to the task (I prefer the MPU9250 for this reason). With no or insufficient calibration, you can get any value of heading and probably will...

    There is some folklore that you can't use a magnetometer in the presence of large (>> 0.5 G) static or transient magnetic fields. This is one reason most drones use a gyro or maybe a gyro and accel but do not use a magnetometer. Big mistake. Heading drift is not possible to correct without a magnetometer, period. The trick to getting fusion to produce reasonably accurate results in the presence of transient magnetic fields is to use the accelerometer to detect and ciorrect for magnetic transients. There is no good open-source code for this, but the EM7180 does it and we have successfully used it with the MPU9250 as an IMU for small (35 g) quads using brushed DC motors where the static and transient magnetic fields are quite large.

    So I am not too worried about the transients associated with the SD Card useage, but I would recommend anyone who is to simply measure them and work out a way to use the accel to test whether magnetic excursions are due to real motion or transients from the SD crad. In principle, this would be straightforward to do...

  22. #22
    Senior Member
    Join Date
    Jul 2014
    Posts
    1,457
    OK,
    I got me same MPU9250 boards from OSH (as I'm not interested in the MS5637 but need a 30+bar pressure sensor, I decided to assemble my own one)
    so I can do some tests.

    Now, concerning calibration, sure that has to be done as regular as possible. It may even not be simple (I had to calibrate a magnetic compass on a 100 m research vessel, so you must move the ship in a circles! (and not only a Teensy with MPU9240 add-on board!))

    The trick to getting fusion to produce reasonably accurate results in the presence of transient magnetic fields is to use the accelerometer to detect and correct for magnetic transients
    [Rant] Why are HW guys and EE's always assume that design errors should be resolved with SW! I prefer to avoid problems with good HW and electronic design, than to blow up SW complexity with handling of HW and system design errors. [/Rant]

    Anyhow, my question was, have there been measurements, and the answer seems to be no.
    Or maybe there is some interference, but not due to current introduced magnetic fields, but due to temporary drops in supply voltage?

    [OT] ultrasonic audio data (from audio shield and other audio boards) saved on uSD with Teensy is full of 'transients' from uSD write access making these types of applications difficult [/OT]

  23. #23
    Senior Member onehorse's Avatar
    Join Date
    Apr 2014
    Location
    Danville, California
    Posts
    920
    No measurements I am aware of. So if you could do some that would be interesting to me. In particular, if you use something like Madgwick or mahony sensor fusion, how does the heading estimation change when using the SD card? Does the heading spin around wildly when reading writing or is the orientation estimation stable? If the former, and you are interested, it might be useful to test mag transients against accel transients. if they are not the same the mag transients could be ignored, etc.

    SD cards are great for capacity, but they are power hungry, surprisingly fragile, and fairly slow. I prefer 128 Mbit or 1 Gbit SPI NOR flash, which is small, cheap, fast, and usually has enough capacity for logging either small amounts of data for a long time or large amounts of data for a short time, which covers a lot (but not all, I admit) use cases.

  24. #24
    Senior Member onehorse's Avatar
    Join Date
    Apr 2014
    Location
    Danville, California
    Posts
    920
    I think it is up on tindie

    very neat add-on.

    I assume it will also work on T3.5?
    I don't have these on Tindie yet, if I get some time I might assemble a few and make them available. I see no reason these won't work on the Teensy 3.5 and 3.6. The 2 x 6 pad version I designed for the Teensy 3.1/2 will definitely not work on the Teensy 3.5/6.

  25. #25
    Senior Member onehorse's Avatar
    Join Date
    Apr 2014
    Location
    Danville, California
    Posts
    920
    I hope I may ask three other questions :

    - Madwick uses deltat, is this microseconds/1000000, fraction of a second ?
    - assume a sensor update rate out of the MPU9250 of 200Hz :
    - is a "call-rate" of the MadgwickQuaternionUpdate 10 times higher sufficient or should it be even higher ?
    - given the max update rate of the AK8963 of 100 hz - am I right that the mag raw data is refreshed only every second data read out of the MPU9250 ?
    Readout in my case is driven by interrupt and I make a readout of all values at the same time (acc, gyro, mag, temp).
    - acc and gyro are filtered by DPLF and therefore get some timelag (up to 66ms). How does this match with the mag data ? Is it possible that
    readout mag data is SOMETIMES "fresher" than data out of the DPLF ? Maybe this question is utterly academic but I am just curious.
    Missed this.

    Units of deltat are seconds.

    Generally 4 -5x the sample data rate should be sufficient. It depends somewhat on the application. Best is to try it at 5x and 10x for your application. There is a point of diminishing returns, since the algorithm will eventually asymptote to a solution for a given set of data.

    About every second read, it's not exact and syncing can be a problem. Usually I ignore rigorous timestamping in these simple sketches but the MPU9250 allows such if you treat the AK8963 as a SLV0 device, read its data using the internal I2C bus into the FIFO, and then read the time aligned data from the FIFO to the host. But if you do, the data rate is somehow clamped at 100 Hz, so there is a tradeoff. Generally I would recommend running the gyro and accel at 400 Hz, the mag at 100 Hz, and running the fusion rate at 2 kHz. This should be adequate for most human and flying robot applications.

    The DPLF doesn't affect the sample rates or introduce time delays per se. The accel data is available to the internal ASIC at 1 kHz and the gyro data at 8 kHz. The DPLF simply determines how these data are averaged internally. They are still provided to the host at 200 Hz or 400 Hz or whatever is specified. But there is a constraint, of course. There are certain combinations of data rate and LPF allowed and others not. Consult the data sheet.

    It is unlikely (I won't say impossible) that the mag data is fresher than the accel/gyro data.Of course, if you set the accel/gyro sample rates at 10 Hz and the mag at 100 Hz this is exactly what you would get. The orientation solution is dominated by the gyro and the fusion filter rate needs to be sized according to the gyro rate. The accel and mag are helper functions to correct for gyro drift. So if you run the gyro at 1 kHz and the accel and mag at 100 Hz, you are likely to get a very reasonable orientation solution provided you run the Madgwick/Mahony fusion at 2 kHz or higher.

    Best is to test out the parameters in your particular application. It might be surprising to some, but this is more art than science. While the basic principles are fairly well understood, the applications vary widely and there is no one-size-fits-all solutions that I am aware of.
    Last edited by onehorse; 12-10-2016 at 06:25 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •