1 #include <twr_soil_sensor.h>
2 #include <twr_module_sensor.h>
5 #include <twr_system.h>
8 #define _TWR_SOIL_SENSOR_TMP112_ADDRESS 0x48
9 #define _TWR_SOIL_SENSOR_ZSSC3123_ADDRESS 0x28
10 #define _TWR_SOIL_SENSOR_EEPROM_ADDRESS 0x51
11 #define _TWR_SOIL_SENSOR_EEPROM_BANK_A 0x000
12 #define _TWR_SOIL_SENSOR_EEPROM_BANK_B 0x080
13 #define _TWR_SOIL_SENSOR_EEPROM_BANK_C 0x100
15 static void _twr_soil_sensor_task_interval(
void *param);
17 static void _twr_soil_sensor_task_measure(
void *param);
18 static bool _twr_soil_sensor_tmp112_init(
twr_ds28e17_t *ds28e17);
19 static bool _twr_soil_sensor_tmp112_measurement_request(
twr_ds28e17_t *ds28e17);
20 static bool _twr_soil_sensor_tmp112_data_fetch(twr_soil_sensor_sensor_t *sensor);
21 static bool _twr_soil_sensor_zssc3123_measurement_request(
twr_ds28e17_t *ds28e17);
22 static bool _twr_soil_sensor_zssc3123_data_fetch(twr_soil_sensor_sensor_t *sensor);
24 static void _twr_soil_sensor_eeprom_fill(twr_soil_sensor_sensor_t *sensor);
25 static bool _twr_soil_sensor_eeprom_save(twr_soil_sensor_sensor_t *sensor);
26 static bool _twr_soil_sensor_eeprom_read(twr_soil_sensor_sensor_t *sensor, uint8_t address,
void *buffer,
size_t length);
27 static bool _twr_soil_sensor_eeprom_write(twr_soil_sensor_sensor_t *sensor, uint8_t address,
const void *buffer,
size_t length);
31 static twr_soil_sensor_sensor_t sensor[1];
38 memset(
self, 0,
sizeof(*
self));
43 self->_sensor = sensors;
44 self->_sensor_count = sensor_count;
52 self->_event_handler = event_handler;
54 self->_event_param = event_param;
59 self->_update_interval = interval;
75 return self->_sensor_found;
80 if (self->_measurement_active)
85 self->_measurement_active =
true;
101 if (!self->_sensor[i]._temperature_raw)
106 *raw = (int16_t) self->_sensor[i]._temperature_raw >> 4;
122 *celsius = (float) raw / 16.f;
136 *fahrenheit = celsius * 1.8f + 32.f;
150 *kelvin = celsius + 273.15f;
169 if (!self->_sensor[i]._cap_valid)
174 *raw =
self->_sensor[i]._cap_raw;
188 if (!self->_sensor[i]._cap_valid)
193 uint16_t raw =
self->_sensor[i]._cap_raw;
194 uint16_t *calibration =
self->_sensor[i]._eeprom.calibration;
196 for (
int i = 0; i < 11; i++)
198 if (raw < calibration[i])
207 *moisture = (((raw - calibration[i - 1]) * 10) / (calibration[i] - calibration[i - 1])) + (10 * (i - 1));
220 for (
int i = 0; i <
self->_sensor_found; i++)
222 if (self->_sensor[i]._ds28e17._device_number == device_address)
233 if (index >= self->_sensor_found)
238 return self->_sensor[index]._ds28e17._device_number;
250 return self->_sensor[i]._eeprom.label;
262 strncpy(self->_sensor[i]._eeprom.label, label, 16);
283 self->_sensor[i]._eeprom.calibration[point] = value;
297 return _twr_soil_sensor_eeprom_save(&self->_sensor[i]);
305 static void _twr_soil_sensor_task_interval(
void *param)
316 self->_error = error;
317 self->_state = TWR_SOIL_SENSOR_STATE_ERROR;
321 static void _twr_soil_sensor_task_measure(
void *param)
325 switch (self->_state)
327 case TWR_SOIL_SENSOR_STATE_ERROR:
331 for (
int i = 0; i <
self->_sensor_found; i++)
333 self->_sensor[i]._temperature_valid =
false;
334 self->_sensor[i]._cap_valid =
false;
337 self->_measurement_active =
false;
341 if (self->_event_handler != NULL)
346 self->_state = TWR_SOIL_SENSOR_STATE_PREINITIALIZE;
350 case TWR_SOIL_SENSOR_STATE_PREINITIALIZE:
366 self->_state = TWR_SOIL_SENSOR_STATE_INITIALIZE;
372 case TWR_SOIL_SENSOR_STATE_INITIALIZE:
374 uint64_t device_address = 0;
376 self->_sensor_found = 0;
384 while ((self->_sensor_found < self->_sensor_count) &&
twr_onewire_search_next(self->_onewire, &device_address))
386 twr_ds28e17_init(&self->_sensor[self->_sensor_found]._ds28e17, self->_onewire, device_address);
388 self->_sensor_found++;
393 if (self->_sensor_found == 0)
402 for (
int i = 0; i <
self->_sensor_found; i++)
404 if (!_twr_soil_sensor_tmp112_init(&self->_sensor[i]._ds28e17))
412 for (
int i = 0; i <
self->_sensor_found; i++)
420 _twr_soil_sensor_eeprom_fill(&self->_sensor[i]);
425 _twr_soil_sensor_error(
self, error);
431 for (
int i = 0; i <
self->_sensor_found; i++)
433 if (i + 1 == self->_sensor_found)
438 _twr_soil_sensor_zssc3123_data_fetch(&self->_sensor[i]);
440 self->_sensor[i]._cap_valid =
false;
443 self->_state = TWR_SOIL_SENSOR_STATE_READY;
445 if (self->_measurement_active)
452 case TWR_SOIL_SENSOR_STATE_READY:
454 self->_state = TWR_SOIL_SENSOR_STATE_MEASURE;
460 case TWR_SOIL_SENSOR_STATE_MEASURE:
464 for (
int i = 0; i <
self->_sensor_found; i++)
466 if (!_twr_soil_sensor_zssc3123_measurement_request(&self->_sensor[i]._ds28e17))
473 if (i + 1 == self->_sensor_found)
478 if (!_twr_soil_sensor_tmp112_measurement_request(&self->_sensor[i]._ds28e17))
487 self->_state = TWR_SOIL_SENSOR_STATE_READ;
493 case TWR_SOIL_SENSOR_STATE_READ:
497 for (
int i = 0; i <
self->_sensor_found; i++)
499 if (!_twr_soil_sensor_tmp112_data_fetch(&self->_sensor[i]))
506 if (i + 1 == self->_sensor_found)
511 if (!_twr_soil_sensor_zssc3123_data_fetch(&self->_sensor[i]))
519 self->_state = TWR_SOIL_SENSOR_STATE_UPDATE;
525 case TWR_SOIL_SENSOR_STATE_UPDATE:
527 self->_measurement_active =
false;
531 if (self->_event_handler != NULL)
533 for (
int i = 0; i <
self->_sensor_found; i++)
539 self->_state = TWR_SOIL_SENSOR_STATE_READY;
545 self->_state = TWR_SOIL_SENSOR_STATE_ERROR;
552 static bool _twr_soil_sensor_tmp112_init(
twr_ds28e17_t *ds28e17)
554 const uint8_t buffer[] = { 0x01, 0x80 };
558 .memory_address = 0x01,
559 .buffer = (
void *) buffer,
560 .length =
sizeof(buffer)
566 static bool _twr_soil_sensor_tmp112_measurement_request(
twr_ds28e17_t *ds28e17)
568 const uint8_t buffer[] = { 0x81 };
572 .memory_address = 0x01,
573 .buffer = (
void *) buffer,
574 .length =
sizeof(buffer)
580 static bool _twr_soil_sensor_tmp112_data_fetch(twr_soil_sensor_sensor_t *sensor)
586 .memory_address = 0x01,
596 if ((buffer[0] & 0x81) != 0x81)
602 memory_transfer.
length = 2;
609 sensor->_temperature_raw = (uint16_t) buffer[0] << 8 | buffer[1];
610 sensor->_temperature_valid =
true;
615 static bool _twr_soil_sensor_zssc3123_measurement_request(
twr_ds28e17_t *ds28e17)
617 const uint8_t buffer[] = { _TWR_SOIL_SENSOR_ZSSC3123_ADDRESS << 1 };
621 .buffer = (
void *) buffer,
622 .length =
sizeof(buffer)
628 static bool _twr_soil_sensor_zssc3123_data_fetch(twr_soil_sensor_sensor_t *sensor)
635 .length =
sizeof(buffer)
643 if ((buffer[0] & 0xc0) == 0)
645 sensor->_cap_raw = (uint16_t) (buffer[0] & 0x3f) << 8 | buffer[1];
647 sensor->_cap_valid =
true;
657 if (!_twr_soil_sensor_eeprom_read(sensor, 0, &header,
sizeof(header)))
690 static void _twr_soil_sensor_eeprom_fill(twr_soil_sensor_sensor_t *sensor)
692 sensor->_eeprom.product = 0;
693 sensor->_eeprom.revision = 0x0104;
695 sensor->_eeprom.calibration[0] = 1700;
696 sensor->_eeprom.calibration[10] = 3000;
698 uint16_t step = (sensor->_eeprom.calibration[10] - sensor->_eeprom.calibration[0]) / 11;
700 for (
int i = 1; i < 10; i++)
702 sensor->_eeprom.calibration[i] = sensor->_eeprom.calibration[i - 1] + step;
705 memset(sensor->_eeprom.label, 0,
sizeof(sensor->_eeprom.label));
708 static bool _twr_soil_sensor_eeprom_save(twr_soil_sensor_sensor_t *sensor)
717 if (!_twr_soil_sensor_eeprom_write(sensor, 0, &header,
sizeof(header)))
730 static bool _twr_soil_sensor_eeprom_read(twr_soil_sensor_sensor_t *sensor, uint8_t address,
void *buffer,
size_t length)
733 uint8_t b[
sizeof(a)];
734 uint8_t c[
sizeof(a)];
736 if ((_TWR_SOIL_SENSOR_EEPROM_BANK_A + address + length) >= _TWR_SOIL_SENSOR_EEPROM_BANK_B)
748 for (
size_t i = 0; i < length; i +=
sizeof(a))
750 memory_transfer.
length = length - i >
sizeof(a) ?
sizeof(a) : length - i;
752 memory_transfer.
memory_address = address + i + _TWR_SOIL_SENSOR_EEPROM_BANK_A;
753 memory_transfer.
buffer = a;
760 memory_transfer.
memory_address = address + i + _TWR_SOIL_SENSOR_EEPROM_BANK_B;
761 memory_transfer.
buffer = b;
768 memory_transfer.
memory_address = address + i + _TWR_SOIL_SENSOR_EEPROM_BANK_C;
769 memory_transfer.
buffer = c;
776 for (j = 0; j < memory_transfer.
length; j++)
778 *p++ = (a[j] & b[j]) | (a[j] & c[j]) | (b[j] & c[j]);
787 uint8_t *original_buffer = memory_transfer->
buffer;
789 for (
int i = 0;; i++)
791 memory_transfer->
buffer = test_buffer;
798 memory_transfer->
buffer = original_buffer;
800 if (memcmp(original_buffer, test_buffer, memory_transfer->
length) == 0)
819 static bool _twr_soil_sensor_eeprom_write(twr_soil_sensor_sensor_t *sensor, uint8_t address,
const void *buffer,
size_t length)
821 if ((_TWR_SOIL_SENSOR_EEPROM_BANK_A + address + length) >= _TWR_SOIL_SENSOR_EEPROM_BANK_B)
832 for (
size_t i = 0; i < length; i +=
sizeof(test))
834 memory_transfer.
length = length - i >
sizeof(test) ?
sizeof(test) : length - i;
835 memory_transfer.
memory_address = address + i + _TWR_SOIL_SENSOR_EEPROM_BANK_A;
836 memory_transfer.
buffer = (uint8_t *) buffer + i;
838 if (!_twr_soil_sensor_eeprom_write_chunk(&sensor->_ds28e17, &memory_transfer, test))
843 memory_transfer.
memory_address = address + i + _TWR_SOIL_SENSOR_EEPROM_BANK_B;
845 if (!_twr_soil_sensor_eeprom_write_chunk(&sensor->_ds28e17, &memory_transfer, test))
850 memory_transfer.
memory_address = address + i + _TWR_SOIL_SENSOR_EEPROM_BANK_C;
852 if (!_twr_soil_sensor_eeprom_write_chunk(&sensor->_ds28e17, &memory_transfer, test))
bool twr_ds28e17_write(twr_ds28e17_t *self, const twr_i2c_transfer_t *transfer)
Write to I2C.
bool twr_ds28e17_memory_read(twr_ds28e17_t *self, const twr_i2c_memory_transfer_t *transfer)
Memory read from I2C.
bool twr_ds28e17_memory_write(twr_ds28e17_t *self, const twr_i2c_memory_transfer_t *transfer)
Memory write to I2C.
void twr_ds28e17_init(twr_ds28e17_t *self, twr_onewire_t *onewire, uint64_t device_number)
Initialize DS28E17.
bool twr_ds28e17_read(twr_ds28e17_t *self, const twr_i2c_transfer_t *transfer)
Read from I2C.
twr_onewire_t * twr_module_sensor_get_onewire(void)
Initialize and get Instance 1-Wire for channel B.
bool twr_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 twr_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.
bool twr_module_sensor_init(void)
Initialize Sensor Module.
void twr_onewire_search_start(twr_onewire_t *self, uint8_t family_code)
Start of manual search, see also twr_onewire_search_next.
bool twr_onewire_transaction_start(twr_onewire_t *self)
Start transaction, enable pll and run timer.
bool twr_onewire_reset(twr_onewire_t *self)
Reset the 1-Wire bus and return the presence of any device.
uint16_t twr_onewire_crc16(const void *buffer, size_t length, uint16_t crc)
Calculate 16-bit CRC, polynomial 0x8005.
bool twr_onewire_transaction_stop(twr_onewire_t *self)
Stop transaction.
void twr_onewire_auto_ds28e17_sleep_mode(twr_onewire_t *self, bool on)
Enable call sleep mode for all ds28e17 after transaction.
bool twr_onewire_search_next(twr_onewire_t *self, uint64_t *device_number)
Manual search of next device.
void twr_scheduler_plan_current_from_now(twr_tick_t tick)
Schedule current task to tick relative from now.
void twr_scheduler_plan_current_relative(twr_tick_t tick)
Schedule current task to tick relative from current spin.
void twr_scheduler_plan_absolute(twr_scheduler_task_id_t task_id, twr_tick_t tick)
Schedule specified task to absolute tick.
void twr_scheduler_plan_now(twr_scheduler_task_id_t task_id)
Schedule specified task for immediate execution.
void twr_scheduler_plan_current_now(void)
Schedule current task for immediate execution.
void twr_scheduler_plan_relative(twr_scheduler_task_id_t task_id, twr_tick_t tick)
Schedule specified task to tick relative from current spin.
twr_scheduler_task_id_t twr_scheduler_register(void(*task)(void *), void *param, twr_tick_t tick)
Register task in scheduler.
bool twr_soil_sensor_get_moisture(twr_soil_sensor_t *self, uint64_t device_address, int *moisture)
Get measured moisture in percent.
twr_soil_sensor_error_t twr_soil_sensor_get_error(twr_soil_sensor_t *self)
Get error number.
bool twr_soil_sensor_get_temperature_raw(twr_soil_sensor_t *self, uint64_t device_address, int16_t *raw)
Get measured temperature as raw value.
char * twr_soil_sensor_get_label(twr_soil_sensor_t *self, uint64_t device_address)
Get device label by its device address.
int twr_soil_sensor_get_index_by_device_address(twr_soil_sensor_t *self, uint64_t device_address)
Get device index by its device address.
int twr_soil_sensor_get_sensor_found(twr_soil_sensor_t *self)
Get sensors found.
struct twr_soil_sensor_t twr_soil_sensor_t
Soil sensor instance.
bool twr_soil_sensor_measure(twr_soil_sensor_t *self)
Start measurement manually.
uint64_t twr_soil_sensor_get_device_address_by_index(twr_soil_sensor_t *self, int index)
Get device device address by its index.
bool twr_soil_sensor_get_temperature_celsius(twr_soil_sensor_t *self, uint64_t device_address, float *celsius)
Get measured temperature in degrees of Celsius.
bool twr_soil_sensor_get_temperature_fahrenheit(twr_soil_sensor_t *self, uint64_t device_address, float *fahrenheit)
Get measured temperature in degrees of Fahrenheit.
twr_soil_sensor_event_t
Callback events.
twr_soil_sensor_error_t
Error numbers.
bool twr_soil_sensor_get_cap_raw(twr_soil_sensor_t *self, uint64_t device_address, uint16_t *raw)
Get capacite as raw value.
void twr_soil_sensor_init(twr_soil_sensor_t *self)
Initialize Soil sensor.
void twr_soil_sensor_init_multiple(twr_soil_sensor_t *self, twr_soil_sensor_sensor_t *sensors, int sensor_count)
Initialize multiple Soil sensor.
void twr_soil_sensor_set_update_interval(twr_soil_sensor_t *self, twr_tick_t interval)
Set measurement interval.
bool twr_soil_sensor_get_temperature_kelvin(twr_soil_sensor_t *self, uint64_t device_address, float *kelvin)
Get measured temperature in kelvin.
bool twr_soil_sensor_calibration_set_point(twr_soil_sensor_t *self, uint64_t device_address, uint8_t point, uint16_t value)
Set value for calibration point by device address.
bool twr_soil_sensor_set_label(twr_soil_sensor_t *self, uint64_t device_address, const char *label)
Get device label by its device address.
void twr_soil_sensor_set_event_handler(twr_soil_sensor_t *self, void(*event_handler)(twr_soil_sensor_t *, uint64_t, twr_soil_sensor_event_t, void *), void *event_param)
Set callback function.
bool twr_soil_sensor_eeprom_save(twr_soil_sensor_t *self, uint64_t device_address)
Save calibration points and label to eeprom by device address.
@ TWR_SOIL_SENSOR_EVENT_UPDATE
Update event.
@ TWR_SOIL_SENSOR_EVENT_ERROR
Error event.
@ TWR_SOIL_SENSOR_ERROR_EEPROM_PAYLOAD_CRC
EEPROM payload crc error.
@ TWR_SOIL_SENSOR_ERROR_TMP112_MEASUREMENT_REQUEST
Tmp112 measurement request.
@ TWR_SOIL_SENSOR_ERROR_NONE
No error.
@ TWR_SOIL_SENSOR_ERROR_ZSSC3123_MEASUREMENT_REQUEST
Zssc3123 measurement request.
@ TWR_SOIL_SENSOR_ERROR_TMP112_DATA_FETCH
Tmp112 data fetch.
@ TWR_SOIL_SENSOR_ERROR_EEPROM_HEADER_READ
EEPROM header read error.
@ TWR_SOIL_SENSOR_ERROR_EEPROM_PAYLOAD_LENGTH
EEPROM payload length error.
@ TWR_SOIL_SENSOR_ERROR_ZSSC3123_DATA_FETCH
Zssc3123 data fetch.
@ TWR_SOIL_SENSOR_ERROR_SENSOR_MODULE_INITIALIZE
Sensor Module initialize error.
@ TWR_SOIL_SENSOR_ERROR_EEPROM_PAYLOAD_READ
EEPROM payload readerror.
@ TWR_SOIL_SENSOR_ERROR_SENSOR_MODULE_POWER_UP
Sensor Module onewire power up error.
@ TWR_SOIL_SENSOR_ERROR_EEPROM_SIGNATURE
EEPROM signature error.
@ TWR_SOIL_SENSOR_ERROR_EEPROM_VERSION
EEPROM version error.
@ TWR_SOIL_SENSOR_ERROR_NO_SENSOR_FOUND
No sensor found.
@ TWR_SOIL_SENSOR_ERROR_TMP112_INITIALIZE
Tmp112 inicialize error.
#define TWR_TICK_INFINITY
Maximum timestamp value.
uint64_t twr_tick_t
Timestamp data type.
I2C memory transfer parameters.
uint32_t memory_address
8-bit I2C memory address (it can be extended to 16-bit format if OR-ed with TWR_I2C_MEMORY_ADDRESS_16...
uint8_t device_address
7-bit I2C device address
size_t length
Length of buffer which is being written or read.
void * buffer
Pointer to buffer which is being written or read.
uint8_t device_address
7-bit I2C device address