Помогите с кодом определения угла акселерометром.

Тема в разделе "Arduino & Shields", создана пользователем AlisherRobotRex, 29 янв 2018.

  1. Программа выдаёт такую ошибку:{
    warning: address of local variable 'data' returned [-Wreturn-local-addr]

    uint8_t data[nbytes];}
    Как это исправить?
    Код (C++):


    #include <Wire.h>
    #include "Kalman.h"



    Kalman kalmanX;
    Kalman kalmanY;

    uint8_t IMUAddress = 0x68;

    /* IMU Data */
    int16_t accX;
    int16_t accY;
    int16_t accZ;
    int16_t tempRaw;
    int16_t gyroX;
    int16_t gyroY;
    int16_t gyroZ;

    double accXangle; // Angle calculate using the accelerometer
    double accYangle;
    double temp;
    double gyroXangle = 180; // Angle calculate using the gyro
    double gyroYangle = 180;
    double compAngleX = 180; // Calculate the angle using a Kalman filter
    double compAngleY = 180;
    double kalAngleX; // Calculate the angle using a Kalman filter
    double kalAngleY;

    uint32_t timer;

    void setup() {

      Serial.begin(115200);
      Wire.begin();
      Serial.begin(9600);
             

      i2cWrite(0x6B,0x00); // Disable sleep mode    
      kalmanX.setAngle(180); // Set starting angle
      kalmanY.setAngle(180);
      timer = micros();
    }

    void loop() {
      /* Update all the values */
      uint8_t* data = i2cRead(0x3B,14);
      accX = ((data[0] << 8) | data[1]);
      accY = ((data[2] << 8) | data[3]);
      accZ = ((data[4] << 8) | data[5]);
      tempRaw = ((data[6] << 8) | data[7]);
      gyroX = ((data[8] << 8) | data[9]);
      gyroY = ((data[10] << 8) | data[11]);
      gyroZ = ((data[12] << 8) | data[13]);

      /* Calculate the angls based on the different sensors and algorithm */
      accYangle = (atan2(accX,accZ)+PI)*RAD_TO_DEG;
      accXangle = (atan2(accY,accZ)+PI)*RAD_TO_DEG;

      double gyroXrate = (double)gyroX/131.0;
      double gyroYrate = -((double)gyroY/131.0);
      gyroXangle += kalmanX.getRate()*((double)(micros()-timer)/1000000); // Calculate gyro angle using the unbiased rate
      gyroYangle += kalmanY.getRate()*((double)(micros()-timer)/1000000);

      kalAngleX = kalmanX.getAngle(accXangle, gyroXrate, (double)(micros()-timer)/1000000); // Calculate the angle using a Kalman filter
      kalAngleY = kalmanY.getAngle(accYangle, gyroYrate, (double)(micros()-timer)/1000000);
      timer = micros();

     
    Serial.println();
        Serial.print("X:");
        Serial.print(kalAngleX,0);
        Serial.print(" ");
     
        Serial.print("Y:");
        Serial.print(kalAngleY,0);
        Serial.println(" ");
      // The accelerometer's maximum samples rate is 1kHz
    }
    void i2cWrite(uint8_t registerAddress, uint8_t data){
      Wire.beginTransmission(IMUAddress);
      Wire.write(registerAddress);
      Wire.write(data);
      Wire.endTransmission(); // Send stop
    }
    uint8_t* i2cRead(uint8_t registerAddress, uint8_t nbytes) {
      uint8_t data[nbytes];
      Wire.beginTransmission(IMUAddress);
      Wire.write(registerAddress);
      Wire.endTransmission(false); // Don't release the bus
      Wire.requestFrom(IMUAddress, nbytes); // Send a repeated start and then release the bus after reading
      for(uint8_t i = 0; i < nbytes; i++)
        data [i]= Wire.read();
      return data;
    }
     
  2. SergeiL

    SergeiL Оракул Модератор

    Так нельзя. На этапе компиляции неизвестно, сколько байт будет передано в функцию.
    Укажите вместо uint8_t data[nbytes]; что то типа uint8_t data[XX];
    где XX - это число. Вы же вызываете функцию с константой 14, вот и укажите с запасом 15.

    Этого тоже мало. У Вас нет буфера data, а есть только указатель. это тоже не правильно.
    Дальше не вникал.
     
  3. Я постараюсь это сделать. А есть код рабочий для работы с акселерометром gpy-521 определения углов(как в коде, по вертикале и по горизонтали)?
     
  4. Можете мне дать готовый рабочий код определения углов(как в коде, который я скинул, по вертикале и по горизонтали) на акселерометр gpy-521?
     
  5. DIYMan

    DIYMan Guest

  6. У меня оказывается акселерометр gy-521. Я нашёл для него код
    Код (C++):
    #include <Wire.h>

    const int MPU_addr = 0x68; // I2C address of the MPU-6050
    int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;

    // переменные для Калмана
    float varVolt = 78.9;   // среднее отклонение (ищем в excel)
    float varProcess = 0.5; // скорость реакции на изменение (подбирается вручную)
    float Pc = 0.0, G = 0.0, P = 1.0, Xp = 0.0, Zp = 0.0, Xe = 0.0;
    // переменные для Калмана

    // Функция фильтрации
    float filter(float val) {
      Pc = P + varProcess;
      G = Pc / (Pc + varVolt);
      P = (1 - G) * Pc;
      Xp = Xe;
      Zp = Xp;
      Xe = G * (val - Zp) + Xp; // "фильтрованное" значение
      return (Xe);
    }

    void setup() {
      Serial.begin(115200);
      Wire.begin();
      Wire.beginTransmission(MPU_addr);
      Wire.write(0x6B); // PWR_MGMT_1 register
      Wire.write(0);    // set to zero (wakes up the MPU-6050)
      Wire.endTransmission(true);
    }

    void loop() {
      Wire.beginTransmission(MPU_addr);
      Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
      Wire.endTransmission(false);
      Wire.requestFrom(MPU_addr, 6, true);  // request a total of 14 registers
      AcX = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
      AcY = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
      AcZ = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)

      Serial.print(AcZ); Serial.print(" "); Serial.println((int)filter(AcZ));
      delay(100);
    }
     
    Но тут только выводится ускорение. А мне нужен угол с фильтрацией. Как это написать? Код с сайта: http://ardulogic.ru/posts/podkluchenie-giroskopa-akselerometra-mpu6050-k-wemos-d1
     
  7. DIYMan

    DIYMan Guest

    AlisherRobotRex нравится это.
  8. А фильтровать значения, чтобы они не слишком прыгали, не нужно получается?
     
  9. DIYMan

    DIYMan Guest

    Зависит от ваших требований. Можно брать среднее (или медианное, на ваш выбор) от пяти измерений, например - и потом уже считать угол.