forked from geda/hx711-lopy
-
Notifications
You must be signed in to change notification settings - Fork 8
/
hx711_pio.py
144 lines (114 loc) · 4.54 KB
/
hx711_pio.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# MIT License
# Copyright (c) 2021
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
from machine import Pin, Timer
import time
import rp2
class HX711:
def __init__(self, clock, data, gain=128, state_machine=0):
self.clock = clock
self.data = data
self.clock.value(False)
self.GAIN = 0
self.OFFSET = 0
self.SCALE = 1
self.time_constant = 0.25
self.filtered = 0
self.sm_timer = Timer()
# create the state machine
self.sm = rp2.StateMachine(state_machine, self.hx711_pio, freq=1_000_000,
sideset_base=self.clock, in_base=self.data,
jmp_pin=self.data)
self.set_gain(gain);
@rp2.asm_pio(
sideset_init=rp2.PIO.OUT_LOW,
in_shiftdir=rp2.PIO.SHIFT_LEFT,
autopull=False,
autopush=False,
)
def hx711_pio():
pull() .side (0) # get the number of clock cycles
mov(x, osr) .side (0)
label("bitloop")
nop() .side (1) # active edge
nop() .side (1)
in_(pins, 1) .side (0) # get the pin and shift it in
jmp(x_dec, "bitloop") .side (0) # test for more bits
label("finish")
push(block) .side (0) # no, deliver data and start over
def set_gain(self, gain):
if gain is 128:
self.GAIN = 1
elif gain is 64:
self.GAIN = 3
elif gain is 32:
self.GAIN = 2
self.read()
self.filtered = self.read()
def conversion_done_cb(self, data):
self.conversion_done = True
data.irq(handler=None)
def read(self):
self.conversion_done = False
self.data.irq(trigger=Pin.IRQ_FALLING, handler=self.conversion_done_cb)
# wait for the device being ready
for _ in range(500):
if self.conversion_done == True:
break
time.sleep_ms(1)
else:
self.data.irq(handler=None)
raise OSError("Sensor does not respond")
# Feed the waiting state machine & get the data
self.sm.active(1) # start the state machine
self.sm.put(self.GAIN + 24 - 1) # set pulse count 25-27, start
result = self.sm.get() >> self.GAIN # get the result & discard GAIN bits
self.sm.active(0) # stop the state machine
if result == 0x7fffffff:
raise OSError("Sensor does not respond")
# check sign
if result > 0x7fffff:
result -= 0x1000000
return result
def read_average(self, times=3):
sum = 0
for i in range(times):
sum += self.read()
return sum / times
def read_lowpass(self):
self.filtered += self.time_constant * (self.read() - self.filtered)
return self.filtered
def get_value(self):
return self.read_lowpass() - self.OFFSET
def get_units(self):
return self.get_value() / self.SCALE
def tare(self, times=15):
self.set_offset(self.read_average(times))
def set_scale(self, scale):
self.SCALE = scale
def set_offset(self, offset):
self.OFFSET = offset
def set_time_constant(self, time_constant = None):
if time_constant is None:
return self.time_constant
elif 0 < time_constant < 1.0:
self.time_constant = time_constant
def power_down(self):
self.clock.value(False)
self.clock.value(True)
def power_up(self):
self.clock.value(False)