Интерференция I2C устройств

В настоящее время я пытаюсь подключить 3 устройства I2C к Arduino Mega, как описано в скетче fritzing. Это датчики: Датчик Max86150 PPG на пробивной плате (5 В), ИК-датчик температуры MLX90614 (3,3 В) и Датчик давления SM9336(3,3 В). По сути, я могу подключить все устройства и считывать датчики с помощью отдельных скетчей, но когда я объединяю скетчи, значения не совпадают, а затем скетч выходит из строя всего через несколько секунд.

Как ни странно, когда я объединяю скетч либо с датчиком температуры и датчиком давления, либо с датчиком температуры и датчиком PPG, он будет работать. Но Давление и PPG не работают вместе.

Кто-нибудь знает, что могло случиться? У меня он работал некоторое время с некоторыми другими проводами, может ли это иметь какое-то отношение к этому? Но даже при этом некоторые результаты, которые я считывал с датчика, были значениями ошибок (например, значение, которое вы получаете, когда ничего не подключено, но это не сбой). Для справки я использую провода 30 AWG и полосовую плату вместо макета во фриттинге. Fritzing Sketch

//PPG
#include "max86150.h"
MAX86150 max86150Sensor;
uint16_t ppgunsigned16;
uint16_t irdata;


// Pressure Sensor
#include <Wire.h>

#define PressureSensor_Data 0x30 // Pressure Register address
#define TemperatureSensor_Data 0x2E // Pressure Temp Sensor Address  


int P0,T0,P1,T1;
int SMD993Address = 0x6C; // Device Address 

//Timing 
#define INTERVAL 10 //10 milliseconds per sample for 100 Hz, change this for different sampling rates.
uint32_t lastMicros = 0;

// Temp
#include <Adafruit_MLX90614.h>
Adafruit_MLX90614 mlx = Adafruit_MLX90614();



void ppgsetup()
{
  max86150Sensor.setup();
}

void PPG() {
   
while (1){
 if(max86150Sensor.check()>0)
    {
        ppgunsigned16 = (uint16_t) (max86150Sensor.getFIFORed()>>2);

        Serial.println(ppgunsigned16);
  //ppgunsigned16 = (uint16_t) (max86150Sensor.getFIFORed()>>2);
  //Serial.println(ppgunsigned16);

  if (ppgunsigned16 > 7000){ 
  

     for (int z = 0; z <= 500; z++){//This takes a reading every 10 milliseconds for 5000 milli seconds which is 5 seconds, 500 readings 
       digitalWrite(ledPin,HIGH);//turning LED on
        //if (micros() - lastMicros > INTERVAL) { //This takes a reading every 100th of a second
            //lastMicros = micros(); // do this first or your interval is too long!
            
            if(max86150Sensor.check()>0)
    {
        ppgunsigned16 = (uint16_t) (max86150Sensor.getFIFORed()>>2);
        irdata = (uint16_t) (max86150Sensor.getFIFOIR()>>2);
            
        Serial.print(ppgunsigned16);
        Serial.print(",");       
        Serial.println(irdata);
            //Serial.print("Check PPG");Serial.println(y);
            //mySerial.write(84);mySerial.print(ppgunsigned16);mySerial.print("/");
            //mySerial.write(83);mySerial.print(irdata);mySerial.print("/");
    }
    } 
    digitalWrite(ledPin,LOW);//turning LED off
    break;
    
}
}
}
}




void spirometry() {
    

    for (int x = 0; x <= 500; x++){
    Wire.beginTransmission(SMD993Address);
    Wire.write(PressureSensor_Data);
    Wire.write(TemperatureSensor_Data);
    Wire.endTransmission();
    Wire.requestFrom(SMD993Address,2);//This takes a reading every 100 milliseconds for 10000 milli seconds which is 10 seconds
 
    //if (micros() - lastMicros > INTERVAL) { //This takes a reading every 1000th of a second
      //lastMicros = micros(); // do this first or your interval is too long!

    if(Wire.available()<= 2) { 
    P0 = Wire.read();
    P1 = Wire.read();
      }
  
    int Ptotal = P0 + (P1<<8); //The high byte is transmitted second so that 
    
    Serial.println(Ptotal); // Print Ptotal to the serial monitor
    //mySerial.write(81);mySerial.print(Ptotal);mySerial.print("/");// Send PTotal over BLE with flag 81, this will change as sending via bytes is more efficient
    
    }
    
    
  }


void temperature() {
  for (int y = 0; y <= 10; y++){
      mlx.begin();
      Serial.println(mlx.readObjectTempC());  
      mySerial.write(82);mySerial.print(mlx.readObjectTempC());mySerial.print("/");
      delay(10);
}
}

void setup() {
  
  
  // BT
  mySerial.begin(9600);
  Serial.begin(9600);//Sets BT Serial Comms to 115200, ensure that BT is allowing for this 
  //LED
  pinMode(ledPin, OUTPUT);
  // PPG
    // Initialize sensor
    if (max86150Sensor.begin(Wire, I2C_SPEED_FAST) == false)
    {
        Serial.println("MAX86150 was not found. Please check wiring/power. ");
        while (1);
    }
    Serial.println(max86150Sensor.readPartID());
    ppgsetup();

    
  //Pressure Sensor

  //Temp 
  

  //Sleep 
  sleep();
  

}

void loop()
{
  // put your main code here, to run repeatedly
  
   PPG();
   delay(10000);
   spirometry();
   delay(1000);
   temperature();

  
   
}

, 👍1

Обсуждение

Вы пробовали добавлять подтягивающие резисторы к линиям? По мере того как вы подключаете к шине все больше устройств, емкость увеличивается. Подтягивания (возможно, 4,7 Ком, которые я в основном использую для I2C) могут помочь в этом. И еще: Какой длины ваши провода? I2C предназначен для довольно коротких соединений в однозначной области cm. Длинные провода могут сделать его ненадежным., @chrisl

Возможно, не стоит полностью спамить шину своими сообщениями (например, вы очень быстро снимаете показания в " спирометрии ()`). Пожалуйста, попробуйте ввести небольшую задержку или что-то подобное там. И почему вы вызываете "mlx.begin ()" 11 раз для чтения температуры? Не будет ли достаточно одного начала в настройке?, @chrisl

@chrisl Я запускал устройства I2C по кабелю 10 м, только с случайными ошибками чтения, так что это вряд ли проблема здесь. Являются ли адреса устройств уникальными?, @PMF

@chrisl AFAIK есть внутренние резисторы pullup в Arduino, но я дам им попробовать и посмотреть, работает ли он лучше. Кабели, вероятно, 10 см максимум, большинство из них будет в одном диапазоне см. Я пробовал играть с задержками, но это, кажется, ничего не меняет, я пытаюсь достичь частоты дискретизации 100 Гц, которая, как я прочитал, должна быть достижима на Arduino Mega. Mlx.begin() находится в неправильном месте, хорошее место, которое я перемещу., @Tee Gallagher

@PMF Да, все адреса уникальны, какой калибр провода вы используете для 10 м?, @Tee Gallagher

@TeeGallagher Это был кабель для передачи данных 8x 0.25mm2. Я использовал 2 провода для заземления, 1x 5V, 1x 3.3 V, 2x для I2C. Пульт имеет 4x20LCD, датчик температуры, расширитель GPIO с несколькими кнопками и светодиодами. Основная проблема на самом деле заключается в том, что 3,3 В не очень стабильны на дальней стороне., @PMF

Вы запускаете провод в высокоскоростном режиме для ppg. Вы не установили это обратно, когда выполняли доступ к проводу для давления. Может ли датчик давления работать в высокоскоростном режиме? Ваш код тихонько нечитаем для меня, так что, возможно, я что-то подслушал., @Peter Paul Kiefer

@PeterPaulKiefer Похоже, это могло бы сработать, мне пришлось заменить провод, потому что он сломался, но это, похоже, решило проблему. Так здорово, спасибо, я вытащил эту строку кода из примера и подумал, что она принадлежит библиотеке. Так мне и надо., @Tee Gallagher


2 ответа


2

Некоторое время назад у меня была похожая проблема, когда я подключил к Raspberry Pi 2 платы сервопривода и батарейную шляпу (которая использовала I2C для считывания уровней мощности). Батарейная плата работала одна, и сервоплата работала одна, но когда присутствовали все три, батарейная плата перестала работать. И все они имели уникальные адреса. После нескольких часов безумия я понял, что на ПИ есть подтягивающие резисторы и все три платы подключены. Общее сопротивление всех 4 параллельных подтягивающих резисторов не соответствовало спецификации для I2C. Я снял резисторы с сервоплат, и все начало работать вместе. Так что, может быть, вы могли бы отключить подтягивания на всех баордах, кроме Ардуино, и посмотреть, есть ли в этом проблема.

,

Спасибо за ответ, похоже, что я неосознанно установил интерфейс провода I2C на высокую скорость и что это было по существу сбой датчика давления и скетча, насколько я могу судить в любом случае., @Tee Gallagher

@TeeGallagher, я проголосовал за это, потому что это был хороший ответ в любом случае. Если у вас есть некоторая уверенность в том, что ваша высокая скорость была проблемой, вы должны сделать отдельный ответ и позже принять его., @timemage


2

Как указал @peterpaulkeifer; Здесь

// Инициализация датчика
    if (max86150Sensor.begin(Wire, I2C_SPEED_FAST) == false)
    {
        Serial.println("MAX86150 не найден. Пожалуйста, проверьте проводку/питание".);
        while (1);
    }

Я устанавливал скорость I2C интерфейсной шины I2C на быструю, и мне показалось, что датчик давления не смог справиться с этим и поэтому давал ответы об ошибках, а затем выходил из строя.

,