Shop OBEX P1 Docs P2 Docs Learn Events
LSM9DS1 9dof Sparkfun sensor help. — Parallax Forums

LSM9DS1 9dof Sparkfun sensor help.

I have a propeller boe-bot connected to the LSM9DS1 from spark fun and cant seem to figure out how the start up sequence goes, say just for the accelerator.

I wondered if anyone has a little experience with this fantastic sensor and if so please be a hero and provide a snpit of code for me. Basically I am trying to convert ardino code (clueless to me) to spin and I am having issues. The data sheet is not very clear (imo) as it list many registers but nothing about how they should act or details.

Ill post my code as soon as I can get that new computer on line, windows 10 sucks a little at the moment, for me.

Comments

  • Would you hate me if I encouraged you to give C++ a try? It will make porting that Arduino code a lot easier.

    It will also likely help if you toss us a link to the arduino code you're using. A quick Google showed this though: https://github.com/sparkfun/SparkFun_LSM9DS1_Arduino_Library
    I'm guessing that's it?
  • So i am using a propeller boe bot and wont need to use an arduino or C++ unless im missing something.

    For the lookers I am starting to get this sensor to work looks like the boe-bot might balance on two wheels soon.
  • I made the suggestion for C++ because you can program a propeller in C++. You can take the code for the arduino, make a few changes to the core code at the bottom (see line 973 for instance, which does the actual writing over SPI/I2C), and then use the rest of the code exactly as it is. If you wanted, it probably wouldn't take me but 15 minutes to convert that code for use on the Propeller for you. I'd have already done it by now just for fun, but I don't have the chip to test it with :(
  • RaymanRayman Posts: 14,651
    I posted this code a while ago with a driver for LSM9DS0:
    http://forums.parallax.com/discussion/161040/another-i2c-assembly-driver

    Maybe that will work for that chip too?
  • Thanks for the link I'll try and look it oregisterght.

    I am having difficulty putting the two bytes together after polling the registers. Otherwise its fairly straight forward. Something about the 2s complement thats getting me stuck.

    I was doing the following after polling a regiater.

    X is suppose to be the value of two bytes
    XH is high byte and XL is the low byte.
      X := XH << 8 | XL
    

    Anyone? Sorry limited code im on a phone.
  • RaymanRayman Posts: 14,651
    edited 2015-10-27 22:30
    If X can be negative, then that wouldn't work...
    You need sign bits in upper 16 bits of 32 bit value...

    You need to shift 24 bits left and then shift "arithmetic" 16 bits right. Then, you can or in the low byte.
  • JasonDorieJasonDorie Posts: 1,930
    edited 2015-11-01 17:43
    You can try this:
    X := ( XH << 8 ) | XL
    X := ~~X
    
    The parenthesis guarantee the operator precedence, just to make sure that you aren't doing XH << (8 | XL)

    The second line is "sign extend word to long"
  • Thanks everyone but I've got it running for some time now. The next issue I'm having i's that the gyro data seems to be fluctuating too much. I'm trying to balance the boe-bot on two wheels and when the bot falls forward the data is positive then returns negative so applying this to a PID results in a mess.
    Is it true that the gyro data should remain positive say clockwise and negative anti-clockwise?
  • RaymanRayman Posts: 14,651
    edited 2015-11-07 13:33
    I think it measures acceleration and not velocity...
    You need to integrate the acceleration to get velocity.

    If your bot starts falling forward, that's positive acceleration.
    When it hits the floor there's a large negative acceleration as it stops.

    So, that's positive and negative signals even though rotating in same direction all the time....


    Was wrong about that... Sensor does measure acceleration, but chip output is velocity in degrees per second...
  • If you're using the gyro it only measures rotational rate, not orientation. When the bot is not moving, you should see a relatively constant value (with some noise). Whatever that value is will be your zero point, and you can subtract that value from your readings to get a true rotation rate.

    When the bot is rotating around an axis in one direction, the value for that axis should be positive, and when the bot is rotating in the other direction it should be negative. Bigger absolute values mean you're rotating faster.

    If you want to know what your absolute orientation is, that's a harder problem. In one axis it's not too bad though. It involves using the accelerometer readings and atan2() to compute an absolute direction for gravity, using the gyro to compute a rotation rate, and using a complimentary filter to merge them together.
  • I find the acceleration data suspicious at the moment because tbe bot turns in a radius fashion. The sensor measures great if it's moving straight for example but twisting is s different issue. I've got loads to learn.
  • I've thought about integrating the acceleration but something is off. I would post code if someone else has the same ic.
  • Would it be better to use Kinematic equation vs a PID calculation in an effort to balance the bot?
  • You can balance a bot with a PID. You're likely not using the sensor data properly, because it's not really intuitive.

    You have two sensors that are useful for this problem in that chip - The accelerometer and the gyro. The gyro gives you your current "instantaneous" rotation speed. The accelerometer gives you your current linear acceleration due to outside forces, which includes the force being applied by the ground that opposes gravity.

    To balance the bot, you need to know its angle, and accurately. If you *just* use the accelerometer, it'll be noisy as all get out. If you *just* use the gyro, you can tell how fast you're rotating, but not your absolute angle, because you have no fixed frame of reference. By fusing the two together you can get what you need.

    If you take the accelerometer reading for "forward" and the one for "vertical" (probably called Y & Z in your code) you can get your current angle like this:
    accelerometerAngle = Math.atan2(y,z)
    

    You can compute a running angle for the gyro like this:
      gyroAngle := 0
      repeat
      {
        gyroVal = gyroReading - gyroZero
        gyroRadians = float( gyroReading ) * GyroUnitsToRadians
    
        gyroAngle = gyroAngle + (gyroRadians / UpdateRate)
      }
    

    So now you have one value that's "absolute" (the accelerometer angle) but it's *really* noisy. You have another value that's reasonably stable (the gyroAngle) but it's going to be completely wrong before too long, because the math is never going to be perfect. It's like trying to know how far you've driven by reading your speedometer once a second.

    The trick is to use one to correct the other, but slowly. Gyros handle noise better than accelerometers, so you can trust them more. Accelerometer, over time, is going to give you a more absolute reading than a gyro will, because it's reading gravity, so you mix a little of the accelerometer angle into the gyro angle to correct it, every update, like this:
      gyroAngle := 0
      repeat
      {
        gyroVal = gyroReading - gyroZero
        gyroRadians = float( gyroReading ) * GyroUnitsToRadians
    
        gyroAngle = gyroAngle + (gyroRadians / UpdateRate)
    
        accelerometerAngle = Math.atan2(y,z)
    
        gyroAngle = (0.98 * gyroAngle) + (0.02 * accelerometerAngle)
      }
    

    ...and that's called a complimentary filter, because the two values compliment each other. You can change the 0.98 and 0.02 to different numbers (they have to sum to 1.0). They're chosen based on how much you trust your sensors. Since the gyro is very trustworthy, it gets the higher number.

    This is intended as a description, by the way, and the code above is totally un-tested. To actually use this, start by reading the accelerometer and gyro values and make sure that they move in the same way. I might have the signs backwards, or used the wrong axis values, or any of a number of things. You also have to make sure they're working in the same units - that's why I have the GyroUnitsToRadians value there - You'll need to figure out what that number is for your gyro.

    As an example, they may tell you that your gyro is 40 LSB's (least significant bits) per degree. In that case, it means a reading of 40 from the gyro is equal to 1 degree per second. To convert that to radians per second, you'd use GyroReading * (PI / (180 * 40)).

    From there, you have to convert the "radians per second" value to "radians per update", since you're only interested in how much you rotated since the last time you checked. If your update rate is 100 times per second, you'd divide by 100.


    That's a lot to digest - read over it and feel free to harass me with questions.
  • Heater.Heater. Posts: 21,230
    Or you could get into some serious "sensor fusion" with Sebastion Magwick's IMU and AHRS sensor fusion algorithms: https://github.com/ZiCog/madgwick.js

    With that you can fuse (combine) accelerometer, gyroscope, magnetometer inputs into an accurate orientation.

    Look for MadgwickAHRS.c or MahonyAHRS.c in there. It's an exercise for the reader to convert that to Spin :)
  • RaymanRayman Posts: 14,651
    Jason is right about the angular velocity output... Just looked at the datasheet and saw that I remembered it wrong. I know the sensor itself can only detect angular acceleration, but it must be self-integrating.
  • RaymanRayman Posts: 14,651
    edited 2015-11-07 14:03
    Heater: Thanks for that link, looks great.
    Wonder if Spin is fast enough. It might be, but kind of tough with all the floating point operations.

    This actually looks like a good use case for PropGCC...
  • LoopyBytelooseLoopyByteloose Posts: 12,537
    edited 2015-11-07 14:34
    Listen to Jason Dorie... he has really put a lot of time and effort into using these devices on the Propeller. Balance a bot is a good simple place to start as you don't have to deal with X, Y, and Z axises together in real time.

    But it is NOT merely about coding in this or that language. The whole concept of tracking rotation and heading involves some fairly exotic maths in order to avoid a problem in calculation called 'gimbal lock'.

    You have 9DOH or degrees of heading. 3 by magnetic compass, 3 by accellerometer, and 3 by gyro. Mostly the accellerometer and gyro work well together to correct errors that cause drift. If you use just the accellerometer or just the gyro, you might have less that desired results.

    So this is where Madjwick and others - (like Mahoney) have created a way to combine to get the best results. You may not need to bother with Madjwick or Mahoney for a balancing bot that stays upright in one place.
  • JasonDorieJasonDorie Posts: 1,930
    edited 2015-11-07 21:21
    For a balancing bot you don't really need to deal with more than one axis, but a full 3D algorithm will obviously work. It's massive overkill for that problem, but it'll work. :)

    The new Elev8-FC flight controller uses the LSM9DS1 sensor, so I have code that uses it, but it also handles the barometric pressure sensor, drift compensation, and the on-board WS2812 LEDs, so it wouldn't be quite "plug & play" for your needs.

    The code is already on GitHub here: https://github.com/parallaxinc/Flight-Controller

    There's currently a Spin version and a C/C++ version. It's in-progress, but the sensor reading and IMU code is fully functional. I'm also testing a fusion of the barometer readings with a double-integrated accelerometer height estimate, and it seems to work pretty well. Complimentary filters are useful things. :) There's a readme file in the "Firmware" folder (the Spin version) that describes all the modules and gives some high-level details on how they work.
  • Heater.Heater. Posts: 21,230
    I agree, a full up Madgwick style 3D data fusion algorithm is overkill for a balancing bot and probably too much for a Prop. Unless you want to graduate to balancing on a ball.

    How about getting a Bosch 9 degrees sensor which does all that data fusion hard work for you ? https://learn.adafruit.com/adafruit-bno055-absolute-orientation-sensor/overview

  • So where is this C compiler for the propeller?
  • Start here : http://learn.parallax.com/propeller-c-tutorials

    SimpleIDE ships with PropellerGCC, and doesn't require you to set up makefiles to compile a project.
Sign In or Register to comment.