C++ MPU6050零运动的工作原理

C++ MPU6050零运动的工作原理,c++,C++,大家晚上好。我目前正在做一个智能窗户的项目,在这个项目中我将测量温度、湿度和加速度,我将有一个陀螺仪来测量窗户的度数。我已经决定继续使用哪些传感器,其中一个是MPU6050。我想问的问题是如何使用传感器,以便在加速度结束时而不是开始时进行测量?我拥有的esp32将一直处于休眠状态,每15分钟醒来一次发送数据,如果收到中断,它将醒来发送数据。我已主动尝试了所有的案例,但没有成功 这是我的零运动代码 #include "Wire.h" #include "SPI.h&q

大家晚上好。我目前正在做一个智能窗户的项目,在这个项目中我将测量温度、湿度和加速度,我将有一个陀螺仪来测量窗户的度数。我已经决定继续使用哪些传感器,其中一个是MPU6050。我想问的问题是如何使用传感器,以便在加速度结束时而不是开始时进行测量?我拥有的esp32将一直处于休眠状态,每15分钟醒来一次发送数据,如果收到中断,它将醒来发送数据。我已主动尝试了所有的案例,但没有成功 这是我的零运动代码

#include "Wire.h"
#include "SPI.h"

// I2Cdev and MPU6050 must be installed as libraries, or else the .cpp/.h files
// for both classes must be in the include path of your project
#include "I2Cdev.h"
#include "MPU6050.h"

// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for InvenSense evaluation board)
// AD0 high = 0x69
MPU6050 accelgyro;

int16_t ax, ay, az;
int16_t gx, gy, gz;
int8_t threshold, count;
float temp;
bool zero_detect;
bool TurnOnZI = false;

bool XnegMD, XposMD, YnegMD, YposMD, ZnegMD, ZposMD;
int minVal=265; int maxVal=402;
double x; double y; double z;

#define LED_PIN 13
#define BUTTON_PIN_BITMASK 0x200000000 // 2^33 in hex
RTC_DATA_ATTR int bootCount = 0;


bool blinkState = false;
void print_wakeup_reason() {
  esp_sleep_wakeup_cause_t wakeup_reason;

  wakeup_reason = esp_sleep_get_wakeup_cause();

  switch (wakeup_reason)
  {
    case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.printf("Wakeup was not caused by deep sleep: %d\n", wakeup_reason); break;
  }
}

void setup() {
  // join I2C bus (I2Cdev library doesn't do this automatically)
  Wire.begin();

  // initialize serial communication
  // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
  // it's really up to you depending on your project)
  Serial.begin(115200);
  //Increment boot number and print it every reboot
  ++bootCount;
  Serial.println("Boot number: " + String(bootCount));

  //Print the wakeup reason for ESP32
  print_wakeup_reason();
  // initialize device
  Serial.println("Initializing I2C devices...");
  accelgyro.initialize();

  // verify connection
  Serial.println("Testing device connections...");
  Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
  esp_sleep_enable_ext0_wakeup(GPIO_NUM_15, 1); //1 = High, 0 = Low

  //accelgyro.setTempSensorEnabled(false);
  
  //Set up zero motion

  /** Get accelerometer power-on delay.
    The accelerometer data path provides samples to the sensor registers, Motion
    detection, Zero Motion detection, and Free Fall detection modules. The
    signal path contains filters which must be flushed on wake-up with new
    samples before the detection modules begin operations. The default wake-up
    delay, of 4ms can be lengthened by up to 3ms. This additional delay is
    specified in ACCEL_ON_DELAY in units of 1 LSB = 1 ms. The user may select
    any value above zero unless instructed otherwise by InvenSense. Please refer
    to Section 8 of the MPU-6000/MPU-6050 Product Specification document for
    further information regarding the detection modules.
    @return Current accelerometer power-on delay
    @see MPU60X0_RA_MOT_DETECT_CTRL
    @see MPU60X0_DETECT_ACCEL_ON_DELAY_BIT
  */
  accelgyro.setAccelerometerPowerOnDelay(3);


  /** Get Zero Motion Detection interrupt enabled status.
    Will be set 0 for disabled, 1 for enabled.
    @return Current interrupt enabled status
    @see MPU60X0_RA_INT_ENABLE
    @see MPU60X0_INTERRUPT_ZMOT_BIT
  **/
  accelgyro.setIntZeroMotionEnabled(true);

  //accelgyro.setIntMotionEnabled(true);


  /** Get the high-pass filter configuration.
    The DHPF is a filter module in the path leading to motion detectors (Free
    Fall, Motion threshold, and Zero Motion). The high pass filter output is not
    available to the data registers (see Figure in Section 8 of the MPU-6000/
    MPU-6050 Product Specification document).

    The high pass filter has three modes:
       Reset: The filter output settles to zero within one sample. This
              effectively disables the high pass filter. This mode may be toggled
              to quickly settle the filter.

       On:    The high pass filter will pass signals above the cut off frequency.

       Hold:  When triggered, the filter holds the present sample. The filter
              output will be the difference between the input sample and the held
              sample.

    ACCEL_HPF | Filter Mode | Cut-off Frequency
    ----------+-------------+------------------
    0         | Reset       | None
    1         | On          | 5Hz
    2         | On          | 2.5Hz
    3         | On          | 1.25Hz
    4         | On          | 0.63Hz
    7         | Hold        | None
    </pre>

    @return Current high-pass filter configuration
    @see MPU60X0_DHPF_RESET
    @see MPU60X0_RA_ACCEL_CONFIG
  */
  //DEBUG_PRINTLN("Setting DHPF bandwidth to 5Hz...");
  accelgyro.setDHPFMode(1);


  /** 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 (Register 32). The Motion detection interrupt is triggered when the
    Motion Detection counter reaches the time count specified in MOT_DUR
    (Register 32).

    The Motion interrupt will indicate the axis and polarity of detected motion
    in MOT_DETECT_STATUS (Register 97).

    For more details on the Motion detection interrupt, see Section 8.3 of the
    MPU-6000/MPU-6050 Product Specification document as well as Registers 56 and
    58 of this document.

    @return Current motion detection acceleration threshold value (LSB = 2mg)
    @see MPU60X0_RA_MOT_THR
  */
  //Serial.println("Setting motion detection threshold to 16...");
  //accelgyro.setMotionDetectionThreshold(16);


  /** 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 (Register 34). The Zero Motion interrupt is triggered when
    the Zero Motion duration counter reaches the time count specified in
    ZRMOT_DUR (Register 34).

    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 (Register 97). 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.

    For more details on the Zero Motion detection interrupt, see Section 8.4 of
    the MPU-6000/MPU-6050 Product Specification document as well as Registers 56
    and 58 of this document.

    @return Current zero motion detection acceleration threshold value (LSB = 2mg)
    @see MPU60X0_RA_ZRMOT_THR
  */
  Serial.println("Setting zero-motion detection threshold to 156...");
  accelgyro.setZeroMotionDetectionThreshold(64);


  /** 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 (Register 31). The Motion detection interrupt is
    triggered when the Motion detection counter reaches the time count specified
    in this register.

    For more details on the Motion detection interrupt, see Section 8.3 of the
    MPU-6000/MPU-6050 Product Specification document.

    @return Current motion detection duration threshold value (LSB = 1ms)
    @see MPU60X0_RA_MOT_DUR
  */
  Serial.println("Setting motion detection duration to 40...");
  //accelgyro.setMotionDetectionDuration(2);


  /** 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 (Register 33). The Zero Motion
    interrupt is triggered when the Zero Motion duration counter reaches the time
    count specified in this register.

    For more details on the Zero Motion detection interrupt, see Section 8.4 of
    the MPU-6000/MPU-6050 Product Specification document, as well as Registers 56
    and 58 of this document.

    @return Current zero motion detection duration threshold value (LSB = 64ms)
    @see MPU60X0_RA_ZRMOT_DUR
  */
  //Serial.println("Setting zero-motion detection duration to 0...");
  accelgyro.setZeroMotionDetectionDuration(64);
  
  //for (int i = 0; i < 1; i++) {
    // read raw accel/gyro measurements from device
    Serial.println("Getting raw accwl/gyro measurements");
    //accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

    Serial.println("Getting Motion indicators, count and threshold");

    XnegMD = accelgyro.getXNegMotionDetected();
    XposMD = accelgyro.getXPosMotionDetected();
    YnegMD = accelgyro.getYNegMotionDetected();
    YposMD = accelgyro.getYPosMotionDetected();
    ZnegMD = accelgyro.getZNegMotionDetected();
    ZposMD = accelgyro.getZPosMotionDetected();

    zero_detect = accelgyro.getIntMotionStatus();
    threshold = accelgyro.getZeroMotionDetectionThreshold();

    //Serial.println("Got to count");
    //count = accelgyro.getMotionDetectionCounterDecrement();

    /** Get current internal temperature.
      @return Temperature reading in 16-bit 2's complement format
      @see MPU60X0_RA_TEMP_OUT_H
    */
    Serial.println("Getting Die Temperature");
    temp = (accelgyro.getTemperature() / 340.) + 36.53;


    /*  The accelerometer and gyroscope measurements are explained in the MPU-6050
      datasheet in the GYRO_CONFIG and ACCEL_CONFIG register descriptions (sections 4.4
      and 4.5 on pages 14 and 15). The scale of each depends on the sensitivity settings
      chosen, which can be one of +/- 2, 4, 8, or 16g for the accelerometer and one of
      +/- 250, 500, 1000, or 2000 deg/sec for the gyroscope. The accelerometer produces data
      in units of acceleration (distance over time2), and the gyroscope produces data in units
      of rotational velocity (rotation distance over time).

      The output scale for any setting is [-32768, +32767] for each of the six axes. The default
      setting in the I2Cdevlib class is +/- 2g for the accel and +/- 250 deg/sec for the gyro. If
      the device is perfectly level and not moving, then:
          X/Y accel axes should read 0
          Z accel axis should read 1g, which is +16384 at a sensitivity of 2g
          X/Y/Z gyro axes should read 0

      In reality, the accel axes won't read exactly 0 since it is difficult to be perfectly level
      and there is some noise/error, and the gyros will also not read exactly 0 for the same reason
      (noise/error).
    */

    // these methods (and a few others) are also available
    accelgyro.getAcceleration(&ax, &ay, &az);
    accelgyro.getRotation(&gx, &gy, &gz);

//    Serial.print(temp); Serial.print(",");
//    Serial.print(ax / 16384.); Serial.print(",");
//    Serial.print(ay / 16384.); Serial.print(",");
//    Serial.print(az / 16384.); Serial.print(",");
//    Serial.print(gx / 131.072); Serial.print(",");
//    Serial.print(gy / 131.072); Serial.print(",");
//    Serial.print(gz / 131.072); Serial.print(",");
    Serial.print(zero_detect); Serial.print(",");
    //Serial.print(XnegMD); Serial.print(",");
    //Serial.println(XposMD);

  int xAng = map(ax,minVal,maxVal,-90,90); 
    int yAng = map(ay,minVal,maxVal,-90,90); 
    int zAng = map(az,minVal,maxVal,-90,90);

x= RAD_TO_DEG * (atan2(-yAng, -zAng)+PI); 
y= RAD_TO_DEG * (atan2(-xAng, -zAng)+PI); 
z= RAD_TO_DEG * (atan2(-yAng, -xAng)+PI);

Serial.print("AngleX= "); Serial.println(x);

Serial.print("AngleY= "); Serial.println(y);

Serial.print("AngleZ= "); Serial.println(z);
    
    // display tab-separated accel/gyro x/y/z values
    /*
      Serial.print("a/g:\t");
      Serial.print(ax/16384.); Serial.print("\t");
      Serial.print(ay/16384.); Serial.print("\t");
      Serial.print(az/16384.); Serial.print("\t");
      Serial.print(gx/131.072); Serial.print("\t");
      Serial.print(gy/131.072); Serial.print("\t");
      Serial.println(gz/131.072);

      Serial.print("DieTemp:\t");Serial.println(temp);

      Serial.print("ZeroMotion(97):\t");
      Serial.print(zero_detect); Serial.print("\t");
      Serial.print("Count: \t");Serial.print(count); Serial.print("\t");
      Serial.print(XnegMD); Serial.print("\t");
      Serial.print(XposMD); Serial.print("\t");
      Serial.print(YnegMD); Serial.print("\t");
      Serial.print(YposMD); Serial.print("\t");
      Serial.print(ZnegMD); Serial.print("\t");
      Serial.println(ZposMD);
    */


   // delay(1000);

    // blink LED to indicate activity
    //    blinkState = !blinkState;
    //    digitalWrite(LED_PIN, blinkState);
  //}


  // configure Arduino LED for
  //pinMode(LED_PIN, OUTPUT);
  Serial.println("Going to sleep now");
  esp_deep_sleep_start();
  Serial.println("This will never be printed");

}

void loop() {

}
#包括“Wire.h”
#包括“SPI.h”
//I2Cdev和MPU6050必须作为库安装,否则将安装.cpp/.h文件
//对于这两个类,必须位于项目的include路径中
#包括“I2Cdev.h”
#包括“MPU6050.h”
//类的默认I2C地址为0x68
//特定的I2C地址可以在此处作为参数传递
//AD0低=0x68(Invense评估板的默认值)
//AD0高=0x69
MPU6050加速度计;
亚利桑那州艾城国际税务局;
int16_t gx,gy,gz;
int8_t阈值,计数;
浮子温度;
布尔零检测;
bool-TurnOnZI=假;
bool-XnegMD、XposMD、YnegMD、YposMD、ZnegMD、ZposMD;
int minVal=265;int-maxVal=402;
双x;双y;双z;
#定义LED_引脚13
#以十六进制定义按钮\u引脚\u位掩码0x200000000//2^33
RTC_DATA_ATTR int bootCount=0;
bool blinkState=false;
无效打印\唤醒\原因(){
尤其是睡眠和醒来的原因;
wakeup_reason=esp_sleep_get_wakeup_cause();
开关(唤醒原因)
{
案例ESP_SLEEP_WAKEUP_EXT0:Serial.println(“使用RTC_IO的外部信号引起的唤醒”);中断;
案例ESP_SLEEP_WAKEUP_EXT1:Serial.println(“使用RTC_CNTL的外部信号引起的唤醒”);中断;
案例ESP_SLEEP_WAKEUP_TIMER:Serial.println(“由定时器引起的唤醒”);中断;
案例ESP_SLEEP_WAKEUP_TOUCHPAD:Serial.println(“由TOUCHPAD引起的唤醒”);中断;
案例ESP_SLEEP_WAKEUP_ULP:Serial.println(“由ULP程序引起的唤醒”);中断;
默认值:Serial.printf(“唤醒不是由深度睡眠引起的:%d\n”,唤醒原因);中断;
}
}
无效设置(){
//加入I2C总线(I2Cdev库不会自动执行此操作)
Wire.begin();
//初始化串行通信
//(选择38400是因为它在8MHz和16MHz下工作得一样好,但是
//这实际上取决于您的项目)
序列号开始(115200);
//增加启动编号,并在每次重新启动时打印
++靴数;
Serial.println(“启动编号:”+字符串(启动计数));
//打印ESP32的唤醒原因
打印唤醒原因();
//初始化设备
Serial.println(“初始化I2C设备…”);
accelgyro.initialize();
//验证连接
Serial.println(“测试设备连接…”);
Serial.println(accelgyro.testConnection()?“MPU6050连接成功”:“MPU6050连接失败”);
esp_sleep_enable_ext0_wakeup(GPIO_NUM_15,1);//1=高,0=低
//accelgyro.SetTempSensor启用(错误);
//设置零运动
/**让加速计上电延迟。
加速计数据路径向传感器寄存器提供样本,包括运动
检测、零运动检测和自由落体检测模块
信号路径包含过滤器,在唤醒时必须使用新的
在检测模块开始操作之前进行采样。默认唤醒
4毫秒的延迟可以延长到3毫秒。这个额外的延迟是
在ACCEL_ON_DELAY中指定,单位为1 LSB=1 ms。用户可以选择
任何高于零的值,除非Invense另有指示。请参考
参见MPU-6000/MPU-6050产品规范文件第8节
关于检测模块的更多信息。
@返回电流加速计上电延迟
@请参阅MPU60X0\u RA\u MOT\u DETECT\u CTRL
@请参阅MPU60X0延迟位上的检测加速
*/
加速度计。设置加速度计功率计(3);
/**获取零运动检测中断启用状态。
将设置为0表示禁用,1表示启用。
@返回当前中断启用状态
@请参阅MPU60X0\u RA\u INT\u启用
@参见MPU60X0\u中断\u ZMOT\u位
**/
accelgyro.setIntZeroMotionEnabled(真);
//accelgyro.setIntMotionEnabled(真);
/**获取高通滤波器配置。
DHPF是通向运动检测器(自由)路径中的一个过滤器模块
下降、运动阈值和零运动)。高通滤波器输出不可用
可用于数据寄存器(参见MPU-6000第8节中的图/
MPU-6050产品规范文件)。
高通滤波器有三种模式:
重置:过滤器输出在一个样本内设置为零。此
有效禁用高通滤波器。可切换此模式
快速沉淀过滤器。
开启:高通滤波器将通过高于截止频率的信号。
保持:触发时,过滤器保持当前样本。过滤器
输出将是输入样本和保持样本之间的差值
样品
加速HPF |滤波模式|截止频率
----------+-------------+------------------
0 |重置|无
1开5赫兹
2 |开| 2.5Hz
3开1.25Hz
4开0.63Hz
7 |保持|无
@返回电流高通滤波器配置
@参见MPU60X0\u DHPF\u重置
@请参阅MPU60X0\u RA\u ACCEL\u配置
*/
//调试_PRINTLN(“将DHPF带宽设置为5Hz…”);
加速度陀螺仪设置DHPFMODE(1);
/**获取运动检测事件加速阈值。
该寄存器配置运动中断的检测阈值
生成。运动单位为1LSB=2mg。当
任何加速计测量值的绝对值都超过此运动
检测阈值。此条件会增加