Ардуино зависает. Помехи?

Тема в разделе "Схемотехника, компоненты, модули", создана пользователем orehov_alex, 29 май 2019.

  1. znamen

    znamen Guest

    Значит мы на правильном пути. Теперь будем сужать проблему. 100% определились,что источник помех
    двигатель. Далее идём по двум путям. 1. Можно попробовать поставить сетевой фильтр на запитку
    220 вольт где записывается ваш мотор. Это такая штучка -набор розеток и в этой же коробке стоят ёмкости
    и индуктивности. В электротоварах продаётся. И второе ,что меня интересует- это,как запитан гироскоп?
    Я имею ввиду следующий момент. Гироскоп стоит на крутилке. Крутилка питается от 220. Вопрос от чего
    запитан гироскоп? От того же питания,что и плата ардуино ?
     
  2. orehov_alex

    orehov_alex Нерд

    Свой уровень я обозначил в конце первого сообщения. Спасибо за ссылки, ознакомлюсь.

    Об этом я не думал. Проверю в следующий раз как доберусь до макета.

    От ноутбука через USB.
    Скетчи я выложил в сообщении 25. Дублирую:
    Код (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();
      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("\t");
     
      //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;
    }
    Второй:
    Код (C++):
    /*
        Kalman Filter Example for MPU6050. Output for processing.
        Read more: http://www.jarzebski.pl/arduino/rozwiazania-i-algorytmy/odczyty-pitch-roll-oraz-filtr-kalmana.html
        GIT: https://github.com/jarzebski/Arduino-KalmanFilter
        Web: http://www.jarzebski.pl
        (c) 2014 by Korneliusz Jarzebski
    */



    #include <Wire.h>
    #include <MPU6050.h>
    #include <KalmanFilter.h>

    MPU6050 mpu;

    KalmanFilter kalmanX(0.001, 0.003, 0.03);
    KalmanFilter kalmanY(0.001, 0.003, 0.03);

    float accPitch = 0;
    float accRoll = 0;

    float kalPitch = 0;
    float kalRoll = 0;

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

      // Initialize MPU6050
      while(!mpu.begin(MPU6050_SCALE_2000DPS, MPU6050_RANGE_2G))
      {
        delay(500);
      }
      // Calibrate gyroscope. The calibration must be at rest.
      // If you don't want calibrate, comment this line.
      mpu.calibrateGyro();
    }

    void loop()
    {
      Vector acc = mpu.readNormalizeAccel();
      Vector gyr = mpu.readNormalizeGyro();

      // Calculate Pitch & Roll from accelerometer (deg)
      accPitch = -(atan2(acc.XAxis, sqrt(acc.YAxis*acc.YAxis + acc.ZAxis*acc.ZAxis))*180.0)/M_PI;
      accRoll  = (atan2(acc.YAxis, acc.ZAxis)*180.0)/M_PI;

      // Kalman filter
      kalPitch = kalmanY.update(accPitch, gyr.YAxis);
      kalRoll = kalmanX.update(accRoll, gyr.XAxis);

      Serial.print(accPitch);
      Serial.print(":");
      Serial.print(accRoll);
      Serial.print(":");
      Serial.print(kalPitch);
      Serial.print(":");
      Serial.print(kalRoll);
      Serial.print(":");
      Serial.print(acc.XAxis);
      Serial.print(":");
      Serial.print(acc.YAxis);
      Serial.print(":");
      Serial.print(acc.ZAxis);
      Serial.print(":");
      Serial.print(gyr.XAxis);
      Serial.print(":");
      Serial.print(gyr.YAxis);
      Serial.print(":");
      Serial.print(gyr.ZAxis);

      Serial.println();
    }

     
    Сбоит на обоих, если что.
     
    Последнее редактирование: 1 июн 2019
  3. znamen

    znamen Guest

    Давайте ещё убедимся в том,что это влияние сетевых помех от двигателя. Выключить ноутбук из сети. Пусть
    он будет записан только от внутреннего аккумулятора. И проверьте ситуацию.
     
    Daniil нравится это.
  4. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Аааа. Это я пропустил. Не пробовали уменьшить скорость обмена ?
    Например Serial.begin(57600) или там Serial.begin(9600)
    Однако вы писали, что на УСБ3 намного меньше сбоит. Значит дело не в движке.
     
  5. orehov_alex

    orehov_alex Нерд

    Проверял сегодня, на сбои не влияет.
    Да, менял. По умолчанию 115200. Ставил и 9600 и 230400 и 500000. Не влияет, сбои также происходят.
     
  6. znamen

    znamen Guest

    А как Вы тогда объясните,что при ручном передвижении крутилки -все в порядке. Кстати ,я тоже обратил
    внимание ,что с юсв3 работает нормально. Значит это юсб более помехи устойчивый,я так думаю.
     
  7. znamen

    znamen Guest

    Т.е Вы хотите сказать,что при работе от внутреннего аккумулятора ноутбука, сбои продолжаются? Без подключения его к сети.
     
  8. orehov_alex

    orehov_alex Нерд

  9. znamen

    znamen Guest

    Я не совсем понимаю осцилограммы в посте 27. Какая там амплитуда сигнала? Там какие то условные
    единицы по оси игрек. Сколько там вольт на клетку? И куда Вы дотрагивались щупом осциллографа?
     
  10. orehov_alex

    orehov_alex Нерд

    Это скриншот из плоттера по последовательному соединению, из самой программы Arduino IDE. По У указывается угловая скорость. Но так как в данном случае я работал с нефильтрованными данными от гироскопа, то вместо град/сек указываются сырые данные (поправьте, если неправильно выразился). Если включу Калмана, то по У будет угловая скорость в град/сек.
    Вывожу нефильтрованные данные потому, что датчик становится более чувствительным и легче отслеживать моменты, когда происходят сбои.
     
  11. orehov_alex

    orehov_alex Нерд

    Про осциллограф я вообще ничего не упоминал, я им не пользуюсь.
     
  12. znamen

    znamen Guest

    Понял. Спасибо. И ещё я понял,что либо я чего то не допонимаю ,либо Вы чего то не договариваете. Объясняю почему у меня сложилось такое впечатление. Мы убедились в том,что помехи даёт двигатель.
    Помехи от двигателя могут быть только сетевыми. Выключая сетевое питание на ноутбуке мы полностью
    изолируется от сети. Не от радио помех же глючит ардуино?
     
  13. Daniil

    Daniil Гуру

    Спасибо, за терпение в ответах!
    Я увидел ваш код.
    Гипотеза.
    Не может ли первый импульс от вращения создавать дребезг контактов между ардуино и модулем?
    Если это так, то это может исказить передаваемые данные - исказить протокол - ошибка - плохо отрабатывается ошибка - зависание.
    Вставьте, пожалуйста, в начало процедуры i2cRead
    Serial.print(1);
    а в конце этой же процедуры
    Serial.print(0); Serial.print("\t");
    Если увидим, что зависает и нет пары "10", значит зависает i2c.

    С другой стороны непонятно почему юсб2 не держит, а юсб3 справляется.
    Может, из-за дребезга где-нибудь кз появляется и юсби3 справляется с нагрузкой, а 2ой нет.

    С розеткой, согласен, стоит проверить.
     
  14. orehov_alex

    orehov_alex Нерд

    Я правда не имею представления какого рода помехи может выдавать эта пятидесятилетняя установка. На буднях доберусь до макета и перепроверю работу с БП и без него еще раз. И заодно сетевой фильтр поставлю.

    Так?
    Код (C++):
    void loop() {
      /* Update all the values */
      Serial.print(1);
      uint8_t* data = i2cRead(0x3B,14);
      Serial.print(0); Serial.print("\t");
      accX = ((data[0] << 8) | data[1]);
     
  15. parovoZZ

    parovoZZ Гуру

    В пространство излучается исключительно радиосигнал. Причём мы видим металлический корпус, а это значит, что у помехи преобладает магнитная составляющая. Как от неё избавится - уже говорил. К тому же на USB кабеле висит ферримагнитное колечко - прекрасная магнитная антенна.
     
  16. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Запустил в Протеусе ваш скетч и скетч из https://voltiq.ru/mpu-9250-and-arduino/
    Виртуального гироскопа в симуляторе нет.
    Ваш скетч выдает что гироскопа нет и больше к плате не обращается совсем.
    Скетч из статьи постоянно опрашивает плату гироскопа.
     
    Последнее редактирование: 1 июн 2019
  17. znamen

    znamen Guest

    Спорить не буду,но на юсб кабелях таких колечек не видил. На кабелях импульсных блоков питания. видил
     
  18. Daniil

    Daniil Гуру

    можно и так)
     
  19. orehov_alex

    orehov_alex Нерд

    Понял, проверю скетч из этой статьи.
    Я правильно понял, что после добавления этих строчек в код при запуске монитора порта перед данными от гироскопа я должен видеть там 1 и 0?
     
  20. parovoZZ

    parovoZZ Гуру