Files
WaterTank/lib/hx710b.py
2026-06-16 13:02:06 +02:00

117 lines
3.5 KiB
Python

from machine import Pin
import time
import json
import os
CALIB_FILE = "calibration.cfg"
# ---------------------------------------------------------
# Calibration File Helpers
# ---------------------------------------------------------
def save_calibration(zero_offset, scale_factor):
"""Save calibration values to internal flash."""
data = {
"zero_offset": zero_offset,
"scale_factor": scale_factor
}
with open(CALIB_FILE, "w") as f:
json.dump(data, f)
print("✔ Calibration saved.")
def load_calibration():
"""Load existing calibration or return defaults."""
if CALIB_FILE not in os.listdir():
print("⚠ No calibration file found, using defaults.")
return 0, 1
try:
with open(CALIB_FILE, "r") as f:
data = json.load(f)
print("✔ Calibration loaded.")
return data.get("zero_offset", 0), data.get("scale_factor", 1)
except Exception as e:
print("⚠ Calibration load error:", e)
return 0, 1
# ---------------------------------------------------------
# HX710B Class
# ---------------------------------------------------------
class HX710B:
def __init__(self, dout_pin, sck_pin):
self.dout = Pin(dout_pin, Pin.IN)
self.sck = Pin(sck_pin, Pin.OUT)
self.sck.value(0)
# Load previous calibration (or defaults)
self.zero_offset, self.scale_factor = load_calibration()
# -----------------------------------------------------
# Low-level raw ADC read
# -----------------------------------------------------
def read_raw(self):
"""Read the 24-bit raw ADC value."""
while self.dout.value():
pass # wait for data ready
count = 0
for _ in range(24):
self.sck.value(1)
count = (count << 1) | self.dout.value()
self.sck.value(0)
# 25th pulse to set gain for next reading
self.sck.value(1)
self.sck.value(0)
# Signed 24-bit conversion
if count & 0x800000:
count -= 0x1000000
return count
# -----------------------------------------------------
# Zero Calibration
# -----------------------------------------------------
def calibrate_zero(self, samples=20):
"""Measure 0 kPa and determine zero offset."""
total = 0
for _ in range(samples):
total += self.read_raw()
time.sleep_ms(5)
self.zero_offset = total / samples
save_calibration(self.zero_offset, self.scale_factor)
print("✔ Zero calibrated:", self.zero_offset)
return self.zero_offset
# -----------------------------------------------------
# Full-scale / Known Pressure Calibration
# -----------------------------------------------------
def calibrate_full(self, known_kpa, samples=20):
"""Measure raw ADC at known pressure and compute scaling."""
total = 0
for _ in range(samples):
total += self.read_raw()
time.sleep_ms(5)
raw_avg = total / samples
self.scale_factor = known_kpa / (raw_avg - self.zero_offset)
save_calibration(self.zero_offset, self.scale_factor)
print("✔ Scale calibrated:", self.scale_factor)
return self.scale_factor
# -----------------------------------------------------
# Convert raw → kPa using saved calibration
# -----------------------------------------------------
def read_kpa(self):
raw = self.read_raw()
return (raw - self.zero_offset) * self.scale_factor