MPU6050 и двигатели

Тема в разделе "Схемотехника, компоненты, модули", создана пользователем Recoshet, 9 апр 2015.

  1. Recoshet

    Recoshet Нерд

    Подключил к дуне модуль GY-521, всё заработало. Но при подключении двигателей и подачи на них питания данные с этого датчика пропадают. Ардуино будто виснет, всё время в разных местах...

    Датчик питал и от 3.3в и от 5в.
    Пробовал отнести датчик и проводку на максимальное далёкое расстояние
    Пробовал подключить друой двигатель
    Менял питание (аккумулятор)
    Менял датчик (у меня их 2)
    Поставил диоды на питание драйвера l293d
    Менял микроконтроллер ATmega328

    Сейчас буду пробовать раздельное питание.

    В интернетах гуглил, известная проблема, но решения не нашёл...

    Update: Разделил питание, всё равно виснет...

    вот код, который использую
    Код (Text):

    #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;


    const int leftUP = 8;
    const int leftDOWN = 12;
    const int rightUP = 7;
    const int rightDOWN = 4;

    const int leftSHIM = 3;
    const int rightSHIM = 9;
    boolean obuch = false;
    int poozhNach = 180;

    void setup() {

      delay(4000);
     
      pinMode(leftUP,OUTPUT);
      pinMode(leftDOWN,OUTPUT);
      pinMode(rightUP,OUTPUT);
      pinMode(rightDOWN,OUTPUT);
     
      pinMode(rightSHIM,OUTPUT);
      pinMode(leftSHIM,OUTPUT);
     
      Serial.begin(115200);
      Wire.begin();  
      i2cWrite(0x6B,0x00); // Disable sleep mode  
      if(i2cRead(0x75,1)[0] != 0x68) { // Read "WHO_AM_I" register
        Serial.print(F("MPU-6050 with address 0x"));
        Serial.print(IMUAddress,HEX);
        Serial.println(F(" is not connected"));
        while(1);
      }      
      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 += gyroXrate*((double)(micros()-timer)/1000000); // Calculate gyro angle without any filter  
      gyroYangle += gyroYrate*((double)(micros()-timer)/1000000);
      //gyroXangle += kalmanX.getRate()*((double)(micros()-timer)/1000000); // Calculate gyro angle using the unbiased rate
      //gyroYangle += kalmanY.getRate()*((double)(micros()-timer)/1000000);
     
      compAngleX = (0.93*(compAngleX+(gyroXrate*(double)(micros()-timer)/1000000)))+(0.07*accXangle); // Calculate the angle using a Complimentary filter
      compAngleY = (0.93*(compAngleY+(gyroYrate*(double)(micros()-timer)/1000000)))+(0.07*accYangle);  
     
      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();
     
      temp = ((double)tempRaw + 12412.0) / 340.0;
     
      /* Print Data */  
      /*
      Serial.print(accX);Serial.print("\t");
      Serial.print(accY);Serial.print("\t");  
      Serial.print(accZ);Serial.print("\t");    
      */
      Serial.print(gyroX);Serial.print("\t");  
      Serial.print(gyroY); Serial.print("\t");  
      Serial.print(gyroZ);Serial.print("\t");  
     
      Serial.print(accXangle);Serial.print("\t");
      Serial.print(accYangle);Serial.print("\t");
       
      Serial.print(gyroXangle);Serial.print("\t");
      Serial.print(gyroYangle);Serial.print("e \t");
     
      if (!obuch){
        poozhNach = gyroYangle;
        obuch = true;
      }
      ravnovesie(gyroYangle);

     
      Serial.print(compAngleX);Serial.print("\t");
      Serial.print(compAngleY); Serial.print("\t");
     
      Serial.print(kalAngleX);Serial.print("\t");
      Serial.print(kalAngleY);Serial.print("\t");
     
      //Serial.print(temp);Serial.print("\t");
       
      Serial.print("\n");
     
      delay(1); // 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;
    }

    void vpered(){
      digitalWrite(leftUP, HIGH);
      digitalWrite(leftDOWN, LOW);
      digitalWrite(rightUP, HIGH);
      digitalWrite(rightDOWN, LOW);
    }

    void nazad(){
      digitalWrite(leftUP, LOW);
      digitalWrite(leftDOWN, HIGH);
      digitalWrite(rightUP, LOW);
      digitalWrite(rightDOWN, HIGH);
    }

    void ravnovesie(int polozh){
      int shim = map(abs(poozhNach-polozh),0,7, 20, 255);
     
      analogWrite(rightSHIM,shim);
      analogWrite(leftSHIM,shim);
     
      if (polozh > poozhNach)
        nazad();
      else
        vpered();
    }
     
     
    Последнее редактирование: 9 апр 2015
  2. bowman85

    bowman85 Нуб

    Абсолютно такая же ситуация, нашли решение?
     
  3. Recoshet

    Recoshet Нерд

    Отдал другу на изучение, пока тишина. Но есть идея повесить неполярные кондёры по больше на каждый двигатель и сделать экран из тонкой пластины над датчиком и привязать его к земле.
     
  4. bowman85

    bowman85 Нуб

    Выяснил, что необходимо программировать MPU так чтобы при готовности передачи данных поднималась нога INT и только после этого считывать значения - зависаний стало значительно меньше. До конца проблема не побеждена, но шаг в правильном направлении.
     
  5. Recoshet

    Recoshet Нерд

    Полностью победил зависания.
    1. Использую прерывание по готовности на ноге int
    2. Завернул сигнальные провода в оплетку от коаксиального кабеля и припаял оплетку к земельному контакту, сам гироскоп не экранировал.
     
  6. Здравствуйте, такая проблема как и у Вас, очень обрадовался, когда увидел Ваше решение, т.к. долго замарачивался с подбором резисиоров. Можете поподробнее рассказать, как прерывания реализовать, и куда подключать INT ногу?