1 wire sensor interface

Hi folks,

I need to interface a Dalas DS2780 sensor, but I have no experience with the 1 wire interface. Any hints on the required coding? If possible I rather use "direct code" rather than a library.

If possible I rather use "direct code" rather than a library.

Why? If someone has gone to the trouble to do the work already, why not use that?

If you KNOW how to build such a library, why are you here?

casemod:
If possible I rather use "direct code" rather than a library.

Absolutely. Just copy and paste the library into your code. Then it is "direct".

casemod, don't get disappointed by the replies. They are actually valid and to the point.
The DS2780 is not easy to communicate with, so you need example code anyway.

However, it is hard to find example code for it.
I found a linux driver: cfa_10036_kernel/w1_ds2780.c at master · crystalfontz/cfa_10036_kernel · GitHub

Perhaps there is a similar sensor, with Arduino code ?

This is the manufacturer page for it : DS2780 Stand-Alone Fuel Gauge IC | Analog Devices
And you should read this : Getting Started with the DS2780 | Analog Devices

When you have studied that, you can tell us how to communicate with it, because I don't understand it.

Go here: Arduino Playground - OneWire
Use the latest OneWire library, and try to understand the DS18B20 code. It's a start.

Thanks for the advice guys. I guess for this case, I was greatly surprised by the complexity of the library!

Anyway:

I got the library installed and managed to read the ROM ID from a DS2780 battery fuel gauge http://datasheets.maximintegrated.com/en/ds/DS2780.pdf

At this point I am unsure how to further write or query the device. A look in the datasheet gives me all the relevant information such as register location, number of bytes and read/write access, I just don't know ho to actually write this information into the code.

Say for example, temperature data, stored on register 0A (MSB) and 0B (LSB), how would one go to have access to this information?

Grateful for any advice

Regards

Peter_n:
casemod, don't get disappointed by the replies. They are actually valid and to the point.
The DS2780 is not easy to communicate with, so you need example code anyway.

Thanks peter. Not at all, every little bit helps :wink:
I'm sure this code could be useful for others aswell. I have a lithium battery that has one, so one could actually run an arduino on some remote place and monitor the battery status with great accuracy!

Peter_n:
However, it is hard to find example code for it.
I found a linux driver: cfa_10036_kernel/drivers/w1/slaves/w1_ds2780.c at master · crystalfontz/cfa_10036_kernel · GitHub

Perhaps there is a similar sensor, with Arduino code ?

I am unfamiliar with the 1Wire protocol, this is my first time using it, so everything is a bit experimental. Looking for the datasheet seems I only have to read the required fields. There is a built in ADC for voltage and current measurements, an accumulator for coulomb counting and a few other registers such as battery voltage, average readings, etc!

The datasheet however specs some communication details for addressing a single or multiple devices, that perhaps I need to add.

I guess perhaps someone with a bit more understanding on the protocol could advise. I started a thread on Paul's forum, since he maintains the library perhaps he can give some hints as to where to start.

Peter_n:
This is the manufacturer page for it : DS2780 Datasheet and Product Info | Analog Devices
And you should read this : Getting Started with the DS2780 | Analog Devices

When you have studied that, you can tell us how to communicate with it, because I don't understand it.

Go here: Arduino Playground - HomePage
Use the latest OneWire library, and try to understand the DS18B20 code. It's a start.

Apparently the DS18B20 code reads the data shifting the required digits to match whatever resolution the sensor is set to. For this it reads a particular field and then does some conversions.
In regards to the app notes on the maxim website they refer the use of a usb interface. Saddly none of my local distributors (Farnell, digikey, mouser) does stock such device. Apparently it can be used with a variety of Maxim products using 1 wire/I2C, etc!

I am guessing the line byte cfg is perhaps a write operation!?

I tried to change the code to read the address 0A for temperature, by adding a new entry for the DS2780.
This is what it returns, so not sure if the read command is not being properly interpreted:

  ROM = 32 E9 6D 66 0 0 0 B5
  Chip = DS2780
  Data = 1 FF FF FF FF FF FF FF FF FF  CRC=C9

This is the code. Not much done, just posted as a reference

Code replaced with something more meaningful. Check next post.

I'm going to bump on this to add some more details:

In accordance with the OneWire library documentation and DS2780 Datasheet, I am following the steps below:

myWire.Search()
The Address array is filled with the device address, indicating successful communication.
Returns: 32 E9 6D 66 0 0 0 B5

myWire.reset()
resets the bus before any communication takes place

myWire.skip()
Skips the device selection. There is only one device on the BUS, so this is fine for testing purposes

myWire.write(Register address)
Here I add whatever register I want to read, in this case 0A, for the MSB temperature register.
According to the datasheet (Pag 20) this should be read first in order to prevent any updates to the LSB while reading.

myWire.Read()
According to the datasheet (Pag 25) the address is incremented automatically after the MSB is received therefore I can make a loop to read the next LSB

for ( i = 0; i < 2; i++) {           // 2 bytes for temperature
    data[i] = myWire.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");

However, the returned data is always FF!

Here is the code I am using:

#include <OneWire.h>

OneWire  myWire(10);  // on pin 10 (a 4.7K resistor is necessary)

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

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

  myWire.search(addr);
  delay(250);

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

  myWire.reset();
  Serial.println();

  myWire.skip(); 
  myWire.write(0x0A);         //Sellect temperature register, MSB 

  for ( i = 0; i < 2; i++) {           // 2 bytes for temperature
    data[i] = myWire.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  Serial.println();
  delay(1000);
}
  byte data[1];

for ( i = 0; i < 2; i++) {           // 2 bytes for temperature
    data[i] = myWire.read();

How are you going to store two values in a one element array?

PaulS:

  byte data[1];

for ( i = 0; i < 2; i++) {           // 2 bytes for temperature
    data[i] = myWire.read();



How are you going to store two values in a one element array?

Nice catch, I forget to add that from when I was reading a single byte.
Still it doesn't help the fact that the result is always returned as FF. Any ideas?

Since the bus is open-collector, perhaps the sensor is not doing anything on the bus at that moment.

Peter_n:
Since the bus is open-collector, perhaps the sensor is not doing anything on the bus at that moment.

What do you mean?

Found the problem by comparing the internal blocks with the DS18S20.

The problem was before the memory can be addressed, one needs to go inside a block called "Function commands"

The code therefore looks like this:

#include <OneWire.h>

OneWire  myWire(10);  // on pin 10 (a 4.7K resistor is necessary)

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

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

  myWire.search(addr);
  delay(250);

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

  Serial.println();

  present = myWire.reset();
  myWire.select(addr);
  //myWire.skip(); 

  myWire.write(0x69);         //Sellect Function commands register 
  myWire.write(0x10);         //Sellect accumulated capacity register, MSB 

  Serial.print("Present = ");
  Serial.println(present, HEX);
  for ( i = 0; i < 2; i++) {           // 2 bytes for stored capacity
    data[i] = myWire.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  Serial.println();
  delay(1000);
}

Same nightmare for writing;

Issuing the commands:

Write to Shadow RAM:

myWire.reset();		    // Start communication
//myWire.select(addr);	    // Use if there is more than one device on them 1Wire BUS
myWire.write(0xCC);         // SKIP
myWire.write(0x6C);         // Sellect Function commands register 
myWire.write(0x69);         // Sellect Rsense register
myWire.write(0x43);         // 15mohm
myWire.reset();             // No more data. Stop communication

Copy Data to EEPROM:

myWire.reset();            // Start communication
myWire.write(0xCC);        // SKIP
//myWire.select(addr);     // Use if there is more than one device on them 1Wire BUS
myWire.write(0x48);        // Issue copy data command
myWire.write(0x69);        // Sellect Rsense register
delay(15);                 // EEProm write delay (suggested add by Maxim support)
myWire.reset();            // No more data - End Communication and save data
delay(15);                 // EEProm write delay

A read operation returns default value... Advice?