1 #include <twr_ds18b20.h>
2 #include <twr_onewire.h>
5 #include <twr_module_sensor.h>
8 #define _TWR_DS18B20_SCRATCHPAD_SIZE 9
9 #define _TWR_DS18B20_DELAY_RUN 5000
10 #define TWR_DS18B20_LOG 1
13 [TWR_DS18B20_RESOLUTION_BITS_9] = 100,
14 [TWR_DS18B20_RESOLUTION_BITS_10] = 190,
15 [TWR_DS18B20_RESOLUTION_BITS_11] = 380,
16 [TWR_DS18B20_RESOLUTION_BITS_12] = 760
19 static void _twr_ds18b20_task_interval(
void *param);
21 static void _twr_ds18b20_task_measure(
void *param);
25 static twr_ds18b20_sensor_t sensors[1];
38 memset(
self, 0,
sizeof(*
self));
40 self->_onewire = onewire;
42 self->_resolution = resolution;
43 self->_sensor = sensors;
44 self->_sensor_count = sensor_count;
46 for (
int i = 0; i <
self->_sensor_count; i++)
48 self->_sensor[i]._device_address = 0;
49 self->_sensor[i]._temperature_valid =
false;
59 self->_event_handler = event_handler;
60 self->_event_param = event_param;
65 self->_update_interval = interval;
81 if (self->_measurement_active)
86 self->_measurement_active =
true;
95 for (
int i = 0; i <
self->_sensor_found; i++)
97 if (self->_sensor[i]._device_address == device_address)
108 if (index >= self->_sensor_found)
113 uint64_t short_address =
self->_sensor[index]._device_address;
114 short_address &= ~(((uint64_t) 0xff) << 56);
117 return short_address;
122 return self->_sensor_found;
127 for (
int i = 0; i <
self->_sensor_found; i++)
129 self->_sensor[i]._device_address = 0;
130 self->_sensor[i]._temperature_valid =
false;
133 self->_measurement_active =
true;
135 self->_state =
self->_sensor_found = 0;
137 self->_state = TWR_DS18B20_STATE_PREINITIALIZE;
144 self->_power_dynamic = on;
151 if (sensor_index == -1)
156 if (!self->_sensor[sensor_index]._temperature_valid)
161 *raw =
self->_sensor[sensor_index]._temperature_raw;
170 if (sensor_index == -1)
175 if (!self->_sensor[sensor_index]._temperature_valid)
181 if ((device_address & 0xFF) == 0x10)
184 *celsius = (float) self->_sensor[sensor_index]._temperature_raw / 2;
188 *celsius = (float) self->_sensor[sensor_index]._temperature_raw / 16;
194 static void _twr_ds18b20_task_interval(
void *param)
212 #ifdef TWR_DS18B20_LOG
217 #ifdef TWR_DS18B20_LOG
218 twr_log_error(
"twr_ds18b20: call twr_module_sensor_onewire_power_up");
233 self->_power =
false;
235 #ifdef TWR_DS18B20_LOG
240 #ifdef TWR_DS18B20_LOG
241 twr_log_error(
"twr_ds18b20: call twr_module_sensor_onewire_power_down");
249 static bool _twr_ds18b20_is_scratchpad_valid(uint8_t *scratchpad)
251 #ifdef TWR_DS18B20_STRICT_VALIDATION
252 if (scratchpad[5] != 0xff)
257 if (scratchpad[7] != 0x10)
271 static void _twr_ds18b20_task_measure(
void *param)
277 switch (self->_state)
279 case TWR_DS18B20_STATE_ERROR:
281 #ifdef TWR_DS18B20_LOG
285 for (
int i = 0; i <
self->_sensor_found; i++)
287 self->_sensor[i]._temperature_valid =
false;
290 self->_measurement_active =
false;
292 _twr_ds18b20_power_down(
self);
294 if (self->_event_handler != NULL)
299 self->_state =
self->_sensor_found > 0 ? TWR_DS18B20_STATE_READY : TWR_DS18B20_STATE_PREINITIALIZE;
303 case TWR_DS18B20_STATE_PREINITIALIZE:
305 #ifdef TWR_DS18B20_LOG
309 self->_state = TWR_DS18B20_STATE_ERROR;
311 if (!_twr_ds18b20_power_up(
self))
316 self->_state = TWR_DS18B20_STATE_INITIALIZE;
322 case TWR_DS18B20_STATE_INITIALIZE:
324 #ifdef TWR_DS18B20_LOG
328 self->_state = TWR_DS18B20_STATE_ERROR;
330 uint64_t _device_address = 0;
331 self->_sensor_found = 0;
334 while ((self->_sensor_found < self->_sensor_count) &&
twr_onewire_search_next(self->_onewire, &_device_address))
336 self->_sensor[
self->_sensor_found]._device_address = _device_address;
337 self->_sensor[
self->_sensor_found]._temperature_valid =
false;
340 self->_sensor_found++;
342 #ifdef TWR_DS18B20_LOG
343 twr_log_debug(
"twr_ds18b20: Found 0x%08llx", _device_address);
347 if (self->_sensor_found == 0)
363 uint8_t buffer[] = {0x4e, 0x75, 0x70,
self->_resolution << 5 | 0x1f};
369 if (self->_measurement_active)
373 else if (self->_power_dynamic)
375 if (!_twr_ds18b20_power_down(
self))
381 self->_state = TWR_DS18B20_STATE_READY;
385 case TWR_DS18B20_STATE_READY:
387 #ifdef TWR_DS18B20_LOG
391 self->_state = TWR_DS18B20_STATE_ERROR;
393 if (!_twr_ds18b20_power_up(
self))
398 self->_state = TWR_DS18B20_STATE_MEASURE;
404 case TWR_DS18B20_STATE_MEASURE:
406 #ifdef TWR_DS18B20_LOG
416 for (
int i = 0; i <
self->_sensor_found; i++)
418 self->_sensor[i]._temperature_valid =
false;
421 if (self->_power_dynamic) {
422 if (!_twr_ds18b20_power_down(
self))
424 self->_state = TWR_DS18B20_STATE_ERROR;
429 self->_state = TWR_DS18B20_STATE_RESULTS;
440 self->_state = TWR_DS18B20_STATE_READ;
446 case TWR_DS18B20_STATE_READ:
448 #ifdef TWR_DS18B20_LOG
452 self->_state = TWR_DS18B20_STATE_ERROR;
454 uint8_t scratchpad[_TWR_DS18B20_SCRATCHPAD_SIZE];
457 for (; i <
self->_sensor_found; i++)
464 self->_sensor[i]._temperature_valid =
false;
476 self->_sensor[i]._temperature_valid = _twr_ds18b20_is_scratchpad_valid(scratchpad);
478 if (self->_sensor[i]._temperature_valid)
480 self->_sensor[i]._temperature_raw = ((int16_t) scratchpad[1]) << 8 | ((int16_t) scratchpad[0]);
482 #ifdef TWR_DS18B20_LOG
483 twr_log_warning(
"twr_ds18b20: invalid scratchpad 0x%08llx", self->_sensor[i]._device_address);
488 for (; i <
self->_sensor_found; i++)
490 self->_sensor[i]._temperature_valid =
false;
493 if (self->_power_dynamic) {
494 if (!_twr_ds18b20_power_down(
self))
500 self->_state = TWR_DS18B20_STATE_RESULTS;
504 case TWR_DS18B20_STATE_RESULTS:
506 #ifdef TWR_DS18B20_LOG
510 self->_measurement_active =
false;
512 self->_state = TWR_DS18B20_STATE_READY;
514 for (
int i = 0; i <
self->_sensor_found; i++)
516 if (self->_event_handler != NULL)
520 self->_event_handler(
self, self->_sensor[i]._device_address, event, self->_event_param);
528 self->_state = TWR_DS18B20_STATE_ERROR;
int twr_ds18b20_get_sensor_found(twr_ds18b20_t *self)
Get number of found sensor.
void twr_ds18b20_set_event_handler(twr_ds18b20_t *self, void(*event_handler)(twr_ds18b20_t *, uint64_t _device_address, twr_ds18b20_event_t, void *), void *event_param)
Set callback function.
void twr_ds18b20_init_single(twr_ds18b20_t *self, twr_ds18b20_resolution_bits_t resolution)
Initialize single ds18b20 over channel B on Sensor Module.
void twr_ds18b20_set_update_interval(twr_ds18b20_t *self, twr_tick_t interval)
Set measurement interval.
void twr_ds18b20_set_power_dynamic(twr_ds18b20_t *self, bool on)
Set power dynamic, Turns VDD on and pull 4k7 only for measurement.
void twr_ds18b20_rescan(twr_ds18b20_t *self)
Request to rescan the bus.
bool twr_ds18b20_get_temperature_celsius(twr_ds18b20_t *self, uint64_t device_address, float *celsius)
Get measured temperature in degrees of Celsius.
void twr_ds18b20_init(twr_ds18b20_t *self, twr_onewire_t *onewire, twr_ds18b20_sensor_t *sensors, int sensor_count, twr_ds18b20_resolution_bits_t resolution)
Initialize ds18b20.
twr_ds18b20_event_t
Callback events.
int twr_ds18b20_get_index_by_device_address(twr_ds18b20_t *self, uint64_t device_address)
Get device index by its device address.
struct twr_ds18b20_t twr_ds18b20_t
BigClown ds18b20 instance.
bool twr_ds18b20_get_temperature_raw(twr_ds18b20_t *self, uint64_t device_address, int16_t *raw)
Get measured temperature in degrees of Celsius.
bool twr_ds18b20_measure(twr_ds18b20_t *self)
Start measurement manually.
uint64_t twr_ds182b0_get_short_address(twr_ds18b20_t *self, uint8_t index)
Get device index by its device address.
void twr_ds18b20_init_multiple(twr_ds18b20_t *self, twr_ds18b20_sensor_t *sensors, int sensor_count, twr_ds18b20_resolution_bits_t resolution)
Initialize multiple ds18b20 over channel B on Sensor Module.
@ TWR_DS18B20_EVENT_UPDATE
Update event.
@ TWR_DS18B20_EVENT_ERROR
Error event.
void void void void void twr_log_error(const char *format,...) __attribute__((format(printf
Log ERROR message (annotated in log as <E>)
void void void void twr_log_warning(const char *format,...) __attribute__((format(printf
Log WARNING message (annotated in log as <W>)
void void twr_log_debug(const char *format,...) __attribute__((format(printf
Log DEBUG message (annotated in log as <D>)
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_write(twr_onewire_t *self, const void *buffer, size_t length)
Select device.
void twr_onewire_write_byte(twr_onewire_t *self, uint8_t data)
Select device.
void twr_onewire_search_start(twr_onewire_t *self, uint8_t family_code)
Start of manual search, see also twr_onewire_search_next.
struct twr_onewire_t twr_onewire_t
1-Wire instance
void twr_onewire_skip_rom(twr_onewire_t *self)
Skip ROM.
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.
void twr_onewire_read(twr_onewire_t *self, void *buffer, size_t length)
Select device.
uint8_t twr_onewire_crc8(const void *buffer, size_t length, uint8_t crc)
Calculate 8-bit CRC.
void twr_onewire_select(twr_onewire_t *self, uint64_t *device_number)
Select device.
bool twr_onewire_transaction_stop(twr_onewire_t *self)
Stop 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_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.
#define TWR_TICK_INFINITY
Maximum timestamp value.
uint64_t twr_tick_t
Timestamp data type.