Skip to main content

Load Cell

Load cells measure force/weight to detect object presence, evaluate structural loading, or monitor mechanical stress. The system supports a dual load cell configuration.configuration, each read through its own HX711 24-bit ADC using GPIO bit-banging. This is the most complete sensor driver on the board: it talks to real hardware with no compile gate.

Hardware Specifications

Parameter

Value

Sensor Count

2 (independent)

ADC

HX711 24-bit, one per load cell

Interface

AnalogGPIO ADCbit-bang (DOUT input, SCK output)

Gain

Channel A, gain 128 (LOAD_CELL_GAIN_PULSES = 1)

Measurement

Force (Newtons) / Mass (grams) after calibration; raw counts always available

UpdateReady Ratetimeout

Configurable200 ms (LOAD_CELL_READY_TIMEOUT_MS)

Supply

HX711 VCC 2.7 to 5.5 V, GND common with the STM32

Wiring and Pin Map (from firmware.ioc)

Unit

HX711 DOUT (data, low = ready)

HX711 SCK (clock)

0

PA5 (WEIGHT_INPUT_1)

PC7 (WEIGHT_CLOCK_1)

1

PA6 (WEIGHT_INPUT_2)

PB5 (WEIGHT_CLOCK_2)

Data Structure

typedef struct {
  // Raw Reading
    int32_t raw_counts;               /* 24-bit two's complement reading */ ADC value from sensor
    
    // Converted Measurements
  float force_newtons;
  // Force in Newtons (N)
    float mass_grams;                   // Equivalent mass in grams (g)
    
    // Calibration Parameters
  float scale_newtons_per_count;    //* Conversiondefault factor1.0 (N/count)passthrough) */
  int32_t tare_offset_counts;         // Zero-load ADC offset
    
    // Status
  bool is_calibrated;               /* true once load_cell_set_scale() called */
  Calibrationbool validread_ok;                     flag/* true if the last poll succeeded */

  /* HX711 hardware binding (set by load_cell_sensor_init_hw) */
  GPIO_TypeDef *dout_port;
  uint16_t dout_pin;
  GPIO_TypeDef *sck_port;
  uint16_t sck_pin;
  uint8_t gain_pulses;
} load_cell_data_t;

Initialization

Initialize Load Cells (as in main.c)

load_cell_data_t load_cell_data[2];

//* SupportUnit 20: sensors

for (size_t iDOUT = 0;PA5, iSCK <= 2;PC7. i++)Unit {1: DOUT = PA6, SCK = PB5. */
load_cell_sensor_init_hw(&load_cell_data[0], GPIOA, GPIO_PIN_5, GPIOC, GPIO_PIN_7);
load_cell_sensor_init_hw(&load_cell_data[1], GPIOA, GPIO_PIN_6, GPIOB, GPIO_PIN_5);
/* init_hw powers up the HX711 and auto-tares */

/* Alternative: load_cell_sensor_init(&load_cell_data[i]data) zero-initialises WITHOUT a
 * hardware binding; poll(); }then returns RESULT_ERR_UNIMPLEMENTED */

Poll Load Cell Sensor

result_t lc_result = poll_load_cell_sensor(&load_cell_data[0]i]);

if (lc_result == RESULT_OK) {
    float force = load_cell_data[0].force_newtons;
    float mass = load_cell_data[0].mass_grams;
    int32_t raw = load_cell_data[0].raw_counts;
}

Data Access Functions

//float Getforce, force in Newtons
result_t load_cell_get_force_newtons(
    const load_cell_data_t *data,scale;
float *force_newtons
);

// Get mass in grams (estimated)
result_t load_cell_get_mass_grams(
    const load_cell_data_t *data,
    float *mass_grams
);

// Get raw ADC counts
result_t load_cell_get_raw_counts(
    const load_cell_data_t *data,mass;
int32_t *raw_countscounts, );

// Get calibration parameters
result_t load_cell_get_calibration(
    const load_cell_data_t *data,
    float *scale_newtons_per_count,
    int32_t *tare_offset_counts
);

// Verify sensor validity
result_t load_cell_sensor_is_valid(
    const load_cell_data_t *data,tare;
bool *is_validvalid;

)load_cell_get_force_newtons(&cell, &force);
load_cell_get_mass_grams(&cell, &mass);
load_cell_get_raw_counts(&cell, &counts);
load_cell_get_calibration(&cell, &scale, &tare);
load_cell_sensor_is_valid(&cell, &valid);

Calibration Procedure

Two-Step Calibration

Step 1: Tare (Zero Load)

1./* RemoveWith allnothing loadon fromthe sensorcell: 2.average MeasureN ADCraw value:reads ADC_zeroand 3.store Setas tare_offset_countszero =offset.
 ADC_zero* init_hw already does this automatically at startup. */
load_cell_tare(&cell, 10);

Step 2: Span (Known Weight)

1./* Place a known weightmass, onread sensorraw 2.counts, Measurethen:
 ADC value: ADC_loaded
3. Know reference force: F_ref (Newtons)

4. Calculate scale:*   scale = (F_ref - 0.0)known_force_newtons / (ADC_loadedraw_counts - ADC_zero)tare_offset_counts)   5.*/
Setload_cell_set_scale(&cell, scale_newtons_per_countnewtons_per_count);   /* sets is_calibrated = scaletrue */

Measurement Formulas

// Raw force calculation
Forceforce_newtons = (raw_counts - tare_offset_counts) × scale_newtons_per_count
// Mass conversion (approximate)
Mass_gramsmass_grams    = (Force_newtonsforce_newtons / 9.81)81 × 1000
           ≈ Force_newtons × 102.04

Dual

Note: Sensorbefore Managementcalibration

Configurationthe Example

default
//scale Initializeis both sensors
for1.0 (size_tpassthrough): iraw_counts =is 0;trustworthy ibut <force_newtons 2;and i++)mass_grams {are load_cell_sensor_init(&load_cell_data[i]);not }physical //units Poll both in sequence
poll_load_cell_sensor(&load_cell_data[0]);
poll_load_cell_sensor(&load_cell_data[1]);

// Access by index
float load_0 = load_cell_data[0].force_newtons;
float load_1 = load_cell_data[1].force_newtons;
yet.

Protobuf Message Format

message SensorBoardLoadCellInfo {
    uint32 sensor_index;            //* 0 or 1 */
    float force_newtons;
    float mass_grams;
    int32 raw_counts;
    float scale_newtons_per_count;
    int32 tare_offset_counts;
    bool is_calibrated;
    SensorState state;
    LoadCellErrorCode error_code;   /* NO_ERROR, COMMUNICATION_FAILURE, INVALID_DATA */
}

Unit Conversions

From

To

Factor

Newtons

kilograms-force (kgf)

÷ 9.81

Newtons

pounds-force (lbf)

÷ 4.448

grams

kilograms

÷ 1000

Manual Unit Conversion Example

// Convert to pounds-force
float force_lbf = load_cell_data[0].force_newtons / 4.448f;

// Convert to kilograms
float mass_kg = load_cell_data[0].mass_grams / 1000.0f;

Typical Specifications

Load Cell Type

Max Load

Accuracy

Strain gauge (±50N)

50N

±0.1%

Load cell (±100N)

100N

±0.05%

Heavy duty (±1000N)

1000N

±0.1%

Integration Notes

  • Supports up to 2Two independent loadunits cellpolled sensors
  • Hardware-specificevery ADCmain implementation
  • Forceloop conversioniteration; viaeach linearis scalingtransmitted model
  • Tarein offsetits correctsown forenvelope sensorwith mechanicalits zero
  • Real-time monitoring of structural loadssensor_index
  • Each sensor maintains separate calibration
  • Independent (tare + scale) and independent error reporting
  • HX711 gain/channel is selected by extra SCK pulses after the 24 data bits (1 = channel A gain 128, 2 = channel B gain 32, 3 = channel A gain 64)
  • The blocking wait for data-ready can take up to 200 ms per sensorcell per poll; keep this in mind when reducing the loop interval
  • A failed read maps to state ERROR with LOAD_CELL_COMMUNICATION_FAILURE; a read with implausible data maps to LOAD_CELL_INVALID_DATA