Dejan Levec

DS28EA00 and Arduino

Recently I found two sample Maxim DS28EA00 temperature sensors that I requested for a project I haven’t finished. I’m currently working on a project requiring somewhat accurate temperature measuring and I will finally be able to use this sensor.

Firstly I needed a way to connect this sensor to Arduino and I made simple breakout board that allows to connect MSOP8 package sensor to breadboard. I wanted to expose three pins: ground, IO and Vcc. Unfortunately I didn’t remember that SMD parts aren’t through holes and therefore they need to be mirrored. Because of this mistake (that I noticed after etching) 3rd outer pin is connected to NC pin on chip and not on the Vcc. Thankfully, 1-wire protocols allows for parasite mode which means that voltage can be sourced from data line, so my breakout board is still useful.

Hardware

To connect this sensor to Arduino you need to:

  • connect sensor GND to Arduino GND,
  • connect sensor IO to one of the digital pins (pin 10 in my case),
  • connect 4.7k ohm resistor from IO line at Arduino to 5V.

In my case it works fine with 2.7k ohm resistor, but 4.7k is recommended. This pull-up resistor allows the use of parasite mode by providing 5V to IO pins of devices.

 

Software

I haven’t found any examples of connecting this sensor to Arduino, so I had to read datasheet and understand what I need to send and what I get back from the sensor. After I finished my code, I found out that the communication is the same as for DS18*20 sensors which is very popular and you can find many examples. I¬†actually started with example for that sensor and removed sensor specific code.

Anyway, here is the code:

#include <OneWire.h>
OneWire ds(10);

void setup(void) {
  Serial.begin(9600);
}

void loop(void) {
  byte i;
  byte present = 0;
  byte data[12];
  byte addr[8];

  if ( !ds.search(addr)) {
     Serial.print("No more addresses.\n");
     delay(1000000);
     ds.reset_search();
      return;
  }

  Serial.print("R=");
  for( i = 0; i < 8; i++) {
    Serial.print(addr[i], HEX);
    Serial.print(" ");
  }

  if ( OneWire::crc8( addr, 7) != addr[7]) {
      Serial.print("CRC is not valid!\n");
      return;
  }

  if ( addr[0] == 0x42) {
      Serial.print("DS28EA00 detected\n");
  }else{
    return;
  }

  ds.reset();
  ds.select(addr);
  ds.write(0x44,1); //convert temperature, parasite mode

  delay(1000); //wait at least 750ms for the conversion to finish

  present = ds.reset();
  ds.select(addr);
  ds.write(0xBE); //read scratchpad

  Serial.print("P=");
  Serial.print(present,HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  Serial.print(" CRC=");
  Serial.print( OneWire::crc8( data, 8), HEX);
  Serial.println();

  byte lsb = data[0];
  byte msb = data[1];
  int16_t temp = (((int16_t)msb) << 8 ) | lsb;
  Serial.println((float)temp * 0.0625, DEC);//0.0625 for 12bit
}

One thing missing with examples for DS18*20 sensors was the explanation of the code. I really like to understand what I’m using and I like to discover how things works.

ds.search searches for OneWire devices on that Arduino pin and continues with the code if it finds one.

if ( OneWire::crc8( addr, 7) != addr[7]) {
      Serial.print("CRC is not valid!\n");
      return;
  }

crc8(byte array, count) calculates CRC code of first 7 bytes and compares it to precalculated CRC code in 8th item of array. If it matches, it means that we received right data, otherwise there is obviously problem with data transfer.

 if ( addr[0] == 0x42) {
      Serial.print("DS28EA00 detected\n");
  }else{
    return;
  }

This checks if first byte matches 0x42, because address of DS28EA00 family of temperature sensors starts with this byte. Otherwise we just return and the loop starts again.

ds.reset();
 ds.select(addr);
 ds.write(0x44,1); //convert temperature, parasite mode

 delay(1000); //wait at least 750ms for the conversion to finish

According to datasheet we need to send reset, select our device and then send the code for starting the conversion (in this case it’s 0x44). Second parameter in write call is used to tell OneWire library that we use it in parasite mode and that the IC needs to source 5V from IO pin.

Datasheet specifies that the conversion will took at most 750ms. We don’t want to push the limits and we will survive to wait additional 250ms.

present = ds.reset();
 ds.select(addr);
 ds.write(0xBE); //read scratchpad


Again, we reset OneWire, select the device and write code for reading the scratchpad (0xBE).

for ( i = 0; i < 9; i++) {
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }

We read first 9 bytes from the device and print it to serial port.

First and second bytes are temperature, third and fourth are for high and low temperature alarm, fifth is for setting precision, and others are reserved.

Ninth byte is CRC of first 8 bytes and we match it to see if there were any transmission errors.

byte lsb = data[0];
 byte msb = data[1];

We save LSB in MSB bytes so sepeperate variables.

int16_t temp = (((int16_t)msb) << 8 ) | lsb;

Temperature is 16-bit number divided to least and most significat byte.

Serial.println((float)temp * 0.0625, DEC);//0.0625 for 12bit

We need to multimly calculated 16-bit integer with 0.0625 (in case of 12bit resolution) and convert it to float. Then we print it to serial port.

Output on serial port:

R=42 F0 25 5 0 0 0 64 DS28EA00 detected
P=1 5D 1 3 3 7F FF 3 10 63 CRC=63
21.8125000000

Leave a Reply

Your email address will not be published. Required fields are marked *