Introduction: DIY Logging Thermometer With 2 Sensors
This project is an enhancement of my previous project "DIY Logging Thermometer". It logs the tempearature measurements to a micro SD card.
Hardware changes
I added a DS18B20 temperature sensor to the real time clock module, where there is provision on the printed circuit board for this device; and added the appropriate wire from the "DS" pin of RTC to D2 of the Arduino.
Software changes
Then I added to and modified the software. The main changes are:
The LCD display shows two temperatures "In" and "Out".
The log files recorded on the SD card have two temperature fields, "temperature In" and "temperature Out".
Because of the longer record on the SD card, the working buffers for the EEPROM were larger and as a result of this I started to have memory conflict problems. I made a number of changes aimed at reducing usage of dynamic memory, including using character arrays for all strings instead of String object.
The part of the software that gets the temperatures has major modifications, much of which is to do with identifying which probe is "in" and which is "out". This identification is mostly automatic. If for some reason the probes are switched around, it can be corrected by unplugging the "out" probe and then plugging it back in again. I have not experienced this reversal myself. The programmer or user does not need to type in the sensor addresses, the software discovers the temperature sensor addresses by itself.
According to the testing I have done, the identification of the temperature probes, and the response to removal and replacement of the SD card, still work seamlessly.
Step 1: Software Development
This step gives you the full software for the completed project. I compiled it using Arduino IDE 1.6.12. It uses 21,400 bytes of program memory (69%) and 1,278 bytes of dynamic memory (62%).
I have put comments in the code in the hope that will make it clear what is going on.
Attachments
Step 2: Working With Two Temperature Sensors - Details
This software uses the "OneWire" library. It does not use any "DallasTemperature" or similar libraries. Instead the commands to and data from the temperature sensors are done by the sketch and can be seen and understood quite easily. I found a useful list of the OneWire library commands at
https://www.pjrc.com/teensy/td_libs_OneWire.html
When there are two (or more) temperature sensors, it becomes necessary to identify which one is which.
I called my two sensors "in" and "out", which is typical of commercial units that have a sensor in the display module which is normally "inside", and the other sensor on a cable so it can be put on the other side of an external wall and thus be "outside".
The usual approach to identifying the different probes is to discover the device addresses and put them in the software along with an identifying label. All of the other projects that I have seen use this approach, whether or not they use the DallasTemperature library or not.
My intention was that the software should automatically identify the sensors and correctly allocate them to "in" and "out". This is easy enough to do by putting them on separate Arduino pins. In this project, A0 to A3 and A6 and A7 are all unused, so one of these could have been used in this case. However I succeeded in having the automatic identification work with the sensors both on the same OneWire bus.
It works like this.
The OneWire library has a command "OneWireObject.search(address)" where "address" is an array of 8 bytes and "OneWireObject" is the name of an instance of the OneWire object that has been previously created. It can have any name you like. Mine is called "ds". When you issue this "search" command, the OneWire library does some signalling on the one wire bus. If it finds a responding sensor, it returns a "TRUE" boolean value and fills in the "address" array with the 8 byte unique identifier of the sensor. This identifier includes a family code (at the beginning) and a check sum (at the end). In between are 6 bytes that uniquely identify the sensor within its family.
One result (address and return TRUE) is obtained each time this command is given, cycling through all of the devices on the OneWire bus. Once every device has responded, the next time "search" is issued, the return is "FALSE", indicating every device on the bus has responded already. If the "search" is issued again, the first device responds again - and so on indefinitely. The devices always respond in the same order. The order of responses is based on the identifiers of the devices on the OneWire bus. It appears to be a binary search starting from the least significant bits of the device identifiers. The protocol used to find these identifiers is quite complex, and is described in pages 51 - 54 of document "Book of iButton Standards" which is a pdf document at http://pdfserv.maximintegrated.com/en/an/AN937.pd...
I tested this search process with from 1 to 11 sensors on a single bus, and found the response order for a given set of devices was always the same, but when I added a new device to the end of the bus, there was no way I could predict where in the search order it would appear. For example, the 11th sensor I added came in at position No.5; and the first sensor I put on the bus was aways the last in the search order.
In this project with two sensors, one of them is soldered in place on the RTC module; the other one is plugged in using a male header on the board and a female header on the cable. It can easily be detached.
When the sensor on the cable (the "out" sensor) is detached, the "search" command produces alternating "TRUE" and "FALSE" returns.
When the sensor on the cable is attached, the "search" command produces a 3-stage cycle, with two "TRUE" and one "FALSE" returns.
My procedure is to issue 1, 2 or 3 "search" commands, until a FALSE result is returned. Then I issue 2 more "search" commands. If the second one fails (ie FALSE) I know there is only one sensor on the bus and that it is the "in" sensor. The device identity is recorded and allocated to the "in" sensor.
At a later time, if both first and second returns are TRUE, I know there are two sensors on the bus. I check which one of them has an identity equal to the "in" sensor, and allocate the other one as the "out" sensor.
The other minor point is that the gathering of the results from the two sensors is done by sending the "start conversion" by what is known as a "skip ROM" command. We have the option of sending commands to a single device (using its unique identifier) or to all devices on the bus (skip ROM). The code looks like this:
ds.reset(); // // send "skip ROM" command (so next command works in both sensors) ds.write(0xCC); // Skip ROM command ds.write(0x44,0); // start conversion in both probes temperature_state = wait_convert ; // go to delay state
When the required delay time has passed, the temperatures are received from each sensor individually. Here is the code for the second sensor (ie the OUT sensor).
if (flag2) { present = ds.reset(); ds.select(DS18B20_addr_out); ds.write(0xBE); // Read Scratchpad of "out" probe data[0] = ds.read(); data[1] = ds.read(); temperature_out = (data[1] << 8) + data[0] ; temperature_out = (6 * temperature_out) + temperature_out / 4; // multiply by 6.25 } else { // not flag2 - ie Out sensor not connected temperature_out = 30000 ; // fix at 300.00 C if temp sensor not working } // end of if (flag2)
I worked out most of this software in a stand-alone sketch that just had the temperature sensors in it, without the complications of LCD, RTC and SD card support. This development sketch is in the file below.
Attachments
Step 3: Preliminary Results
This chart is a combination of the first two part-days of readings.