maximum datalogging frequency with one wire thermocouple breakout

Working on a datalogger for a motorsports application, trying to do it one piece at a time, right now I'm trying to set up thermocouples to measure exhaust gas temperature. I'd like to log at somewhere in the neighborhood of 4-10Hz to an SD card.

Eventually want to add some sort of frequency measurement to log rpm along with a handfull of analog inputs and one or two via I2c, all hopefully logging at around 10 Hz to an SD card.

Right now just working on thermocouples though. I picked up a pair of Adafruit's one-wire thermocouple breakout boards thinking it looked like a simple way to set them up without tying up any analog input pins. The problem is the communication with those breakout boards seems to be very slow. I'm using the "multiple" example in the Dallas Temp library and it is logging to serial at around 1Hz, I can't figure out what it is that is limiting the frequency of logging (I don't see a delay or any timing going on in the example). It appears that it is just requesting the temp from the breakout boards and printing it to serial immediately, which makes me think this process takes ~1 second, so I'm out of luck if I want to log to the sd card faster than that.

I'm very new to this so maybe someone can point out if there is something I can do to speed things up, or if I need to get something else and if so what should I be using for this?

Here is the "multiple" example from Dallas Temp Library.

#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
#define TEMPERATURE_PRECISION 9

// 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 insideThermometer, outsideThermometer;

void setup(void)
{
// start serial port
Serial.begin(9600);
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.”);

// report parasite power requirements
Serial.print("Parasite power is: ");
if (sensors.isParasitePowerMode()) Serial.println(“ON”);
else Serial.println(“OFF”);

// assign address manually. the addresses below will beed to be changed
// to valid device addresses on your bus. device address can be retrieved
// by using either oneWire.search(deviceAddress) or individually via
// sensors.getAddress(deviceAddress, index)
//insideThermometer = { 0x28, 0x1D, 0x39, 0x31, 0x2, 0x0, 0x0, 0xF0 };
//outsideThermometer = { 0x28, 0x3F, 0x1C, 0x31, 0x2, 0x0, 0x0, 0x2 };

// search for devices on the bus and assign based on an index. ideally,
// you would do this to initially discover addresses on the bus and then
// use those addresses and manually assign them (see above) once you know
// the devices on your bus (and assuming they don’t change).
//
// method 1: by index
if (!sensors.getAddress(insideThermometer, 0)) Serial.println(“Unable to find address for Device 0”);
if (!sensors.getAddress(outsideThermometer, 1)) Serial.println(“Unable to find address for Device 1”);

// method 2: search()
// search() looks for the next device. Returns 1 if a new address has been
// returned. A zero might mean that the bus is shorted, there are no devices,
// or you have already retrieved all of them. It might be a good idea to
// check the CRC to make sure you didn’t get garbage. The order is
// deterministic. You will always get the same devices in the same order
//
// Must be called before search()
//oneWire.reset_search();
// assigns the first address found to insideThermometer
//if (!oneWire.search(insideThermometer)) Serial.println(“Unable to find address for insideThermometer”);
// assigns the seconds address found to outsideThermometer
//if (!oneWire.search(outsideThermometer)) Serial.println(“Unable to find address for outsideThermometer”);

// show the addresses we found on the bus
Serial.print("Device 0 Address: ");
printAddress(insideThermometer);
Serial.println();

Serial.print("Device 1 Address: ");
printAddress(outsideThermometer);
Serial.println();

// set the resolution to 9 bit
sensors.setResolution(insideThermometer, TEMPERATURE_PRECISION);
sensors.setResolution(outsideThermometer, TEMPERATURE_PRECISION);

Serial.print("Device 0 Resolution: ");
Serial.print(sensors.getResolution(insideThermometer), DEC);
Serial.println();

Serial.print("Device 1 Resolution: ");
Serial.print(sensors.getResolution(outsideThermometer), DEC);
Serial.println();
}

// 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 < 16) Serial.print(“0”);
_ Serial.print(deviceAddress*, HEX);_
_
}_
_
}_
_
// function to print the temperature for a device*_
void printTemperature(DeviceAddress deviceAddress)
{
* float tempC = sensors.getTempC(deviceAddress);*
_ Serial.print("Temp C: “);
Serial.print(tempC);
Serial.print(” Temp F: ");
Serial.print(DallasTemperature::toFahrenheit(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)
*{ *
* // call sensors.requestTemperatures() to issue a global temperature*
* // request to all devices on the bus*
Serial.print(“Requesting temperatures…”);
* sensors.requestTemperatures();*
Serial.println(“DONE”);_

* // print the device information*
* printData(insideThermometer);*
* printData(outsideThermometer);*
}
[/quote]

I’m trying to figure out what it is that determines when or how fast it prints to serial, I took a look inside the dallas temp liberary and I found this in the .cpp file:

I am VERY much not able to follow what’s going on, but it looks like depending on what “case” is going on it waits for a delay of 94, 188, 375, or 750. Must be currently using the “Case12” delay of 750 which is what’s getting me my 1Hz (actually .75Hz I guess) frequency of printing to serial.

Any idea what determines what the case is and if I can change it to the 94 somehow?

void DallasTemperature::blockTillConversionComplete(uint8_t* bitResolution, uint8_t* deviceAddress)
{
	if(deviceAddress != 0 && checkForConversion && !parasite)
	{
	  	// Continue to check if the IC has responded with a temperature
	  	// NB: Could cause issues with multiple devices (one device may respond faster)
	  	unsigned long start = millis();
		while(!isConversionAvailable(0) && ((millis() - start) < 750));	
	}
	
  	// Wait a fix number of cycles till conversion is complete (based on IC datasheet)
	  switch (*bitResolution)
	  {
	    case 9:
	      delay(94);
	      break;
	    case 10:
	      delay(188);
	      break;
	    case 11:
	      delay(375);
	      break;
	    case 12:
	    default:
	      delay(750);
	      break;
	  }

For reference, the complete Dallas Temp liberary here: (it won't let me post it because it's too long, but I'm trying to make it convenient for anybody who can look at it to help me out)

Dallas Temp:
https://github.com/adafruit/MAX31850_DallasTemp/archive/master.zip

One wire (used by Dallas Temp):
https://github.com/adafruit/MAX31850_OneWire/archive/master.zip

Datasheet for the MAX31850 used on this breakout board:

If I'm reading correctly it says "Thermocouple conversion time" is a maximum of 100ms, so it should be able to do this much more quickly than once every 750ms. I might not be able to get 10Hz out of it but seems like 4Hz should be no problem (??)

aestorbe:
I'm trying to figure out what it is that determines when or how fast it prints to serial,

As far as the sensor goes, the speed is governed by the resolution. With 9-bit resolution, you might get the project to run at 10Hz as the conversion takes about 93mS, but there may be other issues. You might find the SD card is a limiting factor. You might also question if you really need 10Hz. If you really do, it is probably better to use a simpler device than the DS18B20.

Check the Maxxim datasheet. The Hacktronics DS18B20 tutorial is considerably less convoluted than what you are using.

Thank you for your response, a few questions:

  1. “conversion takes about 93mS”<---- how did you come up with this? The only thing I can find in the MAX31850 data sheet is

“Temperature Conversion Time
(Thermocouple, Cold Junction,
Fault Detection)”

Which says max is 100mS (consistant with what you said, but I’m wondering how you came up with that number)

  1. What better options are there? Other than the ~$30 I have invested I’m not emotionally attached to these one wire breakout boards, if there is a better option for reading thermocouples I’m okay with trying something else. Adafriut has I2c boards and analog boards, I was avoiding analog because I didn’t want to tie up the few analog pins I have available, but I also like things that are simple so I’m open to suggestions.

I will stumble through the Hacktronics tutorial and see if I can learn something. I assume I would have to change something in their example to get it to work with my MAX31850 rather than the DS18B20 probably some settings in there somewhere.

Their code has a 2000ms delay, I’m guessing if I can get it working with my hardware, I can then start cutting down that delay time and see how low I can go without problems (?)

I am definitely willing to sacrifice resolution to get speed, I don’t need anywhere near the .25C resolution they claim, I’d be happy with ~2-3C resolution and probably could live with less than that.

I probably don’t need 10Hz, but I need to be in that neighborhood, definitely better than 1Hz. My thermocouple claims “300ms response time!” I’m not sure exactly how they measure that (seems like it would depend on the thermal mass of the thermocouple and the temperature gradient that it is responding too), but I’d like to at least be able to see how quickly the thermocouple responds in my data. (one thing I’m shooting for is the ability to compare how fast different thermocouples respond).

May be on to something of an answer to my question, I found this thread:

http://forums.adafruit.com/viewtopic.php?f=1&t=54888

Which basically says that the DallasTemp library was written for the DS18B20 and then adapted to the MAX31850.

The DS18B20 has a feature to allow changing the resolution which reduces the conversion time, that is what all the business about "case9, case10, case11, case12" is all about. It seems to set the delay based on the max conversion time at those levels of resolution.

The MAX31850 however doesn't have the feature to change resolution, and lists 100ms as it's max conversion time on it's datasheet, so it looks to me like even not knowing how all of this works, I should be able to change all of those numbers to 100 (or maybe 105 to leave some margin) and see what happens. That would get me close to 10Hz.

Does that seem right??

aestorbe:
The only thing I can find in the MAX31850 data sheet is

"Temperature Conversion Time
(Thermocouple, Cold Junction,
Fault Detection)"

Which says max is 100mS (consistant with what you said, but I'm wondering how you came up with that number)

Sorry, it looks like I'm singing the wrong song. I thought from the code in your reply #1 that you were using a DS18B20, and I was alluding to the DS18B20 datasheet from Maxxim.

Does that seem right??

Yes. See my previous.

Hi,

I posted your doubt in Adafruit Forum and got this responce !

I manage to work something out with it! It works like a charm.
I know it is a bit late, though I guess it suits as a solution for this matter.

Best Regards.