0

Good evening. I am trying to use a Raspberry Pi Zero W 2 as an I2C Slave. Trying to implement some of the solutions using bsc_xfer in this forum, I simply cannot get any data back and forth to the master.

The master is an Arduino MKR1010. It transmits some bytes, then requests bytes back. I can sucessfully communicate with other I2C devices that I put on the bus. And when I use i2cdetect -y 1, I can see the other i2c devices on the raspberry pi. Based on this, I think my connections are okay.

Here's the master arduino code:

void setup(void)
{
  Wire.begin();
  Wire.setClock(100000);
  
  Serial.begin(115200);
}

void loop(void)
{
  Serial.print("Send slave data...");
  // Send data to slave
  Wire.beginTransmission(0x55);
  Serial.print("5...");
  Wire.write(0x05);
  Serial.print("6...");
  Wire.write(0x06);
  Serial.print("7...");
  Wire.write(0x07);
  Serial.print("8...");
  Wire.write(0x08);
  Wire.endTransmission();
  Serial.println("Done.");

  delay(10);

  // Pull data from slave
  Serial.print("Request slave data...");
  Wire.requestFrom(0x55, 4);
  if (Wire.available()) {
    Serial.print("Receiving bytes from slave:");
    while (Wire.available()) {
      uint8_t b = Wire.read();
      Serial.print("B=");Serial.print(b);
      if (Wire.available()) Serial.print(", ");
    }
    Serial.println();
  } else {
    Serial.print("No data waiting...");
  }
  Serial.println("Done.");
  delay(10);
}

The Raspberry Pi uses the pigpiod_if2 libraries talking to a pigpiod -s 2. The daemon is started using systemctl start pigpiod, and the pigpiod.service file added the -s 2 option.

Question: When using as a slave, do you configure the i2c interface or not? I've seen conflicting info. I have actually tried both enabling i2c and disabling it with the dtparam=i2c_arm=on and also removing this line. Does anyone know if it should or should not be configured when using the pi as a slave?

Regardless of how I configure, no data ever goes back and forth. Here is the pi code:

#include <stdio.h>
#include <unistd.h>
#include <cstring>
#include <pigpiod_if2.h>

int pi_handle;
bsc_xfer_t xfer;
uint8_t i2caddr = 0x55;

void setup()
  {
    pi_handle = pigpio_start(0, 0);
    if (pi_handle < 0) {
      printf("WHOAAAAAA!\n");
    }

    xfer.control = (uint32_t)((uint32_t)i2caddr << 16) | (1<<7) /*BK*/;
    bsc_xfer(pi_handle, &xfer);
  }

void loop()
{
  int status;
  xfer.control = (uint32_t)((uint32_t)i2caddr << 16) | (1<<9) /*RE*/ | (1<<8) /*TE*/ | (1<<2) /*I2C*/ | (
1<<0) /*EN*/;

  while (true) {

    printf("Check i2c requests...\n");
    printf("Transfer control: 0x%x\n", xfer.control);
    xfer.control = (uint32_t)((uint32_t)i2caddr << 16)
      | (1<<9) /*RE*/ | (1<<8) /*TE*/ | (1<<2) /*I2C*/ | (1<<0) /*EN*/;

    usleep(1000);

    status = bsc_xfer(pi_handle, &xfer);
    printf("Done. status=0x%x, rx=%d, tx=%d\n", status, xfer.rxCnt, xfer.txCnt);

    if ((status >= 0) && (xfer.rxCnt > 0))
      {
        printf("Received %d bytes of control data.\n", xfer.rxCnt);
        printf("Control data = ");
        for (int i = 0; i < xfer.rxCnt; i++) {
          printf("b[%d]=%d", i, xfer.rxBuf[i]);
          if (i < xfer.rxCnt-1) printf(", ");
        }
        printf("\n");
        xfer.rxCnt = 0;
      }

    // SHORT PAUSE
    usleep (1000);
  }

  printf("Done looping.\n");
}

int
main(int argc, char **argv)
{
  setup();
  loop();
}

That's pretty much it. The status coming back from bsc_xfer will change if I add bytes to the transmit queue, but the buffer never drains. It never receives any bytes back in the rxBuf.

I tried it without the pigpiod, direct to the libraries using gpInitialise() and bscXfer(), but it didn't work either.

Any pointers are appreciated. Thank you.

Here is the output from the slave running on the Pi:

Check i2c requests...
Transfer control: 0x550305
Done. status=0x12000000, rx=0, tx=0
Check i2c requests...
Transfer control: 0x550305
Done. status=0x12000000, rx=0, tx=0
Check i2c requests...
Transfer control: 0x550305
Done. status=0x12000000, rx=0, tx=0

lsmod output is as follows:

$ lsmod | grep i2c
i2c_bcm2835            16384  0
i2c_dev                20480  0
0

2 Answers 2

0

It sounds like you have not connected to the correct GPIO and/or have not added pull-ups to 3V3.

See http://abyz.me.uk/rpi/pigpio/pdif2.html#bsc_xfer for the GPIO to use (pigpio always use Broadcom GPIO numbering).

GPIO used for models other than those based on the BCM2711.

       SDA    SCL    MOSI    SCLK    MISO    CE
I2C    18     19     -       -       -       -
SPI    -      -      20      19      18      21

GPIO used for models based on the BCM2711 (e.g. the Pi4B).

       SDA    SCL    MOSI    SCLK    MISO    CE
I2C    10     11     -       -       -       -
SPI    -      -      9       11      10      8
3
  • Thank you for this. The lsmod output says that it is the bcm2835. I added that to the question above. That would suggest GPIO 18, and 19? I will try this. I am currently connected to GPIO 2 and 3 for SDA SCL, which is what the pi zero 2 pinout diagram says. These pins do read the other i2c devices using i2cdetect. Is the bsc slave device on another set of pins? Kind regards.
    – tenchiro
    Sep 24, 2022 at 23:13
  • GPIO 2/3 are only for when the Pi is the bus master. If you want the Pi to act as an I2C slave device you must use the GPIO given in the table.
    – joan
    Sep 25, 2022 at 7:48
  • This solved the problem getting data to go back and forth. Thank you very much. When I read that section, I mistook that I needed to look up the GPIO for the specific board in the pinouts, and erroneously thought I needed to use the I2C GPIO pins. This is a much better design than repurposing the I2C master pins. I'm still having trouble getting reliable data transmissions and trying to determine when a data request has actually been made by the master. But I think I'll experiment for a couple of days and submit a more specific question later if necessary. Thank you very much!
    – tenchiro
    Sep 25, 2022 at 11:25
0

I rewired to use 18 and 19 for the slave SDA and SCL according to the answer from joan above and data started going back and forth between the pi and the Arduino master. Reading the documentation, I did not realize there were two sets of pins for master and slave functionality.

Some timing issues remain in the sample code above which need to be worked through. But data is moving now. Thank you.

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.