HX711 icon indicating copy to clipboard operation
HX711 copied to clipboard

read() output difference v0.1 v0.7

Open MarioJose opened this issue 5 years ago • 3 comments

Hi. I use HX711 as ADC 24bits for voltage read, not for load cell. I noted that when nothing is connected in channel A, for instance, in version 0.1, the raw output was 8388608 (~0V). But, now in version 0.7, when nothing is connected in channel A, the raw output is 0 (~0V). Maybe I not found the commit alerting about this. Revising commits I noted only warning about constructors. If library spring 2019 updates in this level, a note must be added in README. This update broke compatibility with older code more than the constructor line.

MarioJose avatar Aug 28 '19 17:08 MarioJose

Dear @MarioJose,

thanks for writing in about your observations. While I can't pinpoint the root cause for this deviation from my mind, I want to apologize to all for any compatibility issues coming from the most recent 0.7.x release series.

Saying that, we will be very happy about a pull request adding an appropriate admonition note to the README file. On the other hand, I would certainly be interested which amendment might have caused the changed behavior.

Please feel free to add further suggestions or thoughts about improving the current situation.

With kind regards, Andreas.

amotl avatar Aug 28 '19 22:08 amotl

Hi, @amotl!

Thank you for your answer.

Bitmath/Bitwise is a bit complicated for me, but I tried understand the update.

In v0.1, the lines 60-62 in HX711.cpp is:

	data[2] ^= 0x80;

return ((uint32_t) data[2] << 16) | ((uint32_t) data[1] << 8) | (uint32_t) data[0];

and in v0.7. this was updated to (lines 172-184):

	// Replicate the most significant bit to pad out a 32-bit signed integer
	if (data[2] & 0x80) {
		filler = 0xFF;
	} else {
		filler = 0x00;
	}

	// Construct a 32-bit signed integer
	value = ( static_cast<unsigned long>(filler) << 24
			| static_cast<unsigned long>(data[2]) << 16
			| static_cast<unsigned long>(data[1]) << 8
			| static_cast<unsigned long>(data[0]) );

return static_cast<long>(value);

I did this C code to try understand the output.

/*
 * HX711 library read simulation
 */

#include <stdio.h>
#include <string.h>
#include <stdint.h>

/*
 *
 * HX711 output 2's complement format
 * Min (0x800000 8388608): 10000000 00000000 00000000
 * Max (0x7FFFFF 8388607): 01111111 11111111 11111111
 *
 */

int main()
{
  uint32_t value;
  uint8_t data[3] = {0};
  uint8_t filler = 0;

  printf("\n-----------V0.1-----------\n");

  // Min (0x800000 8388608): 10000000 00000000 00000000
  data[0] = 0b00000000;
  data[1] = 0b00000000;
  data[2] = 0b10000000;

  data[2] ^= 0x80; //10000000
  value = 0;
  value |= data[2] << 16;
  value |= data[1] << 8;
  value |= data[0];

  printf("Min Value: (DEC)%d | (LONG)%u\n", value, value);


  // Max (0x7FFFFF 8388607): 01111111 11111111 11111111
  data[0] = 0b11111111;
  data[1] = 0b11111111;
  data[2] = 0b01111111;

  data[2] ^= 0x80; //10000000
  value = 0;
  value |= data[2] << 16;
  value |= data[1] << 8;
  value |= data[0];

  printf("Max Value: (DEC)%d | (LONG)%u\n", value, value);

  printf("\n-----------V0.7-----------\n");

  // Min (0x800000 8388608): 10000000 00000000 00000000
  data[0] = 0b00000000;
  data[1] = 0b00000000;
  data[2] = 0b10000000;

  if (data[2] & 0x80) //10000000
  {
    filler = 0xFF;  //11111111
  } else {
    filler = 0x00;  //00000000
  }
  value = 0;
  value |= filler << 24;
  value |= data[2] << 16;
  value |= data[1] << 8;
  value |= data[0];

  printf("Min Value: (DEC)%d | (LONG)%u\n", value, value);

  // Max (0x7FFFFF 8388607): 01111111 11111111 11111111
  data[0] = 0b11111111;
  data[1] = 0b11111111;
  data[2] = 0b01111111;

  if (data[2] & 0x80) //10000000
  {
    filler = 0xFF;  //11111111
  } else {
    filler = 0x00;  //00000000
  }
  value = 0;
  value |= filler << 24;
  value |= data[2] << 16;
  value |= data[1] << 8;
  value |= data[0];

  printf("Max Value: (DEC)%d | (LONG)%u\n", value, value);

  return 0;
}

And the code output:

-----------V0.1-----------
Min Value: (DEC)0 | (LONG)0
Max Value: (DEC)16777215 | (LONG)16777215

-----------V0.7-----------
Min Value: (DEC)-8388608 | (LONG)4286578688
Max Value: (DEC)8388607 | (LONG)8388607

Other point is that function return uint32_t (unsigned long) not int32_t (signed long). Then, the filler code may result in unexpected value.

Best regards!

Mario

MarioJose avatar Aug 29 '19 19:08 MarioJose

Dear Mario,

I noted that when nothing is connected in channel A, for instance, in version 0.1, the raw output was 8388608 (~0V).

Re-reading this, https://community.hiveeyes.org/t/hx711-with-arduino-uno-constant-8388607-output/2603 might also spark your interest.

But, now in version 0.7, when nothing is connected in channel A, the raw output is 0 (~0V). Maybe I not found the commit alerting about this. Revising commits I noted only warning about constructors. If library spring 2019 updates in this level, a note must be added in README. This update broke compatibility with older code more than the constructor line.

I'm still not sure what could have changed that, but the new behavior feels more sensible, right?

Saying that, we will be very happy about a pull request adding an appropriate admonition note to the README file.

Thanks already and with kind regards, Andreas.

amotl avatar Dec 01 '19 23:12 amotl