What to expect when reading from a register using I2C

Hi,
I'm trying to check the value of a bit in a byte register.
To start, this is the readRegister function for the i2c
ignore the SPI_MODE part

//  ReadRegister
//
//  Parameters:
//    *outputPointer -- Pass &variable (address of) to save read data to
//    offset -- register to read
//
//****************************************************************************//
status_t LSM6DS3Core::readRegister(uint8_t* outputPointer, uint8_t offset) {
	//Return value
	uint8_t result = 0;
	uint8_t numBytes = 1;
	status_t returnError = IMU_SUCCESS;

	switch (commInterface) {

	case I2C_MODE:
		Wire.beginTransmission(I2CAddress);
		Wire.write(offset);
		if( Wire.endTransmission() != 0 )
		{
			returnError = IMU_HW_ERROR;
		}
		Wire.requestFrom(I2CAddress, numBytes);
		while ( Wire.available() ) // slave may send less than requested
		{
			result = Wire.read(); // receive a byte as a proper uint8_t
		}
		break;

	case SPI_MODE:
		// take the chip select low to select the device:
		digitalWrite(chipSelectPin, LOW);
		// send the device the register you want to read:
		SPI.transfer(offset | 0x80);  //Ored with "read request" bit
		// send a value of 0 to read the first byte returned:
		result = SPI.transfer(0x00);
		// take the chip select high to de-select:
		digitalWrite(chipSelectPin, HIGH);
		
		if( result == 0xFF )
		{
			//we've received all ones, report
			returnError = IMU_ALL_ONES_WARNING;
		}
		break;

	default:
		break;
	}

	*outputPointer = result;
	return returnError;
}

Here is my register, the FUNC_SRC in highlighted in yellow

This is what i do to read from it.

// Tilt detection check
//
//***************************************************************************//
uint8_t LSM6DS3::readTilt( void )
{
  uint8_t output;
  readRegister(&output, LSM6DS3_ACC_GYRO_FUNC_SRC);
  return output;
}

readRegister reads a byte and the FUNC_SRC is a byte, unless i'm wrong ?? am i ??
Does readRegister reads the whole byte and packs them up into the output variable ?
How do i get the value of the 5'th bit of FUNC_SRC, from the output variable ??
the 5'th bit is TILT_IA.

It would really help a lot.
kind regards,
gitduino

Using bitRead() would be a convenient way to get the value

If you are going to read just one byte, then why use a while-loop ?
I know you took it from the Sparkfun source code, but that does not mean that you have to write the same cheesy code.
I think that this makes more sense:

    Wire.requestFrom(I2CAddress, 1);
    if (Wire.available() == 1)
    {
      result = Wire.read();
    }

This command is wrong and can be removed: "// slave may send less than requested".

You can turn a parameter that is a pointer into "by reference". Then the source code is easier to read.

Hello

The most common way to get the value of a bit N is to shift N bits to the right, and mask the result with 1 so to keep only the right-most bit.

Example to get the value of bit 5

0b10010111
>> 5
= 0b00000100
& 0b00000001
= 0b00000000

Code : uint8_t bit5 = (value >> 5) & 1;

As said you can use the bitRead macro (it will do exactly the same thing), but now you know how it works :slight_smile:

Hi guys,
thanks for the reply.
alright so this is how i get the byte from the register.

uint8_t LSM6DS3::sensor( void )
{
  uint8_t output;
  readRegister(&output, LSM6DS3_ACC_GYRO_FUNC_SRC);
  return output;
}

So if i'm supposed to use bitRead(x, n);
then i replace the x with output then the n is 5 right ?
example:

int something = 0;
something = bitRead(output, 5);

the return output definitely does contain some values
but when i print output
say,

Serial.print(output);

I get 0 as a result
I know uint8_t returns a byte
after return output, should i convert the content of output into another type
before bitRead(x, n); ??
or perhaps using uint8_t isn't the right approach to extract byte from the register

The bitRead() accepts all variables. It is not even a function but a macro.
It is located in Arduino.h: https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/Arduino.h#L111

#define bitRead(value, bit) (((value) >> (bit)) & 0x01)

The return value is 0 or 1.

The bit number starts counting from 0.
Bit 0 is always shown on the right.

You don't need to test this with I2C. You can make a small sketch with a value and print that value hexadecimal, binary and with bitRead().

If your variable 'something' is zero, then that bit was really zero.
Please show a full sketch. There is a website for that: https://snippets-r-us.com/

Hi Keopel,
Here is the full main sketch

#include "SparkFunLSM6DS3.h"
#include <Wire.h>
LSM6DS3 xMEMS; // addr 0x6B i2c
bool start_up = false;

int something; // check tilt

void setup()
{

  Serial.begin(9600);
  Wire.begin();
  delay(10);
  if(xMEMS.beginCore() != 0){
    Serial.println("lsm6ds3 sensor is invalid!");
    start_up = false;
    
  }
  else{
    Serial.println("passed!");
    start_up = true;
    xMEMS.begin();
    xMEMS.tiltDetect();
  }

}

void loop()
{
  something = xMEMS.sensor();
  Serial.println(bitRead(something, 5));// bitRead(x, n)
  delay(1000);
    
}

What do you see when you print the something variable in binary ?

Hi UKHeliBob,
this is what i get as a result of printing something variable in binary

#include "SparkFunLSM6DS3.h"
#include <Wire.h>
LSM6DS3 xMEMS; // addr 0x6B i2c
bool start_up = false;

int something; // check tilt

void setup()
{

  Serial.begin(9600);
  Wire.begin();
  delay(10);
  if(xMEMS.beginCore() != 0){
    Serial.println("lsm6ds3 sensor is invalid!");
    start_up = false;
    
  }
  else{
    Serial.println("passed!");
    start_up = true;
    xMEMS.begin();
    xMEMS.tiltDetect();
  }

}

void loop()
{
  something = xMEMS.sensor();
  Serial.println(something, BIN);
  delay(1000);
    
}

result is

Processor came out of reset.


passed!
0
0
0
0
0
0
0

  Serial.println(something, BIN);

did not produce this output

Processor came out of reset.


passed!
0
0
0
0
0
0
0

but as you have found the value of the variable was zero so bitRead() was returning the correct value

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.