Wire.endTransmission(false) зависание программы после однократного запуска при использовании MPU6050
Для этого проекта я использовал Elegoo Car V3 и пытался добавить к нему гироскоп. Когда я запускаю код для автомобиля, мой код цикла повторяется один раз, и он всегда может считывать данные датчика. Но после этого программа начинает зависать. Я проследил проблему до строки Wire.endTransmission(false)
в моем коде. По какой-то причине эта строка не была завершена во второй раз.
Я потратил несколько часов, пытаясь найти решение в Интернете. Я трижды проверил свою проводку и все равно не смог найти решения этой проблемы.
Спасибо, что нашли время помочь мне!
Это результат работы программы
RawX= 82
RawY= 241
RawZ= -1
-----------------------------------------
AngleX= 195.41
AngleY= 216.93
AngleZ= 200.14
-----------------------------------------
И это код
#include <Wire.h>
const int MPU_addr = 0x68;
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;
int minVal = 265;
int maxVal = 402;
double x;
double y;
double z;
int c = 0;
//www.elegoo.com
// Right motor truth table
//Here are some handy tables to show the various modes of operation.
// ENB IN3 IN4 Description
// LOW Not Applicable Not Applicable Motor is off
// HIGH LOW LOW Motor is stopped (brakes)
// HIGH LOW HIGH Motor is on and turning forwards
// HIGH HIGH LOW Motor is on and turning backwards
// HIGH HIGH HIGH Motor is stopped (brakes)
// define IO pin
#define ENA 5
#define ENB 6
#define IN1 7
#define IN2 8
#define IN3 9
#define IN4 11
//set car speed
#define CAR_SPEED 100
typedef unsigned char u8; //Change the name of unsigned char to u8
void forward(u8 car_speed)
{
analogWrite(ENA, car_speed);
analogWrite(ENB, car_speed);
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
}
void back(u8 car_speed)
{
analogWrite(ENA, car_speed);
analogWrite(ENB, car_speed);
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
}
void left(u8 car_speed)
{
analogWrite(ENA, 250);
analogWrite(ENB, 250);
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
digitalWrite(IN3, LOW);
digitalWrite(IN4, HIGH);
}
void right(u8 car_speed)
{
analogWrite(ENA, 250);
analogWrite(ENB, 250);
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
digitalWrite(IN3, HIGH);
digitalWrite(IN4, LOW);
}
void stop()
{
digitalWrite(ENA, LOW);
digitalWrite(ENB, LOW);
}
int getGyroData() {
Wire.beginTransmission(MPU_addr);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(MPU_addr,6,true);
AcX = Wire.read()<<8|Wire.read();
AcY = Wire.read()<<8|Wire.read();
AcZ = Wire.read()<<8|Wire.read();
int xAng = map(AcX, minVal, maxVal,-90, 90);
int yAng = map(AcY, minVal, maxVal,-90, 90);
int zAng = map(AcZ, 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);
Serial.println("-----------------------------------------");
}
void turn(int degrees) {
int *originalData;
originalData = getGyroData();
int originalTurn = originalData[2];
bool notDone = true;
while (notDone) {
int *newVal;
newVal = getGyroData();
int newTurn = newVal[2];
int change = originalTurn - newTurn;
Serial.println(change);
}
}
void setup(){
Wire.begin();
Wire.beginTransmission(MPU_addr);
Wire.write(0x6B);
Wire.write(0);
Wire.endTransmission(true);
pinMode(IN1, OUTPUT);//before useing io pin, pin mode must be set first
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
pinMode(ENA, OUTPUT);
pinMode(ENB, OUTPUT);
Serial.begin(9600);
}
void loop(){
c++;
Serial.println(c);
Wire.beginTransmission(MPU_addr);
Serial.println(c);
Wire.write(0x43);
Serial.println(c);
Wire.endTransmission(false);
Serial.println(c);
Wire.requestFrom(MPU_addr,4,true);
AcX = Wire.read()<<8|Wire.read();
AcY = Wire.read()<<8|Wire.read();
AcZ = Wire.read()<<8|Wire.read();
Serial.println(c);
Serial.print("RawX= ");
Serial.println(AcX);
Serial.print("RawY= ");
Serial.println(AcY);
Serial.print("RawZ= ");
Serial.println(AcZ);
Serial.println("-----------------------------------------");
int xAng = map(AcX, minVal, maxVal,-90, 90);
int yAng = map(AcY, minVal, maxVal,-90, 90);
int zAng = map(AcZ, 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);
Serial.println("-----------------------------------------");
delay(500);
}
Это схема машины, которую я нашел
@Akash Dubey, 👍2
1 ответ
Лучший ответ:
В комментариях ниже @chrisl делает что-то явное, чего я не делал в предыдущих правках. Прочтение его первым может облегчить интерпретацию нижеследующего:
Полезный факт о I2C на Arduino:
Wire.endTransmission()
- это функция, которая фактически выполняет связь I2C. До этого (всевызовы Wire.beginTransmission()
иWire.write()
) никакие данные не будут проходить по шине, просто помещенные в буфер библиотек. Таким образом, повешениеWire.endTransmission()
равен заблокированной шине I2C.
На UNO A4 и A5 - это SDA и SCL, те же сигналы, которые доступны рядом с AREF и контактом 13 на другой стороне платы.
Итак, к ультразвуковому дальномер на картинке прилагаются сигналы, которые необходимы для работы шины I2C ("Wire"), и могут легко мешать Wire.endTransmission (false)
. Один из сигналов I2C, вероятно, вызывает срабатывание пальца диапазона во время трафика I2C. После каждого триггера эхо-сигнал от дальномера будет мешать подключенному сигналу шины I2C.
Вы можете попробовать бит-бит I2C, используя библиотеку вместо родного I2C, который находится на A4 / A5, и использовать его для управления гироскопом. Согласно вашей диаграмме, A0-A3 не используются и, по-видимому, являются единственными сигналами, не используемыми UNO. Несмотря на то, что они являются "аналоговыми" штифтами, они также функционируют как цифровые штифты и должны отлично работать для бит-битинга. Однако добраться до них может быть непросто, так как щит, похоже, не делает их снова доступными в виде булавок.
Или же вы можете направить ультразвуковой датчик подальше от A4 / A5, либо не подключая его к коллектору на экране, а вместо этого направляя сигналы от штекера туда, где имеется неиспользуемый набор контактов (опять же A0, хотя A3), а затем соответствующим образом обновляя код. Другая возможность может заключаться в том, чтобы оставить его подключенным к щиту, но согнуть штифты A4 и A5 в сторону, чтобы они не входили в UNO ниже, и использовать перемычки, чтобы направить их от согнутых штифтов к какой-нибудь другой паре доступных штифтов; вы не сможете сгибать их взад и вперед больше, чем раз или два, так что я буду осторожен с этой попыткой.
- Линейное ускорение от MPU 6050
- Снять гравитацию с акселерометра MPU-6050
- Помощь с MPU-6050
- Использование MPU-6050 без I2C
- Почему значение регистра чтения и записи гироскопа MPU6050 равно 0x08 для полной шкалы 500 градусов в секунду?
- Показания гироскопа MPU6050 слишком дрейфуют только при быстрых изменениях
- ESP8266 не работает с MPU 6050 по проводной библиотеке и I2C
- Изменение скорости передачи данных не работает
Полезный факт о I2C на Arduino: "Wire.endTransmission()" - это функция, которая фактически выполняет связь I2C. До этого (все вызовы
Wire.beginTransmission()
иWire.write()
) никакие данные не будут проходить по шине, просто помещенные в буфер библиотек. Таким образом, висящий "Wire.endTransmission()" равен заблокированной шине I2C., @chrislДа, наверное, мне следовало бы сказать об этом прямо. Позже я отредактирую его, чтобы включить ваш комментарий., @timemage
@timemage Это сработало как заклинание! Удаление ультразвукового датчика позволило гироскопу функционировать. Спасибо, что ответили так быстро! Я просто хотел спросить вас, почему контакты A4 и A5 используются для контактов связи SDA и SCL. Могу ли я использовать какие-либо другие аналоговые контакты для гироскопа?, @Akash Dubey
Я могу попытаться обновить ответ, чтобы он был более четким. Контакт на AVR может иметь специальные функции, помимо простого входа GPIO (с возможностью digitalRead / digitalWrite) или подключения к аналого-цифровому преобразователю (с возможностью analogRead). I2C / TWI "Провод" - это специальная функция, найденная только на контактах A4 и A5 UNO. Для сравнения, ультразвуковой датчик использует только общие функции GPIO, которые можно использовать практически на любом выводе. Поэтому имеет смысл поставить гироскоп на A4 / A5 и переместить ультразвуковой датчик на A0-A3, когда это возможно., @timemage
Использование I2C / Wire без помощи встроенной поддержки чипа для I2C ** - это то, что по сути означает "битный стук"., @timemage
Чтобы уточнить, тот факт, что собственный функционал I2C / Wire существует на тех же контактах, что и некоторые функции аналогового входа, зависит от того, как был построен чип ATmega328P, а не от выбора дизайна для Arduino UNO., @timemage