Arduino отключает шину i2c

Я строю самолет. В качестве контроллера я использую Raspberry pi 4. Есть 3 датчика (MPU6050, QMC5883L, BME280) и Arduino Pro Mini, подключенные к Raspberry через i2c. При отправке запросов в Arduino он переводит шину в 0 и выключается(?).

  • Первый скриншот. При первом поиске всех устройств на шине Arduino отвечает и выключается, но не переводит шину в 0. При втором поиске он реагирует и переводит шину в 0.

  • Второй скриншот. Перезагружаем ардуино, линия SDA поднимается. Повторные запуски поиска приводят к тому, что показано на первом скриншоте.

  • Третий скриншот. Arduino генерирует сигнал ШИМ, который прерывается после запроса к i2c.

В качестве тестового запроса я использую команду i2cdetect на Raspberry. Raspberry подключается к шине датчика через преобразователь уровня, поскольку уровень сигналов от Raspberry составляет 3,3В, а датчики принимают 5-вольтовую логику.

Подтягивания шины на верхний уровень нет, он есть на схеме всех используемых датчиков (ей будет достаточно?).

В Arduino есть простой код подчиненного устройства i2c, который записывает в регистры поступившее значение и выводит его на другие элементы (сервоприводы, контроллер двигателя, драйверы шаговых двигателей). Arduino действует как расширитель портов, поскольку у Raspberry всего 2 шины и слишком мало выходов для всех необходимых устройств.

Почему автобус падает и как это исправить?

код Arduino

    #include <Wire.h>
    #include <Servo.h>
    #include <Stepper.h>


    uint16_t servoAngle1 = 90;
    uint16_t servoAngle2 = 90;
    uint16_t servoAngle3 = 90;
    uint16_t servoAngle4 = 90;

    bool zoomIn = false;
    bool zoomOut = false;

    bool focusIn = false;
    bool focusOut = false;

    Servo servo1;
    Servo servo2;
    Servo servo3;
    Servo servo4;

    Servo ESC;

    Stepper zoomMotor(100, 2, 4, 7, 8);
    Stepper focusMotor(100, 10, 11, 12, 13);

    void setup() {
      Wire.begin(0x23);
      Wire.onReceive(receiveEvent);

      servo1.attach(3); 
      servo2.attach(5); 
      servo3.attach(6); 
      servo4.attach(9); 
      ESC.attach(11, 1000, 2000);
    }

    void loop() {
      servo1.write(servoAngle1);
      servo2.write(servoAngle2);
      servo3.write(servoAngle3);
      servo4.write(servoAngle4);
      ESC.write(0);
      if (zoomIn) {
        zoomMotor.step(100);
        zoomIn = false;
      }
      if (zoomOut) {
        zoomMotor.step(-100);
        zoomOut = false;
      }

      if (focusIn) {
        focusMotor.step(100);
        focusIn = false;
      }
      if (focusOut) {
        focusMotor.step(-100);
        focusOut = false;
      }
    }

    void receiveEvent(int howMany) {
      if (howMany == 2) {
        uint8_t action = Wire.read();
        uint8_t value = Wire.read();

        if (action == 1) { servoAngle1 = value; }
        if (action == 2) { servoAngle2 = value; }
        if (action == 3) { servoAngle3 = value; }
        if (action == 4) { servoAngle4 = value; }

        if (action == 10) {
          if (value == 1) { zoomIn = true; }
          if (value == 2) { zoomOut = true; }
        }

        if (action == 11) {
          if (value == 1) { focusIn = true; }
          if (value == 2) { focusOut = true; }
        }
      } else {
        while (true) {
          Wire.read();
        }
      }
    }

Скриншот 1 скриншот 1

Скриншот 2 скриншот 2

Скриншот 3 скриншот 3

и схема подключения схема подключения

, 👍0

Обсуждение

пожалуйста, добавьте в свой пост четкий вопрос, на который можно ответить... также добавьте листинг кода, @jsotola

Автобусу нужно подъехать., @Delta_G

Этот переключатель логического уровня должен быть двунаправленным. Если на нем есть маркировка типа TX/RX, то вряд ли он будет двунаправленным. На сторонах низкого и высокого напряжения шины I2C должны быть подтягивающие резисторы (скажем, 4,7 кОм). Если хотя бы по одному модулю с каждой стороны устройства переключения уровня они есть, этого должно быть достаточно. Модуль mpu6050 (и, возможно, другие) имеет логику 3,3 В и должен находиться на стороне Raspberry Pi переключателя уровня., @6v6gt

добавлен листинг кода., @Xrou

BME280, по-видимому, является устройством с напряжением 3,3 В, поэтому я не знаю, почему он у вас установлен на 5-вольтовой части схемы., @Nick Gammon

Pro Mini также может работать при напряжении 3,3 В — вы усложняете себе задачу с помощью преобразователя логических уровней., @Nick Gammon

Из вашего недавно опубликованного кода. Как он собирается вырваться из этого бесконечного цикла? else { while (true) { Wire.read(); } }, @6v6gt

@NickGammon Как мне подать питание на 3,3 В? У него нет контакта 3,3 В или на контакт VCC можно подать напряжение 3,3 В?, @Xrou

Вам необходимо найти и понять схемы тех модулей, которые вы используете. Вот https://www.waveshare.com/w/upload/4/42/BME280-Environmental-Sensor-Schematic.pdf, например, модуль BME280. Сам чип рассчитан на напряжение 3,3 В, но модуль рассчитан на работу с напряжением 5 В и имеет встроенный переключатель уровня. Если это тот, который вы используете, то в этом случае правильно подключить его к стороне 5 В. А как насчет ошибки кодирования, на которую было указано в моем предыдущем комментарии. Не вызовет ли это симптомы, о которых вы сообщили?, @6v6gt

Вы показываете, что Raspberry Pi имеет напряжение 3,3 В на SDA и SCL — откуда это взялось? Вы показываете свои устройства, такие как BME280, с питанием 3,3 В. Почему вы спрашиваете, откуда берется 3,3В? Если вы не хотите этого делать, посмотрите комментарий 6v6gt. Вам нужен двунаправленный переключатель уровня, иначе I2C не будет работать., @Nick Gammon

Глобальные переменные, которые используются в цикле и обновляются в полученииEvent(), должны быть объявлены как изменчивые, поскольку вызов этой процедуры осуществляется через прерывание. Вы также должны показать код, используемый на ведущем устройстве I2C., @6v6gt


1 ответ


Лучший ответ:

3

Для работы I2C где-то должны быть подтяжки на SDA и SCL (не по одному для каждого устройства). Обычно используются резисторы номиналом 4,7 кОм или около того.

Также вам понадобится двунаправленный преобразователь уровня напряжения. Пример схемы:

Двунаправленный переключатель уровня

Изображение предоставлено: Sparkfun: Руководство по подключению двунаправленного преобразователя логических уровней

Это связано с тем, что устройства I2C активно подтягивают SDA и SCL к низкому уровню, однако они полагаются на подтягивающие резисторы, которые подтягивают их к высокому уровню. Кроме того, это не будет работать, если переключатель уровня напряжения не является двунаправленным.

Для получения дополнительной информации см. Примечания по применению Philips AN97055 — двунаправленный преобразователь уровня для шины I²C и других устройств. системы.

Если вы используете преобразователь уровня, вам потребуются подтягивающие резисторы как на части 3,3 В, так и на части 5 В схемы (показаны как Rp ниже).

Примечания по применению Philips AN97055

,