Проблема с кодом для мультиплексора SDA/SCL TC9548A и датчиков HMC58 83L.

Я впервые пишу на этом форуме, поэтому надеюсь, что мой вопрос здесь уместен. Моя команда работает с коммутационной платой мультиплексора I2C Adafruit TCA9548A 1-8, чтобы попытаться прочитать информацию с шести датчиков коммутации HMC5883L, а я пытаюсь изучить их код, чтобы решить проблему. По какой-то причине код вообще не запускается, если вы не закомментируете определенную строку кода. Как только он закомментирован, код работает как положено.

Теперь нам нужно инициализировать его в setup(), но оператор tcaselect(0) был закомментирован, поэтому он не инициализирует 0-й датчик в setup(). Мы можем оставить другую часть, оператор if(mag0.begin()), и он будет работать как положено. Однако, если мы раскомментируем tcaselect(0) в настройке, весь код выйдет из строя, и все, что мы увидим, это «HM» в окне дисплея. Очень простая схема показана ниже:

schematic

Я провел несколько тестов со своей командой, и когда все шесть HMC5883L и один мультиплексор TCA9548 были подключены к одной макетной плате в соответствии со схемой, они работали, когда tcaselect(0) в setup() не был закомментирован. Далее у нас было устройство для хранения шести датчиков, и мы соединили его длинными проводами, как показано на схеме. Мы подключили его к тому же макету, и код не запустился, если tcaselect(0) в настройке не был закомментирован. Мне кажется странным, что они будут работать при подключении на макетной плате, но при разнесении и подключении к макетной плате длинными проводами они не будут работать, если этот код не будет закомментирован.

https://learn.adafruit.com/adafruit -tca9548a-1-to-8-i2c-multiplexer-breakout?view=all

https://learn.adafruit.com/adafruit-hmc5883l -breakout-triple-axis-магнитометр-компас-датчик/обзор

РЕДАКТИРОВАТЬ: Кто-то упомянул, что у проводов могут быть проблемы с шиной SDA/SCL, поэтому мы используем 4-контактные ленточные кабели с шагом 2,54 мм. Очень приблизительная схема контейнера, который мы используем, показана ниже:

schematic

Извините за грубость. Это лучшее, что я могу сделать, чтобы показать, как собирается контейнер. Компоненты хранятся в коробке размером 8х8 дюймов, поэтому датчики перемещаются из разных мест устройства в центральную коробку, где размещаются Pi, Arduino и макет. Узлы на схеме обозначают расположение датчиков. Учитывая приблизительные размеры, наибольшее расстояние для одного из датчиков составляет около 56,8 дюйма (или примерно 1,45 метра), что требует дополнительной проводки.

Код:

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_HMC5883_U.h>

#define TCAADDR 0x70

/* Assign a unique ID to this sensor at the same time */
Adafruit_HMC5883_Unified mag0 = Adafruit_HMC5883_Unified(0);
Adafruit_HMC5883_Unified mag1 = Adafruit_HMC5883_Unified(1);
Adafruit_HMC5883_Unified mag2 = Adafruit_HMC5883_Unified(2);
Adafruit_HMC5883_Unified mag3 = Adafruit_HMC5883_Unified(3);
Adafruit_HMC5883_Unified mag4 = Adafruit_HMC5883_Unified(4);
Adafruit_HMC5883_Unified mag5 = Adafruit_HMC5883_Unified(5);

//Показать здесь подробную информацию о датчике
void displaySensorDetails(Adafruit_HMC5883_Unified *mag){
  sensor_t sensor;
  mag->getSensor(&sensor);
  Serial.println("------------------------------------");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value);         Serial.println(" uT");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println(" uT");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println(" uT");  
  Serial.println("------------------------------------");
  Serial.println("");
  delay(500);
}

//При наличии датчика i выбираем и записываем в него
void tcaselect(uint8_t i) {
  if (i > 7) return; 
  Wire.beginTransmission(TCAADDR);
  Wire.write(1 << i);
  Wire.endTransmission();  
}

    void setup() {
  Serial.begin(9600);
  /* Initialise the 0st sensor */
   //tcaselect(0);
   if(!mag0.begin())  {
    /* There was a problem detecting the HMC5883 ... check your connections */
    Serial.println("Ooops, no HMC5883 detected ... Check your wiring!");
   }

  /* Initialise Sensors 1-6 */
  tcaselect(1);  if(!mag1.begin())  {  Serial.println("Ooops, no HMC5883 detected ... Check your wiring!");  }  
  tcaselect(2);  if(!mag2.begin())  {  Serial.println("Ooops, no HMC5883 detected ... Check your wiring!");  }
  tcaselect(3);  if(!mag3.begin())  {  Serial.println("Ooops, no HMC5883 detected ... Check your wiring!");  }
  tcaselect(4);  if(!mag4.begin())  {  Serial.println("Ooops, no HMC5883 detected ... Check your wiring!");  }
  tcaselect(5);  if(!mag5.begin())  {  Serial.println("Ooops, no HMC5883 detected ... Check your wiring!");  }


}

void loop() {
  /* Get a new sensor event */ 
  sensors_event_t event0;  sensors_event_t event1; 
  sensors_event_t event2;  sensors_event_t event3;
  sensors_event_t event4;  sensors_event_t event5;

  tcaselect(0);  mag0.getEvent(&event0);  tcaselect(1);  mag1.getEvent(&event1);
  tcaselect(2);  mag2.getEvent(&event2);  tcaselect(3);  mag3.getEvent(&event3);
  tcaselect(4);  mag4.getEvent(&event4);  tcaselect(5);  mag5.getEvent(&event5);  

  /* Display the results (magnetic vector values are in micro-Tesla (uT)) */
  Serial.print(event1.magnetic.x); Serial.print("  ");
  Serial.print(event1.magnetic.y); Serial.print("  ");
  Serial.print(event1.magnetic.z); Serial.print("  ");

  Serial.print(event2.magnetic.x);      Serial.print("  ");
  Serial.print(event2.magnetic.y);      Serial.print("  ");
  Serial.print(event2.magnetic.z + 37); Serial.print("  ");

  Serial.print(event3.magnetic.x); Serial.print("  ");
  Serial.print(event3.magnetic.y); Serial.print("  ");
  Serial.print(event3.magnetic.z); Serial.print("  ");

  Serial.print(event4.magnetic.x); Serial.print("  ");
  Serial.print(event4.magnetic.y); Serial.print("  ");
  Serial.print(event4.magnetic.z + 37); Serial.print("  ");

  Serial.print(event5.magnetic.x); Serial.print("  ");
  Serial.print(event5.magnetic.y); Serial.print("  ");
  Serial.print(event5.magnetic.z); Serial.print("  ");

  delay(500);
}

РЕДАКТИРОВАТЬ: Отличные новости: я попробовал использовать только два датчика и кабели длиной 1,5 м и добавить подтягивающие резисторы номиналом 10 кОм от VCC до SDL/SCA на соответствующих датчиках; с этими изменениями они, кажется, работают даже с tcaselect(0), не закомментированным в настройке, хотя я использовал только два датчика, а не шесть. Коммутационная плата датчика HMC5883L уже содержит подтягивающие резисторы номиналом 10 кОм, поэтому, если добавить еще один резистор номиналом 10 кОм на линию, получится 5 кОм. Будет ли это значение слишком большим или это нормально? Я посмотрел таблицу данных самого датчика, но не могу найти информацию о том, какое значение будет иметь входное сопротивление для SCL/SDA.

Кроме того, еще одно примечание по теме: провода одного из моих датчиков были намеренно перекрещены, поэтому SCL и SDA разделены в кабеле GND и VCC. Я все еще проверяю, нужно ли мне это делать, но рекомендуется ли это делать, даже если для правильной работы в этом нет необходимости? Кто-то упомянул, что расположение SCL/SDA рядом друг с другом было бы плохим, если бы они вызывали проблемы с перекрестными помехами/помехами.

, 👍2

Обсуждение

Вы можете следовать этому руководству от начала до конца. Для каждого из 8 каналов имеется сканер I2C. Вы можете запустить это, чтобы посмотреть, что он найдет. Сколько подтягивающих резисторов вы добавили. Я думаю, что вам нужно 2 подтягивающих резистора, которые есть на модуле мультиплексора, и еще 16 подтягивающих резисторов. Вы читали примечание о подтягиваниях в параграфе «Выводы мультиплексной стороны I2C»? Не выбирайте канал без подтягиваний, когда SDA или SCL низкий, сканер Arduino I2C перестает работать., @Jot

Он останавливается на вашем фиктивном датчике? Что такое аппаратный макет датчика I2C? Я никогда не слышал об этом раньше. Вы патент на это просили? Возможно, вы единственный в мире, у кого он есть., @Jot

Спасибо за ваши ответы. Извините, я использую термин «фиктивный датчик» для обозначения датчика, прикрепленного к установке, но мы его не используем. Это просто еще один HMC5883L, но мы его не используем., @BestQualityVacuum

Коммутационная плата HMC5883L имеет подтягивающие резисторы номиналом 10 кОм от контактов SCL/SDA до VCC, поэтому проблем здесь нет. Для самого мультиплексора мы не добавляли подтягивающие резисторы. Я видел абзац, но с подтягиваниями на датчике должно быть нормально, да?, @BestQualityVacuum

Да, подтягивающие резисторы на модуле HMC5883L в порядке. Выбирайте только те каналы, которые имеют подтягивающие резисторы. Когда ничего не работает и был вызван Wire.begin(), все выводы SDA и SCL на обеих сторонах мультиплексора должны быть в высоком состоянии., @Jot

Прошу прощения, но это не совсем помогает в моей проблеме. Все датчики, которые мы используем, содержат подтягивающие резисторы. Просто что-то происходит, когда у нас нет датчика, подключенного к SD/SC0 на мультиплексоре, поэтому мы не можем читать и с других датчиков. Глядя на tcaselect, кажется, что он записывает 8-битный сигнал в TCAADDR, но с битом «1» в зависимости от устройства. Если это так, то с TCAADDR проблем быть не должно., @BestQualityVacuum

@user101402 user101402 вы пробовали использовать только один датчик?, @frarugi87

Да, я пробовал с одним датчиком на макетной плате. Затем я перешел к двум, трем, а затем и семи датчикам. После этого я подключил датчики к секциям аппарата и длинными проводами подключил их к макетной плате. Провода были правильно подключены в соответствии с моей новой схемой, но это не сработало бы, если бы эта строка кода не была закомментирована., @BestQualityVacuum

Какая длина проводов? что за провода? Подключение SDA и SCL по ленточному кабелю очень вредно для сигналов. Мультиплексор Adafruit имеет подтягивающие резисторы номиналом 10 кОм для сигналов, поступающих на Arduino. Это означает, что он может работать до 50 см. Попробуйте добавить подтягивающие резисторы к Arduino, например, 3к3 или 4к7. Они будут параллельны внутренним подтягивающим резисторам номиналом 10 кОм и внутренним подтягивающим резисторам номиналом 50 кОм платы Arduino. Возможно, вы захотите попробовать Wire.setClock(50000L), чтобы снизить тактовую частоту I2C., @Jot

Емкость шины кажется нормальной, поскольку она обрабатывала 7 датчиков, когда все они были на макетной плате. Провода представляют собой 4-контактные ленточные кабели, длина которых варьируется в зависимости от местоположения. Я отредактирую свой пост, как только получу измерения, но что касается подтягивающих резисторов, будут ли они помещены на линии A4/A5 к +5 В? Я смотрю на схему (Uno Rev 3), но не вижу, где находятся резисторы 50/10 кОм. Датчики и мультиплексор уже имеют подтягивающие резисторы. Кроме того, как снижение частоты I2C поможет с tcaselect(0)? Здесь не объясняется, как эта линия работает с датчиками на макетной плате, но не с проводами., @BestQualityVacuum

Плоский ленточный кабель с расположенными рядом SDA и SCL — худшая возможная проводка для шины I2C. SDA и SCL должны иметь минимальную емкость относительно GND и VCC и не должны мешать друг другу. Если на SDA (или наоборот) появится импульс от SCL, то работа шины I2C станет невозможной. Емкость относительно GND и VCC можно решить (частично), уменьшив номинал подтягивающих резисторов и уменьшив тактовую частоту I2C. Но таким образом невозможно предотвратить перекрестные помехи между SDA и SCL. Вы еще не сказали нам, какой длины провода., @Jot

Я указал расстояние от центрального блока до самого дальнего датчика, составляющее около 1,45 м, то есть примерно такой длины провода. Самое короткое расстояние составляет около 10 дюймов или около того. Я понимаю, что вы говорите о шине I2C и расположении проводов, но это то, с чем мне придется работать. Я могу добавить еще один резистор параллельно, чтобы уменьшить значение подтягивания. Тем не менее, странная проблема все еще остается: с закомментированным в настройке tcaselect(0) все датчики можно было считывать. Странно, что эта строка кода закомментирована; такое ощущение, что этого не должно быть., @BestQualityVacuum

Извините, но SDA и SCL рядом друг с другом в плоском шлейфе - это неправильно, от работы с этим следует отказаться. Вы можете разделить провода по всей длине ленточного кабеля, все. Это улучшит сигналы. Вы забыли Wire.begin? Возможно, некоторому оборудованию требуется время для включения. Вы можете добавить задержку в 500 мс перед началом использования шины I2C., @Jot

Джот, спасибо за ваш комментарий. Я думаю, что одна из моих проблем заключается в том, что мне нужны подтягивающие резисторы. Я использовал резисторы 10 кОм для линий SDA/SCL на датчиках, чтобы с кабелем все работало. Что касается вашего комментария о кабеле, вместо того, чтобы располагать SDA и SCL рядом друг с другом, я переместил припаянные провода вокруг датчика так, чтобы вдоль кабеля SCL был с одной стороны, SDA - с другой, с GND и VCC. между ними двумя. Кажется, это работает вместе с дополнительными подтягивающими резисторами, чтобы все работало, хотя я тестировал это только с двумя датчиками., @BestQualityVacuum


2 ответа


1

Я уверен, что да, но соединили ли вы заземления вместе?

Вы попробовали 1 датчик на SD/C0, а затем переместили его на SD/C1, он должен перестать работать, поэтому неисправность должна быть в SD/C0.

Глядя на ваш код, есть ли причина, по которой вы не инициализировали датчик 0?

 /* Инициализация датчиков 1-6 */

Мне кажется, что ошибка вызвана тем, что вы не вызываете begin() в mag0

,

Мы соединили площадки вместе; все они ведут к узлу на макетной плате, который передает обратную связь на Arduino. Мы попробовали ваше предложение с SD/C0 и SD/C1, но результаты оказались одинаковыми. Я попрошу команду повторить попытку, так как не могу точно проверить это, поскольку меня нет на месте с устройством. Причина, по которой мы не инициализировали датчик 0 с помощью tcaselect(0), заключалась в том, что это приводило к зависанию нашего кода. Как только мы это закомментировали, код продолжился, и мы смогли читать данные со всех датчиков. Ответственный парень проверил это, прокомментировал и обнаружил, что проблема именно в этом, хотя мы до сих пор не знаем, почему., @BestQualityVacuum


0

Попробуйте перенести пустое место в последний слот и изменить цикл for так, чтобы он обрабатывал только первые 7.

Последовательные отпечатки помогают при отладке

,