0

I am building an airplane. As a controller I am using a Raspberry pi 4. There are 3 sensors (MPU6050, QMC5883L, BME280) and arduino pro mini connected to the raspberry via i2c. When sending requests to the arduino it pulls the bus to 0 and shuts down(?).

  • First screenshot. On the first search for all devices on the bus, the arduino responds and shuts down, but does not pull the bus to 0. On the second search It responds and pulls the bus to 0.

  • Second screenshot. Rebooting the arduino, the SDA line goes up. Repeated runs of the search leads to what is shown in the first screenshot.

  • Third screenshot. The arduino generates a PWM signal that is interrupted after a request to i2c.

As a test request I use the i2cdetect command on the Raspberry. Raspberry is connected to the sensor bus through a level converter, because the level of signals from Raspberry is 3.3V, and sensors accept 5 volt logic.

There is no bus pull-up to the upper level, it is on the schematic of all sensors used (will it be enough?).

The arduino has a simple slave i2c device code, writing to registers the value arrived and output it to other elements (servo drives, motor controller, stepper motor drivers). The Arduino acts as a port expander because the Raspberry has only 2 buses and too few outputs for all the necessary devices

Why is the bus falling and how can I fix it?

arduino code

    #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();
        }
      }
    }

Screenshot 1 screenshot 1

Screenshot 2 screenshot 2

Screenshot 3 screenshot 3

and wiring diagram wiring diagram

11
  • 3
    The bus needs a pull-up.
    – Delta_G
    Aug 24 at 18:21
  • 1
    That logic level shifter must be bidirectional. If it has markings on it like TX/RX then it is unlikely to be bidirectional. There should be pullup resistors (say 4.7k) on the low and high voltage sides of the I2C bus. If at least one module on each side of the level shifter has these then that should be enough. The module mpu6050 (and maybe others also) has 3.3 volt logic and should be on the Raspberry Pi side of the level shifter.
    – 6v6gt
    Aug 24 at 23:10
  • 1
    The BME280 is apparently a 3.3V device, so I don't know why you have it on the 5V part of the circuit.
    – Nick Gammon
    Aug 25 at 8:15
  • 1
    The Pro Mini can also run at 3.3V - you are making it hard for yourself with the logic level converter.
    – Nick Gammon
    Aug 25 at 8:18
  • 1
    @NickGammon How do I power it from 3.3V? Does it have no 3.3V pin or can 3.3V be supplied to the VCC pin too?
    – Xrou
    Aug 26 at 9:14

1 Answer 1

3

For I2C to work there needs to be pull-ups on SDA and SCL somewhere (not one for each device). Typically 4.7k resistors or thereabouts would be used.

Also you need a bi-directional voltage level translator. An example schematic is:

Bi-directional level shifter

Image credit: Sparkfun: Bi-Directional Logic Level Converter Hookup Guide

This is because I2C devices actively pull SDA and SCL low, however they rely on the pull-up resistors to pull them high. Also this won't work unless the voltage level shifter is bi-directional.

For more information see the Philips Application Note AN97055 - Bi-directional level shifter for I²C-bus and other systems.

If you use the level shifter you need pull-up resistors on both the 3.3V part and the 5V part of the circuit (shown as Rp below).

Philips Application Note AN97055

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.