Skip to content

Commit ea83610

Browse files
committed
Added load_cell device driver
1 parent 5073494 commit ea83610

1 file changed

Lines changed: 184 additions & 0 deletions

File tree

devices/load_cell.py

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
# pyControl driver for NAU7802 load cell amplifier.
2+
# Adapted from https://github.com/longapalooza/nau7802py
3+
4+
import time
5+
from machine import I2C, SoftI2C
6+
7+
ADDR = 0x2A # I2C address of NAU7802
8+
9+
# NAU7802 register addresses
10+
REGISTER_ADDR = {
11+
"PU_CTRL": 0x00,
12+
"CTRL1": 1,
13+
"CTRL2": 2,
14+
"ADCO_B2": 18,
15+
"ADC": 0x15,
16+
"PGA_PWR": 0x1C,
17+
}
18+
19+
# Bits in the PU_CRTL register
20+
PU_CTRL_BITS = {
21+
"PU_CTRL_RR": 0,
22+
"PU_CTRL_PUD": 1,
23+
"PU_CTRL_PUA": 2,
24+
"PU_CTRL_PUR": 3,
25+
"PU_CTRL_CS": 4,
26+
"PU_CTRL_CR": 5,
27+
"PU_CTRL_OSCS": 6,
28+
"PU_CTRL_AVDDS": 7,
29+
}
30+
31+
32+
# Bits in the CTRL1 register
33+
CTRL1_BITS = {
34+
"CTRL1_GAIN": 2,
35+
"CTRL1_VLDO": 5,
36+
"CTRL1_DRDY_SEL": 6,
37+
"CTRL1_CRP": 7,
38+
}
39+
40+
41+
# Bits to set LDO values
42+
LDO_BITS = {
43+
2.4: 0b111,
44+
2.7: 0b110,
45+
3.0: 0b101,
46+
3.3: 0b100,
47+
3.6: 0b011,
48+
3.9: 0b010,
49+
4.2: 0b001,
50+
4.5: 0b000,
51+
}
52+
53+
# Allowed gains
54+
GAIN_BITS = {
55+
128: 0b111,
56+
64: 0b110,
57+
32: 0b101,
58+
16: 0b100,
59+
8: 0b011,
60+
4: 0b010,
61+
2: 0b001,
62+
1: 0b000,
63+
}
64+
65+
# Allowed samples per second
66+
SAMPLE_RATE_BITS = {
67+
320: 0b111,
68+
80: 0b011,
69+
40: 0b010,
70+
20: 0b001,
71+
10: 0b000,
72+
}
73+
74+
75+
class Load_cell:
76+
# pyControl device for measuring a load cell using the NAU782 amplifier.
77+
78+
def __init__(self, port, offset=0, scale=1):
79+
if port.I2C:
80+
self.i2c = I2C(port.I2C, freq=100000)
81+
else:
82+
self.i2c = SoftI2C(scl=port.DIO_A, sda=port.DIO_B, freq=100000)
83+
self.OFFSET = offset # weight = slope * (DAC_value - offset)
84+
self.SCALE = scale
85+
# Initialise
86+
self.reset() # Reset all registers
87+
self.power_up() # Power on analog and digital sections of the scale
88+
self.set_LDO_voltage(4.5) # Set LDO to 4.5V
89+
self.set_gain(128) # Set gain to 128
90+
self.set_sample_rate(80) # Set samples per second to 80
91+
self.set_register(REGISTER_ADDR["ADC"], 0x30) # Turn off CLK_CHP. From 9.1 power on sequencing.
92+
self.set_bit(7, REGISTER_ADDR["PGA_PWR"]) # Enable decoupling cap on chan 2.
93+
94+
# User functions.
95+
96+
def weigh(self, times=1):
97+
return (self.read_average(times) - self.OFFSET) / self.SCALE
98+
99+
def read(self):
100+
value_bytes = self.i2c.readfrom_mem(ADDR, REGISTER_ADDR["ADCO_B2"], 3)
101+
value = int.from_bytes(value_bytes, "big")
102+
if value > 0x7FFFFF: # Handle negative values given conversion to unsigned int.
103+
value -= 0x1000000
104+
return value
105+
106+
def read_average(self, times=3):
107+
sum = 0
108+
for i in range(times):
109+
sum += self.read()
110+
return sum / times
111+
112+
def tare(self, times=15):
113+
# Set the 0 value.
114+
self.OFFSET = self.read_average(times)
115+
116+
def calibrate(self, weight=1, times=15):
117+
# Calibrate the scale using a known weight, must be done after scale has beenn tared.
118+
self.SCALE = (self.read_average(times) - self.OFFSET) / weight
119+
120+
def available(self):
121+
# Returns true if Cycle Ready bit is set (conversion is complete)
122+
return self.get_bit(PU_CTRL_BITS["PU_CTRL_CR"], REGISTER_ADDR["PU_CTRL"])
123+
124+
# Configuration functions.
125+
126+
def reset(self):
127+
# Resets all registers to Power Of Defaults
128+
self.set_bit(PU_CTRL_BITS["PU_CTRL_RR"], REGISTER_ADDR["PU_CTRL"]) # Set RR
129+
time.sleep(0.001)
130+
self.clear_bit(PU_CTRL_BITS["PU_CTRL_RR"], REGISTER_ADDR["PU_CTRL"]) # Clear RR to leave reset state
131+
132+
def power_up(self): # Power up digital and analog sections of scale, ~2mA
133+
self.set_bit(PU_CTRL_BITS["PU_CTRL_PUD"], REGISTER_ADDR["PU_CTRL"])
134+
self.set_bit(PU_CTRL_BITS["PU_CTRL_PUA"], REGISTER_ADDR["PU_CTRL"])
135+
time.sleep(0.001)
136+
137+
def set_gain(self, gain):
138+
# Set the gain.
139+
assert gain in GAIN_BITS.keys(), "Invalid gain value"
140+
value = self.get_register(REGISTER_ADDR["CTRL1"])
141+
value &= 0b11111000 # Clear gain bits
142+
value |= GAIN_BITS[gain] # Mask in new bits
143+
self.set_register(REGISTER_ADDR["CTRL1"], value)
144+
145+
def set_LDO_voltage(self, voltage):
146+
# Set the onboard LDO voltage regulator to a given value.
147+
assert voltage in LDO_BITS.keys(), "Invalid LDO value"
148+
value = self.get_register(REGISTER_ADDR["CTRL1"])
149+
value &= 0b11000111 # Clear LDO bits
150+
value |= LDO_BITS[voltage] << 3 # Mask in new LDO bits
151+
self.set_register(REGISTER_ADDR["CTRL1"], value)
152+
self.set_bit(PU_CTRL_BITS["PU_CTRL_AVDDS"], REGISTER_ADDR["PU_CTRL"]) # Enable the internal LDO
153+
154+
def set_sample_rate(self, rate):
155+
# Set the readings per second.
156+
self.sample_rate = rate
157+
assert rate in SAMPLE_RATE_BITS.keys(), "Invalid sample rate."
158+
value = self.get_register(REGISTER_ADDR["CTRL2"])
159+
value &= 0b10001111 # Clear CRS bits
160+
value |= SAMPLE_RATE_BITS[rate] << 4 # Mask in new CRS bits
161+
self.set_register(REGISTER_ADDR["CTRL2"], value)
162+
163+
# I2C read/write operations.
164+
165+
def set_register(self, register_address, value):
166+
self.i2c.writeto_mem(ADDR, register_address, value.to_bytes(2, "little"))
167+
168+
def get_register(self, register_address):
169+
# Get contents of a register
170+
return self.i2c.readfrom_mem(ADDR, register_address, 1)[0]
171+
172+
def clear_bit(self, bit, register_address):
173+
# Set specified bit in register to 0.
174+
value = self.get_register(register_address) & ~(1 << bit)
175+
self.set_register(register_address, value)
176+
177+
def set_bit(self, bit, register_address):
178+
# Set specified bit in register to 1.
179+
value = self.get_register(register_address) | (1 << bit)
180+
return self.set_register(register_address, value)
181+
182+
def get_bit(self, bit, register_address):
183+
# Return value of a given bit within a register.
184+
return bool(self.get_register(register_address) >> bit & 1)

0 commit comments

Comments
 (0)