Author Topic: 1-Wire Limitations?  (Read 6092 times)

conspiracyx

  • Newbie
  • *
  • Posts: 7
1-Wire Limitations?
« on: March 08, 2017, 08:19:57 am »
I ran into a problem trying to connect a DS18B20 to my Oak. I followed this tutorial exactly and the Particle console spit out the "-1000" error. As a test, I changed DS18S20_Pin to 3 and moved the thermometer bus from P2 to P3. This worked - the Particle console started showing me reasonable temps. I tried a few other pins and all of them gave me the "-1000." I tried this on both of my Oaks with same results.

I did some cursory Googling afterward for answers with no luck, so I am left with the following questions:
1. Does the Oak have limitations when it comes to using 1-Wire code and devices? The Oak pinout diagram and page don't even mention it.
2. If there are limitations, how come the tutorial is wrong?
3. Am I misinformed and simply missing something?

Thanks!

exeng

  • Sr. Member
  • ****
  • Posts: 452
Re: 1-Wire Limitations?
« Reply #1 on: March 08, 2017, 09:55:48 am »
Instead of the 4.7K pull up, try a stronger pull up, something closer to 2K and see if this makes a difference.

The 4.7K pull up is typically what is spec'd but somethings a stronger pull up is needed.

-1000 indicates that the device address (or any) was not seen during the search for device addresses on the wire.
« Last Edit: March 08, 2017, 10:03:39 am by exeng »

conspiracyx

  • Newbie
  • *
  • Posts: 7
Re: 1-Wire Limitations?
« Reply #2 on: March 08, 2017, 10:34:31 am »
How does the math work out on 2kΩ being greater 4.7kΩ? Does smaller resistance value = greater pull-up?

Nevermind, I Googled and found "A low resistor value is called a strong pull-up (more current flows), a high resistor value is called a weak pull-up (less current flows)." I will give it a go.
If this works, is there something about P3 that made it work with 4.7kΩ?
« Last Edit: March 08, 2017, 10:41:02 am by conspiracyx »

PeterF

  • Hero Member
  • *****
  • Posts: 877
Re: 1-Wire Limitations?
« Reply #3 on: March 08, 2017, 05:49:22 pm »
Yeah, resistors are a bit unintuitive when you first use them... just like when with RF stuff a longer wavelength results in a higher frequency... but once you work out the relationship between the two all is good! ;) With resistors, the value represents how much they resist... so small value means not much (thus more current flow), and higher value means a lot (thus low current flow).

The 4.7k pullup value that is commonly referenced for the DS18B20 is usually in relation to Arduino stuff, and is thus 5v. When running at the lower voltage of 3.3v (i.e. ESP8266/Oak), a slightly stronger pull up is needed to allow the same amount of current as was available at 5v to power the DS18B20 in parasitic mode at the lower voltage. It can sometimes work regardless. And that tutorial is showing the DS18B20 being externally powered by the Oak, so that is strange. I have had problems with the DS18B20s before... I was sent a bunch of DS18B20-PAR instead of DS18B20s, which takes longer them to do the reading ... and was downright annoying. Might be worth considering if that is the problem here - they are marked as DS18B20P instead of DS18B20... note the P on the end.

P3 is also the serial RX pin, so that may be the cause of the different behaviour, as it might be letting a little more power bleed through for the pullup?

As a side note, and something else to try, this is the base code that I use for all my DS18B20 Oaks, so it might be worth trying to see if it behaves any differently. Funnily enough, I'm using P2, and a 4.7k pullup on most of them... so talk about contradicting myself! :-P It's not quite a pretty as the example from the tutorial... but it has yet to fail me. Probably the biggest thing was the delay between the conversion... which was needed if some of those other DS18B20-PAR sensors got pulled out of the parts bin.

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

// Code based on OneWire DS18S20, DS18B20, DS1822 Temperature Example
// http://www.pjrc.com/teensy/td_libs_OneWire.html

OneWire  ds(2);  // on pin 2 (a 4.7K resistor is necessary)
char tmpStr[8];

void setup(void)
{
  #ifdef ARDUINO_ESP8266_OAK
Particle.publish("DS18x20_Temperature sketch started");
  #endif
 
  Serial.begin(9600);
}

void loop(void)
{
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;
 
  if ( !ds.search(addr)) {
    Serial.println("No more addresses.");
    Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }
 
  Serial.print("ROM =");
  for( i = 0; i < 8; i++) {
    Serial.write(' ');
    Serial.print(addr[i], HEX);
  }

  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
      return;
  }
  Serial.println();
 
  // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
      Serial.println("  Chip = DS18S20");  // or old DS1820
      type_s = 1;
      break;
    case 0x28:
      Serial.println("  Chip = DS18B20");
      type_s = 0;
      break;
    case 0x22:
      Serial.println("  Chip = DS1822");
      type_s = 0;
      break;
    default:
      Serial.println("Device is not a DS18x20 family device.");
      return;
  }

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end
 
  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
 
  present = ds.reset();
  ds.select(addr);   
  ds.write(0xBE);         // Read Scratchpad

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

  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0;

  //push to Particle
  dtostrf(celsius, 5, 2, tmpStr);

#ifdef ARDUINO_ESP8266_OAK 
  Particle.publish("tempC",tmpStr,30,PRIVATE);
#endif

  Serial.print("  Temperature = ");
  Serial.print(celsius);
  Serial.print(" Celsius, ");
  Serial.print(fahrenheit);
  Serial.println(" Fahrenheit");

  //use delay, or once WAKE and RST connected, use deepsleep instead
  delay(30000);
  //ESP.deepSleep(5*60*1000000, WAKE_RF_DEFAULT);
}

exeng

  • Sr. Member
  • ****
  • Posts: 452
Re: 1-Wire Limitations?
« Reply #4 on: March 09, 2017, 09:28:11 pm »
Peter is correct the 4.7K resister while typical is spec'd in conjunction with a 5V supply. That said, it does seem to work for the Oak (at 3.3V) but apparently not in all cases. At 3.3V the DS18B20 is operating at the lower end of the it's 3V min to 5.5V max spec and would likely benefit from the stronger pull up. That said, I've also used a DS18B20 water proof version successfully with a 4.7K pull up.

conspiracyx, if the stronger pull up worked for you than perhaps it's time to add a note to the tutorial indicating the need for a lower value resistor when using the Oak's 3.3v supply to the DS18B20.

Let's us know if it worked for you.

conspiracyx

  • Newbie
  • *
  • Posts: 7
Re: 1-Wire Limitations?
« Reply #5 on: March 13, 2017, 11:38:40 pm »
Sorry for the delay in response - had to find time over several nights to try this.

1. I obtained a 2.2kΩ resistor and tried the code from the tutorial again. Again, with DS18S20_Pin = 2 (default) I am not getting anything and when I make it = 3 I get reasonable data on P3.

2. On a whim I decided to try every combination of DS18S20_Pin and physical pin (while still using the 2.2kΩ resistor). Much to my surprise I was reading results on some mismatching pairs, at most one readout per DS18S20_Pin setting. It broke down like this:
<DS18S20_Pin = ><Physical Pin #>
0P2
1P2
2P0
3P3
4P5
5P1
6-10None

3. I also tried PeterF's code and per the above table I only got reading when I moved the data leg to P0.

Maybe it's something about the OneWire library? The Oak's firmware?

exeng

  • Sr. Member
  • ****
  • Posts: 452
Re: 1-Wire Limitations?
« Reply #6 on: March 14, 2017, 12:08:33 am »
In your table I assume you meant GPIO 0, 1 mapped to P2 and P4 respectively?

It's been awhile since I've had my temp sensor operational. I have a bare DS18S20 and a waterproof version of it. When I get some time I'll fire up an Oak and try to recreate the tutorial config and see what I get.

BTW, pin 6 on that Oak cannot be pulled high at boot.

http://digistump.com/wiki/oak/tutorials/pinout

PeterF

  • Hero Member
  • *****
  • Posts: 877
Re: 1-Wire Limitations?
« Reply #7 on: March 14, 2017, 03:17:25 am »
Definitely something strange going on there... because using my code and my Oak, 2 in the code is ... well... 2! (P2), but for you it is 0. I can't comment on the other pins as I never saw the need to change from 2 since it worked!! ;) Are you getting any warnings when you compile the code about multiple OneWire libraries by any chance? Maybe the you've already got a copy install for the Arduino Uno or something, and it's running afoul of the copy included with the Oak?

conspiracyx

  • Newbie
  • *
  • Posts: 7
Re: 1-Wire Limitations?
« Reply #8 on: March 14, 2017, 08:15:08 am »
In your table I assume you meant GPIO 0, 1 mapped to P2 and P4 respectively?

No, the table maps the "DS18S20_Pin" variable in the code to Oak pins (per what's on the solder mask). Looking at the Oak<->GIPO table on the wiki, however, there seems to be a hint of correlation to my table. I don't think I was sloppy in my investigation, but it's possible. I made the presumption that the "DS18S20_Pin" variable referred to Oak pins and not GPIO pins. I didn't try variables in the 12-17 range, however.

BTW, pin 6 on that Oak cannot be pulled high at boot.

I think I was aware of that. At any rate, I started the sketch with the data pin plugged into P0 or nothing and then would plug it into each pin every couple Particle.publish intervals, so I steered clear of that.

Quote from: PeterF
Maybe the you've already got a copy install for the Arduino Uno or something, and it's running afoul of the copy included with the Oak?

I don't recall seeing errors on compile. It is possible the libs are messed up.


So far I am thinking it's one of the following:
1. Bad Arduino IDE install. Maybe I should try this from the Particle IDE - I seem to recall getting different results once.
2. Bad firmware. I think both of my devices are on version 6 and I haven't figured out how to make them update to 10 OTA as I thought the local config tool was supposed to do that and it didn't.
3. Bad wiring - maybe I am missing something on the hardware level.

If either one of you can confirm your Oaks and DS18S20's working fine with the tutorial code I would be grateful. I just want some sort of "it's you" confirmation before I try the process of elimination.

exeng

  • Sr. Member
  • ****
  • Posts: 452
Re: 1-Wire Limitations?
« Reply #9 on: March 14, 2017, 09:29:42 am »
OK before I get on to trying the tutorial again, here are a couple of notes:

1. Correction: I have DS18B20 parts not DS18S20. I have the DS18B20 that comes with the Oak Ultimate Kit from Digistump and a waterproof version https://www.sparkfun.com/products/11050 from Sparkfun.

For reference here is a link to the Maxin doc describing the differences between the DS18B20 and DS18S20.
https://www.maximintegrated.com/en/app-notes/index.mvp/id/4377

2. Looked at my code this morning and most sketches if not all use pin 2. That's digital pin 2 not GPIO 2. Only 2 out of 7 versions alternately use pin 5. The last version running was my pool temp monitor with the waterproof DS18B20 and it uses pin 2, so I know it was working in that configuration.

Again, I'll give this a try again but will most likely be this evening PST or I'll get the eye roll from the lovely wife.


exeng

  • Sr. Member
  • ****
  • Posts: 452
Re: 1-Wire Limitations?
« Reply #10 on: March 14, 2017, 10:20:04 am »
Got in a quick test using pin 2 and 4.7K pull up and it works just fine.

Add this call in setup (you will need a FTDI device for serial output) and see if the GPIO is correct for pin 2.
  Serial.println(ds.gpioPin());

conspiracyx

  • Newbie
  • *
  • Posts: 7
Re: 1-Wire Limitations?
« Reply #11 on: March 14, 2017, 12:15:25 pm »
Got in a quick test using pin 2 and 4.7K pull up and it works just fine.

Add this call in setup (you will need a FTDI device for serial output) and see if the GPIO is correct for pin 2.
  Serial.println(ds.gpioPin());

I don't have anything to use as a serial adapter handy. Can I cheat and send that through Particle.publish?

PeterF

  • Hero Member
  • *****
  • Posts: 877
Re: 1-Wire Limitations?
« Reply #12 on: March 14, 2017, 06:51:08 pm »
It'll probably work. If not, you can use the OakTerm "cloud serial" equivalent" of Particle.begin(), Particle.print() and Particle.println().

Edit: Or not. I'll post a more detailed message in a few minutes once I have the code fully nutted out, but @exeng: what library/version provides ds.gpioPin()? It's not working on either on my Oak Onewire, and it doesn't look like it comes from dallastemperature?
« Last Edit: March 14, 2017, 08:07:21 pm by PeterF »

PeterF

  • Hero Member
  • *****
  • Posts: 877
Re: 1-Wire Limitations?
« Reply #13 on: March 14, 2017, 08:28:00 pm »
Ok, so using the code included below (only because I know it works, not because it is any better than the code from the tutorial), I have been able to access a DS18B20 sensor connected to P2, P3, P6 and P8 without any trouble. I chose the higher ones at random... I have no reason to believe that just about any pin will work (although I would generally avoid any boot related ones, and the serial pins. To test, I simply changed the DS_PIN define to the desired pin (in this case it is still set to (P)8, and connected the DS18B20 to the specified pin after it had reset (or before it reset if it wasn't a boot related pin).

So, this suggests the arduino install is at fault in some way. Try going to Sketch -> Include Library -> Manage libraries, changing the "Type" dropdown to "Installed", and search for OneWire. If you have anything other than the "Built-In" version, remove it (click on it to highlight and the remove button will appear on the right side). You can always add it again later if you need it ;)

Other than that, I have no idea what is going on. btw, this was with a 4.7k resistor still, with power from the Oaks VCC connection.

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

// Code based on OneWire DS18S20, DS18B20, DS1822 Temperature Example
// http://www.pjrc.com/teensy/td_libs_OneWire.html

#define DS_PIN 8

OneWire  ds(DS_PIN);  // on pin 2 (a 4.7K resistor is necessary)
char tmpStr[8];

void setup(void)
{
  Particle.publish("DS18x20_Temperature sketch started");

  Particle.begin();
  Particle.print("DS GPIO pin: ");
  //Particle.println(ds.gpioPin());
  Particle.println(DS_PIN);
}

int resetcount = 0;

void loop(void)
{
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;
 
  if ( !ds.search(addr)) {
    Particle.println("No more addresses.");
    Particle.println();
    ds.reset_search();
    delay(250);
    resetcount++;
    if (resetcount > 5)
    {
      Particle.println("Stopping address search"); //prevent flooding particle with pointless data
     
      //endless loop, which will still allow OTA programming to happen
      while(1)
      {
        delay(5000);
      }
    }
    return;
  }
 
  resetcount = 0;

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

  if (OneWire::crc8(addr, 7) != addr[7]) {
    Particle.println("CRC is not valid!");
    return;
  }
  Particle.println();

  // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
      Particle.println("  Chip = DS18S20");  // or old DS1820
      type_s = 1;
      break;
    case 0x28:
      Particle.println("  Chip = DS18B20");
      type_s = 0;
      break;
    case 0x22:
      Particle.println("  Chip = DS1822");
      type_s = 0;
      break;
    default:
      Particle.println("Device is not a DS18x20 family device.");
      return;
  }

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end

  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.

  present = ds.reset();
  ds.select(addr);
  ds.write(0xBE);         // Read Scratchpad

  Particle.print("  Data = ");
  Particle.print(present, HEX);
  Particle.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    Particle.print(data[i], HEX);
    Particle.print(" ");
  }
  Particle.print(" CRC=");
  Particle.print(OneWire::crc8(data, 8), HEX);
  Particle.println();

  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0;

  Particle.print("  Temperature = ");
  Particle.print(celsius);
  Particle.print(" Celsius, ");
  Particle.print(fahrenheit);
  Particle.println(" Fahrenheit");

  //use delay, or once WAKE and RST connected, use deepsleep instead
  delay(10000);
  //ESP.deepSleep(5*60*1000000, WAKE_RF_DEFAULT);
}
« Last Edit: March 14, 2017, 08:31:42 pm by PeterF »

conspiracyx

  • Newbie
  • *
  • Posts: 7
Re: 1-Wire Limitations?
« Reply #14 on: March 14, 2017, 10:24:12 pm »
So, I had DallasTemperature, OneWire and OneWireHub installed. I was unable to uninstall any of them using the UI, so I decided to nuke the Arduino install completely and try again - better safe than sorry! I also forgot that I had it installed as a "windows app", so this time around I reinstalled using the customary exe installer.

OneWire appears to come pre-installed - I updated it to version 2.3.3. Using PeterF's latest code and a 4.7kΩ pullup in VCC, with "#define DS_PIN 8," and my DQ/data connection in P8 I get (in chronological order):

DS18x20_Temperature sketch started   null
oak/device/stdout   DS GPIO pin: 8 No more addresses.
oak/device/stdout   No more addresses. No more addresses. No more addresses. No more addresses.
oak/device/stdout   No more addresses. Stopping address search


Trying "DS_PIN 2" while checking it on P2 I get the same result.

Per my "brute force" attempts I know that setting "DS_PIN 0" should give me a reading on P2...lo and behold:

oak/device/stdout   No more addresses.
oak/device/stdout   ROM = 28 F7 2F 10 7 0 0 3C Chip = DS18B20
oak/device/stdout   DS GPIO pin: 0 Data = 1 76 1 4B 46 7F FF A 10 79 CRC=79 Temperature = 23.37 Celsius, 74.07 Fahrenheit


I then decided to try "DS_PIN 12" and reading it on P8. This would give credence to the "DS_PIN is actually GPIO pin" idea and I haven't tried setting that variable higher than 10 before. This works as well.

I then re-checked the whole Oak Pin <-> ESP GPIO table on the Pinout Wiki page, just reading each DS_PIN value for GPIO on the expected Oak pin. It corresponds almost completely, other than PIN 6 which I can't check on bootup, pin 10 (which didn't read with DS_PIN 16) and pin 11 pin 10 (which didn't read with DS_PIN 17). I am guessing those last two don't work without PWM

So why am I using GIPO here on my end? Do I need to update firmware?