I am writing an Arduino sketch to read temp data from multiple DS18B20 sensors and then write it to serial. The problem is, as I am connecting more sensors, the delay between my temp data is written to a serial increases (like 100ms for 1 sensor and 1s for 4 sensors). Can I somehow improve my sketch to read it faster?
Here is the sketch I am using: (I am using DallasTemperature to simplify it all)
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 10
#define TEMPERATURE_PRECISION 8
#define BAUD_RATE 9600
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
// arrays to hold device addresses
DeviceAddress devices[10];
int devicesFound = 0;
void setup(void)
{
// start serial port
Serial.begin(BAUD_RATE);
//Serial.println("Dallas Temperature IC Control Library Demo");
// Start up the library
sensors.begin();
// locate devices on the bus
Serial.print("Locating devices...");
Serial.print("Found ");
Serial.print(sensors.getDeviceCount(), DEC);
Serial.println(" devices.");
devicesFound = sensors.getDeviceCount();
// report parasite power requirements
Serial.print("Parasite power is: ");
if (sensors.isParasitePowerMode()) Serial.println("ON");
else Serial.println("OFF");
for (int i = 0; i < devicesFound; i++)
if (!sensors.getAddress(devices[i], i))
Serial.println("Unable to find address for Device" + i);
// show the addresses we found on the bus
for (int i = 0; i < devicesFound; i++)
{
Serial.print("Device " + (String)i + " Address: ");
printAddress(devices[i]);
Serial.println();
}
for (int i = 0; i < devicesFound; i++)
sensors.setResolution(devices[i], TEMPERATURE_PRECISION);
}
// function to print a device address
void printAddress(DeviceAddress deviceAddress)
{
for (uint8_t i = 0; i < 8; i++)
{
// zero pad the address if necessary
if (deviceAddress[i] < 16) Serial.print("0");
Serial.print(deviceAddress[i], HEX);
}
}
// function to print the temperature for a device
String printTemperature(DeviceAddress deviceAddress)
{
float tempC = sensors.getTempC(deviceAddress);
if (tempC < 10)
return "0" + (String)tempC;
else
return (String)tempC;
}
// function to print a device's resolution
void printResolution(DeviceAddress deviceAddress)
{
Serial.print("Resolution: ");
Serial.print(sensors.getResolution(deviceAddress));
Serial.println();
}
// main function to print information about a device
void printData(DeviceAddress deviceAddress)
{
Serial.print("Device Address: ");
printAddress(deviceAddress);
Serial.print(" ");
printTemperature(deviceAddress);
Serial.println();
}
void loop(void)
{
if (devicesFound == 0)
{
Serial.println("No devices found.");
return;
}
sensors.requestTemperatures();
String sent = "";
// print the device information
for (int i = 0; i < devicesFound; i++)
{
sent += printTemperature(devices[i]);
if (i != devicesFound - 1)
sent += " ";
}
Serial.println(sent);
}
2 Answers 2
With 12 bits precision, DS18B20 may take up to 750 ms converting a temp.
Try using async reading, so you don't have to wait for the end of the process.
First you ask for a reading, later your read it
DallasTemperature sensors(&oneWire);
...
sensors.setWaitForConversion(false); // makes it async
sensors.requestTemperatures();
sensors.setWaitForConversion(true);
...
// Do something else while temp is been reading by the sensor
...
float temp = sensors.getTempCByIndex(0);
-
Does the
getTempByIndex
function build in the wait-for-complete or are you assuming your "do something else" section is longer than a conversion?RufusVS– RufusVS2020年08月22日 20:52:14 +00:00Commented Aug 22, 2020 at 20:52
I would start by changing this section:
String sent = "";
// print the device information
for (int i = 0; i < devicesFound; i++)
{
sent += printTemperature(devices[i]);
if (i != devicesFound - 1)
sent += " ";
}
Serial.println(sent);
This section should read and print the temperature directly instead of creating a string. The string handling is a large overhead and it does not allow Serial (UART) to work very much in parallel if the buffer is filled. The printTemperature() function is using a lot of strings (and heap operations).
Otherwise you have done what is possible; 1) reduce the conversion resolution (9-bits is minimum), 2) use single conversion request command to all sensors.
The alternative is to use alarm triggers and only read sensors with alarms.
-
like that pastebin.com/NubeaW4M ?serge1peshcoff– serge1peshcoff2015年12月22日 21:12:55 +00:00Commented Dec 22, 2015 at 21:12
-
What are the results of that? I did some tests and it is possible to issue a conversion request, read and print the results from 48 sensors at 9-bits resolution and 14 sensors at 12-bits resolution (per second).Mikael Patel– Mikael Patel2015年12月22日 22:36:31 +00:00Commented Dec 22, 2015 at 22:36
-
delay is still the sameserge1peshcoff– serge1peshcoff2015年12月22日 23:37:45 +00:00Commented Dec 22, 2015 at 23:37
-
Can you scale it down to a single sensor and measure the conversion request and reading of scratch pad? We need to isolate the issue in the library that you are using.Mikael Patel– Mikael Patel2015年12月23日 15:54:23 +00:00Commented Dec 23, 2015 at 15:54
-
So, I changed my sketch this way: pastebin.com/7EADdVAu, and it shows that around 110ms has passed while reading one sensor.serge1peshcoff– serge1peshcoff2015年12月24日 20:48:41 +00:00Commented Dec 24, 2015 at 20:48
if (i) sent += " ";
as a statement before the statement adding the reading to the string, instead of the statement you currently have after