Bit stuck on bit manipulations ?

Hi,

Wondering if I may ask for a little help with this bit maniulation problem?

I have an I2C sensor which returns 4 bytes but I need to extract 14 bits from the first two and 11 bits from the second two:

Byte 1: 00101100 //use last 6 bits
Byte 2: 11001101 //use all 8 bits
Byte 3: 01011100 //use all 8 bits
Byte 4: 11100000 //use first 3 bits

Aiming for:
Byte1 + Byte2 = Value 1: 10110011001101 = 11469 in Decimal
&
Byte3 + Byte4 = Value 2: 01011100111 = 743 in Decimal

My code currently looks like this but not sure how to manipulate the bits to get the above format correct?

The byte values returned at the moment are (values should be different to the example above):

PMSB = 10100000
PLSB = 100
TMSB = 1011011
TLSB = 1110100

  int value 1;
  int value 2;
  byte PMSB;
  byte PLSB;
  byte TMSB;
  byte TLSB;
  Wire.beginTransmission(0x50);
  Wire.endTransmission();
  Wire.requestFrom(0x50,4);
  PMSB = Wire.read();
  PLSB = Wire.read();
  TMSB = Wire.read();
  TLSB = Wire.read();
  value1 = ((PMSB << 8) | PLSB);
  value2 = ((TMSB << 8) | TLSB);

PS, this is the I2C request and response:

Suggest you mask the relevant bits out of each byte first and convert to ints before you shift and 'bitwise or' them to get the result.

… fab - may I ask how I would mask these bytes please :blush:

Byte 1: 00101100 //use last 6 bits
Byte 2: 11001101 //use all 8 bits
Byte 3: 01011100 //use all 8 bits
Byte 4: 11100000 //use first 3 bits

byte B1 = 00101100 & 0x3F; // 0x3F = 00111111;
byte B4 = 11100000 & 0xE0; // 0xE0 = 11100000;
Bytes B2 and B3 can stay the same.

Cool - I understand how that works :slight_smile:

I now have this but alas no joy yet:

  PMSB = Wire.read();
  PLSB = Wire.read();
  TMSB = Wire.read();
  TLSB = Wire.read();

  PMSB = (PMSB & 00111111);  //Mask off first two bits
  TLSB = (TLSB & 11100000);  //Mask off last five bits
  pressureReading = ((PMSB*256) + PLSB);  //Shift PMSB left 8 bits and add PLSB as INT
  tempReading = ((TMSB*256) + TLSB);  //Shift TMSB left 8 bits and add TLSB as INT

Ok so get a reading of the values before and after you change them, then compare them to what you should be getting.

You might need to typecase the read value as ints then add them.

 0x2F = 00111111;

?

PMSB = (PMSB & 00111111);  //Mask off first two bits

Can we drop the big octal constants?
They're confusing.

Yes, your right. It should have been. byte B1 = B00101100 & 0x3F; // 0x3F = B00111111;
Why is Octal even used anymore, it should just be binary, decimal and hex.

Why is Octal even used anymore, it should just be binary, decimal and hex

Because some of us have a proud DEC heritage

0x2F = B00111111;

No, it doesn't

Yes, your right.

My right what? :wink:

Your correct, in me being wrong, 0x3F = B00111111; I fixed them.

Thanks for helping out folks - I'm very close to seeing this working now....

My 4 BYTES come in as:
1: A0
2: 04
3: 5B
4: D4

I can mask them thansk to you folk giving:
1: 20
2: 04
3: 5B
4: C0

No the problem comes when I try to join BYTE1 to BYTE2 & BYTE3 to BYTE4

I should get the following answer:
1+2 = 0x2004
3+4 = 0x2DE

With this code I get the wrong answer for some reason?

INT pressureReading = ((BYTE1*256) + BYTE2);
INT tempReading = ((BYTE3*256) + BYTE4);

What is INT defined as?
Which device are you running this on?

It may help if you post your code-

Hi,

Here is my code, on an Arduino 328:

  int tempReading = 0;
  int pressureReading = 0;
  int PMSB=0x0;
  int PLSB=0x0;
  int TMSB=0x0;
  int TLSB=0x0;

  Wire.beginTransmission(0x50);
  Wire.endTransmission();
  Wire.requestFrom(0x50,4);
  PMSB = Wire.read();
  PLSB = Wire.read();
  TMSB = Wire.read();
  TLSB = Wire.read();

  PMSB = (PMSB & 0x3F);
  TLSB = (TLSB & 0xE0);
  pressureReading = (PMSB + PLSB);
  tempReading = (TMSB + TLSB);

Here is my code:

No, that doesn't compile, and it has no INTs in it.

Do you mean like this?

void setup()
{
Serial.begin(115200);

byte B_1 = 0xA0 & 0x3F; // already combined 
byte B_2 = 0x04;
byte B_3 = 0x5B;
byte B_4 = 0xD4 & 0xE0; // already combined

int Pressure = (B_1 << 8) | B_2;
int Temp = (B_3 << 8) | B_4;

Serial.println(Pressure,HEX); 
Serial.println(Temp,HEX);
}

void loop() 
{
  
}

Output in HEX

2004
5BC0

Almost :slight_smile:

int Pressure = (B_1 << 8) | B_2;
is correct and gives 0x2004

int Temp = (B_3 << 8) | B_4;
isn’t correct and should give 0x2DE ?

Sorry, I'm not completely following how this works.... however

The result should be with the bits we need to use in BOLD:
Binary values are those recieved, Binary values in BOLD are those to use and HEX values from the Binary values to use:
BYTE1 0x20 = 10100000
BYTE2 0x04 = 00100000
Gives 0010000000000100 = 0x2004

&

BYTE3 0x5B = 01011011
BYTE4 0xC0 = 11010100
Gives 01011011110 = 0x2DE

BYTE1 0x20 = 10100000
BYTE2 0x04 = 00100000

Clearly, neither of those is true.
Well they're true in the C/C++ sense of being non zero, but not in the sense of being equivalent.
It's difficult to see what you're saying.

Oh, then in that case its simple, shift 5BC0 to the right 5 bits.

int Pressure = (B_1 << 8) | B_2; // this is fine
int Temp = (B_3 << 8) | B_4; //this produces 5BC0
Temp >>=5; // 5BC0 >> 5 = 02DE