Coverage for src/main/python/hx711.py : 73%
Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1from utime import sleep_us, time
2from machine import Pin
3from micropython import const
6class HX711Exception(Exception):
7 pass
10class InvalidMode(HX711Exception):
11 pass
14class DeviceIsNotReady(HX711Exception):
15 pass
18class HX711(object):
20 """
21 Micropython driver for Avia Semiconductor's HX711
22 24-Bit Analog-to-Digital Converter
23 """
24 CHANNEL_A_128 = const(1)
25 CHANNEL_A_64 = const(3)
26 CHANNEL_B_32 = const(2)
28 DATA_BITS = const(24)
29 MAX_VALUE = const(0x7fffff)
30 MIN_VALUE = const(0x800000)
31 READY_TIMEOUT_SEC = const(5)
32 SLEEP_DELAY_USEC = const(80)
34 def __init__(self, d_out: int, pd_sck: int, channel: int = CHANNEL_A_128):
35 self.d_out_pin = Pin(d_out, Pin.IN)
36 self.pd_sck_pin = Pin(pd_sck, Pin.OUT, value=0)
37 self.channel = channel
39 def __repr__(self):
40 return "HX711 on channel %s, gain=%s" % self.channel
42 def _convert_from_twos_complement(self, value: int) -> int:
43 """
44 Converts a given integer from the two's complement format.
45 """
46 if value & (1 << (self.DATA_BITS - 1)):
47 value -= 1 << self.DATA_BITS
48 return value
50 def _set_channel(self):
51 """
52 Input and gain selection is controlled by the
53 number of the input PD_SCK pulses
54 3 pulses for Channel A with gain 64
55 2 pulses for Channel B with gain 32
56 1 pulse for Channel A with gain 128
57 """
58 for _ in range(self._channel):
59 self.pd_sck_pin.value(1)
60 self.pd_sck_pin.value(0)
62 def _wait(self):
63 """
64 If the HX711 is not ready within READY_TIMEOUT_SEC
65 the DeviceIsNotReady exception will be thrown.
66 """
67 t0 = time()
68 while not self.is_ready():
69 if time() - t0 > self.READY_TIMEOUT_SEC:
70 raise DeviceIsNotReady()
72 @property
73 def channel(self) -> tuple:
74 """
75 Get current input channel in a form
76 of a tuple (Channel, Gain)
77 """
78 if self._channel == self.CHANNEL_A_128:
79 return 'A', 128
80 if self._channel == self.CHANNEL_A_64:
81 return 'A', 64
82 if self._channel == self.CHANNEL_B_32:
83 return 'B', 32
85 @channel.setter
86 def channel(self, value):
87 """
88 Set input channel
89 HX711.CHANNEL_A_128 - Channel A with gain 128
90 HX711.CHANNEL_A_64 - Channel A with gain 64
91 HX711.CHANNEL_B_32 - Channel B with gain 32
92 """
93 if value not in (self.CHANNEL_A_128, self.CHANNEL_A_64, self.CHANNEL_B_32):
94 raise InvalidMode('Gain should be one of HX711.CHANNEL_A_128, HX711.CHANNEL_A_64, HX711.CHANNEL_B_32')
95 else:
96 self._channel = value
98 if not self.is_ready():
99 self._wait()
101 for _ in range(self.DATA_BITS):
102 self.pd_sck_pin.value(1)
103 self.pd_sck_pin.value(0)
105 self._set_channel()
107 def is_ready(self) -> bool:
108 """
109 When output data is not ready for retrieval,
110 digital output pin DOUT is high.
111 """
112 return self.d_out_pin.value() == 0
114 def power_off(self):
115 """
116 When PD_SCK pin changes from low to high
117 and stays at high for longer than 60 us ,
118 HX711 enters power down mode.
119 """
120 self.pd_sck_pin.value(0)
121 self.pd_sck_pin.value(1)
122 sleep_us(self.SLEEP_DELAY_USEC)
124 def power_on(self):
125 """
126 When PD_SCK returns to low, HX711 will reset
127 and enter normal operation mode.
128 """
129 self.pd_sck_pin.value(0)
130 self.channel = self._channel
132 def read(self, raw=False):
133 """
134 Read current value for current channel with current gain.
135 if raw is True, the HX711 output will not be converted
136 from two's complement format.
137 """
138 if not self.is_ready():
139 self._wait()
141 raw_data = 0
142 for _ in range(self.DATA_BITS):
143 self.pd_sck_pin.value(1)
144 self.pd_sck_pin.value(0)
145 raw_data = raw_data << 1 | self.d_out_pin.value()
146 self._set_channel()
148 if raw:
149 return raw_data
150 else:
151 return self._convert_from_twos_complement(raw_data)