Подключил к дуне модуль 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(); }
Отдал другу на изучение, пока тишина. Но есть идея повесить неполярные кондёры по больше на каждый двигатель и сделать экран из тонкой пластины над датчиком и привязать его к земле.
Выяснил, что необходимо программировать MPU так чтобы при готовности передачи данных поднималась нога INT и только после этого считывать значения - зависаний стало значительно меньше. До конца проблема не побеждена, но шаг в правильном направлении.
Полностью победил зависания. 1. Использую прерывание по готовности на ноге int 2. Завернул сигнальные провода в оплетку от коаксиального кабеля и припаял оплетку к земельному контакту, сам гироскоп не экранировал.
Здравствуйте, такая проблема как и у Вас, очень обрадовался, когда увидел Ваше решение, т.к. долго замарачивался с подбором резисиоров. Можете поподробнее рассказать, как прерывания реализовать, и куда подключать INT ногу?