Firmware SDK
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
bc_soil_sensor.c
1 #include <bc_soil_sensor.h>
2 #include <bc_module_sensor.h>
3 #include <bc_timer.h>
4 #include <bc_i2c.h>
5 #include <bc_system.h>
6 #include <bc_tick.h>
7 
8 #define _BC_SOIL_SENSOR_TMP112_ADDRESS 0x48
9 #define _BC_SOIL_SENSOR_ZSSC3123_ADDRESS 0x28
10 #define _BC_SOIL_SENSOR_EEPROM_ADDRESS 0x51
11 #define _BC_SOIL_SENSOR_EEPROM_BANK_A 0x000
12 #define _BC_SOIL_SENSOR_EEPROM_BANK_B 0x080
13 #define _BC_SOIL_SENSOR_EEPROM_BANK_C 0x100
14 
15 static void _bc_soil_sensor_task_interval(void *param);
16 static void _bc_soil_sensor_error(bc_soil_sensor_t *self, bc_soil_sensor_error_t error);
17 static void _bc_soil_sensor_task_measure(void *param);
18 static bool _bc_soil_sensor_tmp112_init(bc_ds28e17_t *ds28e17);
19 static bool _bc_soil_sensor_tmp112_measurement_request(bc_ds28e17_t *ds28e17);
20 static bool _bc_soil_sensor_tmp112_data_fetch(bc_soil_sensor_sensor_t *sensor);
21 static bool _bc_soil_sensor_zssc3123_measurement_request(bc_ds28e17_t *ds28e17);
22 static bool _bc_soil_sensor_zssc3123_data_fetch(bc_soil_sensor_sensor_t *sensor);
23 static bc_soil_sensor_error_t _bc_soil_sensor_eeprom_load(bc_soil_sensor_sensor_t *sensor);
24 static void _bc_soil_sensor_eeprom_fill(bc_soil_sensor_sensor_t *sensor);
25 static bool _bc_soil_sensor_eeprom_save(bc_soil_sensor_sensor_t *sensor);
26 static bool _bc_soil_sensor_eeprom_read(bc_soil_sensor_sensor_t *sensor, uint8_t address, void *buffer, size_t length);
27 static bool _bc_soil_sensor_eeprom_write(bc_soil_sensor_sensor_t *sensor, uint8_t address, const void *buffer, size_t length);
28 
30 {
31  static bc_soil_sensor_sensor_t sensor[1];
32 
33  bc_soil_sensor_init_multiple(self, sensor, 1);
34 }
35 
36 void bc_soil_sensor_init_multiple(bc_soil_sensor_t *self, bc_soil_sensor_sensor_t *sensors, int sensor_count)
37 {
38  memset(self, 0, sizeof(*self));
39 
40  self->_channel = BC_GPIO_P5;
41  self->_sensor = sensors;
42  self->_sensor_count = sensor_count;
43 
44  self->_task_id_interval = bc_scheduler_register(_bc_soil_sensor_task_interval, self, BC_TICK_INFINITY);
45  self->_task_id_measure = bc_scheduler_register(_bc_soil_sensor_task_measure, self, 10);
46 
47  bc_onewire_init(self->_channel);
48 
50 }
51 
52 void bc_soil_sensor_set_event_handler(bc_soil_sensor_t *self, void (*event_handler)(bc_soil_sensor_t *, uint64_t device_address, bc_soil_sensor_event_t, void *), void *event_param)
53 {
54  self->_event_handler = event_handler;
55 
56  self->_event_param = event_param;
57 }
58 
60 {
61  self->_update_interval = interval;
62 
63  if (self->_update_interval == BC_TICK_INFINITY)
64  {
65  bc_scheduler_plan_absolute(self->_task_id_interval, BC_TICK_INFINITY);
66  }
67  else
68  {
69  bc_scheduler_plan_relative(self->_task_id_interval, self->_update_interval);
70 
72  }
73 }
74 
76 {
77  return self->_sensor_found;
78 }
79 
81 {
82  if (self->_measurement_active)
83  {
84  return false;
85  }
86 
87  self->_measurement_active = true;
88 
89  bc_scheduler_plan_now(self->_task_id_measure);
90 
91  return true;
92 }
93 
94 bool bc_soil_sensor_get_temperature_raw(bc_soil_sensor_t *self, uint64_t device_address, int16_t *raw)
95 {
96  int i = bc_soil_sensor_get_index_by_device_address(self, device_address);
97 
98  if (i == -1)
99  {
100  return false;
101  }
102 
103  if (!self->_sensor[i]._temperature_raw)
104  {
105  return false;
106  }
107 
108  *raw = (int16_t) self->_sensor[i]._temperature_raw >> 4;
109 
110  return true;
111 }
112 
113 bool bc_soil_sensor_get_temperature_celsius(bc_soil_sensor_t *self, uint64_t device_address, float *celsius)
114 {
115  int16_t raw;
116 
117  if (!bc_soil_sensor_get_temperature_raw(self, device_address, &raw))
118  {
119  *celsius = NAN;
120 
121  return false;
122  }
123 
124  *celsius = (float) raw / 16.f;
125 
126  return true;
127 }
128 
129 bool bc_soil_sensor_get_temperature_fahrenheit(bc_soil_sensor_t *self, uint64_t device_address, float *fahrenheit)
130 {
131  float celsius;
132 
133  if (!bc_soil_sensor_get_temperature_celsius(self, device_address, &celsius))
134  {
135  return false;
136  }
137 
138  *fahrenheit = celsius * 1.8f + 32.f;
139 
140  return true;
141 }
142 
143 bool bc_soil_sensor_get_temperature_kelvin(bc_soil_sensor_t *self, uint64_t device_address, float *kelvin)
144 {
145  float celsius;
146 
147  if (!bc_soil_sensor_get_temperature_celsius(self, device_address, &celsius))
148  {
149  return false;
150  }
151 
152  *kelvin = celsius + 273.15f;
153 
154  if (*kelvin < 0.f)
155  {
156  *kelvin = 0.f;
157  }
158 
159  return true;
160 }
161 
162 bool bc_soil_sensor_get_cap_raw(bc_soil_sensor_t *self, uint64_t device_address, uint16_t *raw)
163 {
164  int i = bc_soil_sensor_get_index_by_device_address(self, device_address);
165 
166  if (i == -1)
167  {
168  return false;
169  }
170 
171  if (!self->_sensor[i]._cap_valid)
172  {
173  return false;
174  }
175 
176  *raw = self->_sensor[i]._cap_raw;
177 
178  return true;
179 }
180 
181 bool bc_soil_sensor_get_moisture(bc_soil_sensor_t *self, uint64_t device_address, int *moisture)
182 {
183  int i = bc_soil_sensor_get_index_by_device_address(self, device_address);
184 
185  if (i == -1)
186  {
187  return false;
188  }
189 
190  if (!self->_sensor[i]._cap_valid)
191  {
192  return false;
193  }
194 
195  uint16_t raw = self->_sensor[i]._cap_raw;
196  uint16_t *calibration = self->_sensor[i]._eeprom.calibration;
197 
198  for (int i = 0; i < 11; i++)
199  {
200  if (raw < calibration[i])
201  {
202  if (i == 0)
203  {
204  *moisture = 0;
205 
206  return true;
207  }
208 
209  *moisture = (((raw - calibration[i - 1]) * 10) / (calibration[i] - calibration[i - 1])) + (10 * (i - 1));
210 
211  return true;
212  }
213  }
214 
215  *moisture = 100;
216 
217  return true;
218 }
219 
221 {
222  for (int i = 0; i < self->_sensor_found; i++)
223  {
224  if (self->_sensor[i]._ds28e17._device_number == device_address)
225  {
226  return i;
227  }
228  }
229 
230  return -1;
231 }
232 
234 {
235  if (index >= self->_sensor_found)
236  {
237  return 0;
238  }
239 
240  return self->_sensor[index]._ds28e17._device_number;
241 }
242 
243 char *bc_soil_sensor_get_label(bc_soil_sensor_t *self, uint64_t device_address)
244 {
245  int i = bc_soil_sensor_get_index_by_device_address(self, device_address);
246 
247  if (i == -1)
248  {
249  return false;
250  }
251 
252  return self->_sensor[i]._eeprom.label;
253 }
254 
255 bool bc_soil_sensor_set_label(bc_soil_sensor_t *self, uint64_t device_address, const char *label)
256 {
257  int i = bc_soil_sensor_get_index_by_device_address(self, device_address);
258 
259  if (i == -1)
260  {
261  return false;
262  }
263 
264  strncpy(self->_sensor[i]._eeprom.label, label, 16);
265 
266  return true;
267 }
268 
269 bool bc_soil_sensor_calibration_set_point(bc_soil_sensor_t *self, uint64_t device_address, uint8_t point, uint16_t value)
270 {
271  int i = bc_soil_sensor_get_index_by_device_address(self, device_address);
272 
273  if (i == -1)
274  {
275  return false;
276  }
277 
278  point = point / 10;
279 
280  if (point > 10)
281  {
282  return false;
283  }
284 
285  self->_sensor[i]._eeprom.calibration[point] = value;
286 
287  return true;
288 }
289 
290 bool bc_soil_sensor_eeprom_save(bc_soil_sensor_t *self, uint64_t device_address)
291 {
292  int i = bc_soil_sensor_get_index_by_device_address(self, device_address);
293 
294  if (i == -1)
295  {
296  return false;
297  }
298 
299  return _bc_soil_sensor_eeprom_save(&self->_sensor[i]);
300 }
301 
303 {
304  return self->_error;
305 }
306 
307 static void _bc_soil_sensor_task_interval(void *param)
308 {
309  bc_soil_sensor_t *self = param;
310 
312 
313  bc_scheduler_plan_current_relative(self->_update_interval);
314 }
315 
316 static void _bc_soil_sensor_error(bc_soil_sensor_t *self, bc_soil_sensor_error_t error)
317 {
318  self->_error = error;
319  self->_state = BC_SOIL_SENSOR_STATE_ERROR;
321 }
322 
323 static void _bc_soil_sensor_task_measure(void *param)
324 {
325  bc_soil_sensor_t *self = param;
326 
327  switch (self->_state)
328  {
329  case BC_SOIL_SENSOR_STATE_ERROR:
330  {
332 
333  for (int i = 0; i < self->_sensor_found; i++)
334  {
335  self->_sensor[i]._temperature_valid = false;
336  self->_sensor[i]._cap_valid = false;
337  }
338 
339  self->_measurement_active = false;
340 
342 
343  if (self->_event_handler != NULL)
344  {
345  self->_event_handler(self, 0, BC_SOIL_SENSOR_EVENT_ERROR, self->_event_param);
346  }
347 
348  self->_state = BC_SOIL_SENSOR_STATE_PREINITIALIZE;
349 
350  return;
351  }
352  case BC_SOIL_SENSOR_STATE_PREINITIALIZE:
353  {
354  if (!bc_module_sensor_init())
355  {
356  _bc_soil_sensor_error(self, BC_SOIL_SENSOR_ERROR_SENSOR_MODULE_INITIALIZE);
357 
358  return;
359  }
360 
362  {
363  _bc_soil_sensor_error(self, BC_SOIL_SENSOR_ERROR_SENSOR_MODULE_POWER_UP);
364 
365  return;
366  }
367 
368  self->_state = BC_SOIL_SENSOR_STATE_INITIALIZE;
369 
371 
372  return;
373  }
374  case BC_SOIL_SENSOR_STATE_INITIALIZE:
375  {
376  uint64_t device_address = 0;
377 
378  self->_sensor_found = 0;
379 
380  bc_onewire_transaction_start(self->_channel);
381 
382  bc_onewire_reset(self->_channel);
383 
385 
386  while ((self->_sensor_found < self->_sensor_count) && bc_onewire_search_next(self->_channel, &device_address))
387  {
388  bc_ds28e17_init(&self->_sensor[self->_sensor_found]._ds28e17, self->_channel, device_address);
389 
390  self->_sensor_found++;
391  }
392 
393  bc_onewire_transaction_stop(self->_channel);
394 
395  if (self->_sensor_found == 0)
396  {
397  _bc_soil_sensor_error(self, BC_SOIL_SENSOR_ERROR_NO_SENSOR_FOUND);
398 
399  return;
400  }
401 
403 
404  for (int i = 0; i < self->_sensor_found; i++)
405  {
406  if (!_bc_soil_sensor_tmp112_init(&self->_sensor[i]._ds28e17))
407  {
408  _bc_soil_sensor_error(self, BC_SOIL_SENSOR_ERROR_TMP112_INITIALIZE);
409 
410  return;
411  }
412  }
413 
414  for (int i = 0; i < self->_sensor_found; i++)
415  {
416  bc_soil_sensor_error_t error = _bc_soil_sensor_eeprom_load(&self->_sensor[i]);
417 
418  if (error)
419  {
421  {
422  _bc_soil_sensor_eeprom_fill(&self->_sensor[i]);
423 
424  continue;
425  }
426 
427  _bc_soil_sensor_error(self, error);
428 
429  return;
430  }
431  }
432 
433  for (int i = 0; i < self->_sensor_found; i++)
434  {
435  if (i + 1 == self->_sensor_found) // last sensor
436  {
438  }
439 
440  _bc_soil_sensor_zssc3123_data_fetch(&self->_sensor[i]);
441 
442  self->_sensor[i]._cap_valid = false;
443  }
444 
445  self->_state = BC_SOIL_SENSOR_STATE_READY;
446 
447  if (self->_measurement_active)
448  {
450  }
451 
452  return;
453  }
454  case BC_SOIL_SENSOR_STATE_READY:
455  {
456  self->_state = BC_SOIL_SENSOR_STATE_MEASURE;
457 
459 
460  return;
461  }
462  case BC_SOIL_SENSOR_STATE_MEASURE:
463  {
465 
466  for (int i = 0; i < self->_sensor_found; i++)
467  {
468  if (!_bc_soil_sensor_zssc3123_measurement_request(&self->_sensor[i]._ds28e17))
469  {
470  _bc_soil_sensor_error(self, BC_SOIL_SENSOR_ERROR_ZSSC3123_MEASUREMENT_REQUEST);
471 
472  return;
473  }
474 
475  if (i + 1 == self->_sensor_found) // last sensor
476  {
478  }
479 
480  if (!_bc_soil_sensor_tmp112_measurement_request(&self->_sensor[i]._ds28e17))
481  {
482  _bc_soil_sensor_error(self, BC_SOIL_SENSOR_ERROR_TMP112_MEASUREMENT_REQUEST);
483 
484  return;
485  }
486 
487  }
488 
489  self->_state = BC_SOIL_SENSOR_STATE_READ;
490 
492 
493  return;
494  }
495  case BC_SOIL_SENSOR_STATE_READ:
496  {
498 
499  for (int i = 0; i < self->_sensor_found; i++)
500  {
501  if (!_bc_soil_sensor_tmp112_data_fetch(&self->_sensor[i]))
502  {
503  _bc_soil_sensor_error(self, BC_SOIL_SENSOR_ERROR_TMP112_DATA_FETCH);
504 
505  return;
506  }
507 
508  if (i + 1 == self->_sensor_found) // last sensor
509  {
511  }
512 
513  if (!_bc_soil_sensor_zssc3123_data_fetch(&self->_sensor[i]))
514  {
515  _bc_soil_sensor_error(self, BC_SOIL_SENSOR_ERROR_ZSSC3123_DATA_FETCH);
516 
517  return;
518  }
519  }
520 
521  self->_state = BC_SOIL_SENSOR_STATE_UPDATE;
522 
524 
525  return;
526  }
527  case BC_SOIL_SENSOR_STATE_UPDATE:
528  {
529  self->_measurement_active = false;
530 
531  self->_error = BC_SOIL_SENSOR_ERROR_NONE;
532 
533  if (self->_event_handler != NULL)
534  {
535  for (int i = 0; i < self->_sensor_found; i++)
536  {
537  self->_event_handler(self, self->_sensor[i]._ds28e17._device_number, BC_SOIL_SENSOR_EVENT_UPDATE, self->_event_param);
538  }
539  }
540 
541  self->_state = BC_SOIL_SENSOR_STATE_READY;
542 
543  return;
544  }
545  default:
546  {
547  self->_state = BC_SOIL_SENSOR_STATE_ERROR;
548 
549  return;
550  }
551  }
552 }
553 
554 static bool _bc_soil_sensor_tmp112_init(bc_ds28e17_t *ds28e17)
555 {
556  const uint8_t buffer[] = { 0x01, 0x80 };
557 
558  bc_i2c_memory_transfer_t memory_transfer = {
559  .device_address = _BC_SOIL_SENSOR_TMP112_ADDRESS,
560  .memory_address = 0x01,
561  .buffer = (void *) buffer,
562  .length = sizeof(buffer)
563  };
564 
565  return bc_ds28e17_memory_write(ds28e17, &memory_transfer);
566 }
567 
568 static bool _bc_soil_sensor_tmp112_measurement_request(bc_ds28e17_t *ds28e17)
569 {
570  const uint8_t buffer[] = { 0x81 };
571 
572  bc_i2c_memory_transfer_t memory_transfer = {
573  .device_address = _BC_SOIL_SENSOR_TMP112_ADDRESS,
574  .memory_address = 0x01,
575  .buffer = (void *) buffer,
576  .length = sizeof(buffer)
577  };
578 
579  return bc_ds28e17_memory_write(ds28e17, &memory_transfer);
580 }
581 
582 static bool _bc_soil_sensor_tmp112_data_fetch(bc_soil_sensor_sensor_t *sensor)
583 {
584  uint8_t buffer[2];
585 
586  bc_i2c_memory_transfer_t memory_transfer = {
587  .device_address = _BC_SOIL_SENSOR_TMP112_ADDRESS,
588  .memory_address = 0x01,
589  .buffer = buffer,
590  .length = 1
591  };
592 
593  if (!bc_ds28e17_memory_read(&sensor->_ds28e17, &memory_transfer))
594  {
595  return false;
596  }
597 
598  if ((buffer[0] & 0x81) != 0x81)
599  {
600  return false;
601  }
602 
603  memory_transfer.memory_address = 0x00;
604  memory_transfer.length = 2;
605 
606  if (!bc_ds28e17_memory_read(&sensor->_ds28e17, &memory_transfer))
607  {
608  return false;
609  }
610 
611  sensor->_temperature_raw = (uint16_t) buffer[0] << 8 | buffer[1];
612  sensor->_temperature_valid = true;
613 
614  return true;
615 }
616 
617 static bool _bc_soil_sensor_zssc3123_measurement_request(bc_ds28e17_t *ds28e17)
618 {
619  const uint8_t buffer[] = { _BC_SOIL_SENSOR_ZSSC3123_ADDRESS << 1 };
620 
621  bc_i2c_transfer_t transfer = {
622  .device_address = _BC_SOIL_SENSOR_ZSSC3123_ADDRESS,
623  .buffer = (void *) buffer,
624  .length = sizeof(buffer)
625  };
626 
627  return bc_ds28e17_write(ds28e17, &transfer);
628 }
629 
630 static bool _bc_soil_sensor_zssc3123_data_fetch(bc_soil_sensor_sensor_t *sensor)
631 {
632  uint8_t buffer[2];
633 
634  bc_i2c_transfer_t transfer = {
635  .device_address = _BC_SOIL_SENSOR_ZSSC3123_ADDRESS,
636  .buffer = buffer,
637  .length = sizeof(buffer)
638  };
639 
640  if (!bc_ds28e17_read(&sensor->_ds28e17, &transfer))
641  {
642  return false;
643  }
644 
645  if ((buffer[0] & 0xc0) == 0)
646  {
647  sensor->_cap_raw = (uint16_t) (buffer[0] & 0x3f) << 8 | buffer[1];
648 
649  sensor->_cap_valid = true;
650  }
651 
652  return true;
653 }
654 
655 static bc_soil_sensor_error_t _bc_soil_sensor_eeprom_load(bc_soil_sensor_sensor_t *sensor)
656 {
658 
659  if (!_bc_soil_sensor_eeprom_read(sensor, 0, &header, sizeof(header)))
660  {
662  }
663 
664  if (header.signature != 0xdeadbeef)
665  {
667  }
668 
669  if (header.version != 1)
670  {
672  }
673 
674  if (header.length != sizeof(bc_soil_sensor_eeprom_t))
675  {
677  }
678 
679  if (!_bc_soil_sensor_eeprom_read(sensor, sizeof(header), &sensor->_eeprom, sizeof(bc_soil_sensor_eeprom_t)))
680  {
682  }
683 
684  if (header.crc != bc_onewire_crc16(&sensor->_eeprom, sizeof(bc_soil_sensor_eeprom_t), 0))
685  {
687  }
688 
690 }
691 
692 static void _bc_soil_sensor_eeprom_fill(bc_soil_sensor_sensor_t *sensor)
693 {
694  sensor->_eeprom.product = 0;
695  sensor->_eeprom.revision = 0x0104;
696 
697  sensor->_eeprom.calibration[0] = 1700;
698  sensor->_eeprom.calibration[10] = 3000;
699 
700  uint16_t step = (sensor->_eeprom.calibration[10] - sensor->_eeprom.calibration[0]) / 11;
701 
702  for (int i = 1; i < 10; i++)
703  {
704  sensor->_eeprom.calibration[i] = sensor->_eeprom.calibration[i - 1] + step;
705  }
706 
707  memset(sensor->_eeprom.label, 0, sizeof(sensor->_eeprom.label));
708 }
709 
710 static bool _bc_soil_sensor_eeprom_save(bc_soil_sensor_sensor_t *sensor)
711 {
713  .signature = 0xdeadbeef,
714  .version = 1,
715  .length = sizeof(bc_soil_sensor_eeprom_t),
716  .crc = bc_onewire_crc16(&sensor->_eeprom, sizeof(bc_soil_sensor_eeprom_t), 0)
717  };
718 
719  if (!_bc_soil_sensor_eeprom_write(sensor, 0, &header, sizeof(header)))
720  {
721  return false;
722  }
723 
724  if (!_bc_soil_sensor_eeprom_write(sensor, sizeof(header), &sensor->_eeprom, sizeof(bc_soil_sensor_eeprom_t)))
725  {
726  return false;
727  }
728 
729  return true;
730 }
731 
732 static bool _bc_soil_sensor_eeprom_read(bc_soil_sensor_sensor_t *sensor, uint8_t address, void *buffer, size_t length)
733 {
734  uint8_t a[8];
735  uint8_t b[sizeof(a)];
736  uint8_t c[sizeof(a)];
737 
738  if ((_BC_SOIL_SENSOR_EEPROM_BANK_A + address + length) >= _BC_SOIL_SENSOR_EEPROM_BANK_B)
739  {
740  return false;
741  }
742 
743  bc_i2c_memory_transfer_t memory_transfer = {
744  .device_address = _BC_SOIL_SENSOR_EEPROM_ADDRESS,
745  };
746 
747  size_t j = 0;
748  uint8_t *p = buffer;
749 
750  for (size_t i = 0; i < length; i += sizeof(a))
751  {
752  memory_transfer.length = length - i > sizeof(a) ? sizeof(a) : length - i;
753 
754  memory_transfer.memory_address = address + i + _BC_SOIL_SENSOR_EEPROM_BANK_A;
755  memory_transfer.buffer = a;
756 
757  if (!bc_ds28e17_memory_read(&sensor->_ds28e17, &memory_transfer))
758  {
759  return false;
760  }
761 
762  memory_transfer.memory_address = address + i + _BC_SOIL_SENSOR_EEPROM_BANK_B;
763  memory_transfer.buffer = b;
764 
765  if (!bc_ds28e17_memory_read(&sensor->_ds28e17, &memory_transfer))
766  {
767  return false;
768  }
769 
770  memory_transfer.memory_address = address + i + _BC_SOIL_SENSOR_EEPROM_BANK_C;
771  memory_transfer.buffer = c;
772 
773  if (!bc_ds28e17_memory_read(&sensor->_ds28e17, &memory_transfer))
774  {
775  return false;
776  }
777 
778  for (j = 0; j < memory_transfer.length; j++)
779  {
780  *p++ = (a[j] & b[j]) | (a[j] & c[j]) | (b[j] & c[j]);
781  }
782  }
783 
784  return true;
785 }
786 
787 static bool _bc_soil_sensor_eeprom_write_chunk(bc_ds28e17_t *ds28e17, bc_i2c_memory_transfer_t *memory_transfer, void *test_buffer)
788 {
789  uint8_t *original_buffer = memory_transfer->buffer;
790 
791  for (int i = 0;; i++)
792  {
793  memory_transfer->buffer = test_buffer;
794 
795  if (!bc_ds28e17_memory_read(ds28e17, memory_transfer))
796  {
797  return false;
798  }
799 
800  memory_transfer->buffer = original_buffer;
801 
802  if (memcmp(original_buffer, test_buffer, memory_transfer->length) == 0)
803  {
804  return true;
805  }
806 
807  if (i > 3)
808  {
809  break;
810  }
811 
812  if (!bc_ds28e17_memory_write(ds28e17, memory_transfer))
813  {
814  return false;
815  }
816  }
817 
818  return false;
819 }
820 
821 static bool _bc_soil_sensor_eeprom_write(bc_soil_sensor_sensor_t *sensor, uint8_t address, const void *buffer, size_t length)
822 {
823  if ((_BC_SOIL_SENSOR_EEPROM_BANK_A + address + length) >= _BC_SOIL_SENSOR_EEPROM_BANK_B)
824  {
825  return false;
826  }
827 
828  bc_i2c_memory_transfer_t memory_transfer = {
829  .device_address = _BC_SOIL_SENSOR_EEPROM_ADDRESS,
830  };
831 
832  uint8_t test[2];
833 
834  for (size_t i = 0; i < length; i += sizeof(test))
835  {
836  memory_transfer.length = length - i > sizeof(test) ? sizeof(test) : length - i;
837  memory_transfer.memory_address = address + i + _BC_SOIL_SENSOR_EEPROM_BANK_A;
838  memory_transfer.buffer = (uint8_t *) buffer + i;
839 
840  if (!_bc_soil_sensor_eeprom_write_chunk(&sensor->_ds28e17, &memory_transfer, test))
841  {
842  return false;
843  }
844 
845  memory_transfer.memory_address = address + i + _BC_SOIL_SENSOR_EEPROM_BANK_B;
846 
847  if (!_bc_soil_sensor_eeprom_write_chunk(&sensor->_ds28e17, &memory_transfer, test))
848  {
849  return false;
850  }
851 
852  memory_transfer.memory_address = address + i + _BC_SOIL_SENSOR_EEPROM_BANK_C;
853 
854  if (!_bc_soil_sensor_eeprom_write_chunk(&sensor->_ds28e17, &memory_transfer, test))
855  {
856  return false;
857  }
858  }
859 
860  return true;
861 }
void * buffer
Pointer to buffer which is being written or read.
Definition: bc_i2c.h:66
I2C transfer parameters.
Definition: bc_i2c.h:42
uint64_t bc_tick_t
Timestamp data type.
Definition: bc_tick.h:16
GPIO channel P5.
Definition: bc_gpio.h:30
bool bc_soil_sensor_get_temperature_celsius(bc_soil_sensor_t *self, uint64_t device_address, float *celsius)
Get measured temperature in degrees of Celsius.
bool bc_soil_sensor_measure(bc_soil_sensor_t *self)
Start measurement manually.
uint8_t length
Data Length.
bool bc_onewire_search_next(bc_gpio_channel_t channel, uint64_t *device_number)
Manual search of next device.
Definition: bc_onewire.c:408
void bc_scheduler_plan_absolute(bc_scheduler_task_id_t task_id, bc_tick_t tick)
Schedule specified task to absolute tick.
Definition: bc_scheduler.c:124
Sensor Module initialize error.
struct bc_soil_sensor_t bc_soil_sensor_t
Soil sensor instance.
uint8_t version
Data Version.
void bc_soil_sensor_set_event_handler(bc_soil_sensor_t *self, void(*event_handler)(bc_soil_sensor_t *, uint64_t, bc_soil_sensor_event_t, void *), void *event_param)
Set callback function.
bool bc_soil_sensor_get_cap_raw(bc_soil_sensor_t *self, uint64_t device_address, uint16_t *raw)
Get capacite as raw value.
bool bc_soil_sensor_set_label(bc_soil_sensor_t *self, uint64_t device_address, const char *label)
Get device label by its device address.
uint8_t device_address
7-bit I2C device address
Definition: bc_i2c.h:45
uint64_t bc_soil_sensor_get_device_address_by_index(bc_soil_sensor_t *self, int index)
Get device device address by its index.
bc_scheduler_task_id_t bc_scheduler_register(void(*task)(void *), void *param, bc_tick_t tick)
Register task in scheduler.
Definition: bc_scheduler.c:56
void bc_scheduler_plan_now(bc_scheduler_task_id_t task_id)
Schedule specified task for immediate execution.
Definition: bc_scheduler.c:119
bool bc_ds28e17_read(bc_ds28e17_t *self, const bc_i2c_transfer_t *transfer)
Read from I2C.
Definition: bc_ds28e17.c:73
bc_soil_sensor_event_t
Callback events.
bool bc_onewire_transaction_stop(bc_gpio_channel_t channel)
Stop transaction.
Definition: bc_onewire.c:67
void bc_onewire_auto_ds28e17_sleep_mode(bool on)
Enable call sleep mode for all ds28e17 after transaction.
Definition: bc_onewire.c:545
void bc_ds28e17_init(bc_ds28e17_t *self, bc_gpio_channel_t channel, uint64_t device_number)
Initialize DS28E17.
Definition: bc_ds28e17.c:14
void bc_scheduler_plan_current_relative(bc_tick_t tick)
Schedule current task to tick relative from current spin.
Definition: bc_scheduler.c:149
bc_soil_sensor_error_t bc_soil_sensor_get_error(bc_soil_sensor_t *self)
Get error number.
uint32_t memory_address
8-bit I2C memory address (it can be extended to 16-bit format if OR-ed with BC_I2C_MEMORY_ADDRESS_16_...
Definition: bc_i2c.h:63
bool bc_soil_sensor_eeprom_save(bc_soil_sensor_t *self, uint64_t device_address)
Save calibration points and label to eeprom by device address.
bool bc_module_sensor_onewire_power_down(void)
Semaphore for 1Wire Power down: for R1.1 set VDD Off, for R1.0 pull none on channel A...
bool bc_soil_sensor_get_temperature_raw(bc_soil_sensor_t *self, uint64_t device_address, int16_t *raw)
Get measured temperature as raw value.
uint8_t device_address
7-bit I2C device address
Definition: bc_i2c.h:60
bool bc_soil_sensor_get_temperature_kelvin(bc_soil_sensor_t *self, uint64_t device_address, float *kelvin)
Get measured temperature in kelvin.
bool bc_soil_sensor_get_moisture(bc_soil_sensor_t *self, uint64_t device_address, int *moisture)
Get measured moisture in percent.
DS28E17 instance.
Definition: bc_ds28e17.h:14
void bc_soil_sensor_init(bc_soil_sensor_t *self)
Initialize Soil sensor.
void bc_onewire_search_start(uint8_t family_code)
Start of manual search, see also bc_onewire_search_next.
Definition: bc_onewire.c:396
bool bc_onewire_reset(bc_gpio_channel_t channel)
Reset the 1-Wire bus and return the presence of any device.
Definition: bc_onewire.c:91
void bc_onewire_init(bc_gpio_channel_t channel)
Initialize 1-Wire.
Definition: bc_onewire.c:35
I2C memory transfer parameters.
Definition: bc_i2c.h:57
EEPROM payload length error.
void bc_scheduler_plan_relative(bc_scheduler_task_id_t task_id, bc_tick_t tick)
Schedule specified task to tick relative from current spin.
Definition: bc_scheduler.c:129
char * bc_soil_sensor_get_label(bc_soil_sensor_t *self, uint64_t device_address)
Get device label by its device address.
void bc_soil_sensor_set_update_interval(bc_soil_sensor_t *self, bc_tick_t interval)
Set measurement interval.
int bc_soil_sensor_get_sensor_found(bc_soil_sensor_t *self)
Get sensors found.
bool bc_onewire_transaction_start(bc_gpio_channel_t channel)
Start transaction, enable pll and run timer.
Definition: bc_onewire.c:51
bc_soil_sensor_error_t
Error numbers.
uint32_t signature
Signature 0xdeadbeef.
void bc_scheduler_plan_current_from_now(bc_tick_t tick)
Schedule current task to tick relative from now.
Definition: bc_scheduler.c:154
bool bc_soil_sensor_calibration_set_point(bc_soil_sensor_t *self, uint64_t device_address, uint8_t point, uint16_t value)
Set value for calibration point by device address.
uint16_t bc_onewire_crc16(const void *buffer, size_t length, uint16_t crc)
Calculate 16-bit CRC, polynomial 0x8005.
Definition: bc_onewire.c:224
bool bc_ds28e17_write(bc_ds28e17_t *self, const bc_i2c_transfer_t *transfer)
Write to I2C.
Definition: bc_ds28e17.c:62
#define BC_TICK_INFINITY
Maximum timestamp value.
Definition: bc_tick.h:12
int bc_soil_sensor_get_index_by_device_address(bc_soil_sensor_t *self, uint64_t device_address)
Get device index by its device address.
Sensor Module onewire power up error.
bool bc_soil_sensor_get_temperature_fahrenheit(bc_soil_sensor_t *self, uint64_t device_address, float *fahrenheit)
Get measured temperature in degrees of Fahrenheit.
bool bc_ds28e17_memory_write(bc_ds28e17_t *self, const bc_i2c_memory_transfer_t *transfer)
Memory write to I2C.
Definition: bc_ds28e17.c:84
size_t length
Length of buffer which is being written or read.
Definition: bc_i2c.h:69
bool bc_module_sensor_init(void)
Initialize Sensor Module.
bool bc_module_sensor_onewire_power_up(void)
Semaphore for 1Wire Power up: for R1.1 set VDD On, for R1.0 pull up 56R on channel A...
void bc_scheduler_plan_current_now(void)
Schedule current task for immediate execution.
Definition: bc_scheduler.c:139
bool bc_ds28e17_memory_read(bc_ds28e17_t *self, const bc_i2c_memory_transfer_t *transfer)
Memory read from I2C.
Definition: bc_ds28e17.c:109
void bc_soil_sensor_init_multiple(bc_soil_sensor_t *self, bc_soil_sensor_sensor_t *sensors, int sensor_count)
Initialize multiple Soil sensor.