DS18B20, OneWire and P2/Photon2

I just wasted a day trying to get a chain of DS18B20's working on the P2 platform.

Please add a note in the OneWire Library ( GitHub - particle-iot/OneWireLibrary: Provides support for the Dallas One Wire protocol on Particle devices. ) that, even if it compiles it won't run on P2/Photon2 perhaps with a link to some of the forum posts about it.

Actually please add notes to all the libraries/hardware that just doesn't work- save us all the frustration.

1 Like

Hi there, while I appreciate your frustration, the library is a contributed community library.

Testing each contributed library is unfortunately not a feasible approach.
The compilation test is a compromise, and has a warning that states it does not guarantee the library will be functional.

Generally; the approach here would be to submit an issue via Github so that the author of the library can take a look: Issues Β· particle-iot/OneWireLibrary Β· GitHub
If you have a contribution/fix, Github is also the path to get it in.

It is not currently possible to use the OneWire (DS18B20) protocol on the RTL872x (P2, Photon 2, M-SoM). The speed of the GPIO is not sufficient to support the protocol in bit-bang mode as the OneWire library does.

In theory, it may be possible to use the SPI peripheral, which is how the NeoPixel library was implemented on RTL872x, however there is no implementation at this time. Also, since SPI has separate read and write pins, and OneWire is a single pin, it would also require some additional hardware to manage dupexing.

The only viable alternative is to use an I2C to OneWire bridge at this time.

1 Like

@no1089 It looks like someone updated the OneWireLibrary README.md - thanks!

@rickkas7 Yeah, I have some DS2482's on the way now. I spent yesterday banging my head on a wall, since all the signals looked clean, and worked on other micros so I was neck deep in several libraries trying to figure it out. Have you seen any adapter boards with a DS2482, 5V 1-Wire to 3.3V logic and TVS protection?

1 Like

I have not seen a pre-built adapter board for the DS2482. I've added them to my boards for a long time, even on gen 3 (nRF52) devices because it's so much more efficient with the bridge chip. The DS2482-RK library works well on both nRF52 and RTL872x devices and is fully asynchronous and works well with multi-drop if you need that.

Thanks! Off to learn ++11 lambda syntax.

The Tracker OneWire project is for the Tracker, but if you leave off the M8 connection and voltage regulator it would work on any device.

It has a PCA9306 for I2C level shifting to 5V and runs the DS2482-100 at 5V. It's really simple and the SOIC versions of those chips are easy to solder.

Thanks for that- that's a good board reference. I had been looking at the DS2483 / DS2484 as well which have independent I2C and 1-Wire voltages and built-in ESD protection which reduces the part count considerably.

As far as I can tell the only difference between the DS2483 and DS2484 is that the DS2484 adds 1.8V 1-Wire support to the 3.3V and 5.0V.

They both can do I2C at 1.8V, 3.3V and 5.0V based on a separate supply pin.

In my case I think I would just use Vusb for the 5 volt 1-Wire supply.

I haven't looked to see if they'll be library compatible or easily portable but otherwise they simplify things considerably and actually cost less. Don't know if you can comment here on compatibility...?

Oh wow, that's a way better chip. There are a few new configuration parameters but the bulk of the I2C registers appear to be the same. There's an app note for migrating and it looks easy.

I'll order some and try it out.

Based on the datasheets it looks like DS2484 corrected the minimum 1-Wire Vcc that may have been errantly high in the DS2483 silicon. They took care of some other DS2483 quirks since they were having to do a revision.

I1C Address pins A0 & A1 are just moved into register along with the other address bits (Figure 8 in all 3 datasheets)

The communications examples are all identical except the new chips add sections:

  • Adjust 1-Wire Port (after power-up, e.g., to select a 1-Wire timing other than the default)

  • Verifying the 1-Wire port configuration

Should be mostly compatible.

1 Like

@rickkas7 Head's up Adafruit just released a DS2484 breakout. I've ordered some to test with

Adafruit DS2484 I2C to 1-Wire Bus Adapter Breakout

https://www.adafruit.com/product/5976
2 Likes

I tested the DS18B20 via DS2484 with the Adafruit Library on the P2 and it works. Note that @rickkas7 also posted an Asynchronous library example above, but it you want to use the Adafruit Lib here's some example code:

Note: You need to copy Adafruit_BusIO and Adafruit_DS248x into your_project_folder/lib then create a src folder in each library and move the .ccp and .h files into their respective src folders.

Something like this (click to show)
your_project_folder
β”‚
β”œβ”€β”€β”€lib
β”‚   β”œβ”€β”€β”€Adafruit_BusIO
β”‚   β”‚   β”œβ”€β”€β”€examples
β”‚   β”‚   └───src
β”‚   β”‚           Adafruit_BusIO_Register.cpp
β”‚   β”‚           Adafruit_BusIO_Register.h
β”‚   β”‚           Adafruit_I2CDevice.cpp
β”‚   β”‚           Adafruit_I2CDevice.h
β”‚   β”‚           Adafruit_I2CRegister.h
β”‚   β”‚           Adafruit_SPIDevice.cpp
β”‚   β”‚           Adafruit_SPIDevice.h
β”‚   β”‚
β”‚   └───Adafruit_DS248x
β”‚       β”œβ”€β”€β”€examples
β”‚       └───src
β”‚               Adafruit_DS248x.cpp
β”‚               Adafruit_DS248x.h
β”œβ”€β”€β”€src
β”‚       your_project.cpp
/* 
 * your_project.cpp
 * Project: P2 DS2484 Adafruit Example - Based on Adafruit's DS2484_DS18B20.ino Example Code (MIT License)
 * Author: Idea
 * Date:  2024-06-27
 */
 */

// Include Particle Device OS APIs
#include "Particle.h"
#include "Adafruit_I2CDevice.h"
#include "Adafruit_DS248x.h"
#define DS18B20_FAMILY_CODE 0x28
#define DS18B20_CMD_CONVERT_T 0x44
#define DS18B20_CMD_MATCH_ROM 0x55
#define DS18B20_CMD_READ_SCRATCHPAD 0xBE
Adafruit_DS248x ds248x;
float readTemperature(uint8_t *rom);

SYSTEM_MODE(AUTOMATIC);
SYSTEM_THREAD(ENABLED);
SerialLogHandler logHandler(LOG_LEVEL_INFO);

void setup() {
  if (!ds248x.begin(&Wire, DS248X_ADDRESS)) {
      Log.error("DS248x initialization failed.");
    while (1);
  }
  Log.info("DS248x Found!");
  while (! ds248x.OneWireReset()) {
    Log.error("Failed to do a 1W reset");
    if (ds248x.shortDetected()) {
      Log.error("\tShort detected");
    }
    if (!ds248x.presencePulseDetected()) {
      Log.error("\tNo presense pulse");
    }
    delay(1000);
  }
  Log.info("One Wire bus reset OK");
}

void loop() {
  uint8_t rom[8];
  if (!ds248x.OneWireSearch(rom)) {
    Log.info("No more devices found\n\n");
    return;
  }

//char str_addr_buffer[18];
//snprintf(str_addr_buffer,strlen(str_addr_buffer),"%02X%02X%02X%02X%02X%02X%02X%02X",rom[0],rom[1],rom[2],rom[3],rom[4],rom[5],rom[6],rom[7]);

  // Check if the device is a DS18B20 (Family code 0x28)
  if (rom[0] == DS18B20_FAMILY_CODE) {
      // Read and print temperature
      float celsius_f = readTemperature(rom);
      Log.info("Address:%02X%02X%02X%02X%02X%02X%02X%02X \tTemperature: %f C",rom[0],rom[1],rom[2],rom[3],rom[4],rom[5],rom[6],rom[7],celsius_f);
  }else{
      Log.info("Other Device Found: %s",str_addr_buffer);
  }
}



float readTemperature(uint8_t *rom) {
    // Select the DS18B20 device
    ds248x.OneWireReset();
    ds248x.OneWireWriteByte(DS18B20_CMD_MATCH_ROM); // Match ROM command
    for (int i = 0; i < 8; i++) {
        ds248x.OneWireWriteByte(rom[i]);
    }

    // Start temperature conversion
    ds248x.OneWireWriteByte(DS18B20_CMD_CONVERT_T); // Convert T command
    delay(750); // Wait for conversion (750ms for maximum precision)

    // Read scratchpad
    ds248x.OneWireReset();
    ds248x.OneWireWriteByte(DS18B20_CMD_MATCH_ROM); // Match ROM command
    for (int i = 0; i < 8; i++) {
        ds248x.OneWireWriteByte(rom[i]);
    }
    ds248x.OneWireWriteByte(DS18B20_CMD_READ_SCRATCHPAD); // Read Scratchpad command

    uint8_t data[9];
    for (int i = 0; i < 9; i++) {
        ds248x.OneWireReadByte(&data[i]);
    }

    // Calculate temperature
    int16_t raw = (data[1] << 8) | data[0];
    float celsius = (float)raw / 16.0;

    return celsius;
}

Not sure if you're meant to, but I tested adding & removing 1-wire devices live and it picks up the changes just fine without restarting.

Example Output:

INFO: Address:28F0AEFF00000001         Temperature: 25.625000 C
INFO: Address:2888B645D4123456         Temperature: 22.812500 C
INFO: No more devices found
3 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.