(fixed) Using EEPROM in DS18B20

Hi Guys,

I want to use the 1-Wire Temperature Sensor DS18B20 from Maxim but i have problem with using its internal EEPROM.
I downloaded the DallasTemperature.h library that is using the OneWire.h library. My problem is, that i want to store a SensorNumber into the LowerTemperature Register.
As far i understood the datasheet, this should be one of the three registers that are stored into the nonvolatile EEPROM, but as soon I disconnect my sensors, the register is empty.
I also tried to recall the data from the EEOROM by using these lines:

_wire->reset();
_wire->select(deviceAddress);
_wire->write(RECALLSCRATCH);
_wire->reset();

but even if I do so, the Scratchpad stays empty.

Does anybody know how to store and load data with this device?

Thanks in advance for your help!

Short Update:

it seems that the Recalling-step is done during every power up of the chip. In that case there must be something wrong with the storing part..
I took the code for that as it was (from the Library)

// writes device's scratch pad
void DallasTemperature::writeScratchPad(uint8_t* deviceAddress, const uint8_t* scratchPad)
{
  _wire->reset();
  _wire->select(deviceAddress);
  _wire->write(WRITESCRATCH);
  _wire->write(scratchPad[HIGH_ALARM_TEMP]); // high alarm temp
  _wire->write(scratchPad[LOW_ALARM_TEMP]); // low alarm temp
  // DS18S20 does not use the configuration register
  if (deviceAddress[0] != DS18S20MODEL) _wire->write(scratchPad[CONFIGURATION]); // configuration
  _wire->reset();
  // save the newly written values to eeprom
  _wire->write(COPYSCRATCH, parasite);
   
  if (parasite) delay(10); // 10ms delay
  _wire->reset();
}

btw: I am not using the Parasite Powered Mode, Vcc and Gnd are connected to the Arduino's power supply.

From the datasheet: "Data can also be reloaded from EEPROM to the scratchpad at any time using the Recall E2 [B8h] command."

Once you reload the scratchpad, then you can read the contents.

The same applies in reverse. To write to EEPROM, load what you want into the scratchpad, then use the Copy Scratchpad [48h] to save the contents of the scratchpad into the EEPROM.

Mitch

i tried both, but it everytime i power down the sensor it has the values +70 in the LowTemp register and +75 in the HighTemp register.
I assume those are the standard values.

The code i am using to copy a new value into the scratchpad should automatically write the data to the EEPROM.. i have no idea why it doesn't keep my values....

Make sure you are actually updating the scratchpad before copying it to EEPROM. Write you TH, TL bytes (plus the config register - it is needed!) to the scratchpad. Then read it back to confirm. If it matches, go ahead and copy the SP to the EEPROM.

Mitch

Hey Mitch,
Thanks for your help, but I am sitting in front of this problem for over a day, and i have tried so many things now..

At the moment my programm consists only of:

Setup:

  • Initializing 5 sensors with my own ID (0 to 4) by writing these numbers into the Low and Hi Temperature register

Loop:

  • ReadScratchPad and send ID via Serial.print() to PC
  • After every reading cycle copy the data AGAIN into the EEPROM

.... the response to the first readScratchPad commands are correct, but as soon i disconnect the power the result switches to +70 and +75...
This is what I display in my terminal Programm (all values are read from the sensor)

Entering Setup<<
Initializing Sensors<<

Entering Loop<<
DevAddr: 281E7AAB40025
LO: 0 HI: 0
DevAddr: 28B6FAA400B4
LO: 1 HI: 1
DevAddr: 28ADFDAA4006E
LO: 2 HI: 2
DevAddr: 285352AB400DC
LO: 3 HI: 3
DevAddr: 2851B6AA400F8
LO: 4 HI: 4

DevAddr: 281E7AAB40025
LO: 70 HI: 75
DevAddr: 28B6FAA400B4
LO: 70 HI: 75
DevAddr: 28ADFDAA4006E
LO: 70 HI: 75
DevAddr: 285352AB400DC
LO: 70 HI: 75
DevAddr: 2851B6AA400F8
LO: 70 HI: 75

Post your entire code and let's see where that takes us.

Maybe someone will be able to spot the problem.

This is the Code that is used.
(the methods setSensorNumber() and getSensorNumber() are from my own library Harness.h but I only use those two at the moment, so i copied them underneath).

hopefully someone can help me with this.

Is it possible that it is a hardware issue?

i am using Vcc and Gnd from the Board, and the DQ line has a pullup of 1k (instead of 4k). Everything except the storing into the EEPROM works until 50m cable length (so far)

#include <OneWire.h>
#include <DallasTemperature.h>
#include <Harness.h>
void setup(void)
{
	
	
	delay(3000);
        //Initialize uart1
        Serial.begin(115200); 
	
        //Initialize harness (search and enumberate Device)
	harness1.begin();
	harness1.setWaitForConversion(FALSE);
	
        //write own IDs to Scratchpad
	harness1.setSensorNumber(0x28, 0x1E, 0x7A, 0xAB, 0x04, 0x00, 0x00, 0x25, 0);
	harness1.setSensorNumber(0x28, 0x0B, 0x6F, 0xAA, 0x04, 0x00, 0x00, 0xB4, 1);
	harness1.setSensorNumber(0x28, 0xAD, 0xFD, 0xAA, 0x04, 0x00, 0x00, 0x6E, 2);
	harness1.setSensorNumber(0x28, 0x53, 0x52, 0xAB, 0x04, 0x00, 0x00, 0xDC, 3);
	harness1.setSensorNumber(0x28, 0x51, 0xB6, 0xAA, 0x04, 0x00, 0x00, 0xF8, 4);
	
	
}
void loop(void)
{

	harness1.getSensorNumber(0x28, 0x1E, 0x7A, 0xAB, 0x04, 0x00, 0x00, 0x25);
	harness1.getSensorNumber(0x28, 0x0B, 0x6F, 0xAA, 0x04, 0x00, 0x00, 0xB4);
	harness1.getSensorNumber(0x28, 0xAD, 0xFD, 0xAA, 0x04, 0x00, 0x00, 0x6E); 
	harness1.getSensorNumber(0x28, 0x53, 0x52, 0xAB, 0x04, 0x00, 0x00, 0xDC);
	harness1.getSensorNumber(0x28, 0x51, 0xB6, 0xAA, 0x04, 0x00, 0x00, 0xF8);

	delay(1000); 
}

void Harness::setSensorNumber(uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4, uint8_t x5, uint8_t x6, uint8_t x7, uint8_t x8, uint8_t sensorNumber)
{
	ScratchPad scratchPad;
	DeviceAddress deviceAddress; 
	deviceAddress[0]=x1;
	deviceAddress[1]=x2;
	deviceAddress[2]=x3;
	deviceAddress[3]=x4;
	deviceAddress[4]=x5;
	deviceAddress[5]=x6;
	deviceAddress[6]=x7;
	deviceAddress[7]=x8;
	if (ch->isConnected(deviceAddress, scratchPad))
	{
		ch->readScratchPad(deviceAddress, scratchPad);
		scratchPad[LOW_ALARM_TEMP] = (uint8_t)sensorNumber;
		scratchPad[HIGH_ALARM_TEMP] = (uint8_t)sensorNumber;
		
		ch->writeScratchPad(deviceAddress, scratchPad);
	}
}

uint8_t Harness::getSensorNumber(uint8_t x1, uint8_t x2, uint8_t x3, uint8_t x4, uint8_t x5, uint8_t x6, uint8_t x7, uint8_t x8)
{
	ScratchPad scratchPad;
	DeviceAddress deviceAddress;
	deviceAddress[0]=x1;
	deviceAddress[1]=x2;
	deviceAddress[2]=x3;
	deviceAddress[3]=x4;
	deviceAddress[4]=x5;
	deviceAddress[5]=x6;
	deviceAddress[6]=x7;
	deviceAddress[7]=x8;
	if (ch->isConnected(deviceAddress, scratchPad))
	{
		Serial.print("DevAddr: ");
		for(uint8_t i=0; i<8; i++)
		{
			Serial.print(deviceAddress[i], HEX); 
		}
		Serial.println("");
		ch->readScratchPad(deviceAddress, scratchPad);
		Serial.print("LO: "); Serial.print(scratchPad[LOW_ALARM_TEMP]); Serial.print("  HI: "); Serial.println(scratchPad[HIGH_ALARM_TEMP]);
		ch->writeScratchPad(deviceAddress, scratchPad);
	}
	return scratchPad[HIGH_ALARM_TEMP] ; 
}

I found the problem by myself...
the Library DallasTemperature.h has an error in the function writeScratchPad().

after writing the Scratchpad it says it is storing the Data also into the EEPROM, but before it does that, it is neccessary to send an _wire->reset().
unfortunately it forgets to address the device newly, so the no device will accept the next copy-command.

here the code snippet that i've corrected

  _wire->reset();
  _wire->select(deviceAddress); //<--this line was missing
  // save the newly written values to eeprom
  _wire->write(COPYSCRATCH, 0);//parasite);
   
  if (parasite) delay(10); // 10ms delay
  _wire->reset();

Great find!

posted the solution as an issue here - persistant write to EEPROM · Issue #14 · milesburton/Arduino-Temperature-Control-Library · GitHub -

Thanks guys,

I've pushed the fix.

Hello, I am having the same problem as dave on the temp library.
I manually modified the library .cpp file to add the suggested missing line, but it didn't work.
With that modification the sensor doesn't keep the low alarm temperature that I set before power down, moreover it doesn't even accept the setting.
If I read the scratchpad after setting the low alarm temperature byte, its value stays at 0x46 (70) that is the default one.

Did I miss stg?

Here's the code in which I read and write the sensor scratch pad

/*-----( Import needed libraries )-----*/
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Streaming.h>

/*-----( Declare Constants and Pin Numbers )-----*/
#define SENSOR_PIN 5     // Any pin 2 to 12 (not 13) and A0 to A5
#define WAKEUP_PIN 6     // Autoritiene il segnale di sveglia da RTC e spegne la board
#define SET_TIME_PIN 7   // Riceve il comando di set time da pulsantino
#define MAX_PROBES_NR 40 // Max number of probes on bus
#define MIN_INTERVAL 1   // Intervallo di campionamento in minuti
#define DELIM ','        // Carattere delimitatore di campo su trasmissione seriale

typedef struct {
  DeviceAddress Address;
  float Temp;
} TempProbe;

TempProbe TProbe[MAX_PROBES_NR];

/*-----( Declare objects )-----*/
OneWire  oneWire(SENSOR_PIN);         // Create a 1-wire object
DallasTemperature sensors(&oneWire);  // Pass our oneWire reference to Dallas Temperature.

/*-----( Declare Variables )-----*/
// Assign the addresses of your 1-Wire temp sensors.
// See the tutorial on how to obtain these addresses:
// http://www.hacktronics.com/Tutorials/arduino-1-wire-address-finder.html

DeviceAddress OneWireDevice[MAX_PROBES_NR];
byte          ProbesFndNr;
byte          probeMark;
byte          scratchPad[9];

void setup()  /****** SETUP: RUNS ONCE ******/
{
  byte i = 0;
  
  Serial.begin(9600);
  
  //discoverOneWireDevices();  // Everything happens here!
  ProbesFndNr=discoverProbes();
  
  if (ProbesFndNr<=0) Serial << F("No temp probes found") << endl;
  else 
  {
    if (ProbesFndNr>1) Serial << F("Error! Found multiple temp probes") << endl;
    else
    {
     sensors.readScratchPad(TProbe[0].Address,scratchPad);
     Serial << F("Current mark: ") << scratchPad[3] << endl;
    }
  }
  
}//--(end setup )---

void loop()   /****** LOOP: RUNS CONSTANTLY ******/
{ 
  static boolean flag;
  byte i;
  
  if ((ProbesFndNr==1) && (!flag))
  { 
    if (Serial.available()>0) 
    {
      delay(10);
      probeMark=Serial.parseInt();
      scratchPad[3]=probeMark;
      //scratchPad[2]=0x79;
      sensors.writeScratchPad(TProbe[0].Address,scratchPad);
      sensors.readScratchPad(TProbe[0].Address,scratchPad);
      Serial << F("Probe scratchpad:") << endl;
      for( i = 0; i < 9; i++) 
      {
        Serial.print("0x");
        if (scratchPad[i] < 16) 
        {
          Serial.print('0');
        }
        Serial.print(scratchPad[i], HEX);
        if (i < 8) 
        {
          Serial.print(", ");
        }
      }         
      Serial << endl << F("Mark written: ") << probeMark << endl;
      flag=1;
    }
  }
}

byte discoverProbes(void) 
{
  byte i,deviceID = 0,probeID = 0;  
 
  while(oneWire.search(OneWireDevice[deviceID]))
  {
    // Serial.print("\n\r\n\rFound \'1-Wire\' device with address:\n\r");
    Serial << F("Device ");
    if ((deviceID+1)<10) Serial << F("0");
    Serial << deviceID+1 << F(": "); 
    for( i = 0; i < 8; i++) {
      Serial.print("0x");
      if (OneWireDevice[deviceID][i] < 16) {
        Serial.print('0');
      }
      Serial.print(OneWireDevice[deviceID][i], HEX);
      if (i < 7) {
        Serial.print(", ");
      }
    }
    if ( OneWire::crc8( OneWireDevice[deviceID], 7) != OneWireDevice[deviceID][7]) {
      Serial << ("CRC is not valid!") << endl;
      return 0;
    }
    if (OneWireDevice[deviceID][0]=0x28)
    {
      for( i = 0; i < 8; i++)  TProbe[probeID].Address[i]=OneWireDevice[deviceID][i];
      probeID++;
    }  
    deviceID++;
    Serial << endl;
  }

  oneWire.reset_search();
  
  return probeID;
 
}

Hello again, I managed to solve the issue. Now I can write bytes in DS18B20 EEPROM correctly and they are retained after power up by using the same code listed above.

I basically added a 20ms delay after the COPYSCRATCHPAD command in the .cpp file, to allow the EEPROM to be written (10ms needed as specified by DS18B20 datasheet). This time must be added to the 10ms delay used when in parasite mode.

Please note that I used an Arduino Mega 2560 for this.

It would be great to have some feedback about this, just to have a confirmation that this works also for others.

Please refer to the code below:

// writes device's scratch pad
void DallasTemperature::writeScratchPad(const uint8_t* deviceAddress, const uint8_t* scratchPad)
{
    _wire->reset();
    _wire->select(deviceAddress);
    _wire->write(WRITESCRATCH);
    _wire->write(scratchPad[HIGH_ALARM_TEMP]); // high alarm temp
    _wire->write(scratchPad[LOW_ALARM_TEMP]); // low alarm temp
    // DS1820 and DS18S20 have no configuration register
    if (deviceAddress[0] != DS18S20MODEL) _wire->write(scratchPad[CONFIGURATION]); // configuration
    _wire->reset();
    _wire->select(deviceAddress); //<--this line was missing
    // save the newly written values to eeprom
    _wire->write(COPYSCRATCH, parasite);
    delay(20);  // <--- added 20ms delay to allow 10ms long EEPROM write operation (as specified by datasheet) 
    if (parasite) delay(10); // 10ms delay
    _wire->reset();
}