The image is for illustrative purposes only; please refer to the product data sheet for precise specifications.
| Part Number | HX711 |
|---|---|
| Manufacturer |
|
| Description | The HX711 is a high-precision 24-bit analog-to-digital converter (ADC) developed by Avia Semiconductor, specifically designed for weigh scale and industrial control applications. It integrates a low-noise programmable gain amplifier (PGA) and a high-resolution ADC, making it ideal for directly interfacing with load cells and strain gauges. The device features two selectable input channels, with programmable gain options of 32, 64, and 128, allowing flexible adaptation to different sensor sensitivities. Channel A supports gains of 128 or 64, while Channel B provides a fixed gain of 32 for auxiliary measurements. The HX711 operates with a simple 2-wire serial interface (clock and data), eliminating the need for complex communication protocols and making it easy to integrate with microcontrollers such as Arduino, ESP8266, and STM32 platforms. It supports selectable output data rates of 10 SPS or 80 SPS, balancing between noise performance and speed. The device includes an on-chip regulator and oscillator, reducing external component requirements and simplifying circuit design. It operates within a supply voltage range of 2.6V to 5.5V, making it suitable for both battery-powered and standard embedded systems. With its high resolution, low noise, and integrated amplification, the HX711 is widely used in applications such as digital weighing scales, industrial measurement systems, force sensors, pressure measurement, and IoT-based weight monitoring systems, where accurate and stable signal conversion is essential. |
| Product Group | ADC |
| MOQ | 2000 pcs |
| SPQ | 2000 pcs |
| Figure/Case | SOP-16 |
| Package | T&R Pack |
| | |
| Ship From | Hong Kong |
| Shipment Way | DHL / Fedex / TNT / UPS / Others |
| Delivery Term | Ex-Works |
| Send RFQ | sales@signalhk.com |
#include
#include
// =========================
// Pin definitions
// =========================
#define HX711_DOUT D5
#define HX711_SCK D6
#define TMP102_ADDR 0x48
// =========================
// Calibration structure
// =========================
struct ScaleCal {
long zero_offset; // HX711 raw @ zero load and T_ref
float scale_coeff; // counts per unit weight
float temp_zero_coeff; // counts / °C
float temp_span_coeff; // 1 / °C
float temp_ref; // °C
};
ScaleCal cal = {
0,
1000.0f, // placeholder
0.0f, // placeholder
0.0f, // placeholder
25.0f
};
// =========================
// HX711 low-level
// =========================
bool hx711_is_ready() {
return digitalRead(HX711_DOUT) == LOW;
}
long hx711_read_raw() {
while (!hx711_is_ready()) {
delay(1);
}
unsigned long value = 0;
noInterrupts();
for (uint8_t i = 0; i < 24; i++) {
digitalWrite(HX711_SCK, HIGH);
delayMicroseconds(1);
value = (value << 1) | digitalRead(HX711_DOUT);
digitalWrite(HX711_SCK, LOW);
delayMicroseconds(1);
}
// Channel A, gain 128
digitalWrite(HX711_SCK, HIGH);
delayMicroseconds(1);
digitalWrite(HX711_SCK, LOW);
interrupts();
// Sign extend 24-bit value to 32-bit signed long
if (value & 0x800000UL) {
value |= 0xFF000000UL;
}
return (long)value;
}
long hx711_read_average(uint8_t samples) {
long long sum = 0;
for (uint8_t i = 0; i < samples; i++) {
sum += hx711_read_raw();
}
return (long)(sum / samples);
}
// =========================
// TMP102 read
// =========================
bool tmp102_read_celsius(float &tempC) {
Wire.beginTransmission(TMP102_ADDR);
Wire.write(0x00); // temperature register
if (Wire.endTransmission(false) != 0) {
return false;
}
if (Wire.requestFrom(TMP102_ADDR, 2) != 2) {
return false;
}
uint8_t msb = Wire.read();
uint8_t lsb = Wire.read();
int16_t raw = ((int16_t)msb << 8) | lsb;
raw >>= 4; // TMP102 12-bit default mode
if (raw & 0x0800) {
raw |= 0xF000; // sign extend
}
tempC = raw * 0.0625f;
return true;
}
// =========================
// Weight calculation
// =========================
float scale_get_weight_units(uint8_t samples = 10) {
float T;
if (!tmp102_read_celsius(T)) {
return NAN;
}
long raw = hx711_read_average(samples);
float dt = T - cal.temp_ref;
float raw_comp = (float)raw
- (float)cal.zero_offset
- cal.temp_zero_coeff * dt;
float scale_temp = cal.scale_coeff * (1.0f + cal.temp_span_coeff * dt);
if (fabs(scale_temp) < 0.000001f) {
return NAN;
}
return raw_comp / scale_temp;
}
// =========================
// Calibration helpers
// =========================
// Step 1: tare at reference temperature
void calibrate_tare(uint8_t samples = 20) {
float T;
if (!tmp102_read_celsius(T)) {
Serial.println("TMP102 read failed");
return;
}
cal.zero_offset = hx711_read_average(samples);
cal.temp_ref = T;
Serial.println("Tare done");
Serial.print("zero_offset = "); Serial.println(cal.zero_offset);
Serial.print("temp_ref = "); Serial.println(cal.temp_ref, 4);
}
// Step 2: apply known weight at same temperature
void calibrate_scale(float known_weight, uint8_t samples = 20) {
float T;
if (!tmp102_read_celsius(T)) {
Serial.println("TMP102 read failed");
return;
}
long raw = hx711_read_average(samples);
float dt = T - cal.temp_ref;
float raw_corr = (float)raw - (float)cal.zero_offset - cal.temp_zero_coeff * dt;
cal.scale_coeff = raw_corr / known_weight;
Serial.println("Scale calibration done");
Serial.print("scale_coeff = "); Serial.println(cal.scale_coeff, 6);
}
// Step 3: zero temperature drift measurement
// Do this with NO LOAD at a different temperature
void calibrate_temp_zero(float raw_zero_at_T2, float T2) {
float dT = T2 - cal.temp_ref;
if (fabs(dT) < 0.000001f) {
Serial.println("Temperature delta too small");
return;
}
cal.temp_zero_coeff = (raw_zero_at_T2 - cal.zero_offset) / dT;
Serial.println("Temp zero calibration done");
Serial.print("temp_zero_coeff = "); Serial.println(cal.temp_zero_coeff, 6);
}
// Step 4: span temperature drift measurement
// Do this with the SAME known weight at another temperature
void calibrate_temp_span(float raw_loaded_at_T2, float known_weight, float T2) {
float dT = T2 - cal.temp_ref;
if (fabs(dT) < 0.000001f || known_weight == 0.0f) {
Serial.println("Invalid input");
return;
}
float scale2 = (raw_loaded_at_T2 - cal.zero_offset - cal.temp_zero_coeff * dT) / known_weight;
cal.temp_span_coeff = (scale2 / cal.scale_coeff - 1.0f) / dT;
Serial.println("Temp span calibration done");
Serial.print("temp_span_coeff = "); Serial.println(cal.temp_span_coeff, 8);
}
void print_cal() {
Serial.println("=== Calibration ===");
Serial.print("zero_offset = "); Serial.println(cal.zero_offset);
Serial.print("scale_coeff = "); Serial.println(cal.scale_coeff, 6);
Serial.print("temp_zero_coeff = "); Serial.println(cal.temp_zero_coeff, 6);
Serial.print("temp_span_coeff = "); Serial.println(cal.temp_span_coeff, 8);
Serial.print("temp_ref = "); Serial.println(cal.temp_ref, 4);
}
// =========================
// Setup / loop
// =========================
void setup() {
Serial.begin(115200);
delay(1000);
pinMode(HX711_DOUT, INPUT);
pinMode(HX711_SCK, OUTPUT);
digitalWrite(HX711_SCK, LOW);
Wire.begin();
Serial.println("HX711 + TMP102 scale ready");
print_cal();
// Example workflow:
// 1) With empty scale:
// calibrate_tare();
//
// 2) Place known weight, then:
// calibrate_scale(1000.0f); // e.g. 1000 grams
//
// 3) At another temperature, empty scale:
// long rz = hx711_read_average(20);
// float t2; tmp102_read_celsius(t2);
// calibrate_temp_zero((float)rz, t2);
//
// 4) At another temperature, same known weight:
// long rl = hx711_read_average(20);
// float t3; tmp102_read_celsius(t3);
// calibrate_temp_span((float)rl, 1000.0f, t3);
}
void loop() {
float T;
bool ok = tmp102_read_celsius(T);
float w = scale_get_weight_units(10);
if (ok) {
Serial.print("Temp: ");
Serial.print(T, 2);
Serial.print(" C, ");
} else {
Serial.print("Temp read error, ");
}
Serial.print("Weight: ");
Serial.println(w, 3);
delay(500);
}
Room 1304, 13/F, Allways Centre, 468 Jaffe Road, Causeway Bay, Hong Kong. |