Go Down

Topic: How to use 1-wire to I2C bridge (Maxim DS28E17) [SOLVED] (Read 4507 times) previous topic - next topic

Xiviar

Hello to all!

Anyone familiar with the Maxim DS28E17 chip? (bridge 1-wire to I2C)
I am trying to send bytes to an I2C connected arduino slave, through the DS28E17, using the oneWire.h and wire.h libraries, but I am not sure how to do it.

My code successfully recognizes and interacts with the DS28E17 chip, but it seems I am not sending the correct commands to activate I2C transmission.

What I need to do is sending a byte to the Arduino slave via one-wire DS28E17, make the slave read the byte an print it on the serial monitor.

Arduino Master -> 1-wire communication -> DS28E17 bridge -> I2C communication -> Arduino Slave (same board)

Any ideas?
I can provide code/ other details if needed.

Thank you.

Riva

I could be wrong (it happens a lot)  :smiley-confuse:
A quick look at the chip and the logic of it seems wrong to me as it is an I2C master device and the Arduino is the slave. Usually slave devices are there to serve and do not issue commands.

The DS2482-100 seems the right way round logically as it speaks to I2C masters so the Arduino is in control.
Don't PM me for help as I will ignore it.

Xiviar

First of all thank you for your reply.

The chip DS28E17 converts one-wire signals to I2C, basically, it works as a bridge and thus it must be connected  with both a master and a slave. In my case the same arduino (Is it feasible?)

I am sending one-wire commands to the bridge,  but the slave I2C is silent. I don't know if I am sending the wrong commands, if I chose a wrong frequency of transmission, or there are other issues.

The first thing I was wondering is if it is possible to use the same board as a one-wire master and I2C slave.

Riva

Ignore my previous post, for some reason I completely missed/blanked the "Arduino Master -> 1-wire communication -> DS28E17 bridge -> I2C communication -> Arduino Slave (same board)" line so you are using the right chip (I2C master).

Post your code for both the 1 Wire master and I2C slave Arduinos.
Don't PM me for help as I will ignore it.

Xiviar

#4
Oct 30, 2016, 11:43 pm Last Edit: Oct 31, 2016, 10:26 pm by Xiviar
Code: [Select]
#include <Wire.h>
#include <OneWire.h>


#define ONEWIRE_PIN  (8)

#define FAMILY_ID     0x19  //0001 1001
#define ACCESS_READ   0xF5  //1111 0101
#define DACCESS_WRITE 0x5A  //0101 1010
#define ACK_SUCCESS   0xAA  //1010 1010
#define ACK_ERROR     0xFF  //1111 1111

OneWire oneWire(ONEWIRE_PIN);
uint8_t address[8] = { 0, 0, 0, 0, 0, 0, 0,  };

void printBytes(uint8_t* addr, uint8_t count, bool newline=0)
{
  for (uint8_t i = 0; i < count; i++)
  {
    Serial.print(addr[i]>>4, HEX);  //prints the first 4 bits (most left) of addr[i] in Hexadecimal system
    Serial.print(addr[i]&0x0f, HEX); //BitWise between addr[i] e 00001111, allows to print the other 4 bits (on the right)
    Serial.print(" ");
  }
  if (newline)
  {
    Serial.println();
  }
}


bool write(uint8_t state)    //command order based on datasheet
{
 
 
  oneWire.reset();
  oneWire.select(address);
  oneWire.write(0x4B);    //0x4B is"Write Data With Stop" command
  oneWire.write(0x04);    //I2C slave address
  oneWire.write(0x01);    //Number of bytes to send (one)
  oneWire.write(state);   //Sends the byte
  oneWire.write(address[7]); //Sends CRC
  delay(50);
  oneWire.reset();
   
 
}


void setup() {
  Serial.begin(9600); 
 
  Serial.println(F("Asking for ID"));
  oneWire.reset_search();
  delay(250);
  oneWire.search(address);

  Serial.println(F("Got these values..."));
  printBytes(address, 8); 

  if (address[0]==0x19)
   Serial.println(F("Found a DS28E17 I2C Bridge"));

  if (address[0]==0x3A)
   Serial.println(F("Found a DS2413 Dual Channel Switch"));

 
}
void loop() {

write(15);   //15 is an arbitrary value
delay(3000);

}

Xiviar

I my previous post above the master code. Here below the slave code

#include <Wire.h>
#include <OneWire.h>



/*void Reception(int data)
{
//This function triggers when data is sent by Master

Serial.print(F("Data on BUS detected: "));
byte x = Wire.read();
Serial.println(x);
}*/




void setup() {
  Serial.begin(9600); 
 
  //Slave Code
  Wire.begin(0x04);   //Initializing Arduino as Slave with address 0x04h
  Wire.onReceive(Reception); //Call the function Reception when data is sent
 

 
}
void loop() {

delay(1000);

}


Riva

You should really go back and alter your last 2 posts to put the sketch in code tags.

I have knocked about your code to hopefully do what you want but without having any hardware to test it on I cannot be sure if it will work (probably not)

Code: [Select]
#include <OneWire.h>


#define ONEWIRE_PIN 8

#define DS28E17_ID            0x19
#define WRITE_DATA_WITH_STOP  0x4B
#define I2C_ADDRESS           0x04

OneWire oneWire(ONEWIRE_PIN);

uint8_t address[8];

void printBytes(uint8_t *addr, uint8_t count, bool newline=0)
{
  for (uint8_t i = 0; i < count; i++)
  {
    Serial.print(addr[i] >> 4, HEX);  //prints the first 4 bits (most left) of addr in Hexadecimal system
    Serial.print(addr[i] & 0x0f, HEX); //BitWise between addr e 00001111, allows to print the other 4 bits (on the right)
    Serial.print(" ");
  }
  if (newline)
  {
    Serial.println();
  }
}

/*
bool write(uint8_t i2cAddress, uint8_t i2cRegister, uint8_t i2cData) // Write a single byte to register of the I2C slave
{
  uint8_t packet[7];                        // Reserve 7 bytes to transmit data
  
  packet[0] = WRITE_DATA_WITH_STOP;         // Command ("Write Data With Stop")
  packet[1] = i2cAddress;                   // I2C slave to address
  packet[2] = 0x02;                         // Number of data bytes to write
  packet[3] = i2cRegister;                  // The register to write
  packet[4] = i2cData;                      // The data to write
  // Is this calculating the correct CRC16?
  uint16_t CRC16 = oneWire.crc16(&packet[1], 4);
  // Are the CRC16 bytes being stored in the correct order?
  packet[5] = CRC16 >> 8;                   // Most significant byte of 16 bit CRC
  packet[6] = CRC16 & 0x0F;                 // Least significant byte of 16 bit CRC
  
  oneWire.reset();
  oneWire.select(address);
  oneWire.write_bytes(packet, sizeof(packet), 1); //Write the packet and hold the bus
  while(oneWire.read_bit() == true)         // Wait for not busy
  {
    delay(1);
  }
  Serial.print(F("Status ="));
  Serial.println(oneWire.read());
  Serial.print(F("Write Status ="));
  Serial.println(oneWire.read());
  
  oneWire.depower();                        // Release the bus
}
*/
  
bool write(uint8_t i2cAddress, uint8_t i2cData) // Write a single byte to the I2C slave
{
  uint8_t packet[6];                        // Reserve bytes to transmit data
  
  packet[0] = WRITE_DATA_WITH_STOP;         // Command ("Write Data With Stop")
  packet[1] = i2cAddress;                   // I2C slave to address
  packet[2] = 0x01;                         // Number of data bytes to write
  packet[3] = i2cData;                      // The data to write
  // Is this calculating the correct CRC16?
  uint16_t CRC16 = oneWire.crc16(&packet[1], 3);
  // Are the CRC16 bytes being stored in the correct order?
  packet[4] = CRC16 >> 8;                   // Most significant byte of 16 bit CRC
  packet[5] = CRC16 & 0x0F;                 // Least significant byte of 16 bit CRC
  
  oneWire.reset();
  oneWire.select(address);
  oneWire.write_bytes(packet, sizeof(packet), 1); //Write the packet and hold the bus
  while(oneWire.read_bit() == true)         // Wait for not busy
  {
    delay(1);
  }
  Serial.print(F("Status ="));
  Serial.println(oneWire.read());
  Serial.print(F("Write Status ="));
  Serial.println(oneWire.read());
  
  oneWire.depower();                        // Release the bus
}
  
void setup()
{
  Serial.begin(9600);
  
  Serial.println(F("Looking for ID"));
  if (!oneWire.search(address))
  {
    Serial.println(F("No address."));
  }
  else
  {
    Serial.println(F("Got this address..."));
    printBytes(address, sizeof(address), true);
  }
  
  if (address[0] == DS28E17_ID)
  {
    Serial.println(F("Found a DS28E17 I2C Bridge"));
  }
  else
  {
    while (1);  // Halt if not the right 1 wire device
  }
  
}

void loop()
{
  //write(I2C_ADDRESS, 0, 15);   //I2C Address, I2C Register, I2C Data Byte
  write(I2C_ADDRESS, 15);   //I2C Address, I2C Data Byte
  delay(3000);
}



The receive code is almost unaltered.
Code: [Select]
#include <Wire.h>

void Reception(int data)
{
  //This function triggers when data is sent by Master
  
  Serial.print(F("Data on BUS detected: "));
  byte x = Wire.read();
  Serial.println(x);
}


void setup() {
  Serial.begin(9600);
  
  //Slave Code
  Wire.begin(0x04);   //Initializing Arduino as Slave with address 0x04h
  Wire.onReceive(Reception); //Call the function Reception when data is sent
  
  
}
void loop() {
  
}
Don't PM me for help as I will ignore it.

Xiviar

Riva,

Thank you very much for your help, I see that my code required quite a cleaning and i missed a few commands.

I will try the code with the chip tomorrow, meanwhile i will read and try to understand your corrections carefully.

I will post if it works or not!

Riva

Thank you very much for your help, I see that my code required quite a cleaning and i missed a few commands.
I suspect it will probably not work first time (if ever) and the most likely cause will be CRC16. As commented in the code...
Code: [Select]
  // Is this calculating the correct CRC16?
  uint16_t CRC16 = oneWire.crc16(&packet[1], 4);
  // Are the CRC16 bytes being stored in the correct order?
  packet[5] = CRC16 >> 8;                   // Most significant byte of 16 bit CRC
  packet[6] = CRC16 & 0x0F;                 // Least significant byte of 16 bit CRC
 

I don't know if the 1-wire libraries built in crc16 function is using the same algorithm as the chip expects or if the start seed for crc16 is correct (I went with default). Also I could not find the the byte order the 16 bit crc is stored in the transmit array but sleeping on it think it more likely they would use low byte, hight byte where I coded the other way round.
If it ever gets as far as returning a valid status & write status then looking at the bits should help point to what is wrong.
Don't PM me for help as I will ignore it.

Xiviar

#9
Nov 01, 2016, 05:18 pm Last Edit: Nov 01, 2016, 05:39 pm by Xiviar
Tested,

The chip is being detected correctly.

The outupts I receive from Serial.Print are:

Status=1                (B00000001)
Write Status= 255    (B11111111)

Which according to the datasheet, means writing has failed, and the only error is the invalid CRC. (which is however already a great improvement from my original code)

the code you gave me that calculates the CRC is this part:

Code: [Select]

  packet[0] = WRITE_DATA_WITH_STOP;         // Command ("Write Data With Stop")
  packet[1] = i2cAddress;                   // I2C slave to address
  packet[2] = 0x01;                         // Number of data bytes to write
  packet[3] = i2cData;                      // The data to write
  // Is this calculating the correct CRC16?
  uint16_t CRC16 = oneWire.crc16(&packet[1], 3);
  // Are the CRC16 bytes being stored in the correct order?
  packet[4] = CRC16 >> 8;                   // Most significant byte of 16 bit CRC
  packet[5] = CRC16 & 0x0F;     

 

If I understands correctly it calculates the CRC of the three bytes [1] [2] and [3] of the packet array?

According to the datasheet, the  CRC should be calculated from (command,Slave Address, writ length, write data), thus 4 bytes, including
  • .) However as I changed the code with

Code: [Select]
uint16_t CRC16 = oneWire.crc16(&packet[1], 4);
 

or

Code: [Select]
uint16_t CRC16 = oneWire.crc16(&packet[0], 4);

Still gives me the same status outputs. (error on CRC)

Don't know if it is the CRC to be wrong or its storing in the packet, the data sheet says:

Formed 1-Wire Packet:
[Command 4Bh] [I2C Slave Address][Write Length][Write Data][CRC16][Delay or Busy Poll][Status][Write Status]

 CRC16 of command, I2C slave address, write length, and write data.





Riva

#10
Nov 01, 2016, 07:28 pm Last Edit: Nov 02, 2016, 08:42 am by Riva Reason: Tidy message
EDIT: Tidied post on PC.

Not on PC now so cannot type well on a pad but yes I had missed the command in the crc so the
Code: [Select]
uint16_t CRC16 = oneWire.crc16(&packet[0], 4);
is the correct one. I think you can also get rid of the square brackets and just use.
Code: [Select]
uint16_t CRC16 = oneWire.crc16(&packet, 4);

Try changing the order the CRC16 is stored so it looks like...
Code: [Select]
 packet[5] = CRC16 >> 8;                   // Most significant byte of 16 bit CRC
 packet[4] = CRC16 & 0x0F;    
Don't PM me for help as I will ignore it.

Xiviar

Ok, Thank you again for your quick answer, i am still struggling to make it work.
 

Is this line correct?

Code: [Select]
packet[4] = CRC16 & 0x0F;

Since it is a CRC16 shouldn't be

Code: [Select]
packet[4] = CRC16 & 0xFF;

Otherwise It would discard 4 bits,is there a reason for that?


However it is still not working, and always getting :

Code: [Select]
Status =1
Write Status =255

I am trying to understand what i am doing wrong, I am not sure anymore if Status = B00000001 means that only crc is invalidg, since I tested by putting a different, wrong I2C address, and it still gives me 1.

might it be the slave code?    perhaps (9600) is not a correct frequency for serial?

Riva

Hi Xiviar,

Yes your correct about the CRC16 masking (another mistake on my behalf) and it should be 0xFF and not 0x0F.

Reading the data sheet some more on CRC16 and I see...
Quote
CRC-16 Generation
The DS28E17 uses two types of CRCs.
One CRC is an 8-bit type and is stored in the most significant byte of the 64-bit ROM ID. The bus master can compute a CRC value from the first 56 bits of the 64-bit ROM ID and compare it to the value stored within the DS28E17 to determine if the ROM data has been received error-free. The equivalent polynomial function of this CRC is X8 + X5 + X4 + 1. This 8-bit CRC is received in the true (noninverted) form as shown previously in Figure 3. The other CRC is a 16-bit type, generated according to the standardized CRC-16 polynomial function X16 + X15 + X2 + 1. This CRC in DS28E17 is used for fast verification of a data transfer when receiving a formed 1-Wire packet. In contrast to the 8-bit CRC, the 16-bit CRC is always communicated in the inverted form. A CRC generator inside the DS28E17 device (Figure 8) calculates a new 16- bit CRC, and compares it to the received CRC from the host. The DS28E17 compares the CRC value read from the host to the one it calculates from the 1-Wire formed packet and decides whether to continue with an I2C operation or to set the CRC16-bit error flag. When the CRC16 flag is set, the ED pin goes high since an error was detected. For more information on generating CRC values, refer to Application Note 27: Understanding and Using Cyclic Redundancy Checks with Maxim iButtonĀ® Products.
The part of interest is "In contrast to the 8-bit CRC, the 16-bit CRC is always communicated in the inverted form." so it looks like the CRC16 value needs inverting before storing in the data array (still not sure what order though)

Here is the code that rounds up the bugs and this addition. I still don't know if the crc16 should be stored high byte first or low byte first so if it does not work first time then swap the order and try again.

Code: [Select]
#include <OneWire.h>


#define ONEWIRE_PIN 8

#define DS28E17_ID            0x19
#define WRITE_DATA_WITH_STOP  0x4B
#define I2C_ADDRESS           0x04

OneWire oneWire(ONEWIRE_PIN);

uint8_t address[8];

void printBytes(uint8_t *addr, uint8_t count, bool newline=0)
{
  for (uint8_t i = 0; i < count; i++)
  {
    Serial.print(addr[i] >> 4, HEX);  //prints the first 4 bits (most left) of addr in Hexadecimal system
    Serial.print(addr[i] & 0x0f, HEX); //BitWise between addr e 00001111, allows to print the other 4 bits (on the right)
    Serial.print(" ");
  }
  if (newline)
  {
    Serial.println();
  }
}

bool write(uint8_t i2cAddress, uint8_t i2cData) // Write a single byte to the I2C slave
{
  uint8_t packet[6];                        // Reserve bytes to transmit data
 
  packet[0] = WRITE_DATA_WITH_STOP;         // Command ("Write Data With Stop")
  packet[1] = i2cAddress;                   // I2C slave to address
  packet[2] = 0x01;                         // Number of data bytes to write
  packet[3] = i2cData;                      // The data to write
  // Is this calculating the correct CRC16?
  uint16_t CRC16 = oneWire.crc16(&packet[0], 4);
  // Are the CRC16 bytes being stored in the correct order?
  CRC16 = ~CRC16;                           // Invert the crc16 value
  packet[4] = CRC16 >> 8;                   // Most significant byte of 16 bit CRC
  packet[5] = CRC16 & 0xFF;                 // Least significant byte of 16 bit CRC
 
  oneWire.reset();
  oneWire.select(address);
  oneWire.write_bytes(packet, sizeof(packet), 1); //Write the packet and hold the bus
  while(oneWire.read_bit() == true)         // Wait for not busy
  {
    delay(1);
  }
  Serial.print(F("Status ="));
  Serial.println(oneWire.read(),BIN);
  Serial.print(F("Write Status ="));
  Serial.println(oneWire.read(),BIN);
 
  oneWire.depower();                        // Release the bus
}

void setup()
{
  Serial.begin(9600);
 
  Serial.println(F("Looking for ID"));
  if (!oneWire.search(address))
  {
    Serial.println(F("No address."));
  }
  else
  {
    Serial.println(F("Got this address..."));
    printBytes(address, sizeof(address), true);
  }
 
  if (address[0] == DS28E17_ID)
  {
    Serial.println(F("Found a DS28E17 I2C Bridge"));
  }
  else
  {
    while (1);  // Halt if not the right 1 wire device
  }
 
}

void loop()
{
  write(I2C_ADDRESS, 15);   //I2C Address, I2C Data Byte
  delay(3000);
}

Don't PM me for help as I will ignore it.

Xiviar

So, tested the code again, and gives me these returns:

Status=0;
Write Status=0;

which means that writing works!
Thank you Riva, here below the final function that is now working correctly, if someone might need it.



Code: [Select]
uint8_t packet[6];                        // Reserve bytes to transmit data
 
  packet[0] = WRITE_DATA_WITH_STOP;         // Command ("Write Data With Stop")
  packet[1] = i2cAddress;                   // I2C slave to address
  packet[2] = 0x01;                         // Number of data bytes to write
  packet[3] = i2cData;                      // The data to write
 
  uint16_t CRC16 = oneWire.crc16(&packet[0], 4);
 
  CRC16 = ~CRC16;
  packet[5] = CRC16 >> 8;                   // Most significant byte of 16 bit CRC
  packet[4] = CRC16 & 0xFF;                 // Least significant byte of 16 bit CRC
 
  oneWire.reset();
  oneWire.select(address);
  oneWire.write_bytes(packet, sizeof(packet), 1); //Write the packet and hold the bus
  while(oneWire.read_bit() == true)         // Wait for not busy
  {
    delay(1);
  }
  Serial.print(F("Status ="));
  Serial.println(oneWire.read());
  Serial.print(F("Write Status ="));
  Serial.println(oneWire.read());
 
  oneWire.depower();                        // Release the bus



My next step in the project has some issues with reading from the I2C, but I think It is better if I open another topic.

Thank you again!


Riva

I'm glad you finally got the code working and posted the code so it may be of use to others.
Don't PM me for help as I will ignore it.

Go Up