Несколько РАЗРЫВОВ I2C с подтягивающими резисторами не работают
[ОБНОВЛЕНИЕ] Теперь он работает нормально, но как только я добавляю модуль GY-521 (аппаратное, а не программное обеспечение), он начинает отправлять мне дрянную информацию
В проекте используются:
Arduino Pro Mini в качестве мозга
FTDI как программатор
Гироскоп GY-521/ускорение
MPL3115A2 баро/высотомер
DS3231 часы реального времени
Адаптер карты Micro SD для регистрации данных
В GY-521, MPL3115A2 и DS3231 используется I2C, и они являются пробойными платами, поэтому они включают в себя подтягивающие резисторы на плате. Теперь GY-521 и MPL3115A2 отлично работают вместе, но как только я добавляю DS3231, все это освобождается. Мой код в порядке, и я в этом уверен.
Теперь моя теория заключается в том, что все эти подтягивающие резисторы вызвали какую-то проблему в цепи. Я знаю, что для обычного I2C требуются подтягивающие резисторы на 4,7 К Ом. Теперь я СЧИТАЮ, что GY-521 использует подтягивающие резисторы 4,7 К, MPL3115A2 использует подтягивающие резисторы 10 К, а DS3231 также использует подтягивающие резисторы 10 К.
Я не знаю, может ли эта настройка сработать, и я хотел бы знать, могу ли я добавить несколько внешних резисторов, чтобы немного успокоить все созвездие I2C. Обратите внимание, что я не хочу ничего добавлять к прорывам и не хочу их изменять.
Вот код:
Вкладка 1: ОСНОВНЫЕ
//==================================================
#include <SPI.h> //include the SPI library
#include <SD.h> //include the SD card library
#include <Wire.h> //include I2C library
#include "I2Cdev.h" //include another I2C library
#include "Wire.h" //include another I2C library (yes, again)
#include "MPU6050_6Axis_MotionApps20.h" //include the MPU6050 library
#include "SparkFunMPL3115A2.h" //include the MPL3115A2 library
#include <DS3231.h> //include the DS3231 library
//==================================================
#define testtest //*** COMMENT THIS LINE BEFORE UPLOADING OFFICIAL CODE TO FINAL PROJECT ***
#define chipSelect 10 //pin for the CS/SS
#define led 2 //led and/or buzzer
volatile bool mpuInterrupt = false; //just one of those bools
bool ledState = false; //state of the led and/or buzzer
bool dmpReady = false; //state of the mpu6050
int yprInt[3]; //gyro data in a integer because the extra precision of the float is total bullshit
int altitude; //altitude above takeoff point in meters
int altitudeCalibration; //calibration for the altimeter
int temperature; //temperature in degrees Celcius
float counter = 0; //time counter, a somewhat internal clock that starts when the module starts dataloging
uint8_t mpuIntStatus; //holds actual interrupt status byte from MPU
uint8_t devStatus; //return status after each device operation (0 = success, !0 = error)
uint8_t fifoBuffer[64]; //FIFO storage buffer
uint16_t packetSize; //expected DMP packet size (default is 42 bytes)
uint16_t fifoCount; //count of all bytes currently in FIFO
String day; //day of the week
String ymd; //date: year,month,day
String hms; //time: hour,minute,second
MPU6050 mpu; //MPU6050 object declaration as mpu
Quaternion q; //quaternion container
VectorFloat gravity; //gravity vector
MPL3115A2 myPressure; //MPL3115A2 object declaration as myPressure
DS3231 rtc(SDA, SCL); //DS3231 object declaration as rtc
//==================================================
void setup()
{
generalSetup();
gyroSetup();
baroSetup();
dataSetup();
}
//==================================================
void loop()
{
gyro(); //read angles
baro(); //read altitude and temperature
timeClock(); //read day, date, time
dataPrint(); //serial print the information
dataLog(); //write data in sd card
timer(); //time delay and led flash
}
Вкладка 2: НАСТРОЙКА
//==================================================
void generalSetup()
{
Serial.begin(115200); //start serial communication
Wire.begin(); //start I2C communication
rtc.begin(); //start DS3231
pinMode(led, OUTPUT); //led or buzzer; used to easily find a lost device
}
//==================================================
void dmpDataReady() {
mpuInterrupt = true;
}
void gyroSetup()
{
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
TWBR = 24;
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
//while (!Serial);
mpu.initialize();
devStatus = mpu.dmpInitialize();
mpu.setXGyroOffset(220);
mpu.setYGyroOffset(76);
mpu.setZGyroOffset(-85);
mpu.setZAccelOffset(1788);
if (devStatus == 0)
{
mpu.setDMPEnabled(true);
attachInterrupt(0, dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();
dmpReady = true;
packetSize = mpu.dmpGetFIFOPacketSize();
}
else
{
return;
}
}
//==================================================
void baroSetup()
{
myPressure.begin(); //start MPL3115A2 communication
myPressure.setModeAltimeter();
myPressure.setOversampleRate(7);
myPressure.enableEventFlags();
altitudeCalibration = myPressure.readAltitude(); //read altitude
}
//==================================================
void dataSetup()
{
if (SD.begin());
}
//==================================================
Вкладка 3: ФУНКЦИИ
//==================================================
void gyro()
{
float yprFlo[3]; //gyro data in a float
mpu.resetFIFO();
mpuInterrupt = false;
mpuIntStatus = mpu.getIntStatus();
fifoCount = mpu.getFIFOCount();
if (mpuIntStatus & 0x02)
{
while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
mpu.getFIFOBytes(fifoBuffer, packetSize);
fifoCount -= packetSize;
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
mpu.dmpGetYawPitchRoll(yprFlo, &q, &gravity);
for (int i = 0; i < 3; i++)
{
yprFlo[i] = yprFlo[i] * 180 / M_PI; //simplify the variable for serial printing and dataloging
}
for (int i = 0; i < 3; i++)
{
yprInt[i] = yprFlo[i]; //changing the variable from a float to a int
}
}
}
//==================================================
void baro()
{
altitude = myPressure.readAltitude() - altitudeCalibration; //read altitude
temperature = myPressure.readTemp(); //read temperature
}
//==================================================
void dataPrint() //serial print all the data
{
Serial.print(day);
Serial.print(" ");
Serial.print(ymd);
Serial.print(" -- ");
Serial.print(hms);
Serial.print(", ");
Serial.print(counter);
Serial.print(", ");
Serial.print(yprInt[0]);
Serial.print(", ");
Serial.print(yprInt[1]);
Serial.print(", ");
Serial.print(yprInt[2]);
Serial.print(", ");
Serial.print(altitude);
Serial.print(" ,");
Serial.print(temperature);
Serial.println();
}
//==================================================
void dataLog()//wirte all the data in a note file on the sd card
{
if (altitude > 1) //if the device is higher then 1m, then we sstart recording everything
{
File dataFile = SD.open("datalog.txt", FILE_WRITE);
if (dataFile)
{
dataFile.print(day);
dataFile.print(" ");
dataFile.print(ymd);
dataFile.print(" -- ");
dataFile.print(hms);
dataFile.print(", ");
dataFile.print(counter);
dataFile.print(", ");
dataFile.print(yprInt[0]);
dataFile.print(", ");
dataFile.print(yprInt[1]);
dataFile.print(", ");
dataFile.print(yprInt[2]);
dataFile.print(", ");
dataFile.print(altitude);
dataFile.print(" ,");
dataFile.print(temperature);
dataFile.println();
dataFile.close();
}
}
}
//==================================================
void timeClock()
{
day = rtc.getDOWStr();
ymd = rtc.getDateStr();
hms = rtc.getTimeStr();
}
//==================================================
void timer()
{
counter = counter + 0.5;
#ifndef testtest
ledState = !ledState;
digitalWrite(led, ledState);
#endif
delay(500);
}
//==================================================
@Dat Ha, 👍0
Обсуждение3 ответа
Лучший ответ:
На самом деле MPU-6050 на GY521 и DS3231 оба используют адрес I2C 0x68. Если бы вы посмотрели на источник заголовочных файлов, которые вы включили для каждого, это было бы очевидно.
Сверившись с паспортом данных для каждого чипа, вы, скорее всего, найдете способ либо изменить адрес I2C, изменив контакт конфигурации, либо потенциально включить/отключить чип, изменив его с помощью GPIO. Однако это, вероятно, потребует хирургической модификации несущей платы.
Вы также можете переместить любое устройство, к которому вы ожидаете получить доступ, по меньшей мере, на отдельную "мягкую" шину I2C, битую на других выводах GPIO. Никакого одобрения не подразумевается, но первая такая библиотека, которая появилась в веб-поиске, была:
http://playground.arduino.cc/Main/SoftwareI2CLibrary
вероятно, вы можете найти для себя другие варианты или потенциально можете создать свой собственный.
В семействе MPU-6050 также есть другие чипы, которые говорят на SPI вместо или так же, как на I2C, однако они, как правило, дороже.
По моим расчетам, общее подтягивание составляет:
1 / (1/10 + 1/10 + 1/4.7) = 2.423 k
Как я показываю на своей странице о I2C, подтягивающий резистор 2,2 К дает достаточно хороший сигнал:
Таким образом, я не думаю, что проблема в резисторах. И я не вижу, как добавление большего количества "немного успокоит все созвездие I2C".
Хорошо, мне придется проверить это еще раз. Спасибо!, @Dat Ha
Я думаю, что есть столкновение между DS3231 и GY-521. Если я удалю любой из них, код будет нормально работать с MPL3115A2. Но если они будут выполняться вместе, с MPL3115A2 или без него, программа не будет иметь предсказанного конечного результата. Если вы хотите, я мог бы включить код в редактирование моего вопроса., @Dat Ha
Было бы полезно добавить код к вашему вопросу., @Nick Gammon
Код был добавлен!, @Dat Ha
GY-521 имеет 2k2 или 10k подтягиваний в зависимости от игровой площадки Arduino. http://playground.arduino.cc/Main/MPU-6050, @Mikael Patel
Когда параллельно добавляются дополнительные резисторы, что происходит при добавлении новых устройств I2C на шину I2C, общий резистор снижается. Это может вызвать проблему с устройствами, которые не могут обеспечить достаточный ток при низком сопротивлении подтягиванию. Следовательно, устройство не будет хорошо функционировать, когда сопротивление подтягивания ниже определенного значения. Чтобы устранить проблему, я рекомендую удалить все параллельные подтягивающие резисторы и просто держать по одному на каждой линии, чтобы получить хорошее значение резистора примерно 4,7 К-Ом.
- Несколько датчиков I2C с одинаковым адресом
- Чтение датчика давления от 4 до 20 мА с использованием uno
- Проблемы с подключением I2C на ESP8266 — 12F, какие контакты использовать?
- Wire.endTransmission() зависает
- Пайка несовмещенных выводов Arduino Pro Mini
- Лазерный датчик ToF (VL53L0X) не работает
- MAX30100 не работает
- Минимальное значение I2C-подтягивающий резистор для arduino
Если проблема является общей, вызванной съемными резисторами, подключение одной из плат *без* попыток поговорить с ней все равно вызовет проблемы при общении с другими. Вы также можете проверить теорию подтягивания, добавив несколько дополнительных параллельно - если она все еще работает с одной из плат, замененных другим набором резисторов 2,2 К, это, вероятно, не проблема с резисторами. Проблема с адресом не повлияет на другие устройства с уникальными адресами. Строго говоря, разные платы могут иметь разную восприимчивость к чрезмерно жесткому подтягиванию шины от нескольких параллельных резисторов., @Chris Stratton
В вашей функции ISR "dmpDataReady" вы устанавливаете "mpuInterrupt = true;" - эта переменная должна быть объявлена " изменчивой`., @Nick Gammon
`как только я добавлю DS3231, все это исчезнет " - можете ли вы кое-что уточнить? Вы добавляете оборудование, и оно зависает, или вы *изменяете код*, а также добавляете оборудование?, @Nick Gammon
Программное обеспечение не меняется. Я еще не тестировал volatile, но я знаю, что в примере скетча они использовали volatile для этого. В этом может быть проблема. Когда я добавляю DS3231 в смысле аппаратного обеспечения. Программа запускает MPL3115A2 + GY-521 = НОРМАЛЬНО. MPL3115A2 + DS3231 = ОТЛИЧНО. GY-521 + DS3231 = ПРОБЛЕМА. Речь идет об оборудовании., @Dat Ha
Вы не можете правильно выполнить тесты, которые, как вы утверждаете, есть, не изменив программное обеспечение - оставив программное обеспечение, которое пытается разговаривать с чипом, которого там нет, *вызовет проблемы, как минимум замедление, если будет реализован тайм-аут, но неясно, что есть, и в этом случае программа может зависнуть., @Chris Stratton