This repository has been archived by the owner on Dec 13, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathhx711_rpio.go
132 lines (114 loc) · 3.34 KB
/
hx711_rpio.go
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
// +build !windows,gpiomem
package hx711
import (
"fmt"
"strconv"
"time"
"github.com/stianeikeland/go-rpio/v4"
)
// HostInit opens /dev/gpiomem. This needs to be done before Hx711 can be used.
func HostInit() error {
return rpio.Open()
}
// NewHx711 creates new Hx711.
// Make sure to set clockPinName and dataPinName to the correct pins.
// The pin numbers must comply with BCM numbering schema.
// https://cdn.sparkfun.com/datasheets/Sensors/ForceFlex/hx711_english.pdf
// https://godoc.org/github.com/stianeikeland/go-rpio#Pin
func NewHx711(clockPinName string, dataPinName string) (*Hx711, error) {
clockPin, err := strconv.ParseInt(clockPinName, 10, 32)
if err != nil {
return nil, err
}
dataPin, err := strconv.ParseInt(dataPinName, 10, 32)
if err != nil {
return nil, err
}
hx711 := &Hx711{numEndPulses: 1}
hx711.clockPin = rpio.Pin(int(clockPin))
hx711.dataPin = rpio.Pin(int(dataPin))
hx711.dataPin.Input()
hx711.clockPin.Output()
return hx711, nil
}
// setClockHighThenLow sets clock pin high then low
func (hx711 *Hx711) setClockHighThenLow() error {
hx711.clockPin.Write(rpio.High)
hx711.clockPin.Write(rpio.Low)
return nil
}
// Reset starts up or resets the chip.
// The chip needs to be reset if it is not used for just about any amount of time.
func (hx711 *Hx711) Reset() error {
hx711.clockPin.Write(rpio.Low)
hx711.clockPin.Write(rpio.High)
time.Sleep(70 * time.Microsecond)
hx711.clockPin.Write(rpio.Low)
return nil
}
// Shutdown puts the chip in powered down mode.
// The chip should be shutdown if it is not used for just about any amount of time.
func (hx711 *Hx711) Shutdown() error {
hx711.clockPin.Write(rpio.High)
return nil
}
// waitForDataReady waits for data to go to low which means chip is ready
func (hx711 *Hx711) waitForDataReady() error {
var level rpio.State
hx711.dataPin.Detect(rpio.FallEdge)
hx711.clockPin.Write(rpio.Low)
defer hx711.dataPin.Detect(rpio.NoEdge)
level = hx711.dataPin.Read()
if level == rpio.Low {
return nil
}
const (
// since there's no way to intercept the edge without using sysfs and epoll, we need to
// read the GPIO memory bit multiple times until the edge presence is detected.
EDGE_TRY_LOOP = 1500
// delay between reading attempts
BUSY_LOOP_DELAY = 250 * time.Microsecond
)
for i := 0; i < EDGE_TRY_LOOP; i++ {
if hx711.dataPin.EdgeDetected() {
return nil
}
time.Sleep(BUSY_LOOP_DELAY)
}
return ErrTimeout
}
// ReadDataRaw will get one raw reading from chip.
// Usually will need to call Reset before calling this and Shutdown after.
func (hx711 *Hx711) ReadDataRaw() (int, error) {
err := hx711.waitForDataReady()
if err != nil {
return 0, fmt.Errorf("waitForDataReady error: %v", err)
}
var level rpio.State
var data int
for i := 0; i < 24; i++ {
err = hx711.setClockHighThenLow()
if err != nil {
return 0, fmt.Errorf("setClockHighThenLow error: %v", err)
}
level = hx711.dataPin.Read()
data = data << 1
if level == rpio.High {
data++
}
}
for i := 0; i < hx711.numEndPulses; i++ {
err = hx711.setClockHighThenLow()
if err != nil {
return 0, fmt.Errorf("setClockHighThenLow error: %v", err)
}
}
// if high 24 bit is set, value is negtive
// 100000000000000000000000
if (data & 0x800000) > 0 {
// flip bits 24 and lower to get negtive number for int
// 111111111111111111111111
data |= ^0xffffff
}
return data, nil
}