forked from bogde/HX711
-
Notifications
You must be signed in to change notification settings - Fork 34
/
HX711-multi.cpp
179 lines (146 loc) · 4.55 KB
/
HX711-multi.cpp
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#include <Arduino.h>
#include <HX711-multi.h>
HX711MULTI::HX711MULTI(int count, byte *dout, byte pd_sck, byte gain) {
PD_SCK = pd_sck;
DOUT = dout; //TODO - make the input of dout to the function a const, or otherwise copy the values for local storage
COUNT = count;
debugEnabled = false;
pinMode(PD_SCK, OUTPUT);
for (int i=0; i<count; i++) {
pinMode(DOUT[i], INPUT);
}
set_gain(gain);
OFFSETS = (long *) malloc(COUNT*sizeof(long));
for (int i=0; i<COUNT; ++i) {
OFFSETS[i] = 0;
}
}
HX711MULTI::~HX711MULTI() {
free(OFFSETS);
}
bool HX711MULTI::is_ready() {
bool result = true;
for (int i = 0; i<COUNT; ++i) {
if (digitalRead(DOUT[i]) == HIGH) {
result = false;
}
}
return result;
}
void HX711MULTI::set_gain(byte gain) {
switch (gain) {
case 128: // channel A, gain factor 128
GAIN = 1;
break;
case 64: // channel A, gain factor 64
GAIN = 3;
break;
case 32: // channel B, gain factor 32
GAIN = 2;
break;
}
digitalWrite(PD_SCK, LOW);
read(); //a read is needed to get gain setting to come into effect. (for the next read)
}
byte HX711MULTI::get_count() {
return COUNT;
}
//TODO: write a function / state variable that 'learns' (stores/tracks) the expected noise figure from the cells, and automatically selects a reasonable 'tolerance' for tare.
// i.e. a 'best recently seen stability'. Keep it up-to-date automatically by updating it with every read. (reads will probably need to be time-aware)
bool HX711MULTI::tare(byte times, uint16_t tolerance) {
//TODO: change this implementation to use a smarter read strategy.
// right now samples are read 'times' times, but only the last is used (the multiple samples)
// are just being used to verify the spread is < tolerance.
//
// This should be done by creating a smarter multiple-reads function which returns a struct with values and metadata (number of good samples, standard deviation, etc.)
int i,j;
long values[COUNT];
long minValues[COUNT];
long maxValues[COUNT];
for (i=0; i<COUNT; ++i) {
minValues[i]=0x7FFFFFFF;
maxValues[i]=0x80000000;
//OFFSETS[i]=0; //<--removed this line, so that a failed tare does not undo previous tare
}
for (i=0; i<times; ++i) {
readRaw(values);
for (j=0; j<COUNT; ++j) {
if (values[j]<minValues[j]) {
minValues[j]=values[j];
}
if (values[j]>maxValues[j]) {
maxValues[j]=values[j];
}
}
}
if (tolerance!=0 && times>1) {
for (i=0; i<COUNT; ++i) {
if (abs(maxValues[i]-minValues[i])>tolerance) {
//one of the cells fluctuated more than the allowed tolerance, reject tare attempt;
if (debugEnabled) {
Serial.print("Rejecting tare: (");
Serial.print(i);
Serial.print(") ");
Serial.println(abs(maxValues[i]-minValues[i]));
}
return false;
}
}
}
//set the offsets
for (i=0; i<COUNT; ++i) {
OFFSETS[i] = values[i];
}
return true;
}
//reads from all cahnnels and sets the values into the passed long array pointer (which must have at least 'count' cells allocated)
//if you are only reading to toggle the line, and not to get values (such as in the case of setting gains) you can pass NULL.
void HX711MULTI::read(long *result) {
readRaw(result);
// Datasheet indicates the value is returned as a two's complement value, so 'stretch' the 24th bit to fit into 32 bits.
if (NULL!=result) {
for (int j = 0; j < COUNT; ++j) {
result[j] -= OFFSETS[j];
}
}
}
void HX711MULTI::readRaw(long *result) {
int i,j;
// wait for all the chips to become ready
while (!is_ready());
// pulse the clock pin 24 times to read the data
for (i = 0; i < 24; ++i) {
digitalWrite(PD_SCK, HIGH);
if (NULL!=result) {
for (j = 0; j < COUNT; ++j) {
bitWrite(result[j], 23-i, digitalRead(DOUT[j]));
}
}
digitalWrite(PD_SCK, LOW);
}
// set the channel and the gain factor for the next reading using the clock pin
for (i = 0; i < GAIN; ++i) {
digitalWrite(PD_SCK, HIGH);
digitalWrite(PD_SCK, LOW);
}
// Datasheet indicates the value is returned as a two's complement value, so 'stretch' the 24th bit to fit into 32 bits.
if (NULL!=result) {
for (j = 0; j < COUNT; ++j) {
if ( ( result[j] & 0x00800000 ) ) {
result[j] |= 0xFF000000;
} else {
result[j] &= 0x00FFFFFF; //required in lieu of re-setting the value to zero before shifting bits in.
}
}
}
}
void HX711MULTI::setDebugEnable(bool debugEnable) {
debugEnabled = debugEnable;
}
void HX711MULTI::power_down() {
digitalWrite(PD_SCK, LOW);
digitalWrite(PD_SCK, HIGH);
}
void HX711MULTI::power_up() {
digitalWrite(PD_SCK, LOW);
}