How to add Blynk to my MPU-6050 "Movement Detector"

@Gunner

Wouldn’t the 10L be scanning 100 times per second? I think it should be 100L.

Also, wouldn’t the display on the app almost immediately change back to “Bike Secure” as the loop would cycle again in .1 seconds, and the LimitationFlag would be 1?

not saying I could do better, just what I noticed.

@Gunner I’m back. :smiley:

I tried the new code, its still slow to react, and that’s if it reacts at all. It seems to pick up initial movement after four or five seconds of moving the sensor but then it’s as though it ignores any succeeding movements?
So, I got some new code, but these damn “Braces” keep beating me. Would you mind taking a look, see if I’m almost there, or still wondering around in the dark(which is the most likely. :pensive: )

#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>`
#include <BlynkSimpleEsp8266.h>
#include <Wire.h>
#include <MPU6050.h>

char auth[] = "060348058fd549f083b9b649e6784852";
char ssid[] = "BTHub6-P38S";
char pass[] = "wAwhd7rKg3cT";

MPU6050 mpu;

void setup() 
{
  Serial.begin(115200);

  Blynk.begin(auth, ssid, pass);

  Serial.println("Initialize MPU6050");

  while(!mpu.begin(MPU6050_SCALE_2000DPS, MPU6050_RANGE_16G))
  {
    Serial.println("Could not find a valid MPU6050 sensor, check wiring!");
    delay(500);
  }

  mpu.setAccelPowerOnDelay(MPU6050_DELAY_3MS);

  mpu.setIntFreeFallEnabled(false);  
  mpu.setIntZeroMotionEnabled(false);
  mpu.setIntMotionEnabled(false);
  
  mpu.setDHPFMode(MPU6050_DHPF_5HZ);

  mpu.setMotionDetectionThreshold(2);
  mpu.setMotionDetectionDuration(5);

  mpu.setZeroMotionDetectionThreshold(4);
  mpu.setZeroMotionDetectionDuration(2);
  
  checkSettings();
 
}

void checkSettings()
{
  Serial.println();
  
  Serial.print(" * Sleep Mode:                ");
  Serial.println(mpu.getSleepEnabled() ? "Enabled" : "Disabled");

  Serial.print(" * Motion Interrupt:          ");
  Serial.println(mpu.getIntMotionEnabled() ? "Enabled" : "Disabled");

  Serial.print(" * Zero Motion Interrupt:     ");
  Serial.println(mpu.getIntZeroMotionEnabled() ? "Enabled" : "Disabled");

  Serial.print(" * Free Fall Interrupt:       ");
  Serial.println(mpu.getIntFreeFallEnabled() ? "Enabled" : "Disabled");
  
  Serial.print(" * Motion Threshold:          ");
  Serial.println(mpu.getMotionDetectionThreshold());

  Serial.print(" * Motion Duration:           ");
  Serial.println(mpu.getMotionDetectionDuration());

  Serial.print(" * Zero Motion Threshold:     ");
  Serial.println(mpu.getZeroMotionDetectionThreshold());

  Serial.print(" * Zero Motion Duration:      ");
  Serial.println(mpu.getZeroMotionDetectionDuration());
  
  Serial.print(" * Clock Source:              ");
  switch(mpu.getClockSource())
  {
    case MPU6050_CLOCK_KEEP_RESET:     Serial.println("Stops the clock and keeps the timing generator in reset"); break;
    case MPU6050_CLOCK_EXTERNAL_19MHZ: Serial.println("PLL with external 19.2MHz reference"); break;
    case MPU6050_CLOCK_EXTERNAL_32KHZ: Serial.println("PLL with external 32.768kHz reference"); break;
    case MPU6050_CLOCK_PLL_ZGYRO:      Serial.println("PLL with Z axis gyroscope reference"); break;
    case MPU6050_CLOCK_PLL_YGYRO:      Serial.println("PLL with Y axis gyroscope reference"); break;
    case MPU6050_CLOCK_PLL_XGYRO:      Serial.println("PLL with X axis gyroscope reference"); break;
    case MPU6050_CLOCK_INTERNAL_8MHZ:  Serial.println("Internal 8MHz oscillator"); break;
  }
  
  Serial.print(" * Accelerometer:             ");
  switch(mpu.getRange())
  {
    case MPU6050_RANGE_16G:            Serial.println("+/- 16 g"); break;
    case MPU6050_RANGE_8G:             Serial.println("+/- 8 g"); break;
    case MPU6050_RANGE_4G:             Serial.println("+/- 4 g"); break;
    case MPU6050_RANGE_2G:             Serial.println("+/- 2 g"); break;
  }  

  Serial.print(" * Accelerometer offsets:     ");
  Serial.print(mpu.getAccelOffsetX());
  Serial.print(" / ");
  Serial.print(mpu.getAccelOffsetY());
  Serial.print(" / ");
  Serial.println(mpu.getAccelOffsetZ());

  Serial.print(" * Accelerometer power delay: ");
  switch(mpu.getAccelPowerOnDelay())
  {
    case MPU6050_DELAY_3MS:            Serial.println("3ms"); break;
    case MPU6050_DELAY_2MS:            Serial.println("2ms"); break;
    case MPU6050_DELAY_1MS:            Serial.println("1ms"); break;
    case MPU6050_NO_DELAY:             Serial.println("0ms"); break;
  }  
  {
  Serial.println();
}

  Vector rawAccel = mpu.readRawAccel();
  Activites act = mpu.readActivites();
  if (act.isActivity)
  {
    Blynk.virtualWrite(V14, "Bike Movement Detected");
  } else
  {
    Blynk.virtualWrite(V14, "Bike Secure");
  }

  if (act.isInactivity)
  {
    Blynk.virtualWrite(V14, "Bike Movement Detected");
  } else
  {
    Blynk.virtualWrite(V14, "Bike Secure");
  }

void loop()
{
  Blynk.run();
  timer.run();
}

@Shadeyman

I think we need to determine what these do first, and when they are triggered:

  mpu.setMotionDetectionThreshold(2);
  mpu.setMotionDetectionDuration(5);

  mpu.setZeroMotionDetectionThreshold(4);
  mpu.setZeroMotionDetectionDuration(2);

act.isActivity

act.isInactivity
2 Likes

here is the code you provided formatted a bit to include a timer, and proper braces.

#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>`
#include <BlynkSimpleEsp8266.h>
#include <Wire.h>
#include <MPU6050.h>

char auth[] = "060348058fd549f083b9b649e6784852";
char ssid[] = "BTHub6-P38S";
char pass[] = "wAwhd7rKg3cT";

BlynkTimer timer;

MPU6050 mpu;

void setup() 
{
  Serial.begin(115200);

  Blynk.begin(auth, ssid, pass);

  Serial.println("Initialize MPU6050");

  while(!mpu.begin(MPU6050_SCALE_2000DPS, MPU6050_RANGE_16G))
  {
    Serial.println("Could not find a valid MPU6050 sensor, check wiring!");
    delay(500);
  }

  mpu.setAccelPowerOnDelay(MPU6050_DELAY_3MS);

  mpu.setIntFreeFallEnabled(false);  
  mpu.setIntZeroMotionEnabled(false);
  mpu.setIntMotionEnabled(false);
  
  mpu.setDHPFMode(MPU6050_DHPF_5HZ);

  mpu.setMotionDetectionThreshold(2);
  mpu.setMotionDetectionDuration(5);

  mpu.setZeroMotionDetectionThreshold(4);
  mpu.setZeroMotionDetectionDuration(2);
  
  checkSettings();
  timer.setInterval(100L, MotionSensorRead); // run the scan for motion function loop 10x/second
 
}

void checkSettings()
{
  Serial.println();
  
  Serial.print(" * Sleep Mode:                ");
  Serial.println(mpu.getSleepEnabled() ? "Enabled" : "Disabled");

  Serial.print(" * Motion Interrupt:          ");
  Serial.println(mpu.getIntMotionEnabled() ? "Enabled" : "Disabled");

  Serial.print(" * Zero Motion Interrupt:     ");
  Serial.println(mpu.getIntZeroMotionEnabled() ? "Enabled" : "Disabled");

  Serial.print(" * Free Fall Interrupt:       ");
  Serial.println(mpu.getIntFreeFallEnabled() ? "Enabled" : "Disabled");
  
  Serial.print(" * Motion Threshold:          ");
  Serial.println(mpu.getMotionDetectionThreshold());

  Serial.print(" * Motion Duration:           ");
  Serial.println(mpu.getMotionDetectionDuration());

  Serial.print(" * Zero Motion Threshold:     ");
  Serial.println(mpu.getZeroMotionDetectionThreshold());

  Serial.print(" * Zero Motion Duration:      ");
  Serial.println(mpu.getZeroMotionDetectionDuration());
  
  Serial.print(" * Clock Source:              ");
  switch(mpu.getClockSource())
  {
    case MPU6050_CLOCK_KEEP_RESET:     Serial.println("Stops the clock and keeps the timing generator in reset"); break;
    case MPU6050_CLOCK_EXTERNAL_19MHZ: Serial.println("PLL with external 19.2MHz reference"); break;
    case MPU6050_CLOCK_EXTERNAL_32KHZ: Serial.println("PLL with external 32.768kHz reference"); break;
    case MPU6050_CLOCK_PLL_ZGYRO:      Serial.println("PLL with Z axis gyroscope reference"); break;
    case MPU6050_CLOCK_PLL_YGYRO:      Serial.println("PLL with Y axis gyroscope reference"); break;
    case MPU6050_CLOCK_PLL_XGYRO:      Serial.println("PLL with X axis gyroscope reference"); break;
    case MPU6050_CLOCK_INTERNAL_8MHZ:  Serial.println("Internal 8MHz oscillator"); break;
  }
  
  Serial.print(" * Accelerometer:             ");
  switch(mpu.getRange())
  {
    case MPU6050_RANGE_16G:            Serial.println("+/- 16 g"); break;
    case MPU6050_RANGE_8G:             Serial.println("+/- 8 g"); break;
    case MPU6050_RANGE_4G:             Serial.println("+/- 4 g"); break;
    case MPU6050_RANGE_2G:             Serial.println("+/- 2 g"); break;
  }  

  Serial.print(" * Accelerometer offsets:     ");
  Serial.print(mpu.getAccelOffsetX());
  Serial.print(" / ");
  Serial.print(mpu.getAccelOffsetY());
  Serial.print(" / ");
  Serial.println(mpu.getAccelOffsetZ());

  Serial.print(" * Accelerometer power delay: ");
  switch(mpu.getAccelPowerOnDelay())
  {
    case MPU6050_DELAY_3MS:            Serial.println("3ms"); break;
    case MPU6050_DELAY_2MS:            Serial.println("2ms"); break;
    case MPU6050_DELAY_1MS:            Serial.println("1ms"); break;
    case MPU6050_NO_DELAY:             Serial.println("0ms"); break;
  }  
  
  Serial.println();
}

void MotionSensorRead() {  // Motion sensor read
  Vector rawAccel = mpu.readRawAccel();
  Activites act = mpu.readActivites();
  if (act.isActivity)
  {
    Blynk.virtualWrite(V14, "Bike Movement Detected");
  } else
  {
    Blynk.virtualWrite(V14, "Bike Secure");
  }

  if (act.isInactivity)
  {
    Blynk.virtualWrite(V14, "Bike Movement Detected");
  } else
  {
    Blynk.virtualWrite(V14, "Bike Secure");
  }
}

  

void loop()
{
  Blynk.run();
  timer.run();
}
1 Like

Try the code above, but with this MotionSensorRead function instead, and maybe it will help to figure out when each part is triggered. Then we can determine when/where to add the notification. you will need a display on V14 and V15, both set to PUSH.

void MotionSensorRead() {  // Motion sensor read
  Vector rawAccel = mpu.readRawAccel();
  Activites act = mpu.readActivites();
  if (act.isActivity)
  {
    Blynk.virtualWrite(V14, "Is Activity");
  } else
  {
    Blynk.virtualWrite(V14, "Not Activity");
  }

  if (act.isInactivity)
  {
    Blynk.virtualWrite(V15, "Is Inactivity");
  } else
  {
    Blynk.virtualWrite(V15, "NOT Inactivity");
  }
}
1 Like

@Toro_Blanco Thank you.

I ran it, and I forgot something. :roll_eyes:

BlynkTimer timer;

So now it works, thank you very much. :hugs:

Does the display in the APP change when you shake the sensor?

Yes.
This is very sensitive.

  if (act.isInactivity)
  {
    Blynk.virtualWrite(V15, "Is Inactivity");
  } else
  {
    Blynk.virtualWrite(V15, "NOT Inactivity");
  }
}

I don’t think its detecting movement, I think its detecting when its perfectly still. Which I’m finding very difficult to do., maybe its too sensitive?

Try increasing these values

  mpu.setMotionDetectionThreshold(2);
  mpu.setMotionDetectionDuration(5);

  mpu.setZeroMotionDetectionThreshold(4);
  mpu.setZeroMotionDetectionDuration(2);

I’d change them one at a time, and see if you can notice what it does. From the little reading I did the threshold is how hard the shaking needs to be and the duration is for how long (kinda obvious I guess). Maybe start with just threshold.

If this is true, maybe this can be used to detect when the bike is “Secure” and also used for the notification flag reset.

Perhaps “DetectionThreshold” is sensitivity,
And “DetectionDuration” is time in milli seconds?

I’ll test … :+1:

@Toro_Blanco Google is king. :wink:

While waiting for it to compile and upload I found this.

mpu.setMotionDetectionThreshold
Get motion detection event acceleration threshold. This register configures the detection threshold for Motion interrupt generation. The unit of MOT_THR is 1LSB = 2mg. Motion is detected when the absolute value of any of the accelerometer measurements exceeds this Motion detection threshold. This condition increments the Motion detection duration counter. The Motion detection interrupt is triggered when the Motion Detection counter reaches the time count specified in MOT_DUR.

Returns:
Current motion detection acceleration threshold value (LSB = 2mg)

mpu.setMotionDetectionDuration
Get motion detection event duration threshold. This register configures the duration counter threshold for Motion interrupt generation. The duration counter ticks at 1 kHz, therefore MOT_DUR has a unit of 1LSB = 1ms. The Motion detection duration counter increments when the absolute value of any of the accelerometer measurements exceeds the Motion detection threshold. The Motion detection interrupt is triggered when the Motion detection counter reaches the time count specified in this register.

Returns:
Current motion detection duration threshold value (LSB = 1ms)

mpu.setZeroMotionDetectionThreshold
Get zero motion detection event acceleration threshold. This register configures the detection threshold for Zero Motion interrupt generation. The unit of ZRMOT_THR is 1LSB = 2mg. Zero Motion is detected when the absolute value of the accelerometer measurements for the 3 axes are each less than the detection threshold. This condition increments the Zero Motion duration counter. The Zero Motion interrupt is triggered when the Zero Motion duration counter reaches the time count specified in ZRMOT_DUR.

Unlike Free Fall or Motion detection, Zero Motion detection triggers an interrupt both when Zero Motion is first detected and when Zero Motion is no longer detected.

When a zero motion event is detected, a Zero Motion Status will be indicated in the MOT_DETECT_STATUS register. When a motion-to-zero-motion condition is detected, the status bit is set to 1. When a zero-motion-to- motion condition is detected, the status bit is set to 0.

Returns:
Current zero motion detection acceleration threshold value (LSB = 2mg)

mpu.setZeroMotionDetectionDuration
Get zero motion detection event duration threshold. This register configures the duration counter threshold for Zero Motion interrupt generation. The duration counter ticks at 16 Hz, therefore ZRMOT_DUR has a unit of 1 LSB = 64 ms. The Zero Motion duration counter increments while the absolute value of the accelerometer measurements are each less than the detection threshold. The Zero Motion interrupt is triggered when the Zero Motion duration counter reaches the time count specified in this register.

Returns:
Current zero motion detection duration threshold value (LSB = 64ms)

https://www.i2cdevlib.com/docs/html/class_m_p_u6050.html

Yes it is.

Here is link to source in case anyone else is interested.

https://www.i2cdevlib.com/devices/mpu6050#source

https://www.i2cdevlib.com/docs/html/class_m_p_u6050.html

EDIT: Oops, didn’t see it there at the end of your post.

1 Like

@Toro_Blanco
As far as I can tell

These:

  mpu.setMotionDetectionThreshold(2);
  mpu.setMotionDetectionDuration(5);

Are the settings for this

if (act.isActivity)

And these

  mpu.setZeroMotionDetectionThreshold(4);
  mpu.setZeroMotionDetectionDuration(2);

Are the settings for this:

  if (act.isInactivity)

I was editing the post as I went along, probably still “copy and pasting” stuff in when you posted.

Once you get the sensitivity all sorted out, give this a try:

int LimitationFlag = 0;

void MotionSensorRead() {  // Motion sensor read
  Vector rawAccel = mpu.readRawAccel();
  Activites act = mpu.readActivites();
  if (act.isActivity)
  {
    if (LimitationFlag = 1){
    Blynk.virtualWrite(V14, "BIKE BEING STOLEN!");
    Blynk.notify("BIKE BEING STOLEN!");
    LimitationFlag = 0;
    }
  } 
  if (act.isInactivity)
  {
    Blynk.virtualWrite(V14, "BIKE SECURE");
    LimitationFlag = 1;
  }
    
}

Remember notifications can only be sent every 15 seconds (BLYNK SERVER). Although there may be a way to get around that using the eventor widget (easy), or by using a LOCAL SERVER (hard).

1 Like

I’m no longer using the Notification widget, or is that not what you mean?

Oh, I thought you wanted the notification on your phone to alert you when the bike was being moved? Otherwise you will have to be constantly looking at the display.

1 Like

I do, but not while I’m testing. I removed it after @Gunner told me the same thing, limit was max 1 every 15 seconds. :+1:

These setting make both react evenly.

  mpu.setMotionDetectionThreshold(2);
  mpu.setMotionDetectionDuration(5);

  mpu.setZeroMotionDetectionThreshold(8);
  mpu.setZeroMotionDetectionDuration(2);

Well that last snipet of code I provided should still run without the notification widget, you just wont get any push notifications until you add it.

As for sensitivity settings, I would shoot for something that is reliable. That is, when installed on your bike, and the bike is not being moved/touched, the isInactivity should be triggered and stable. Same for isActivity and when it is being moved/touched.

1 Like

At home I’m sure sensitivity wont be an issue. However I work on building sites, heavy plant is nearly always nearby so sensitivity will be an issue. I guess that will be a “work in progress” as I’ve no way of replicating the vibrations from a tracked 37 ton JCB Excavator rolling by.
On the plus side my office(a shipping container) has WiFi I can configure to match my home SSID and password so the bike logging into Blynk wont be a problem.