One-wire bus can now handle multiple sensors.

Sat, 12 Oct 2019 21:05:09 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Sat, 12 Oct 2019 21:05:09 +0200
changeset 10
d08c7466bb40
parent 9
a85995941d0d
child 11
e33f2d325d15

One-wire bus can now handle multiple sensors.

main/task_ds18b20.c file | annotate | diff | comparison | revisions
--- a/main/task_ds18b20.c	Fri Oct 11 15:56:30 2019 +0200
+++ b/main/task_ds18b20.c	Sat Oct 12 21:05:09 2019 +0200
@@ -52,35 +52,32 @@
  */
 void task_ds18b20(void *pvParameter)
 {
-    int			num_devices = 0;
-    float		readings = 0;
+    int			i, num_devices = 0;
     bool		found = false;
-    DS18B20_ERROR	errors = 0;
+    EventBits_t         uxBits;
 
     ESP_LOGI(TAG, "Starting DS18B20 sensors");
     ds18b20_state = malloc(sizeof(DS18B20_State));
     ds18b20_state->valid = false;
     ds18b20_state->num_sensors = 0;
 
-    for (int i = 0; i < DS18B20_MAX; i++) {
+    for (i = 0; i < DS18B20_MAX; i++) {
     	ds18b20_state->sensor[i].temperature = 0.0;
     	ds18b20_state->sensor[i].rom_code[0] = '\0';
     	ds18b20_state->sensor[i].error = DS18B20_ERR_READ;
     }
 
-    /* event handler and event group for the wifi driver */
+    /*
+     * event handler and event group for the one-wire bus
+     */
     xEventGroupDS18B20 = xEventGroupCreate();
 
     /*
-     * Initialize the MLT and HLT one-wire busses.
+     * Initialize the one-wire bus.
      */
-    OneWireBus *owb;
-    owb_rmt_driver_info rmt_driver_info_bottle;
-    owb = owb_rmt_initialize(&rmt_driver_info_bottle, GPIO_DS18B20_BUS, RMT_CHANNEL_1, RMT_CHANNEL_0);
-    owb_use_crc(owb, true);                     // enable CRC check for ROM code
-
-    DS18B20_Info * ds18b20_info = ds18b20_malloc();
-    EventBits_t uxBits;
+    owb_rmt_driver_info	rmt_driver_info_bottle;
+    OneWireBus		*owb = owb_rmt_initialize(&rmt_driver_info_bottle, GPIO_DS18B20_BUS, RMT_CHANNEL_1, RMT_CHANNEL_0);
+    owb_use_crc(owb, true);
 
     /*
      * Task loop forever.
@@ -88,8 +85,10 @@
     while (1) {
 
 	uxBits = xEventGroupWaitBits(xEventGroupDS18B20, TASK_DS18B20_REQUEST_TEMPS, pdFALSE, pdFALSE, portMAX_DELAY );
+	if (uxBits & TASK_DS18B20_REQUEST_TEMPS) {
 
-	if (uxBits & TASK_DS18B20_REQUEST_TEMPS) {
+	    ESP_LOGI(TAG, "Requested DS18B20 readings");
+	    OneWireBus_ROMCode device_rom_codes[DS18B20_MAX] = {0};
 	    num_devices = 0;
 	    OneWireBus_SearchState search_state = {0};
 	    found = false;
@@ -98,62 +97,90 @@
 		char rom_code_s[17];
         	owb_string_from_rom_code(search_state.rom_code, rom_code_s, sizeof(rom_code_s));
 		rom_code_s[16] = '\0';
+#if 0
         	printf("  %d : %s %d\n", num_devices + 1, rom_code_s, strlen(rom_code_s));
+#endif
+		device_rom_codes[num_devices] = search_state.rom_code;
 		strncpy(ds18b20_state->sensor[num_devices].rom_code, rom_code_s, 17);
 	    	++num_devices;
 	    	owb_search_next(owb, &search_state, &found);
 	    }
 
-	    if (num_devices == 1) {
-	    	ds18b20_init_solo(ds18b20_info, owb);		// only one device on bus
-	    	ds18b20_use_crc(ds18b20_info, true);			// enable CRC check for temperature readings
-	    	ds18b20_set_resolution(ds18b20_info, DS18B20_RESOLUTION);	// returns true if ok.
+	    if (num_devices) {
+		/*
+            	 * Create DS18B20 devices on the bus
+            	 */
+		DS18B20_Info * devices[DS18B20_MAX] = {0};
+		for (i = 0; i < num_devices; ++i) {
+		    DS18B20_Info * ds18b20_info = ds18b20_malloc();  // heap allocation
+		    devices[i] = ds18b20_info;
+
+		    if (num_devices == 1) {
+			ds18b20_init_solo(ds18b20_info, owb);          // only one device on bus
+		    } else {
+			ds18b20_init(ds18b20_info, owb, device_rom_codes[i]); // associate with bus and device
+		    }
+		    ds18b20_use_crc(ds18b20_info, true);           // enable CRC check for temperature readings
+		    ds18b20_set_resolution(ds18b20_info, DS18B20_RESOLUTION);
+		}
 
 	    	// Read temperatures more efficiently by starting conversions on all devices at the same time
 	    	ds18b20_convert_all(owb);
-	    	ds18b20_wait_for_conversion(ds18b20_info);
+	    	ds18b20_wait_for_conversion(devices[0]);
+
+		// Read the results immediatly after conversion.
+		float readings[DS18B20_MAX] = { 0 };
+            	DS18B20_ERROR errors[DS18B20_MAX] = { 0 };
 
-	    	errors = ds18b20_read_temp(ds18b20_info, &readings);
+            	for (i = 0; i < num_devices; ++i) {
+                    errors[i] = ds18b20_read_temp(devices[i], &readings[i]);
+            	}
 
+		// Process the results with a locked semaphore
 	    	if (xSemaphoreTake(xSemaphoreDS18B20, 25) == pdTRUE) {
-		    ds18b20_state->num_sensors = 1;
-	    	    if (errors == DS18B20_OK) {
-		    	ds18b20_state->sensor[0].error = DS18B20_ERR_NONE;
-		    	ds18b20_state->valid = true;
-		    	ds18b20_state->sensor[0].temperature = readings;
-	    	    } else {
-		    	if (errors == DS18B20_ERROR_CRC)
-		    	    ds18b20_state->sensor[0].error = DS18B20_ERR_CRC;
-			else
-		    	    ds18b20_state->sensor[0].error = DS18B20_ERR_READ; // All other errors
-		    	ds18b20_state->valid = false;
-		    	ds18b20_state->sensor[0].temperature = 0.0;
-	    	    }
+		    ds18b20_state->valid = true;
+		    for (i = 0; i < num_devices; ++i) {
+			if (errors[i] != DS18B20_OK) {
+			    if (errors[i] == DS18B20_ERROR_CRC)
+                            	ds18b20_state->sensor[i].error = DS18B20_ERR_CRC;
+                            else
+                            	ds18b20_state->sensor[i].error = DS18B20_ERR_READ; // All other errors
+			    ds18b20_state->valid = false;
+			    ds18b20_state->sensor[i].temperature = 0.0;
+			} else {
+			    ds18b20_state->sensor[i].error = DS18B20_ERR_NONE;
+                            ds18b20_state->sensor[i].temperature = readings[i];
+			}
+#if 1
+			ESP_LOGI(TAG, "Temperature %d %s %.4f %s", i, ds18b20_state->sensor[i].rom_code,
+					ds18b20_state->sensor[i].temperature, dsErrors[ds18b20_state->sensor[i].error]);
+#endif
+		    }
+		    ds18b20_state->num_sensors = num_devices;
 		    xSemaphoreGive(xSemaphoreDS18B20);
-	    	}
-
+		}
 	    } else {
-	    	/*
-	    	 * Zero or more then one device, this is an error.
-	    	 */
-	    	if (xSemaphoreTake(xSemaphoreDS18B20, 25) == pdTRUE) {
-	    	    if (num_devices == 0)
-		    	ds18b20_state->sensor[0].error = DS18B20_ERR_READ;
-	    	    else
-		    	ds18b20_state->sensor[0].error = DS18B20_ERR_READ;
-	    	    ds18b20_state->valid = false;
-		    ds18b20_state->num_sensors = 0;
-		    xSemaphoreGive(xSemaphoreDS18B20);
-	    	}
-	    } // if num_devices == 1
+
+		ESP_LOGW(TAG, "No temperature sensors found.");
+	    }
+
+	    /*
+	     * Set the remainder of the ds18b20 entries
+	     */
+	    if (xSemaphoreTake(xSemaphoreDS18B20, 25) == pdTRUE) {
+		ds18b20_state->num_sensors = num_devices;
+		for (i = num_devices; i < DS18B20_MAX; i++) {
+		    ds18b20_state->sensor[i].temperature = 0.0;
+        	    ds18b20_state->sensor[i].rom_code[0] = '\0';
+        	    ds18b20_state->sensor[i].error = DS18B20_ERR_READ;
+		}
+		xSemaphoreGive(xSemaphoreDS18B20);
+	    }
 	
 	    xEventGroupClearBits(xEventGroupDS18B20, TASK_DS18B20_REQUEST_TEMPS);
 	    xEventGroupSetBits(xEventGroupDS18B20, TASK_DS18B20_REQUEST_DONE);
-#if 1
-	    ESP_LOGI(TAG, "Temperature %.3f %s", ds18b20_state->sensor[0].temperature, dsErrors[ds18b20_state->sensor[0].error]);
-#endif
 	}
-	vTaskDelay( (TickType_t)10);
+	vTaskDelay(10 / portTICK_PERIOD_MS);
     }
 }
 

mercurial