pico-scale
scale.c
Go to the documentation of this file.
1 // MIT License
2 //
3 // Copyright (c) 2022 Daniel Robertson
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in all
13 // copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 // SOFTWARE.
22 
23 #include <assert.h>
24 #include <math.h>
25 #include <stdbool.h>
26 #include <stddef.h>
27 #include <stdlib.h>
28 #include "pico/time.h"
29 #include "../include/scale.h"
30 #include "../include/scale_adaptor.h"
31 #include "../include/util.h"
32 
34  scale_options_t* const opt) {
35  assert(opt != NULL);
36  *opt = SCALE_DEFAULT_OPTIONS;
37 }
38 
40  scale_t* const sc,
41  scale_adaptor_t* const adaptor,
42  const mass_unit_t unit,
43  const int32_t ref_unit,
44  const int32_t offset) {
45 
46  assert(sc != NULL);
47  assert(adaptor != NULL);
48  assert(ref_unit != 0);
49 
50  sc->_adaptor = adaptor;
51  sc->unit = unit;
52  sc->ref_unit = ref_unit;
53  sc->offset = offset;
54 
55 }
56 
58  const scale_t* const sc,
59  const double* const raw,
60  double* const normalised) {
61 
62  assert(sc != NULL);
63  assert(raw != NULL);
64  assert(normalised != NULL);
65 
66  //protect against div / 0
67  if(sc->ref_unit == 0) {
68  return false;
69  }
70 
71  *normalised = (*raw - sc->offset) / sc->ref_unit;
72  return true;
73 
74 }
75 
77  scale_t* const sc,
78  int32_t* const arr,
79  const size_t len) {
80 
81  assert(sc != NULL);
82  assert(sc->_adaptor != NULL);
83  assert(arr != NULL);
84 
85  for(size_t i = 0; i < len; ++i) {
86  if(!sc->_adaptor->get_value(sc->_adaptor, &(arr[i]))) {
87  return false;
88  }
89  }
90 
91  return true;
92 
93 }
94 
96  scale_t* const sc,
97  int32_t* const arr,
98  const size_t arrlen,
99  size_t* const len,
100  const uint timeout) {
101 
102  assert(sc != NULL);
103  assert(sc->_adaptor != NULL);
104  assert(arr != NULL);
105  assert(arrlen > 0);
106  assert(len != NULL);
107 
108  //the absolute end time for seeking values (now + timeout)
109  const absolute_time_t end = make_timeout_time_us(timeout);
110  int32_t val; //temporary value from the adaptor
111  int64_t diff; //difference in us from current time to end; updated
112 
113  //reset len to 0
114  *len = 0;
115 
116  for(;;) {
117 
118  if(*len >= arrlen) {
119  //no more room left
120  break;
121  }
122 
123  //update the time diff between now and the end
124  diff = absolute_time_diff_us(get_absolute_time(), end);
125 
126  if(diff <= 0) {
127  //timeout reached
128  break;
129  }
130 
131  if(sc->_adaptor->get_value_timeout(sc->_adaptor, &val, (uint)diff)) {
132 
133  //new value available, so increase the counter
134  //this is the actual number of values obtained
135  ++(*len);
136 
137  //store the value in the array
138  arr[(*len) - 1] = val;
139 
140  }
141  else {
142  /* the last get_value_timeout call might fail because there is little time
143  left until the timeout is reached, so fail only if no values were read at all. */
144  break;
145  }
146 
147  }
148 
149  return *len > 0;
150 
151 }
152 
154  scale_t* const sc,
155  double* const val,
156  const scale_options_t* const opt) {
157 
158  assert(sc != NULL);
159  assert(val != NULL);
160  assert(opt != NULL);
161 
162  size_t len;
163  bool ok = false; //assume error
164 
165  switch(opt->strat) {
166  case strategy_type_time:
168  sc,
169  opt->buffer,
170  opt->bufflen,
171  &len,
172  opt->timeout);
173  break;
174 
176  default:
177  assert(opt->bufflen >= opt->samples);
178  len = opt->samples;
180  sc,
181  opt->buffer,
182  len);
183  break;
184  }
185 
186  //exit early if fail
187  if(!ok) {
188  return false;
189  }
190 
191  switch(opt->read) {
192  case read_type_average:
193  util_average(opt->buffer, len, val);
194  break;
195 
196  case read_type_median:
197  default:
198  util_median(opt->buffer, len, val);
199  break;
200  }
201 
202  return true;
203 
204 }
205 
207  scale_t* const sc,
208  const scale_options_t* const opt) {
209 
210  assert(sc != NULL);
211  assert(opt != NULL);
212 
213  double val;
214  const int32_t refBackup = sc->ref_unit;
215  bool ok = false;
216 
217  sc->ref_unit = 1;
218 
219  if((ok = scale_read(sc, &val, opt))) {
220  //only change the offset if the read
221  //succeeded
222  sc->offset = (int32_t)round(val);
223  }
224 
225  sc->ref_unit = refBackup;
226 
227  return ok;
228 
229 }
230 
232  scale_t* const sc,
233  mass_t* const m,
234  const scale_options_t* const opt) {
235 
236  assert(sc != NULL);
237  assert(m != NULL);
238  assert(opt != NULL);
239 
240  double val;
241 
242  //if the read fails, return false
243  if(!scale_read(sc, &val, opt)) {
244  return false;
245  }
246 
247  //if normalising the value fails, return false
248  if(!scale_normalise(sc, &val, &val)) {
249  return false;
250  }
251 
252  mass_init(m, sc->unit, val);
253 
254  return true;
255 
256 }
mass_unit_t
Definition: mass.h:64
void mass_init(mass_t *const m, const mass_unit_t unit, const double val)
Initialises a mass_t with the given unit and value.
Definition: mass.c:64
bool scale_zero(scale_t *const sc, const scale_options_t *const opt)
Zeros the scale (tare) by adjusting its offset from 0 according to the given options....
Definition: scale.c:206
bool scale_weight(scale_t *const sc, mass_t *const m, const scale_options_t *const opt)
Obtains a weight from the scale according to the given options. Returns true if the operation succeed...
Definition: scale.c:231
bool scale_get_values_samples(scale_t *const sc, int32_t *const arr, const size_t len)
Fills arr with len number of samples from the scale. Returns true if the operation succeeded.
Definition: scale.c:76
void scale_options_get_default(scale_options_t *const opt)
Fill options will default values.
Definition: scale.c:33
bool scale_read(scale_t *const sc, double *const val, const scale_options_t *const opt)
Obtains a value from the scale according to the given options. Returns true if the operation succeede...
Definition: scale.c:153
void scale_init(scale_t *const sc, scale_adaptor_t *const adaptor, const mass_unit_t unit, const int32_t ref_unit, const int32_t offset)
Initialise the scale with a hx711_t.
Definition: scale.c:39
bool scale_normalise(const scale_t *const sc, const double *const raw, double *const normalised)
Adjusts a raw value to a normalised value according to the scale's reference unit and offset....
Definition: scale.c:57
bool scale_get_values_timeout(scale_t *const sc, int32_t *const arr, const size_t arrlen, size_t *const len, const uint timeout)
Fills arr with as many number of samples as possible up to the timeout. Returns true if the operation...
Definition: scale.c:95
static const scale_options_t SCALE_DEFAULT_OPTIONS
Definition: scale.h:56
@ strategy_type_samples
Definition: scale.h:38
@ strategy_type_time
Definition: scale.h:39
@ read_type_median
Definition: scale.h:43
@ read_type_average
Definition: scale.h:44
Definition: mass.h:93
bool(* get_value)(struct scale_adaptor *const sa, int32_t *const value)
Function pointer to function.
Definition: scale_adaptor.h:46
bool(* get_value_timeout)(struct scale_adaptor *const sa, int32_t *const value, const uint timeout)
Function pointer to function.
Definition: scale_adaptor.h:56
int32_t * buffer
Definition: scale.h:52
strategy_type_t strat
Definition: scale.h:48
size_t samples
Definition: scale.h:50
read_type_t read
Definition: scale.h:49
size_t bufflen
Definition: scale.h:53
uint timeout
Definition: scale.h:51
Definition: scale.h:73
int32_t ref_unit
Definition: scale.h:75
scale_adaptor_t * _adaptor
Definition: scale.h:77
mass_unit_t unit
Definition: scale.h:74
int32_t offset
Definition: scale.h:76
void util_median(int32_t *const arr, const size_t len, double *const med)
Calculates the median value from an array of signed 32-bit integers.
Definition: util.c:46
void util_average(const int32_t *const arr, const size_t len, double *const avg)
Calculates the average value from an array of signed 32-bit integers.
Definition: util.c:27