0

So, I've found the address of my device using a I2C device scanner. I then looked up the datasheet for a magnetic sensor I am trying to grab data from.

I'm now trying to communicate with the device by following the 'Example Measurement' section in the data sheet.

Here is my code so far...

#include <Wire.h>
#define address 0b110000 // find the actual address, it is at 0x30, which is 0b00110000

void setup() {
  Serial.begin(9600);
  Wire.begin(address);
}


void loop() {
  int x, y, z;

  Wire.requestFrom(0b00110000, 1); // START condition?, starts with a 0 to indicate a WRITE request
  if(Wire.available() > 0) {
    Serial.println("1");
    Wire.read();
  }
  Serial.println(Wire.read());
  Wire.write(0b00000111);
  if(Wire.available() > 0) {
    Serial.println("2");
    Wire.read();
  }
  Wire.write(0b00000001); 
  if(Wire.available() > 0) {
    Serial.println("3");
    Wire.read();
  }
  Wire.requestFrom(0b00110000, 1); // write request
  if(Wire.available() > 0) {
    Serial.println("4");
    Wire.read();
  }
  Wire.write(0b00000110);
  if(Wire.available() > 0) {
    Serial.println("5");
    Wire.read();
  }
  Wire.requestFrom(0b10110000, 1); // READ request 
  if(Wire.available() > 0) {
    Serial.println("6");
    Wire.read();
  }
  // not sure what to do for the 7th cycle???
  // am I even doing the previous correct?
  Wire.endTransmission(address);
  delay(1000);
}

The numbers in each of the if statements represent the cycle within the 'Example Measurement' section of the datasheet, I'm never able to read data from the device and I am sure that I am doing something wrong.

I appreciate any help! This is my first time ever trying to understand I2C, and I've just been staring at this datasheet for too long without getting anywhere.

  • The Wire.request does not need beginTransmission or endTransmission. Only the Wire.request is needed when data needs to be read. You can use one or more Wire.read or Wire.available if you like. To write data, you need Wire.beginTransmission, Wire.write (none, one, or more) and Wire.endTransmission. You request data from different i2c addresses. Please use: const int mmc3416Address = 0x30; – Jot Jun 27 '17 at 20:46
  • What is the difference between reading data and requesting data? It seems to me that the Wire.read() depends on which address was called to Wire.begin() whereas Wire.request() takes in an address of the device? Is this correct? – dchin2 Jun 27 '17 at 22:31
  • 2
    No, sorry, that is not correct. You need to learn about using the Wire library. Start here: arduino.cc/en/Reference/Wire I think you are confused with a serial port. The I2C functions are similar to the functions of a serial port, but it is not the same, since the I2C uses packets of data, and not a stream of data. The I2C can not read and write at the same time. Either a packet of data is transmitted to a sensor or a packet of data is requested from a sensor. – Jot Jun 28 '17 at 4:15
  • I have read the datasheet, and it is very confusing, even for me. The Wire library does all the start and stop and handles the acknowledge and set the read/write bit if needed. You don't have to worry about that. When communicating with the sensor, sometimes a delay is needed. The delay is the only odd thing, the sensor is just like any other I2C sensor. – Jot Jun 28 '17 at 13:00
  • I've never messed with any I2C protocols before, so if the Wire library takes care of all the start and stop and handling acknowledge for me, what exactly do I need to do? It seems like I would be in charge of writing particular bits, as described in the example measurement section. Also, which functions in the Wire library take care of the start and stop stuff for me? Thanks for your responses! – dchin2 Jun 28 '17 at 21:19
1

This is how you send a byte to your slave:

  Wire.beginTransmission(SLAVE_ADDRESS);
  Wire.write(someByteValue);
  Wire.endTransmission();

You must sandwich the writes between a beginTransmission/endTransmission. Output buffer is 32 bytes long, so keep things short.

Wire.write() doesn't write; just put thing in an output buffer, waiting for your endTransmission().

If you need an answer (said, a byte), first you said how many bytes you want and then read them:

  byte pin;
  Wire.requestFrom(SLAVE_ADDRESS, 1);
  if (Wire.available() == 1) {
    pin = Wire.read();
  }

Your are Wire.read()ing, but you are not capturing the return value!

Disclaimer: after requestFrom, you have to be prepared to wait for the data (it may be not inmediatly available). Also, data may arrive in chunks.

  • 1
    After Wire.requestFrom, the received data is in a buffer in the Wire library. The Wire.available returns the number of bytes in the buffer. The Wire.read reads a byte from that buffer. There is never any need to wait for data after Wire.requestFrom. – Jot Jul 1 '17 at 10:58
  • @Jot. The slave can take a while to send the answer; it's not always immediatly available. According to docs, requestFrom is "Used by the master to request bytes from a slave device. The bytes may then be retrieved with the available() and read() functions." – user31481 Jul 1 '17 at 12:22
  • 1
    could you look into that, or ask anyone who knows the Wire library. It is a common made mistake. The documentation is confusing, it should read: "The bytes may be retrieved from the receive buffer with available() and read()". The Wire.requestFrom does a START, puts the address with read bit, can do clock pulse stretching if requested by the Slave, reads bytes, stores bytes in a buffer, gives ACK after each byte, with a NAK at the last byte, and finally a STOP. Only then the Wire.requestFrom returns. There is really no other way. When Wire.requestFrom returns, all the data is ready. – Jot Jul 1 '17 at 14:37
  • @jot. It is not clear to me that requestFrom is blocking. It seems to be blocking. I don't think it is a good idea, because blocking calls means a frozen program under Murphy's Law. Sad! – user31481 Jul 1 '17 at 15:17
  • 1
    For most Arduino users, the blocking interface is best, however, they really should provide a timeout and error condition. Without that, one solitary single glitch can leave the sketch hung until reset. That said, horrible documentation of APIs has been a persistent problem with the Arduino website; they try to simplify things so much that to find an actual answer to a critical detail that any serious library would put in the documentation, you often have to dig into the source code. – Chris Stratton Jul 1 '17 at 15:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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