MPU-6050 - interrupt threshold

Hi,

I'm using MPU6050 breakout board with I2CDevLib (mpu6050 teapot example) written by Jeff Rowberg.

What I would like to achieve is that interrupt is triggered when there is actually some motion on sensor
(if I move it with hand for example).

Based on MPU6050 documentation I set INT_ENABLE (with setIntEnabled function) to B00000010.
This should mean that interrupt should be triggered based on the selected motion threshold only.

Well, the problem is that no matter how I set threshold I still get continues interrupts at ~100Hz rate (100 int/sec)
(measured by oscilloscope on MPU int line)

As mpuIntStatus I get 00000011 or 00000010. Which means that interrupt was triggered by "motion detection" (MOT_INT).

This are my current threshold settings:
Actually they are as they were in teapot example.

      DEBUG_PRINTLN(F("Setting motion detection threshold to 2..."));
      setMotionDetectionThreshold(2);

      DEBUG_PRINTLN(F("Setting zero-motion detection threshold to 156..."));
      setZeroMotionDetectionThreshold(156);

      DEBUG_PRINTLN(F("Setting motion detection duration to 80..."));
      setMotionDetectionDuration(80);

      DEBUG_PRINTLN(F("Setting zero-motion detection duration to 0..."));
      setZeroMotionDetectionDuration(0);

I'm wondering:

  • what could I overlooked? Are there some additional register settings I need to make?
  • What is triggering motion interrupt?
  • Do I maybe have faulty MPU - received values are looking fine/are quite stable though.

I would be glad if someone could give me some suggestion where to look further. I already spent few days figuring this out.

Regards,
Gregor

Anyone?1? :~

Another question is regarding calibration.
If I put sensor on flat surface and set offset so that ypr values are 0,0,0 how long would that calibration last?
I need accuracy about 1deg.

I don't know how long the calibration will last. It should last a very long time, since the earth gravity with filters keep the position.
Perhaps due to temperature changes, the internal offset could change. You have to test that yourself.
As far as I know, the internal offset is specific for a chip and doesn't change a lot over time.

The i2cdevlib sets the MPU-6050 to generate interrupts and data at 100Hz. That creates a steady peace of data, fast enough to balance a robot, slow enough for the Arduino to do some serious calculations.
If you use the i2cdevlib that way, you should detect the motion in software.

Caltoa,

Thanks for the answer. Do you maybe know how to change i2cdevlib so that interrupts will come only when there is some movement?

I tried setting interrupt registers and thresholds, but with out luck :frowning:

That is not how the i2cdevlib is designed. The 'dmp' example is based on a steady pace of 100Hz of data samples.
You can test the values that come out of it.

Caltoa,

Are you sure your info is correct?
I’m using teapot example where data is pulled based on interrupts. There are also two functions to set interrupt register.

If I set it to B00000000 - that means no interrupts - then I don’t get any interrupts - so writing to registry works fine.
If I enable ONLY motion interrupt B00000010 then I’m getting interrupts at 100Hz - which is not correct. I should get interrupt only on motion.

If I change sample rate to something lower than default, then interrupts are triggered in slower rate.

Why this is so important to me?
I would like to use interrupt from MPU to wake-up arduino on movement - to save battery, when device is not in use.
We are talking about gaming dice here. Circuit should be awake only when someone is holding/throwing it.

Is there some other lib that would work for my problem better than i2cdevlib ?

Okay, now I understand: the MPU in sleep mode.

Every modern accellerator chip has things like drop detection or motion detection, so I guess the MPU-6050 has them. But I have not used it yet.
Perhaps a certain 'dmp' firmware should be loaded for that. That is what all that MotionApps and MotionFusion and DMP is about.
http://www.invensense.com/mems/gyro/mpu6050.html

I see that you asked your question on i2cdevlib.com, and they are telling about undocumented features!
MPU-6050 - interrupt threshold - MPU-6050 6-axis accelerometer/gyroscope (InvenSense) - I2Cdevlib Forums

My best suggestion is to use an other accelerometer.

I don't know if you know what you are talking about or this are only speculations?

As I know MPU-6050 standard (default)firmware supports sleep mode, motion detection etc. This is also "well" documented in datasheet. So I don't really know what are you trying to say.

Also in i2cdevlib there are functions to setup this functionalities:
setMotionDetectionThreshold();
setZeroMotionDetectionThreshold();
setMotionDetectionDuration();
setZeroMotionDetectionDuration();
setIntEnabled();
setSleepEnabled();
setWakeCycleEnabled();

Yes on i2cdevlib forum I also posted very similar post and also described what I would like to achieve. But haven't receive any usable reply.

The question is if I forgot so setup something or my MPU is dead or i2cdevlib has some bug or there is some wired trick to make this work?!?

Are there some similar boards to MPU6050 that would work better for my example?

Sorry, bad mistake =(
I forgot about all those functions, and have not looked the datasheet for more than a year.

Hi guys,

Is there any updates on how to set up motion interrupt with the MPU-6050? I started a similar thread the other day and I assume my problem is the same. I now also contacted Invensense's application support, let's see what they respond.

My thread: Sparkfun MPU6050 accelero and gyro - help needed with interrupt from sensor - Sensors - Arduino Forum

Hi all,
i was succesfull to make to work a interrupt generation for MPU6050 and ATmega8.
I use library from David Gironi ( http://davidegironi.blogspot.cz/2013/02/avr-atmega-mpu6050-gyroscope-and.html#.VwovxXqSdiU )

and to mpu6050.c add this function:

void mpu6050_DMPinit() {

//MOTION INT ENABLE
mpu6050_writeByte(MPU6050_RA_INT_ENABLE,0x40);

//MOTION DURATION
mpu6050_writeByte(MPU6050_RA_MOT_DUR,1);

//MOTION THR
mpu6050_writeByte(MPU6050_RA_MOT_THR,20);

_delay_ms(1);

//set HPF to HOLD settings
mpu6050_writeBits(MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_ACCEL_HPF_BIT, MPU6050_ACONFIG_ACCEL_HPF_LENGTH, 0b111);

//PIN INT0
mpu6050_writeBits(MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_INT_LEVEL_BIT, 2, 0b10);
}

And this finally work! Then i make some investigations and figured out it also in standby mode (less power consumption). Find that in encosure - Eclipse project.
About power consumption - now the module takes 1,7 mA but through I2C wires goes most of this current (i will try to correct it somehow)

MotoUnit.zip (64.3 KB)

"Why this is so important to me?
I would like to use interrupt from MPU to wake-up arduino on movement - to save battery, when device is not in use.
... Circuit should be awake only when someone is holding/throwing it."

Hi maybe it's too late to answer this... but for record, I solved this problem using the LowPower.h library and the SW420 sensor; not MPU6050.

For anyone interested in this topic I setup the esp32 using arduino framework and the mpu6050 in my project.

Had the same problem, figured it out all while still using the I2Cdev libraries:

#include "Wire.h"
#include "MPU6050.h"
#include "avr/sleep.h"

#define LED_PIN 13
#define INTERRUPT_PIN 2

#define MOTION_THRESHOLD 1
#define MOTION_EVENT_DURATION 40

MPU6050 accelgyro;
volatile bool ledState = true;

void setup() {
  Wire.begin();
  Serial.begin(38400);
  accelgyro.initialize();

  // verify connection to MPU6050
  Serial.println("Testing device connections...");
  Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");

  accelgyro.setAccelerometerPowerOnDelay(3);
  accelgyro.setInterruptMode(true); // Interrupts enabled
  accelgyro.setInterruptLatch(0); // Interrupt pulses when triggered instead of remaining on until cleared
  accelgyro.setIntMotionEnabled(true); // Interrupts sent when motion detected

  // Set sensor filter mode.
  // 0 -> Reset (disable high pass filter)
  // 1 -> On (5Hz)
  // 2 -> On (2.5Hz)
  // 3 -> On (1.25Hz)
  // 4 -> On (0.63Hz)
  // 5 -> Hold (Future outputs are relative to last output when this mode was set)
  accelgyro.setDHPFMode(1);


  // Motion detection acceleration threshold. 1LSB = 2mg.
  accelgyro.setMotionDetectionThreshold(MOTION_THRESHOLD);

  // Motion detection event duration in ms
  accelgyro.setMotionDetectionDuration(MOTION_EVENT_DURATION);
}

void sleepNow() {
  sleep_enable();
  attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), wakeUp, RISING);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_cpu();
}

void wakeUp() {
  sleep_disable();
  detachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN));
  ledState = !ledState;
}

void loop() {
  digitalWrite(LED_PIN, ledState);
  sleepNow();
}

Using this, the onboard LED on my Uno toggles by tapping the MPU6050, and the Arduino is fast asleep the rest of the time.