• I'm getting very random results using DS18B20 one wire probes on two MDBT42Q boards. I'm using the latest firmware (as of March 2) but even simple searches for probes turns up unreliable results.
    I'm using pin D11, have two DS18B20 probes that I've used reliably with other hardware (not Espruino), the probes' VDD pin is hard wired to VDD and I have a 4.7K pullup resistor.

    Here is the code:

    var ds = new OneWire(D11);
    var sensors;
    digitalWrite(D3,0);
    function searchFor() {
      digitalWrite(D3,1);     // pulse trigger
      ds.reset();
      digitalWrite(D3,0);     // pulse trigger
      sensors = ds.search();
    
    if (sensors.length >= 1) {
      console.log("Found "+sensors.length+" probes!");
      console.log(sensors);
      
    } else
      console.log("No One Wire probes found!");
    } 
    
    setInterval(searchFor, 20000);   // search every 20 seconds
    

    Attached is a snap of the IDE output.


    1 Attachment

    • OneWireSearchBreakout.JPG
  • Sun 2019.03.03

    While I have no experience with this module, I do observe the following:

    ref http://www.espruino.com/DS18B20

    Line #2 of the code example above doesn't appear to pull in the corresponding module, and most likely isn't creating an object instance.

    See snippet under heading 'Software' also 2nd line:
    var sensor = require("DS18B20").connect(ow);

    Therefore what is being observed is in fact what the circuitry sees. Unknown



    Was the example on that page tried verbatim?

  • @TomWS' code goes only after the wire and queries it for how may devices are connected... it has nothing to do yet with the device(s) he's planning connect to the wire or has already connected.

    My explanation is that for what ever reason the attached sensor has two ids or detection is messed up.

    As far as I know, every setup of single wire with multiple participants and the related CSMA/CA (or CSMA/CD) technique managing it, has ways to discover: Upon a particular devices discovery signal on the (one wire) bus,. devices send - respond - with random delays their ID... and I hope this double thing does not show because of collision. On the other hand, I see that it is only these two IDs that come repeatedly.

    Since there is a CRC in the reception, we have to believe that receive information is ok. I assume TomWS uses 3 wires... GND, Signal AND POWER, because there are one wire devices that can power by the parasitic power provided through the 4.7k pull-up resistor (and a local capacitor - local to with or on the device). The protocol sequence is then a bit different, because the signal line has to be high long enough on initial powering and between signaling that (depleted) capacitors can recharge enough to power the device for the next operation...

    @TomWs, can you provide a pic of your HW setup?

  • If you are using two sensors on the same pin - you only need one resistor - you don't want it on both.

    Is vdd 3.3v? If so a 3.3k resistor might be better.

    If it more reliable when you only connect one sensor at a time?

    Also - comment out the reset - that might be causing an issue before the search.

  • I've used DS18B20s at 3.3V with 4.7K without issue before. I think it's a timing issue. It seems as if the master (the MDBT42Q) sometimes drives the one wire signal low for longer than spec and/or doesn't sample the slave device response in time to get accurate data and, consequently, gives up during the search. The same issues would render the data reads unreliable. But this code doesn't even bother with that issue. Doing a search and getting a reliable response is fundamental to a reliable OW interface.
    However, having said all that, I will try a 3.3K just 'because'. :-)
    Also, to answer your question, reliability didn't seem to be affected by whether there was one probe or two plugged in.
    Also, I noticed when looking at the traces, that the search code does a Reset as well, so the one I have in this code is redundant. I don't think it would cause issues with the search but I'll remove it.
    Tom

  • I think I've come across this before. OneWire is a bit unreliable on the nRF52 because the softdevice has a habit of just jumping in and doing stuff during reasonably timing critical sections.

    While I believe interrupts are disabled during OneWire, I can't disable them fully without hitting instability, so the high priority low level Bluetooth ones still get serviced.

    What you're seeing is a particularly bad case because you've got an active connection that's probably in high-speed mode, so the Bluetooth stack is pretty active.

    I've got a few things using DS18B20 on nRF52 and they work pretty reliably - once disconnected I'm finding the failure rate is 1 in 50 or something and it's trivial to just try again if there's an error (which is good practice anyway I guess).

    While I could use IRQs for the timing I believe that will also break, since the BLE stack always has higher priority than I can have I think. I'm pretty sure I did see someone setting up a timer peripheral to produce the relevant pulses, so that could be a possibility.

  • When I get a chance I'll look into modifying the base code to see if I can improve the reliability on this device. I do have applications where DS18B20s are useful. The only real critical timing is during a bit read or bit write which require reliable timing within 15uS-60uS windows. Spacing between bits is not critical so turning of ALL interrupts during the narrow window and leaving them on at other times seems safe.

  • That's really good to know! Using the nRF52 PPI with a spare timer would probably work really nicely for the pulses then.

    The real gotcha is just that I'm trying to support a bunch of platforms with the same code, but actually just ifdefing the relevant code for nRF52 wouldn't be too bad: https://github.com/espruino/Espruino/blo­b/master/src/jswrap_onewire.c#L54

    (or actually adding an jshAccuratePulse function to jshardware.c and then doing an ifdef based on that would be a reasonably nice, flexible way of fixing it)

  • Since jshDelayMicroseconds() uses the nrf_delay_us() function then that should be good enough. The key is to make sure that interrupts are absolutely stopped, including softdevice, during the window. This probably means new interrupt_off & on functions that turn off everything but won't be used indiscriminately. I'll work on it at some point, it's just the important thing for me at thing point.

  • The key is to make sure that interrupts are absolutely stopped, including softdevice, during the window.

    The problem is that as far as I remember this can potentially break bluetooth and/or trigger a watchdog which will reset the device, which is why it's not done on nRF52 with Bluetooth.

    I figured the occasional OneWire error was preferable to the whole device restarting - There was a specific commit to change it some time ago: https://github.com/espruino/Espruino/com­mit/e8ceb5c61bd145e7a74e92a620f4af1cbb96­dd78

  • I'll mess around with it at some point. Right now it's a low priority. Thanks for looking into it. I'll post a follow up when I get some new info.
    Tom

  • I got a chance to look into this again and found, not surprisingly, that the OW search failures occurred when the read bit function was apparently interrupted. The image below is a screen cap of the logic analyzer showing the last operation of a failed search. In the photo you can see the read bit sequence took almost 101uS instead of the usual 68uS. While the time is within spec for a OW Time Slot, it indicates there was some interruption during the operation. My guess is that the processor didn't get to read the '0' bit in time and read a '1' bit instead. This would cause the search algorithm to fail since two '1' bits were read in a row (meaning no probes were responding).
    So, with this theory, I modified the jshardware.c file in the targets/nrf5x/ folder to:

    static uint32_t prevPriMask=0;
    
    void jshInterruptOff() {
    [#if](http://forum.espruino.com/search/?­q=%23if) defined(BLUETOOTH) && defined(NRF52)
      // TWS: replaced: disable non-softdevice IRQs. This only seems available on Cortex M3 (not the nRF51's M0)
      // TWS: With: turn off all IRQs after saving current priority mask
      prevPriMask = __get_PRIMASK();
      __disable_irq();
      //__set_BASEPRI(4<<5); // Disabling interrupts completely is not reasonable when using one of the SoftDevices.
    [#else](http://forum.espruino.com/search­/?q=%23else)
      __disable_irq();
    [#endif](http://forum.espruino.com/searc­h/?q=%23endif)
    }
    
    void jshInterruptOn() {
    [#if](http://forum.espruino.com/search/?­q=%23if) defined(BLUETOOTH) && defined(NRF52)
      //__set_BASEPRI(0);
      // TWS: Restore previous piority mask (probably 0)
      __set_PRIMASK(prevPriMask); 
    [#else](http://forum.espruino.com/search­/?q=%23else)
      __enable_irq();
    [#endif](http://forum.espruino.com/searc­h/?q=%23endif)
    }
    
    

    Making this change the one wire search routine ALWAYS finds the two probes I have attached to the MDBT42Q. This seems safe for the one wire case since the interrupts are disabled for a short time in the read and write 1 cases (<= 13uS). The write 0 case, however, is longer (65uS), but a change to the OW code would improve this to 15uS if

        } else {  // long pulse
          jshInterruptOff();
          jshPinSetValue(pin, 0);
          jshDelayMicroseconds(65);
          jshPinSetValue(pin, 1);
          jshInterruptOn();
          jshDelayMicroseconds(5);
        }
    

    Was changed to this:

        } else {  // long pulse
          jshInterruptOff();
          jshPinSetValue(pin, 0);
          jshDelayMicroseconds(15);
          jshInterruptOn();
          jshDelayMicroseconds(50);
          jshPinSetValue(pin, 1);
          jshDelayMicroseconds(5);
        }
    
    

    This splits the 65uS delay into a critical 15uS delay and a not so critical 50uS adder.

    I'm not going to generate a pull request for this until I play with it a while, although I'm not sure that jshInterruptOff() is used in that many places (Soft SPI, UART, Neopixel), it would still be worthwhile making sure there aren't any SoftDevice failures because of this...
    Tom


    1 Attachment

    • FailedOW_SearchTiming.JPG
  • Nice - thanks! Did you find a reference somewhere that 15uS was ok though?

    As far as I could find, Nordic say that disabling IRQs even for a small amount of time will break the connection eventually: https://devzone.nordicsemi.com/f/nordic-­q-a/7321/how-to-enable-and-disable-all-i­nterrupts

    Ideally I'd like to avoid doing something that they very specifically say not to do.

  • Agreed it's risky without any confirmation from Nordic. I'll check in on that since the referenced article was based on nRF51 implementation. I would like to think that the newer device has a little more tolerance for 15uS latency. The fact that the non-nRF52 implementation of jsInterruptOff() DOES disable interrupts is interesting. In any case, I'll call this WIP and report as findings occur.
    In practice it may not be an issue (at least for me). I would tend to isolate sensor readings to times when my node was not BT connected and then, start advertising once a reading was completed. That model doesn't work too well when connected to IDE, but, hopefully, that's not the operating case.

  • Any news regarding usage of OneWire on NRF52?
    Did anyone tried to use an UART peripheral to achieve OneWire communication, as proposed by Analog Devices in this application note?

  • I hadn't done much on this to date I'm afraid. I do have several devices using OneWire on nRF52 that are running constantly, and they do work fine - but I just have to ensure the code can cope with occasional errors and retry.

    Personally, I feel like as @TomWS said, a 15uS delay should really be ok. However Nordic are really super clear on this so I'm very hesitant to add it: https://devzone.nordicsemi.com/f/nordic-­q-a/7321/how-to-enable-and-disable-all-i­nterrupts

    Bottom line - you can't do it. The max period you can disable interrupts is ZERO, you may not disable interrupts when the softdevice is running, not for 1ms, not for 1us, not at all, not ever. That is the contract you make with the softdevice. You cannot do time-sensitive operations with the softdevice running. Period.

    I'm not sure about the UART option - you might been external circuitry to combing RX and TX pins.

    However, I looked into the timeslot option and it wasn't too painful to implement, so I've just gone ahead and done it. If you use a cutting edge build now, everything should work.

    Onewire search in particular is quite slow now (1 second) because we use the timeslot API to schedule every single write, but I figure for most people that's a price worth paying :)

    Github issue at : https://github.com/espruino/Espruino/iss­ues/1831

  • @Gordon you are just fantastic, it works like a charm! I still don't understand how you can be so reactive on so many topics. Maybe we all think there is only one Gordon, but in reality you are a whole dedicated team sharing the same account name ;-)

    Anyway, regardless of the number of Gordons out there, thank you very much for your help!

  • Glad that fixed it - and thanks for trying it out so quickly!

    And thanks! I end up doing a bunch of small stuff, but I think most everyday users they don't really see any big improvements at all as they're mostly internal - so it's nice when someone does ;)

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Getting very random results using OneWire on MDBT42Q

Posted by Avatar for TomWS @TomWS

Actions