|
1 /** |
|
2 * @file task_ds18b20.c |
|
3 * @brief The FreeRTOS task to query the DS18B20 sensors on one or two |
|
4 * one-wire busses. Each bus must have only one sensor. That way |
|
5 * we don't need to care about the DS18B20 internal ROM address. |
|
6 * The task will update the DS18B20_State structure. |
|
7 */ |
|
8 |
|
9 |
|
10 #include "owb.h" |
|
11 #include "owb_rmt.h" |
|
12 #include "ds18b20.h" |
|
13 #include "config.h" |
|
14 |
|
15 |
|
16 #define GPIO_DS18B20_BUS (CONFIG_ONE_WIRE_BUS) |
|
17 #define MAX_DEVICES (8) |
|
18 #define DS18B20_RESOLUTION (DS18B20_RESOLUTION_12_BIT) |
|
19 #define SAMPLE_PERIOD (2000) // milliseconds |
|
20 |
|
21 |
|
22 static const char *TAG = "task_ds18b20"; |
|
23 static const char *dsErrors[] = { "Ok", "No sensor", "Too many sensors", "CRC error", "Read error" }; |
|
24 |
|
25 SemaphoreHandle_t xSemaphoreDS18B20 = NULL; ///< Semaphire DS18B20 task |
|
26 EventGroupHandle_t xEventGroupDS18B20; ///< Events DS18B20 task |
|
27 DS18B20_State *ds18b20_state; ///< Public state for other tasks |
|
28 |
|
29 |
|
30 const int TASK_DS18B20_REQUEST_TEMPS = BIT0; ///< Request temperature measurements |
|
31 const int TASK_DS18B20_REQUEST_DONE = BIT1; ///< Request is completed |
|
32 |
|
33 |
|
34 |
|
35 void request_ds18b20(void) |
|
36 { |
|
37 xEventGroupClearBits(xEventGroupDS18B20, TASK_DS18B20_REQUEST_DONE); |
|
38 xEventGroupSetBits(xEventGroupDS18B20, TASK_DS18B20_REQUEST_TEMPS); |
|
39 } |
|
40 |
|
41 |
|
42 |
|
43 bool ready_ds18b20(void) |
|
44 { |
|
45 if (xEventGroupGetBits(xEventGroupDS18B20) & TASK_DS18B20_REQUEST_DONE) |
|
46 return true; |
|
47 return false; |
|
48 } |
|
49 |
|
50 |
|
51 |
|
52 /* |
|
53 * Task to read temperature sensors on request. |
|
54 */ |
|
55 void task_ds18b20(void *pvParameter) |
|
56 { |
|
57 int num_devices = 0; |
|
58 float readings = 0; |
|
59 bool found = false; |
|
60 DS18B20_ERROR errors = 0; |
|
61 |
|
62 ESP_LOGI(TAG, "Starting DS18B20 sensors"); |
|
63 ds18b20_state = malloc(sizeof(DS18B20_State)); |
|
64 ds18b20_state->bottle_valid = false; |
|
65 ds18b20_state->bottle_temperature = 0.0; |
|
66 ds18b20_state->bottle_error = DS18B20_ERR_NOSENSOR; |
|
67 |
|
68 /* event handler and event group for the wifi driver */ |
|
69 xEventGroupDS18B20 = xEventGroupCreate(); |
|
70 |
|
71 /* |
|
72 * Initialize the MLT and HLT one-wire busses. |
|
73 */ |
|
74 OneWireBus *owb_bottle; |
|
75 owb_rmt_driver_info rmt_driver_info_bottle; |
|
76 owb_bottle = owb_rmt_initialize(&rmt_driver_info_bottle, GPIO_DS18B20_BUS, RMT_CHANNEL_1, RMT_CHANNEL_0); |
|
77 owb_use_crc(owb_bottle, true); // enable CRC check for ROM code |
|
78 |
|
79 DS18B20_Info * ds18b20_info = ds18b20_malloc(); |
|
80 EventBits_t uxBits; |
|
81 |
|
82 /* |
|
83 * Task loop forever. |
|
84 */ |
|
85 while (1) { |
|
86 |
|
87 uxBits = xEventGroupWaitBits(xEventGroupDS18B20, TASK_DS18B20_REQUEST_TEMPS, pdFALSE, pdFALSE, portMAX_DELAY ); |
|
88 |
|
89 if (uxBits & TASK_DS18B20_REQUEST_TEMPS) { |
|
90 num_devices = 0; |
|
91 OneWireBus_SearchState bottle_search_state = {0}; |
|
92 found = false; |
|
93 owb_search_first(owb_bottle, &bottle_search_state, &found); |
|
94 while (found) { |
|
95 ++num_devices; |
|
96 owb_search_next(owb_bottle, &bottle_search_state, &found); |
|
97 } |
|
98 |
|
99 if (num_devices == 1) { |
|
100 ds18b20_init_solo(ds18b20_info, owb_bottle); // only one device on bus |
|
101 ds18b20_use_crc(ds18b20_info, true); // enable CRC check for temperature readings |
|
102 ds18b20_set_resolution(ds18b20_info, DS18B20_RESOLUTION); // returns true if ok. |
|
103 |
|
104 // Read temperatures more efficiently by starting conversions on all devices at the same time |
|
105 ds18b20_convert_all(owb_bottle); |
|
106 ds18b20_wait_for_conversion(ds18b20_info); |
|
107 |
|
108 errors = ds18b20_read_temp(ds18b20_info, &readings); |
|
109 |
|
110 if (xSemaphoreTake(xSemaphoreDS18B20, 25) == pdTRUE) { |
|
111 if (errors == DS18B20_OK) { |
|
112 ds18b20_state->bottle_error = DS18B20_ERR_NONE; |
|
113 ds18b20_state->bottle_valid = true; |
|
114 ds18b20_state->bottle_temperature = readings; |
|
115 } else { |
|
116 if (errors == DS18B20_ERROR_CRC) |
|
117 ds18b20_state->bottle_error = DS18B20_ERR_CRC; |
|
118 if (errors == DS18B20_ERROR_OWB) |
|
119 ds18b20_state->bottle_error = DS18B20_ERR_READ; |
|
120 if (errors == DS18B20_ERROR_DEVICE) |
|
121 ds18b20_state->bottle_error = DS18B20_ERR_READ; |
|
122 ds18b20_state->bottle_valid = false; |
|
123 ds18b20_state->bottle_temperature = 0.0; |
|
124 } |
|
125 xSemaphoreGive(xSemaphoreDS18B20); |
|
126 } |
|
127 |
|
128 } else { |
|
129 /* |
|
130 * Zero or more then one device, this is an error. |
|
131 */ |
|
132 if (xSemaphoreTake(xSemaphoreDS18B20, 25) == pdTRUE) { |
|
133 if (num_devices == 0) |
|
134 ds18b20_state->bottle_error = DS18B20_ERR_NOSENSOR; |
|
135 else |
|
136 ds18b20_state->bottle_error = DS18B20_ERR_TOOMANY; |
|
137 ds18b20_state->bottle_valid = false; |
|
138 ds18b20_state->bottle_temperature = 0.0; |
|
139 xSemaphoreGive(xSemaphoreDS18B20); |
|
140 } |
|
141 } // if num_devices == 1 |
|
142 |
|
143 xEventGroupClearBits(xEventGroupDS18B20, TASK_DS18B20_REQUEST_TEMPS); |
|
144 xEventGroupSetBits(xEventGroupDS18B20, TASK_DS18B20_REQUEST_DONE); |
|
145 #if 1 |
|
146 ESP_LOGI(TAG, "Temperature %.3f %s", ds18b20_state->bottle_temperature, dsErrors[ds18b20_state->bottle_error]); |
|
147 #endif |
|
148 } |
|
149 vTaskDelay( (TickType_t)10); |
|
150 } |
|
151 } |
|
152 |