The personal website of Scott W Harden
November 15th, 2022

Interfacing HX710 Differential ADC with Arduino

This page demonstrates how to read differential voltage from a HX710 ADC using Arduino. I recently obtained some pressure sensor boards from Amazon for less than $3 each under names like 6pcs 3.3-5V Digital Barometric Air Pressure Sensor Module Liquid Water Level Controller Board 0-40KPa that use this ADC. Several years ago I worked on a precision pressure meter project based on an I2C temperature and pressure sensor (MS5611), and now that I see new inexpensive SPI pressure sensor modules on the consumer market I'm interested to learn more about their capabilities.

Analog-to-Digital Converter IC

The ADC chip is easily identified as a HX710B 24-Bit Analog-to-Digital Converter (ADC) with Built-in Temperature Sensor. According to the datasheet it can be powered by a 3.3V or 5V supply, and the value it reports is the differential voltage between two input pins.

The datasheet indicates this device can be run from a 3.3V or 5V supply, it uses a built-in fixed-gain (128x) differential amplifier, and it can read up to 40 samples per second. The datasheet provides an example circuit demonstrating how this ADC can be used to measure weight from a scale sensor:

Pressure Sensor

To get a better idea of how this sensor works it would be helpful to locate its product number. I had a hunch it was beneath the part so I desoldered it, and indeed I found part identification information.

The pressure sensor is labeled as a PSG010S but unfortunately I struggled to find a quality datasheet for it. I did find some now-deleted images from an AliExpress listing showing the differences between the base model and the R and S variants. I found this PSG010R datasheet (curiously written in Comic Sans) indicating that maximum voltage is 5V and that the gauge pressure is 0 - 40KPa (0 - 5.8 PSI). This seems to be a fairly standard differential pressure sensor design using a pair of voltage dividers where the pressure is a function of the difference in voltage at the two mid-points (a Wheatstone bridge).

Update (2022-12-23): I received an email from somebody offering additional information about this component:

The PSG010 reports positive and negative pressures and can easily have its range shifted to almost double in one direction with almost none in the other. All that is needed is to lift the +V (2) or ground pin (5) and insert a surface mount 75R ±15R under it. Lifting the ground side by 75R makes it double positive, while pushing the applied +V down makes it double negative (vacuum).
-- bruceg

Read HX710B with Arduino

This code demonstrates how to measure HX710B values using Arduino and display the readings in the serial terminal sufficient to graph in real time using the serial plotter. The animated plot is what it looks like when I blow puffs of air on the sensor.

const int HX_OUT_PIN = 2;
const int HX_SCK_PIN = 3;

enum HX_MODE { NONE, DIFF_10Hz, TEMP_40Hz, DIFF_40Hz};
const byte HX_MODE = DIFF_40Hz;

void setup() {
  pinMode(HX_SCK_PIN, OUTPUT);
  pinMode(HX_OUT_PIN, INPUT);
  Serial.begin(9600);
}

void loop() {
  Serial.println(readHX());
}

unsigned long readHX() {

  // pulse clock line to start a reading
  for (char i = 0; i < HX_MODE; i++) {
    digitalWrite(HX_SCK_PIN, HIGH);
    digitalWrite(HX_SCK_PIN, LOW);
  }

  // wait for the reading to finish
  while (digitalRead(HX_OUT_PIN)) {}

  // read the 24-bit pressure as 3 bytes using SPI
  byte data[3];
  for (byte j = 3; j--;) {
    data[j] = shiftIn(HX_OUT_PIN, HX_SCK_PIN, MSBFIRST);
  }

  data[2] ^= 0x80;  // see note

  // shift the 3 bytes into a large integer
  long result;
  result += (long)data[2] << 16;
  result += (long)data[1] << 8;
  result += (long)data[0];

  return result;
}

Note: This code flips the most significant bit of the sensor reading. The sensor always returns this bit as 1, except for the case of an out-of-range error (see excerpt from datasheet below). By simply flipping the bit our reported values are a continuous range from 0 to 2^14-1, with the edge values representing out-of-range errors.

The output 24 bits of data is in 2’s complement format. When input differential signal goes out of the 24 bit range, the output data will be saturated at 0x800000 (MIN) or 0x7FFFFF (MAX) until the input signal comes back to the input range.
-- HX710 datasheet

Update (2022-12-23): I received an email from someone offering feedback about this code:

This code works in a loop, but perhaps by accident. The strongly worded statements in the HX710 datasheet about 25 - 27 clocks per readout imply that it is risky to rely on this. It may be that hanging clocks induce unwanted sleep modes or over-run into the next read cycle, etc. There is simply no real explanation in what is shown, so best to be safe - always set the next mode immediately AFTER collecting a reading and then always poll for new data ready before attempting a collection. Your 'pulse clock line to start a reading' loop before a reading should be 'add next mode' after a reading to comply with the timing specification. This will ensure that the next conversion will be available rather than the next scheduled conversion AFTER the mode is eventually sent.
-- bruceg

Open-Source HX710B Libraries

Although some libraries are available which facilitate interacting with the HX710, here I engage with it discretely to convey each step of the conversion and measurement process. I found that many libraries use the 10 Hz mode by default, whereas I certainly prefer the 40 Hz mode. More frustratingly, code in many libraries refer to this as gain, which is incorrect. The datasheet indicates gain is fixed at 128 and cannot be changed in software.

Update (2022-12-23): I received an email explaining why people often use "gain" and "mode" when referring to the HX710:

The HX711 is similar to the HX710 but it has user selectable gain AND user selectable sample rates BUT only certain combinations are allowed, so setting mode WILL also select its matched gain value. The HX710 uses most of the same internals, but with just 3 modes - reading the Wheatstone Bridge always using 128 gain at 10 or 40Hz while swapping to Avolt (HX710A) or internal Temperature (HX710B) uses a lower gain and less digits. So for people familiar with the HX711 there is no ambiguity in mixing mode and gain.
-- bruceg

Resources

Markdown source code last modified on December 24th, 2022
---
Title: Interfacing HX710 Differential ADC with Arduino
Description: How to read differential voltage from a HX710 ADC using Arduino
Date: 2022-11-15 12:30AM EST
Tags: circuit, microcontroller
---

# Interfacing HX710 Differential ADC with Arduino

**This page demonstrates how to read differential voltage from a HX710 ADC using Arduino.** I recently obtained some pressure sensor boards from Amazon for less than $3 each under names like _6pcs 3.3-5V Digital Barometric Air Pressure Sensor Module Liquid Water Level Controller Board 0-40KPa_ that use this ADC. Several years ago I worked on a [precision pressure meter project](https://swharden.com/blog/2017-04-29-precision-pressure-meter-project/) based on an [I2C](https://en.wikipedia.org/wiki/I%C2%B2C)  temperature and pressure sensor ([MS5611](https://www.te.com/commerce/DocumentDelivery/DDEController?Action=showdoc&DocId=Data+Sheet%7FMS5611-01BA03%7FB3%7Fpdf%7FEnglish%7FENG_DS_MS5611-01BA03_B3.pdf%7FCAT-BLPS0036)), and now that I see new inexpensive [SPI](https://en.wikipedia.org/wiki/Serial_Peripheral_Interface) pressure sensor modules on the consumer market I'm interested to learn more about their capabilities.

<img src="hx710b-pressure-board.jpg" class="my-5 border border-dark shadow img-fluid w-75 mx-auto d-block">

## Analog-to-Digital Converter IC

**The ADC chip is easily identified as a [HX710B](https://www.electronicscomp.com/datasheet/hx710b-ic-datasheet.pdf) _24-Bit Analog-to-Digital Converter (ADC) with Built-in Temperature Sensor_.** According to the datasheet it can be powered by a 3.3V or 5V supply, and the value it reports is the differential voltage between two input pins. 

<img src="hx710b-pinout.jpg" class="my-5 img-fluid w-75 mx-auto d-block">

The datasheet indicates this device can be run from a 3.3V or 5V supply, it uses a built-in fixed-gain (128x) differential amplifier, and it can read up to 40 samples per second. The datasheet provides an example circuit demonstrating how this ADC can be used to measure weight from a scale sensor:

<img src="hx710-datasheet.jpg" class="my-5 img-fluid w-75 mx-auto d-block">

## Pressure Sensor

To get a better idea of how this sensor works it would be helpful to locate its product number. I had a hunch it was beneath the part so I desoldered it, and indeed I found part identification information.

<img src="hx710b-pressure-psg010s.jpg" class="my-5 border border-dark shadow img-fluid w-75 mx-auto d-block">

**The pressure sensor is labeled as a PSG010S** but unfortunately I struggled to find a quality datasheet for it. I did find some now-deleted images from an AliExpress listing showing the differences between the base model and the R and S variants. 
I found [this PSG010R datasheet](https://www.katranji.com/tocimages/files/536845-544144.pdf) (curiously written in Comic Sans) indicating that maximum voltage is 5V and that the gauge pressure is 0 - 40KPa (0 - 5.8 PSI). This seems to be a fairly standard [differential pressure sensor](https://www.avnet.com/wps/portal/abacus/solutions/technologies/sensors/pressure-sensors/measurement-types/differential/) design using a pair of voltage dividers where the pressure is a function of the difference in voltage at the two mid-points (a [Wheatstone bridge](https://en.wikipedia.org/wiki/Wheatstone_bridge)).

**Update (2022-12-23):** I received an email from somebody offering additional information about this component:

> The PSG010 reports positive and negative pressures and can easily have its range shifted to almost double in one direction with almost none in the other.  All that is needed is to lift the +V (2) or ground pin (5) and insert a surface mount 75R ±15R under it. 
Lifting the ground side by 75R makes it double positive, while pushing the applied +V down makes it double negative (vacuum).<br>
> -- <cite class="text-end">bruceg</cite>


<img src="psg-pressure-sensor.jpg" class="my-5 border border-dark shadow img-fluid w-75 mx-auto d-block">

## Read HX710B with Arduino

**This code demonstrates how to measure HX710B values using Arduino** and display the readings in the serial terminal sufficient to graph in real time using the serial plotter. The animated plot is what it looks like when I blow puffs of air on the sensor.

<img src="hx710-arduino-plot.gif" class="my-5 img-fluid mx-auto d-block">

```c
const int HX_OUT_PIN = 2;
const int HX_SCK_PIN = 3;

enum HX_MODE { NONE, DIFF_10Hz, TEMP_40Hz, DIFF_40Hz};
const byte HX_MODE = DIFF_40Hz;

void setup() {
  pinMode(HX_SCK_PIN, OUTPUT);
  pinMode(HX_OUT_PIN, INPUT);
  Serial.begin(9600);
}

void loop() {
  Serial.println(readHX());
}

unsigned long readHX() {

  // pulse clock line to start a reading
  for (char i = 0; i < HX_MODE; i++) {
    digitalWrite(HX_SCK_PIN, HIGH);
    digitalWrite(HX_SCK_PIN, LOW);
  }

  // wait for the reading to finish
  while (digitalRead(HX_OUT_PIN)) {}

  // read the 24-bit pressure as 3 bytes using SPI
  byte data[3];
  for (byte j = 3; j--;) {
    data[j] = shiftIn(HX_OUT_PIN, HX_SCK_PIN, MSBFIRST);
  }
  
  data[2] ^= 0x80;  // see note

  // shift the 3 bytes into a large integer
  long result;
  result += (long)data[2] << 16;
  result += (long)data[1] << 8;
  result += (long)data[0];

  return result;
}
```

**Note: This code flips the most significant bit of the sensor reading.** The sensor always returns this bit as `1`, except for the case of an out-of-range error (see excerpt from datasheet below). By simply flipping the bit our reported values are a continuous range from `0` to `2^14-1`, with the edge values representing out-of-range errors.

> The output 24 bits of data is in [2’s complement format](https://en.wikipedia.org/wiki/Two%27s_complement).
> When input differential signal goes out of the 24 bit range, the output data will be saturated at `0x800000` (MIN) or `0x7FFFFF` (MAX)
> until the input signal comes back to the input range.<br>
> -- <cite class="text-end"><a href='https://www.electronicscomp.com/datasheet/hx710b-ic-datasheet.pdf'>HX710 datasheet</a></cite>

**Update (2022-12-23):** I received an email from someone offering feedback about this code:

> This code works in a loop, but perhaps by accident. The strongly worded statements in the [HX710 datasheet](https://www.electronicscomp.com/datasheet/hx710b-ic-datasheet.pdf) about 25 - 27 clocks per readout imply that it is risky to rely on this.  It may be that hanging clocks induce unwanted sleep modes or over-run into the next read cycle, etc.  There is simply no real explanation in what is shown, so best to be safe - always set the next mode immediately AFTER collecting a reading and then always poll for new data ready before attempting a collection. Your 'pulse clock line to start a reading' loop before a reading should be 'add next mode' after a reading to comply with the timing specification.  This will ensure that the next conversion will be available rather than the next scheduled conversion AFTER the mode is eventually sent.<br>
> -- <cite class="text-end">bruceg</cite>

## Open-Source HX710B Libraries

Although some libraries are available which facilitate interacting with the HX710, here I engage with it discretely to convey each step of the conversion and measurement process. I found that many libraries use the 10 Hz mode by default, whereas I certainly prefer the 40 Hz mode. More frustratingly, code in many libraries refer to this as _gain_, which is incorrect. The datasheet indicates gain is fixed at 128 and cannot be changed in software.

**Update (2022-12-23):** I received an email explaining why people often use "gain" and "mode" when referring to the HX710:

> The [HX711](https://www.digikey.com/htmldatasheets/production/1836471/0/0/1/HX711.pdf) is similar to the [HX710](https://www.electronicscomp.com/datasheet/hx710b-ic-datasheet.pdf) but it has user selectable gain AND user selectable sample rates BUT only certain combinations are allowed, so setting mode WILL also select its matched gain value.
The HX710 uses most of the same internals, but with just 3 modes - reading the Wheatstone Bridge always using 128 gain at 10 or 40Hz while swapping to Avolt (HX710A) or internal Temperature (HX710B) uses a lower gain and less digits. So for people familiar with the HX711 there is no ambiguity in mixing mode and gain.<br>
> -- <cite class="text-end">bruceg</cite>

## Resources

* [Pressure Sensor Guide](https://www.electroschematics.com/pressure-sensor-guide/) by T.K. HAREENDRAN - A similar write-up that goes into additional detail. They didn't de-solder the pressure sensor to identify the component name, but there's lots of good information on this page.

* [bogde/HX711 on GitHub](https://github.com/bogde/HX711) - An Arduino library to interface the Avia Semiconductor HX711 24-Bit Analog-to-Digital Converter (ADC) for reading load cells / weight scales. Code on this page does not use this library, but others may find it helpful.

* [HX710 datasheet (English)](https://www.electronicscomp.com/datasheet/hx710b-ic-datasheet.pdf)

* [Differential pressure sensors](https://www.avnet.com/wps/portal/abacus/solutions/technologies/sensors/pressure-sensors/measurement-types/differential/) - Article about the topic which includes a good example of an instrumentation amplifier.

* [Design tips for a resistive-bridge pressure sensor in industrial process-control systems](https://www.ti.com/lit/an/slyt640/slyt640.pdf) - Texas Instruments application note

* [The Wheatstone Bridge](https://meritsensor.com/the-wheatstone-bridge/) by Michael Daily