I wanted to use HX711 24-bit adc standalone to measure voltage range of 2mv - 20mv.

Problem is:

  1. I cannot interpret the adc readings as it is in 2's compliment.
  2. What should I do in my code (code below) so that it prints voltages not decimal values.

Tried with different values of voltages (shared below), and I am totally confused with the readings I am getting. I don't know how to convert these values in voltage. What is the logic behind. Please help!


   0mv  ---  5219,
 1.1mv  ---  5095,
 2.3mv  ---  4981,
 2.5mv  ---  4960,
 2.9mv  ---  4918,
   5mv  ---  4693,
10.6mv  ---  4075,
15.1mv  ---  3597,
22.7mv  ---  2700,
40.7mv  ---   562,
5volts  --- -8388608,
-5volts --- -8388607.

Board is arduino leonardo, and a simple voltage divider is used for voltage generation(for testing only).

A bogde/HX711 library is used: https://github.com/bogde/HX711 Code:

/#include "HX711.h"
/#define DOUT  3
/#define CLK  2

HX711 scale(DOUT, CLK);

void setup() {

void loop() {
  long avg = scale.get_value(60);
  Serial.print("Digital Code = ");

Circuit Diagram


A good plan is to start by drawing a graph. If you start by assuming the ADC is OK, then a graph will tell you what sort of offset, gain, polarity you have. Just whacking the first few numbers you posted into a spreadsheet, and doing an XY graph, yields this.

The general equation for a straight line is y=mx+c. A good ADC will have a straight line relationship between the input voltage and the output code.

The spreadsheet has two columns, one the actual input voltage, the other y=mx+c, where x is the ADC reading. I've roughly adjusted m and c to give a reasonable fit over part of the curve. I've left the offset off a bit so you can see all of both traces.

You will notice that you need to multiply the ADC reading by a small floating point number. Whether you can do this with your particular compiler, and exactly how, is a programming exercise for you.

enter image description here

As you see, the points do not fit a straight line. It might be the ADC is non-linear. It might be your voltage measurements are non linear. You will need to investigate which before you put your trust in this system.

I would suggest swinging the voltage from -FSD to +FSD (is it designed to go between +/- 5v ?) in a dozen or so steps, and then drawing a similar graph. When you can see what's happening on the large scale, examine smaller ranges. Notice where the ends of the valid range are, and see what code it outputs when it overloads. Try to understand where any discrepancies from linear are coming from.

  • \$\begingroup\$ You are write Neil, but how these values(5219,5095,4981,4960,4918,4693,4075,3597,2700,562, -8388608,-8388607) can be converted to voltage, how these are related. hx711 is a differential adc with 2's complement coding. I am getting decimal values(provided above). I calculated voltage from a multimeter, but I wanted this adc should give voltage equivalent of these readings. \$\endgroup\$ – ShivankG Jul 17 '16 at 9:46
  • \$\begingroup\$ I'm sorry, but if you can't see from a linear graph how to relate one to the other, I am not going to teach you the fundamentals of sums. OK, a big hint. Write Vout = mx+c (the equation of a straight line from sums 101), where x is the ADC reading, m and c are constants, which may be negative. Although you can solve for m and c with only two reading/output pairs using simultaneous equations, it might be easier for you to put them in a spreadsheet and play with the values of m and c until the curve fits. Hint, m will be negative, because the graph slope is. \$\endgroup\$ – Neil_UK Jul 17 '16 at 11:53
  • \$\begingroup\$ Ok, I dont want the line equations, I know them already, there must be some relationship between differential ADC count and voltage. So that I can implement in the code and it gives out voltages not these values. \$\endgroup\$ – ShivankG Jul 17 '16 at 15:07
  • \$\begingroup\$ The line equation is the relationship. Are you saying you don't know how to multiply and add floats in your code? \$\endgroup\$ – Neil_UK Jul 17 '16 at 19:26
  • \$\begingroup\$ @ShivankG OK, done the sums 101 for you in the answer, any problems now? \$\endgroup\$ – Neil_UK Jul 17 '16 at 20:00

Note that 2's complements is in a sense the "normal" signed integer representation, so what's actually required is to extend the 24-bit 2's complement to 32-bit int, which could be done like this (assuming raw contains the raw 24 bit reading from HX711):

uint32_t raw = 0 ;
... // read HX711 bits in raw
int32_t val = ((int32_t)(raw<<8))>>8;

This is just shifting the MSB to the left and then shift the singed integer back, so the sign is preserved.

Please also note that according to HX711 the common mode of the differential input should be between AGND+1.2 and AVDD-1.3. This means both inputs, i.e. A+/A- should be in this range - 1.2V to 3.7V, in the case AVDD is 5V (which it is not on a common HX711 module board). So scaling A+/A- down to the 2mV-20mV range won't work. (I had a hard time, and some extremely weird non-linear readings until a found the common mode in the spec).

So you'll need to both scale and shift your input, so both A+/A- are in the AGND+1.2 to AVDD-1.3 range.

Converting to mV ist than \$\frac{AVDD}{2^{24}}\frac{1000}{gain}val\$.


The voltage equivalence of your ADC code output depends on the full-scale range of the ADC and its resolution. For example, an ACD with a \$\pm 5\mathrm{V}\$ input range and a 10-bit output has:

\$ \frac{V_{max}-V_{min}}{2^N\mathrm{bits}} = \frac{5\mathrm{V} - (-5\mathrm{V})}{2^{10}\mathrm{bits}} = 9.765625 \frac{\mathrm{mV}}{\mathrm{LSB}} \$

The units mV/LSB are fairly common when working with ADCs. You can then find the expected input voltage by simply multiplying the current ADC count by its equivalent voltage step per count.

Looking at the HX711 datasheet from Sparkfun, the full-scale range is variable and depends on the use of the A or B inputs. From the datasheet:

Channel A differential input is designed to interface directly with a bridge sensor’s differential output. It can be programmed with a gain of 128 or 64. The large gains are needed to accommodate the small output signal from the sensor. When 5V supply is used at the AVDD pin, these gains correspond to a full-scale differential input voltage of ±20mV or ±40mV respectively.

Channel B differential input has a fixed gain of 32. The full-scale input voltage range is ±80mV, when 5V supply is used at the AVDD pin.

With the internal ADC resolution being 24 bits, you can calculate the LSB weight for each of the gains of 32, 64, and 128. The Sparkfun Library on GitHub may demonstrate how to implement this in code.

  • \$\begingroup\$ Hi user2943160, u got my problem, actually I am using this formula only, when I multiply my ADC count to LSB it not give the corresponding values e.g: LSB =4.8 nV, LSB*562 != 40mV. \$\endgroup\$ – ShivankG Jul 18 '16 at 17:31
  • \$\begingroup\$ Also, I am using ChannelA with 5 volts AVDD, a simple potential divider to scale down voltage to 2mV to 40mV. As u can see in the given I am already using the sparkfun library, I will manage to post my circuit diagram too. \$\endgroup\$ – ShivankG Jul 18 '16 at 17:37
  • \$\begingroup\$ Please post a schematic of your test setup in your question (in addition to the wiring diagram). Just show the connections for the mV signal creation and the Ain or Bin connector for the HX711. You need to make sure that your input signals are also inside the valid input range of the analog inputs. \$\endgroup\$ – user2943160 Jul 18 '16 at 19:35

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.