I have a DS18B20 Temperature Sensor with which I measure changes on an peltier element, but the default Resolution of 12 seems to be too slow to measure the temperature the DS18B20 can not handle temperature changes with a rate of > 1°C/s.
So I wanted to change the Resolution to 9 or 10, but it does not work.
I tried the following code from a tutorial:
#include <OneWire.h>
#define OUT_PIN 3 // output digital pin
OneWire ds(OUT_PIN); // Connect your 1-wire device to pin "OUT_PIN"
byte addr[10][8];
byte device_nb = 0;
void setup(void) {
Serial.begin(9600);
SearchDevices(); // search 1-wire devices
// Set configuration
for( device_nb = 0; device_nb < 10; device_nb++) {
if (addr[device_nb][0] == 0x28){
Serial.print("\r\nScratch Pad before modification: \r\n");
ReadScratchPad(addr[device_nb]); // display scratchpad
WriteScratchPad(addr[device_nb], 10); // write scratchpad configuration, ask for a 9, 10, 11 or 12 bits resolution
Serial.print("\r\nScratch Pad after modification: \r\n");
ReadScratchPad(addr[device_nb]); // display scratchpad
Serial.print("\r\n");
}
}
}
void loop(void) {
// do nothing
}
void SearchDevices(){
byte i;
Serial.print("Looking for 1-Wire devices...\n\r");
while(ds.search(addr[device_nb])) {
if ( OneWire::crc8( addr[device_nb], 7) != addr[device_nb][7]) {
Serial.print("CRC is not valid!\n");
break;
}
if (device_nb < 10){
device_nb++;
} else {
Serial.print("More than 10 devices, unable to load them all\n");
break;
}
}
ds.reset_search();
if (device_nb < 9){
addr[device_nb][0] = 0; // erase last 1-wire device as it is accounted 2 times
}
for( device_nb = 0; device_nb < 10; device_nb++) {
if (addr[device_nb][0] == 0x28){
Serial.print("Device Number ");
Serial.print(device_nb);
Serial.print(" : ");
for( i = 0; i < 8; i++) {
Serial.print(addr[device_nb][i], HEX);
Serial.print(" ");
}
Serial.print("\n\r");
}
}
}
void ReadScratchPad(byte addr[8]){
byte data[12];
byte i;
ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
Serial.print(data[i], HEX);
Serial.print(" ");
}
}
void WriteScratchPad(byte addr[8], byte res_bit){
byte reg_cmd;
switch(res_bit){
case 9: reg_cmd = 0x1F; break;
case 10: reg_cmd = 0x3F; break;
case 11: reg_cmd = 0x5F; break;
case 12: reg_cmd = 0x7F; break;
default: reg_cmd = 0x7F; break;
}
ds.reset();
ds.select(addr);
ds.write(0x4E); // Write scratchpad command
ds.write(0x00); // TL data
ds.write(0x00); // TH data
ds.write(0x3F);
//ds.write(reg_cmd); // Configuration Register (resolution) 7F=12bits 5F=11bits 3F=10bits 1F=9bits
ds.reset(); // This "reset" sequence is mandatory
ds.select(addr); // it allows the DS18B20 to understand the copy scratchpad to EEPROM command
ds.write(0x48); // Copy Scratchpad command
}
But the Scratchpad content does not seem to change, the program prints the following:
Looking for 1-Wire devices...
Device Number 0 : 28 61 64 11 B2 4B 9F 48
Scratch Pad before modification:
6D 1 FF FF 7F FF FF FF 6B
Scratch Pad after modification:
6D 1 FF FF 7F FF FF FF 6B
What am I doing wrong? I also tried using the DallasTemperature Library to change the resolution, but that did not work as well.
I also tried several different Sensors, but I can not modify the resolution on any of those.
TitusJonas:
I also tried using the DallasTemperature Library to change the resolution, but that did not work as well.
Maybe you are mixing codes. If you are using the DallasTemperature library in some standard code, like this, I think it just a matter of keeping the names right.
// Assign the unique addresses of your 1-Wire temp sensors.
DeviceAddress insideThermometer = { 0x28, 0x94, 0xE2, 0xDF, 0x02, 0x00, 0x00, 0xFE };
void setup(void)
{
sensors.begin();
sensors.setResolution(insideThermometer, 10);
........etc
After changing the resolution, you are reading the 64-bit ROM/Address Code of the sensor; you don't see any change here; accordingly, you think that the resolution change has not taken place. Actual facts are: This is not correct. Please, see Post#4 @el_supremo
1. 64-Bit ROM/Address Code is always a fixed value for each and every sensor. No two sensors will have the same code.
2. The resolution value is reflected in byte-4 of the Scratchpad Data of the DS18B20 sensor. Therefore, you need to read the Scratchpad memory to see the change. Please see the following figure:
3. Byte-4 of the figure of Step-2 is the Configuration Register which contains the values of the R1-R0 bits that determine the resolution as per following definition:
4. The execution of the following Sketch prints the 64-bit ROM/Address Code and the Resolution of the Sensor.
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 3
OneWire ds(3);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress insideThermometer;
byte data[9]; //to hold Scratch Pad data of Ds18B20
void setup(void)
{
Serial.begin(9600);
// Serial.println("Dallas Temperature IC Control Library Demo");
Serial.print("Locating devices...");
sensors.begin();
Serial.print("Found ");
Serial.print(sensors.getDeviceCount(), DEC);
Serial.println(" devices.");
// Serial.print("Parasite power is: ");
if (sensors.isParasitePowerMode())
{
Serial.println("ON");
}
else
{
;// Serial.println("OFF");
}
if (!sensors.getAddress(insideThermometer, 0))
{
Serial.println("Unable to find address for Device 0");
}
// Serial.print("Device 0 Address/64-Bit Fixed ROM Code: ");
// printAddress(insideThermometer);
Serial.println();
sensors.setResolution(insideThermometer, 9); // 0 R1 R0 1 1 1 1 1; R1 R0 = 00 (9); 01 (01); 10; 10 (11); 11 (12)
// Serial.print("Device 0 Resolution: ");
//Serial.print(sensors.getResolution(insideThermometer), DEC);
// Serial.println();
ds.reset();
ds.select(insideThermometer);//addr2); //selectimg the desired DS18B20
ds.write(0xBE); //Function command to read Scratchpad Memory (9Byte)
ds.read_bytes(data, 9); //data comes from DS-scratchpad and are saved into buffer data[8]
// Serial.print("Configuration Register for Resolution = ");
// Serial.println(data[4], BIN); // 0 R1 R0 1 1 1 1 1; R1 R0 = 00 (9); 01 (01); 10; 10 (11); 11 (12)
Serial.print("Fixed 64-Bit ROM/Address Code = ");
printAddress(insideThermometer);
Serial.print(" : Sensor Resolution = ");
Serial.print(data[4], HEX); // 0 R1 R0 1 1 1 1 1; R1 R0 = 00 (9); 01 (01); 10; 10 (11); 11 (12)
Serial.print(" (");
Serial.print(sensors.getResolution(insideThermometer), DEC);
Serial.println(")");
// while (1);
}
void printTemperature(DeviceAddress deviceAddress)
{
float tempC = sensors.getTempC(deviceAddress);
Serial.print("Temp C: ");
Serial.print(tempC);
Serial.print(" Temp F: ");
Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
}
void loop(void)
{
// Serial.println("Requesting temperatures...");
sensors.requestTemperatures();
// Serial.println("DONE");
printTemperature(insideThermometer); // Use a simple function to print out the data
delay(1000);
}
void printAddress(DeviceAddress deviceAddress)
{
for (uint8_t i = 0; i < 8; i++)
{
if (deviceAddress[i] < 16) Serial.print("0");
Serial.print(deviceAddress[i], HEX);
}
}
Change the resolution value in the program as 9, 10, 11,, and 12. Re-run the program and observe that the new value has been reflected in the Configuration Register. Also, observe that the 64-bit ROM/Address code has not changed.
After changing the resolution, you are reading the 64-bit ROM/Address Code of the sensor
No he isn't. The code reads and prints the ROM address, reads and prints the scratchpad, writes to the scratchpad and then reads and prints the scratchpad again.
The problem is the missing delay after copying the scratchpad with ds.write(0x48);
The code copies the scratchpad and immediately tries to read the scratchpad. This does not give the device time to write the scratchpad data to the EEPROM. There must be a delay of at least 10ms after issuing the copy scratchpad command and before trying to access the sensor again.
@OP: One thing you might try at the same time is to use 0x20 instead of 0x3F for the resolution. The bottom 5 bits can't be changed anyway so don't bother trying
@TitusJonas: I tried your code on a Nano. At first, I couldn't get it to work even with the delay. I meddled with the code a bit and then it started to work. Now I have gone back to your original code without the delay and it also works. I then tried with a different DS18B20 and the original code still works.
Hmmm. Gremlins?
P.S. I wouldn't count on the code working without the delay after issuing the Copy Scratchpad command. It is required even if it appears to work sometimes without it. Add a delay(20).
el_supremo:
No he isn't. The code reads and prints the ROM address, reads and prints the scratchpad, writes to the scratchpad and then reads and prints the scratchpad again.
Yes! You are right. The OP was reading/printing Scratchpad Memory. I stand corrected!
TitusJonas:
Scratch Pad before modification:
6D 1 FF FF 7F FF FF FF 6B
Scratch Pad after modification:
6D 1 FF FF 7F FF FF FF 6B
TitusJonas:
It's really hard to debug hardware confuse:
I guess that's true, but the sensors are not that likely to be defective and they are pretty robust. There is a possibilty that they aren't actually DS18B20s. You won't be the first to have that but, if they really look like sensors rather than transistors, they probably are sensors. Your code seems to be unnecessarily complicated, try there.
The sensors are almost certainly DS18B20 because they return a valid-looking ROM code: 28 61 64 11 B2 4B 9F 48.
The contents of the scratchpad also look correct. The only problem is that it doesn't change.
I figured out why it didn't work for me. I have the DS18B20 on pin 4 on the Nano. I changed the define of ONE_WIRE_BUS to 4 but didn't change "OneWire ds(3);" to 4. It would still be best to use the fix I suggested do that the pin number is defined in one place. Also, the first line has "include" which should, of course, be "#include".