LowPowerLab Forum

Hardware support => General topics => Topic started by: Lukapple on July 26, 2017, 03:27:23 AM

Title: DS18B20 - temperature on request, battery lifetime?
Post by: Lukapple on July 26, 2017, 03:27:23 AM
Hi all,
I'm working on simple temperature node, which will report temperature reading on request - base node sends RF "request-temperature" message. I've already searched forum for simmilar projects, but most of projects reports temperature reading to base station in intervals, so radio can be most of time in a sleep mode.
Currently my setup(see attachment) drains 9v battery in a day or so.
Do you guys have any suggestion how to preserve battery life in my case?

Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: TomWS on July 26, 2017, 08:05:37 AM
Quote from: Lukapple on July 26, 2017, 03:27:23 AM
Hi all,
I'm working on simple temperature node, which will report temperature reading on request - base node sends RF "request-temperature" message. I've already searched forum for simmilar projects, but most of projects reports temperature reading to base station in intervals, so radio can be most of time in a sleep mode.
Currently my setup(see attachment) drains 9v battery in a day or so.
Do you guys have any suggestion how to preserve battery life in my case?
Is there a reason you want to be able to request the temperature at any arbitrary moment?

General practice is low duty cycle periodic reporting to a central, mains powered server of some sort, so, as you point out, power isn't wasted between samples.  The server can then be queried at any arbitrary time and the data is sufficiently fresh.

With on demand temperature reading you need your radio on all the time (or use Listen Mode, which hasn't proven all that reliable) and this puts your device in constant mA type current drain, where a battery efficient design would target single digit microamp (or less) average current drain.

Also, a 9V battery is wasting 2/3s of your available power unless you use a switching regulator to drop 9V to 3.3V.  And this is tricky to do at these low power levels.

Tom
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: ChemE on July 26, 2017, 08:22:56 AM
How are you sleeping your radio and microcontroller?  If you were using listen mode you should be able to get your idle current down to 250nA plus the draw from the DS18B20.  The temperature sensor draws little enough current that you can elect to power it from a digital pin and thus be able to turn it off completely when not needed.  Finally, you can skip the pullup resistor and just use those built into the 328p.  I posted some hyper fast code for a DS18B20 that uses the internal pullups. 

https://github.com/cdl1051/DS18B20_NROO

This code is also non-blocking so you can sleep the uC while the temperature conversion happens and then wake back up and TX the result.  You should be able to get the project down well below 1uA and your 9V battery should last well over a year.

Regarding batteries, a 9V battery wastes a lot of power since you only need 3.0V for the temperature sensor according to the datasheet.  The Mote will run all the way down to 1.8V.  A LiPo or two AAA batteries will give you a lot more mAh for the same space.
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: Lukapple on July 26, 2017, 09:12:19 AM
Thanks for your answers guys. Sorry for newbie questions - electronics is something that interests me, but otherwise I'm a software dev.

@Tom
QuoteIs there a reason you want to be able to request the temperature at any arbitrary moment?
Well probably not, looks like I've chosen wrong approach. I'm measuring pool water temperature and for template sketch I took my garage mote sketch, which sends door status on request :). I'll probably switch to periodic reporting.  Thanks for your explanation.

@ChemE
QuoteHow are you sleeping your radio and microcontroller?
Currently I'm not using any sleep methods. In a loop I call radio.receiveDone() and then 1s delay.

QuoteThe temperature sensor draws little enough current that you can elect to power it from a digital pin and thus be able to turn it off completely when not needed.
For temperature reading I'm using DallasTemperature library, with default settings:
init:
  _oneWire = OneWire(pin);
  _sensors = DallasTemperature(&_oneWire);
  _sensors.begin();


temperature request:
_sensors.requestTemperatures();
_sensors.getTempCByIndex(0);


How can I completly turn off digital pin#4?

This code is also non-blocking so you can sleep the uC while the temperature conversion happens and then wake back up and TX the result.  You should be able to get the project down well below 1uA and your 9V battery should last well over a year.
That sounds fantastic, thanks for the code, I'll check it out.
My goal is to get battery running for at least for a month or 2. I hope that your code will help me to achieve this goal, otherwise I'll probably switch to periodic reporting.

About batteries, will my setup work on two AAA batteries, 2x1.5V? Doesn't Moteino require minimum 3.3V input? Sorry again for noob questions.
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: ChemE on July 26, 2017, 09:46:19 AM
The Moteino is actually quite happy down to 1.8V and there have been a number of folks who have proven this out pretty thoroughly so don't worry about that.  You'll have to switch your brown out protection bits off though (I've never had any success changing my fuse bits personally) otherwise the 328p will reboot at 2.7V due to the brown out protection.  And don't worry about asking questions I enjoy sharing what I've learned which is little compared to some others here.
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: ChemE on July 26, 2017, 09:54:07 AM
Quote from: Lukapple on July 26, 2017, 09:12:19 AM
Thanks for your answers guys. Sorry for newbie questions - electronics is something that interests me, but otherwise I'm a software dev.
...
That sounds fantastic, thanks for the code, I'll check it out.
My goal is to get battery running for at least for a month or 2. I hope that your code will help me to achieve this goal, otherwise I'll probably switch to periodic reporting.

If you use Felix's LowPower library to sleep the processor between temperature measurements you will drop your current from 4mA down to 4.4uA.  That alone will push your battery life well past two months.  Additionally, there are software tricks to extend things even further.  This node absolutely does not need to run at 16MHz to serve this purpose.  You can divide down the clock to run at 8MHz or less and still have full speed conversations with the temperature probe and radio.  That will significantly cut your active current (but not change your sleep current).  It won't be hard to get that battery to last a year.
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: TomWS on July 26, 2017, 09:55:36 AM
Quote from: Lukapple on July 26, 2017, 09:12:19 AM
About batteries, will my setup work on two AAA batteries, 2x1.5V? Doesn't Moteino require minimum 3.3V input? Sorry again for noob questions.
The setup will work quite well on a couple of AAA batteries IF you remove the voltage regulator chip (easy to do, it's 3 pins and you lift the single pin side first) AND you reprogram the fuses to operate at 8MHz instead of 16MHz (which further extends battery life). 
UPDATE: ChemE is correct that you can keep the fuses at 16MHz and use the external crystal as a time base and then, in setup() reprogram the prescaler to run at a lower speed.  This saves power, but won't be as low as the internal 8MHz RC oscillator (which requires the fuse change).

If you don't want to or don't have the means to reprogram the fuses, you can run very nicely on 2 Lithium AAA (Eveready Ultimates) which will give you a nominal voltage of about 3.4V.

Tom
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: Felix on July 26, 2017, 10:35:01 AM
I have a slightly different approach, because I am "lazy".
Below is my approach and it works well for me, so you have a few different opinions to consider.

I have used a few Moteinos (stock, with LDO) on LiPos for years when properly put to sleep (with watchdog sleep, which yields ~6uA). I have some that are before the RFM69_ATC era and still keep going. The LDO uses 2uA, not a ton when other things can use many times more than that.

As mentioned before, to run LDO-less (saves you the cost of a 1xAA) you will need to load the 8mhz bootloader version (https://github.com/LowPowerLab/DualOptiboot/blob/master/Dualoptiboot_v5.0_atmega328_8mhz_57600baud_BlinkD9_SPIdisable.hex) and reprogram fuses for internal 8mhz resonator. And you have to be careful not to feed more than 3.6v onto any of the pins - that would permanently damage the RFM radio (and FLASHMEM). So you have to make sure your FTDI/USB-serial adapter is all 3.3v, not more. This allows you to save an extra 2uA and run from less than ~3.4v.
I need to mention that a stock Moteino can also run from less than that, but the LDO's 2uA quiescent becomes 200uA when you reach that point.

By "proper sleep" I mean put the MCU (moteino atmega328p) to watchdog sleep (periodic wakeup, 4uA), or deep sleep (wakeup by external source/interrupt, 0.1uA). All my sleepy nodes use the 328p watchdog to wakeup periodically (8second max watchdog timer sleep then wakeup to do something or just sleep again, so thats a 4uA that watchdog uses).
The LDO takes ~2uA. The radio is 0.1uA in sleep mode.
Of course, your sensor has to be slept too when not used, whatever that means (powering from another digital pin or via mosfet and cutting power, or if it has a "sleep" mode).

So overall my nodes sip ~6-7uA and are very happy. My MotionMote nodes are around 9-10uA (with the panasonic 2uA PIRs) and I got tired to keep looking at their voltage because they just go "forever" even with tiny LiPo cells, and when they do run out they charge the LiPo via USB and back to work.

IMHO before you sweat too much about the LDO, try it without, you can screw up too many variables going that route and you will (I did too). Getting your code right and sleeping your sensors and any other power drains is more important than saving 2uA.
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: TomWS on July 26, 2017, 07:20:06 PM
Quote from: Felix on July 26, 2017, 10:35:01 AM
IMHO before you sweat too much about the LDO, try it without [sic removing the LDO], you can screw up too many variables going that route and you will (I did too). Getting your code right and sleeping your sensors and any other power drains is more important than saving 2uA.
If you use can use LiPo batteries, with a simple solar charger, the battery will last 'forever'1 and you WILL need to keep the LDO in that case.

Tom
Note 1:  Where 'forever' means as long as the LiPo has recharge cycles left in it and your ambient temperature stays above -10C.  Since you're measuring pool water temperature, I think we're safe here...
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: Lukapple on July 27, 2017, 03:29:53 AM
Hi Guys,
whoa, thanks for all the informations.
You are all talking about "periodic" reporting, where radio is in sleep mode, right?
Here are all the informations, that I gathered from your posts.
I'll try setup with options, that are marked with red. I've also added some questions, that are marked with blue.



   
   
   
   
   
   
   
   
   
   
Battery2x 1.5V AA (do I have to remove LDO voltage regulator if on 2xAA?)1x 9V
Voltage regulator(LDO)yes(default)no
Data requestperiodicon demand
Pullup resistorexternalinternal(328p) - sketch DS18B20 posted by ChemE
Sleep mode MCUsleep MCU between temp. measurements (lib by Felix) and periodic sleep (so this is watchdog sleep?)none
Sleep mode temp. sensor DS18B20not sure how. sensor doesn't have sleep mode. I should use mosfet or feed it from another digital pin?none
Temperature libDallasTemperature
https://github.com/milesburton/Arduino-Temperature-Control-Library (https://github.com/milesburton/Arduino-Temperature-Control-Library)
DS18B20 by ChemE
 https://github.com/cdl1051/DS18B20_NROO (https://github.com/cdl1051/DS18B20_NROO)
Brown out protection bitson(default) do I need to turn that off if on 2x1.5 AA?off
328p clock8Mhz (do I have to remove LDO?)16Mhz
Solar chargeryesno
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: ChemE on July 27, 2017, 08:39:40 AM
If you use the Energizer Ultimate Lithium batteries that are recommended you do not need to worry too much about removing the LDO.  Below is the discharge curve for these batteries (the AAA, the l92, has the same shape just smaller capacities).  Two of these will run your project from their initial voltage all the way down to 1.5V for certain.  I have some DS18B20s that I can test out to see if they will still behave properly at lower voltages than that but the datasheet says 3.3V minimum.  The Mote itself will behave perfectly all the way down to a single-cell voltage of 1.35V at which point the brown out protection will start forcing reboots.  If you were wanting to go further than that, you could change the fuse bits to disable BOP and then the Mote would run down to a single-cell voltage of 0.9V which is flat dead meaning you've been able to use the battery's entire charge. You can see from the graph that there is very little difference in mAh between 1.35V and 0.9V so the view doesn't really justify the climb in this case.  As Felix said, at some point the voltage will go low enough that the LDO will start consuming far more than 2uA.  This could be as high as 1.7V which sucks for these batteries since you get there essentially right away.  It is a shame that Felix didn't use the 3.0V LDOs but I understand why he went with 3.3V.

(http://i.imgur.com/mn1V29D.png)

Concerning the DS18B20, just power it from any three digital pins don't worry about a MOSFET.  The sensor does not have a sleep mode but there is little penalty to cutting the cord and then powering it up again next time you want a reading.  The Dallas library will work fine it is just bloated, blocking, and slow compared to my code (not that I'm biased mind).
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: Felix on July 27, 2017, 08:58:18 AM
In my post above I referred to periodic reporting of some variable. For instance temperature and humidity is something you want to report not more often than every 5-10 minutes in normal circumstances (a room or garage or attic or even outside). To do that I sleep my Moteinos+WeatherShield (this uses a BME280 which is 0.1uA in sleep mode) using the 328p watchdog timer. So overall the consumption is around 6-7uA of the whole node, powered from a LiPo. Runs for a very long time, reports temp+hum+voltage every 5 minutes. Transmits at full power (no ATC), I have one deployed in summer 2015 at ~4.1v, now at 3.89v.

The watchdog uses a timer that alllows up to 8seconds max sleep before a wakeup occurs. So to sleep more than that I just use multiples of 8seconds.
The DS18B20 is not exactly a very low power friendly sensor. It's been discussed here in the forum before. It's also slow to measure and uses a lot of current when measuring. I think to make it low power enough you have to keep measuring cycle long enough and power it off while not in use. You might need to initialize it every time you power it back up, which might also be a power hungry process. I would recommend a sensor like BME280 which is far better in all aspects.

For 2xAA you will need to remove LDO to make consumption low enough.
There's many ways to keep consumption low. Tom uses a hardware TPL5110 watchdog chip to keep consumption below 0.1uA.

Brown-out - I would think you don't need this even if running from 2xAA. When voltage gets below 2V I would consider that the dead point.
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: ChemE on July 27, 2017, 09:35:42 AM
Quote from: Felix on July 27, 2017, 08:58:18 AM
Brown-out - I would think you don't need this even if running from 2xAA. When voltage gets below 2V I would consider that the dead point.

I thought the stock fuse bits set the BOD at 2.7V is it actually 2.0V?
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: Lukapple on July 27, 2017, 10:48:21 AM
@Felix
QuoteFor 2xAA you will need to remove LDO to make consumption low enough.
For now I don't want to remove LDO. Could you suggest which LiPo cells should I use(V, mAH) ?

QuoteThe DS18B20 is not exactly a very low power friendly sensor.
I choose DS18B20 because it's in waterproof housing (https://www.adafruit.com/product/381). I hope that it will last for 2 months with LiPo.

@ChemE
QuoteThe Dallas library will work fine it is just bloated, blocking, and slow compared to my code (not that I'm biased mind).
Thanks, I'll try to use your code for DS18B20.
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: ChemE on July 27, 2017, 11:09:39 AM
I decided to fool around with this a little and I've modified my code to be Moteino friendly.  Place Pin 3 (Vdd) of the DS18B20 in pin 7 of the Mote and Pin 1 (GND) of the DS18B20 in pin 9 of the Mote like I've pictured below.
(http://i.imgur.com/abr86nE.jpg?2)

Here is the code I'm using...

#include <LowPower.h>

// Solder-free method of detecting the ROM of a DS18B20 - spread the 3 legs of the sensor wide enough to fit into GND, 13, and 12
// and place the sensor in these pins with the flat side facing the LED on the Uno and the round side facing away from the Uno. 
// Then upload and open a serial monitor with a baud rate of 9600.
#include <util/delay.h>

// ====================================================== Pre-Compiler Definitions ======================================================
#define DEBUG 1   // Controls the inclusion or exclusion of serial debug information
#define CLOCK 1   // Controls whether or not temperature reading duration is timed

// Direct port manipulation needed to conduct the OneWire bus
#define   PowerPin              PB1                      // Pin 12 - we will be using this pin to supply Vcc to the DS18B20
#define   POWER_TEMP_PROBE      PORTB |= (1<<PowerPin)    // Define method for powering the DB18B20
#define   DEPOWER_TEMP_PROBE    PORTB &= ~(1<<PowerPin)   // Define method for depowering the DB18B20
#define   GroundPin             PD7
#define   Pin                   PB0                       // Set up pin 13 as the data pin
#define   DIRECT_MODE_OUTPUT    DDRB |= (1<<Pin)//_BV(Pin)          // Much faster and smaller version of pinMode(Pin, OUTPUT)
#define   DIRECT_MODE_INPUT     DDRB &= ~(1<<Pin)         // Much faster and smaller version of pinMode(Pin, INPUT)
#define   DIRECT_WRITE_HIGH     PORTB |= (1<<Pin)         // Much faster and smaller version of digitalWrite(Pin, HIGH)
#define   DIRECT_WRITE_LOW      PORTB &= ~(1<<Pin)        // Much faster and smaller version of digitalWrite(Pin, LOW)
#define   DIRECT_READ           PINB & (1<<Pin) ? 1 : 0   // One line if else statement using the format [test ? true return : false return]

// Delay values needed for conducting a OneWire bus
#define   clk_div               1                         // This code assumes a processor frequency of 16MHz but this can be lowered as long as clk_div is updated
#define   DELAY_A               6/clk_div                 // Delay values obtained from http://www.maximintegrated.com/app-notes/index.mvp/id/126
#define   DELAY_B               64/clk_div
#define   DELAY_C               60/clk_div
#define   DELAY_D               10/clk_div
#define   DELAY_E               9/clk_div
#define   DELAY_F               55/clk_div
#define   DELAY_G               0/clk_div
#define   DELAY_H               480/clk_div
#define   DELAY_I               72/clk_div
#define   DELAY_J               410/clk_div

// DS18B20 command codes
#define   READROM               0x33                      // Read the ROM of a OneWire device; there must only be one OneWire device on the bus!
#define   STARTCONVO            0x44                      // Tells device to take a temperature reading and put it on the scratchpad
#define   READSCRATCH           0xBE                      // Read from the scratchpad
#define   WRITESCRATCH          0x4E                      // Write to the scratchpad
#define   COPYSCRATCH           0x48                      // Tells the DS18B20 to copy the contents of the scratchpad to EEPROM
#define   SKIPROM               0xCC                      // Tells all OneWire sensors on the bus that the next command applies to them
#define   MATCHROM              0x55                      // Tells all OneWire sensors on the bus to listen for a specific ROM next

#define   BAUD_RATE             57600
#define   myubbr                (F_CPU/clk_div/16/BAUD_RATE-1) // Baud rate for UART

int main() { 
  bool present = 0;
  uint8_t ROM[8] ;
 
  #if DEBUG
    #if CLOCK
      unsigned long start_time, end_time;
      // Timer 0 initialization from wiring.c for a ATmega 328P (Arduino Uno rev 3) + 12 bytes to sketch size
      TCCR0A = _BV(WGM01) | _BV(WGM00);      // set timer 0 prescale factor to 64
      TCCR0B = _BV(CS01) | _BV(CS00);        // set timer 0 prescale factor to 64
      TIMSK0 = _BV(TOIE0);                 // enable timer 0 overflow interrupt
    #endif
   
    // Initialize the UART
    UBRR0H = (unsigned char)(myubbr>>8);
    UBRR0L = (unsigned char)myubbr;
    UCSR0A = 0;//Disable U2X mode
    UCSR0B = (1<<TXEN0);//Enable transmitter
    UCSR0C = (3<<UCSZ00);//N81
    _delay_ms(100);
  #endif

  // Setup for the power pin
  DDRB |= (1<<PowerPin);    // Set the power pin as an output
  POWER_TEMP_PROBE;         // Drive the power pin high to power the DS18B20
 
  // Setup for the ground pin
  DDRD |= (1<<GroundPin); // Set the ground pin as an output 
  PORTD &= ~(1<<GroundPin);  // Pull the ground pin low
 
  // Set the sensor's resolution to 11 bits
  SetResolution(9);
 
  for(;;) {  // Loop forever

    POWER_TEMP_PROBE;
    // Perform a OneWire reset pulse and see if we detect a presence pulse afterward
    present = reset();
   
    // If a one-wire device is present, attempt to read its ROM
    if (present) {
      write(READROM);
      for(uint8_t i=0;i<8;i++) {
        ROM[i]=read();
      }
    }
   
    #if DEBUG
      simpletx("Presence pulse: ");
      if(present) {
        simpletx("Detected");
      } else {
        simpletx("Not Detected");
      }
     
      simpletx("\tROM is: ");
      for(uint8_t i=0;i<8;i++) {
        simpletx("0x");
        txByteAsHex(ROM[i]);
        if (i!=7) simpletx(",");
      }
      simpletx("\t\t");
    #endif
   
   
    // If we detected a Dallas family sensor, let's go ahead and take a temperature reading
    if (ROM[0]=0x28) {  // The first byte of all dallas sensors is always 0x28
      reset();
      write(SKIPROM);
      write(STARTCONVO);
     
      #if CLOCK
        start_time = millis();
      #endif
     
      LowPower.powerDown(SLEEP_60MS, ADC_OFF, BOD_OFF);   // Put the uC to sleep while the temperature conversion proceeds to save power
      LowPower.powerDown(SLEEP_15MS, ADC_OFF, BOD_OFF);   // Put the uC to sleep while the temperature conversion proceeds to save power
      //while(!read());  //_delay_ms(750);    // Can either wait 750 ms for the conversion to be done or else read until we get a 1 back from the DS18B20 meaning it is signaling complete
     
      #if CLOCK
        end_time = millis();
      #endif
     
      reset();
      write(SKIPROM);
      write(READSCRATCH);
      uint8_t tempLSB = read();
      uint8_t tempMSB = read();
      DEPOWER_TEMP_PROBE;  // Rather than perform a reset to tell the probe to stop sending data, just cut the power and it will get the message!
     
      #if DEBUG
        simpletx("Temperature: ");
        txRawTempAsFloat( tempMSB<<8 | tempLSB );
        simpletx("F");
       
        #if CLOCK
          simpletx("\tConversion took ");
          txInt(end_time-start_time);
          simpletx(" ms");
        #endif
        simpletx("\n");
        _delay_us(300);
      #endif
    }

    uint8_t sleep_count=0;
    do LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
    while (++sleep_count < 4);
    //_delay_ms(10000);
  }  // End for
}  // End main

// ============================================================================================================================================================
// Sets the temperature measurement resolution of the DS18B20 to either 9, 10, 11, or 12 bits  If any other number is passed, the sensor will be set to 12 bits
// Only works if there is a single DS18B20 on the one wire network
// ============================================================================================================================================================
static inline void SetResolution(uint8_t resolution) {
  reset();
  write(SKIPROM);
  write(WRITESCRATCH);
  write(0x00);
  write(0x00);
  switch (resolution) {
    case 9: write(0x1F);  break;
    case 10: write(0x3F); break;
    case 11: write(0x5F); break;
    default: write(0x7F); break;
  }
  reset();
  write(SKIPROM);
  write(COPYSCRATCH);
  //_delay_ums(15);
}


static inline uint8_t read() {
  uint8_t r=0;
     
  noInterrupts();
  for (uint8_t bitMask = 0x01; bitMask; bitMask <<= 1) {
    DIRECT_MODE_OUTPUT;
    DIRECT_WRITE_LOW;
    _delay_us(DELAY_A);
    DIRECT_MODE_INPUT;
    DIRECT_WRITE_HIGH;  // New line for no resistor modification / enable pull-up resistor
    _delay_us(DELAY_E);
    if (DIRECT_READ) r |= bitMask;
    _delay_us(DELAY_F);
  }
  interrupts();
  return r;
}

static inline void write(uint8_t v) {
  noInterrupts();
  for (uint8_t bitMask = 0x01; bitMask; bitMask <<= 1) {
    DIRECT_WRITE_LOW;
    DIRECT_MODE_OUTPUT;
    if (bitMask & v) {
      _delay_us(DELAY_A);
      DIRECT_WRITE_HIGH;
      _delay_us(DELAY_B);
    } else {
      _delay_us(DELAY_C);
      DIRECT_WRITE_HIGH;
      _delay_us(DELAY_D);
    }
  }
  DIRECT_MODE_INPUT;
  interrupts();
}

static inline uint8_t reset(void) {
  noInterrupts();
  DIRECT_MODE_INPUT;     
  DIRECT_WRITE_LOW;
  DIRECT_MODE_OUTPUT;
  _delay_us(DELAY_H);
  DIRECT_MODE_INPUT;
  DIRECT_WRITE_HIGH;  // New line for no resistor modification / enable pull-up resistor
  _delay_us(DELAY_I);
  uint8_t ret = !(DIRECT_READ);
  interrupts();
  _delay_us(DELAY_J);
  return ret;
}

static inline void simpletx( char * string ) {
  /*if (UCSR0B != (1<<TXEN0)) { //do we need to init the uart?
    UBRR0H = (unsigned char)(myubbr>>8);
    UBRR0L = (unsigned char)myubbr;
    UCSR0A = 0;//Disable U2X mode
    UCSR0B = (1<<TXEN0);//Enable transmitter
    UCSR0C = (3<<UCSZ00);//N81
    _delay_ms(30);
  }*/
  while (*string) {
    while ( !( UCSR0A & (1<<UDRE0)) );
    UDR0 = *string++; //send the data
  }
}

static inline void txByteAsHex(uint8_t inp) {
  char snd[3];
  uint8_t tmp = inp>>4;
 
  if (tmp<10) {
    snd[0]=48+tmp;
  } else {
    snd[0]=55+tmp;
  }
 
  tmp=inp%16;
  if (tmp<10) {
    snd[1]=48+tmp;
  } else {
    snd[1]=55+tmp;
  }
  snd[2]='\0';
  simpletx(snd);
}

static inline void txInt(long inp) {
  long temp = inp;
  uint8_t numChars=0;
  boolean isNegative=false;
 
  // Check to see if there is a negative sign
  if(temp<0){
    isNegative=true;
    numChars++;
    temp*=-1;
  }
 
  do {
    numChars++;
    temp /= 10;
  } while ( temp );
  char buf[numChars];
 
  // Write the negative sign if present and the terminating null character
  temp=inp;
  buf[numChars]=0;
  if(isNegative) {
    temp*=-1;
    buf[0]='-';
  }
 
  int i = numChars - 1;
  do {
      buf[i--] = temp%10 + '0';
      temp /= 10;
  } while (temp);
 
  simpletx(buf);
}

// Converts the raw temperature from a DS18B20 directly to a string containing the temperature in °F with 1 decimal place
// avoids unnecessary floating point math, float variables, and casts, and 32-bit math
// TODO: May not work properly with temperatures below 32°F
static inline void txRawTempAsFloat(uint16_t raw) { 
  char buffer[6];

  uint8_t decimalPos = 2;  // default case of a temp between 0 and 99.9
  uint8_t nullPos = 4;     // default case of a temp between 0 and 99.9
  uint16_t temp;
 
  // Check to see if the temperature passed in is negative
  if (raw>>11) {
    // Can't get here unless one of the 5 most-significant bits are ones which means we have a negative number, convert it
    raw = ~(raw-1);    // Convert the two's compliment number back into one's compliment
   
    if (raw > 284) {  // This temperature is far enough negative in the celcius scale that it is also negative on the farhenheit scale
      decimalPos += 1;   // Account for the negative sign's place in the string
      nullPos += 1;      // Account for the negative sign's place in the string
      buffer[0] = '-';   // Write the negative sign in the string
    }
    temp = (9*raw)/8-320;                   // Keeps only 1 decimal place but uses 16-bit math
  } else {
    temp = (9*raw)/8+320;                   // Keeps only 1 decimal place but uses 16-bit math
  }


  // Convert the raw temperature into the temperature in Fx10 so that one decimal place is kept
  //uint32_t temp = (raw*1125ul+320000ul)/1000ul;  // Keeps all 4 decimal places but uses 32-bit math 
  if(temp>=1000) {  // We're looking at a positive number with three digits
    decimalPos += 1;
    nullPos += 1;
  }
 
  buffer[nullPos--] = '\0';
  do {
    if (nullPos==decimalPos) buffer[nullPos--] = '.';
    buffer[nullPos--] = temp % 10 + '0';
    temp /= 10;
  } while (temp); 
 
  simpletx(buffer);
}


This uses Felix's LowPower library to sleep the processor for 32 seconds between temperature readings.  I also sleep the processor for 75ms during a 9-bit temperature conversion which saves a teeny amount of power.  There are still things you could and should do to extend this.  I'm not sleeping the radio, you most certainly should that saves a good amount of power.  Also, you can turn up the clock divider in code without messing with fuse bits (I'll add this soonish just to have a play myself).  As Felix said, the DS18B20 isn't all that battery friendly but 75ms of active time every 5 minutes is a 0.025% duty cycle.  At a current draw of 1mA when it is measuring that works out to an average current draw of 250nA which is all kinds of acceptable on a 2xAAA battery powered project.
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: ChemE on July 27, 2017, 11:51:57 AM
I just added my own code to sleep the radio and measured the sleep current at 7.4uA with my uCurrent from EEVblog.  This is running from 2xAA Energizer Ultimate Lithium batteries (L91 hereafter) and using the stock LDO.  The battery set is currently putting out 3.36V so the LDO is still playing nice and not going past its rated quiescent current.  A pair of L91's will put out around 1,500mAh until they drop to 3.3V at which point the LDO will dominate and quickly drain the batteries so let's say the system is dead at 3.3V.

1,500mAh / 8uA = 21 years

Granted there is some self-discharge of the batteries but without performing surgery on your Mote and using a battery-unfriendly DS18B20 you can still make an extremely long-lived temperature node.
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: Felix on July 27, 2017, 01:39:17 PM
Thanks ChemE for the code and knowledge, can you add the radio sleep code to your code sample?
Also I wonder why you use static inline for every function?
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: ChemE on July 27, 2017, 01:56:04 PM
You know, I'm glad I decided to start fooling around with this even though I thought that I understood it.  Turns out my turning on and off the DS18B20 wasn't doing anything which is why I'm getting 7.4uA sleep currents.  Pull the probe out of the breadboard and you go down to the 6.4uA we expect.  I've revised my code again (I know I'm crazy) and am using pins 4-6 in order to not conflict with the on-board LED.  I'm also now turning the ground pin into an input prior to sleeping and that is having the desired effect. Attached is my huge somewhat messy code that sleeps the radio as well as properly depowers the DS18B20.

Side note that is totally bizarre and I might need to open a new thread: I notice on my 4th 8S sleep that my current goes from 6.4uA down to 5.9uA.  On a whim, I added 3 15ms sleeps prior to my 32s sleep loop and sure enough now I spend all 32s at 5.9uA.  If that is real for some strange reason that is a big darn deal!

I static inline the routines to make everything faster Felix.  Yes I know I'm only saving a few cycles on a few jumps but I write such tiny code that I can afford to have my routines inlined and save the jumps/returns.  Net effect, slightly larger .hex and faster execution.  I don't have a scope so I can't strictly confirm that but it should be the case based on my understanding.
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: Lukapple on July 27, 2017, 04:55:45 PM
ChemE,
Thanks for sharing your code with us. Your measurements sounds fantastic. I'll try your code as soon as I get home. Is there any other techniques for precise current measurements except using special instruments like uCurrent adapter? I've just multimeter and some USB scope, which I used only once :)
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: ChemE on July 28, 2017, 11:45:15 AM
I am not aware of another means of detecting such low currents other than the uCurrent.  On a side note, using a uCurrent and FTDI breakout with a Mote creates quite a rat's nest of wires so I've designed a teeny board to clean this up.  I'll be getting four copies but only need one, so if anyone would like a copy for themselves message me.

(http://i.imgur.com/JpeKKPT.jpg)

https://pcbs.io/share/8D2M0
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: Lukapple on July 28, 2017, 04:53:44 PM
Hi,
I've tested your code and it works fine!
Presence pulse: Detected ROM is: 0x28,0xFF,0x0C,0xBF,0x63,0x16,0x04,0x04 Temperature: 78.8F Conversion took 0 ms

A lot of low-level stuff in your code :) now I have to figure out how to send temperature data to my base node. Can you maybe help me and add a "low-level" method for sending data? Otherwise I'll probably just include RFM69 Felix's library and use sendWithRetry method. :D

And thanks for sharing "teeny board" for uCurrent :)
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: ChemE on July 28, 2017, 05:18:35 PM
Glad it is working for you, it will barely make a dent in your 9V battery even after a few months.  As far as a low level send, I have some code I'll post shortly which should do the trick.  It can't receive an ACK so it isn't totally reliable; my own library is still pretty young.  I would just send the 2-byte raw value read from the DS18B20 back to the gateway and let the gateway do the conversion to Celsius.  This is what you're after:


uint8_t tempLSB = read();
uint8_t tempMSB = read();


No need to do the calculations on a battery powered node.  If you have a voltage divider you could also read the battery voltage and send it back as well; that is quite commonly done.
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: ChemE on July 28, 2017, 05:27:38 PM
This should work with the code I've already posted.
static inline void SendFrame(uint8_t toAddress, const void* buffer, uint8_t bufferSize) {  // Level 2 code - do useful work
  SELECT;
  SPI_XFER(REG_FIFO | 0x80);   // write to FIFO using SPI burst mode
  SPI_XFER(bufferSize + 3);    // LEN byte
  SPI_XFER(toAddress);         // 1st byte
  SPI_XFER(NODEID);            // 2nd byte
  SPI_XFER(0x00);              // 3rd byte
  for (uint8_t i = 0; i < bufferSize; i++) SPI_XFER(((uint8_t*) buffer)[i]);  // Write 6 more bytes to the FIFO
  UNSELECT;
}


It is called like so:


uint8_t data[8];  //16-bit temp, 16-bit RH, 16-bit Vcc, 16-bit packet counter
...
data[6] = (++packet_cnt & 0xFF);                  // Increment packet_count and stash the LSB
data[7] = (packet_cnt >> 8);                         // Stash the MSB of the packet counter
...
SendFrame(RECEIVER, data, 8);                   // Send the data
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: Lukapple on July 28, 2017, 05:58:18 PM
Great, thanks.
Did a quick test, and it doesn't work.
I'm using RFM69HW on RF69_433MHZ. I probably need some additional settings?
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: ChemE on July 28, 2017, 09:17:47 PM
Yeah sorry that low-level code is really just written for my radio right now which is a 915MHz RFM69CW.  It isn't even safe to use my code because it might fry your radio since it doesn't do anything with PA1 and PA2.
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: Lukapple on July 29, 2017, 05:09:55 AM
Ah, ok, my radio still works. Do you have plans to support RFM69HW 433MHZ  ;) ?
Do I have to remove following parts of code if I want to use RFM69.h lib?
Probably this parts:
  CHANGE_OP_MODE(SLEEP_MODE); // sleep the radio right away
...
UCSR0B = (1<<TXEN0);//Enable transmitter


and call RFM69's init method instead:
Quote_radio.initialize(FREQUENCY,ID,NETWORKID);
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: ChemE on July 29, 2017, 07:28:40 AM
Exactly right.  And yes, eventually my library will support all radios.  It is actually just three lines in radio.init that need to change.
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: Lukapple on July 29, 2017, 07:43:40 AM
Sounds great, thanks. I'll try to find those 3 lines later when I get home :)
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: ChemE on July 29, 2017, 10:02:30 AM
I forgot that I was able to be super-sneaky.  When the radio module reboots, its frequency defaults to 915MHz so I just removed the three lines which set the RF carrier frequency.  Here are the lines in Felix's library:


{ REG_FRFMSB, (uint8_t) (freqBand==RF69_315MHZ ? RF_FRFMSB_315 : (freqBand==RF69_433MHZ ? RF_FRFMSB_433 : (freqBand==RF69_868MHZ ? RF_FRFMSB_868 : RF_FRFMSB_915))) },
    /* 0x08 */ { REG_FRFMID, (uint8_t) (freqBand==RF69_315MHZ ? RF_FRFMID_315 : (freqBand==RF69_433MHZ ? RF_FRFMID_433 : (freqBand==RF69_868MHZ ? RF_FRFMID_868 : RF_FRFMID_915))) },
    /* 0x09 */ { REG_FRFLSB, (uint8_t) (freqBand==RF69_315MHZ ? RF_FRFLSB_315 : (freqBand==RF69_433MHZ ? RF_FRFLSB_433 : (freqBand==RF69_868MHZ ? RF_FRFLSB_868 : RF_FRFLSB_915))) },


And for specifically 433MHz and translated to my routines it should look like:


#define REG_FRFMSB                  0x07
#define REG_FRFMID                  0x08
#define REG_FRFLSB                  0x09
#define RF_FRFMSB_433             0x6C
#define RF_FRFMID_433             0x40
#define RF_FRFLSB_433             0x00
writeReg( REG_FRMSB, RF_FRMSB_433 );
writeReg( REG_FRMID, RF_FRMID_433 );
writeRef( REG_FRLSB, RF_FRLSB_433 );


The only other thing you might need to do is tweak your PA1 and PA2 settings.  Use Felix's library to initialize your radio and set the power level to what you need and then do readRegsCompact to see what the PA1 and PA2 registers are set at.  Then use the writeReg routines to set those in my radio_init routine and you should be good.
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: Lukapple on July 29, 2017, 04:01:18 PM
Thanks for hints. Somehow I can't get it to work, I must be missing something  :'(
Is REG_PALEVEL the right register for PA1 and PA2? I can't find method readRegsCompact, so I used:
uint8_t f_palevel = readReg(REG_PALEVEL);
... and on the end of the RadioInit
    writeReg(REG_PALEVEL, f_palevel); //7F
    writeReg( REG_FRFMSB, RF_FRFMSB_433 );
    writeReg( REG_FRFMID, RF_FRFMID_433 );
    writeReg( REG_FRFLSB, RF_FRFLSB_433 );   


I've attached modified sketch.
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: Darren on July 29, 2017, 06:35:40 PM
I do what Felix does but I don't used Lithium polymer batteries but Titus Hybrid Pulse Capacitors or commonly known as SuperCaps.

SuperCaps can replace rechargeable batteries with the same mAh rating and work at -55C to +85C temperatures.

Supercaps don't need any fancy recharging circuit since they are capacitors and will charge to 3.6 Vdc from a 5 volt Solar cell.


Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: ChemE on July 30, 2017, 12:44:33 AM
Darren,

Can you post a link or part number to that supercap?  I didn't realize that it was safe to supply a 4.0V supercap with 5.0V from a solar panel.
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: Lukapple on July 30, 2017, 02:08:40 AM
Wow, interesting stuff.

@ChemE,
Please see my last post on page#2. :D
Thanks!
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: ChemE on July 30, 2017, 02:44:09 AM
Are you applying all the same settings on the RX radio as well?  The only thing you would not want to mimic is the automode register setting since that makes the node a transmitter rather than receiver.  Also you've turned AES on, turn it off for both radios.
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: Lukapple on July 30, 2017, 06:41:42 AM
On the gateway node I'm using initialize from the RFM69 lib. I tought that other register settings were the same.
For now I'll just inject a RFM69 lib to your code, for sending temperature to gateway node (I hope that I'll get those 2 months of juice anyway). Then I'll try to play around with your code and get it working. I hope that you'll release your lib soon ;)

One more question...
I've checked out RFM69HW's datasheet and there are following operating modes available:

Transceiver's operating modes:
000 → Sleep mode (SLEEP)
001 → Standby mode (STDBY)
010 → Frequency Synthesizer mode (FS) 011 → Transmitter mode (TX)
100 → Receiver mode (RX)


In your RadioInit method you put radio to sleep mode. Where is code, that puts radio to TX mode.
There probably shoud be something like:
CHANGE_OP_MODE(TRANSMITTER_MODE)
before you call "SendFrame" method?
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: ChemE on July 30, 2017, 06:48:17 AM
I make use of automode on the node which automatically puts the radio in TX mode as soon as the number of bytes in the FIFO hit a user-defined threshold.  I'll have to double check but I'm pretty sure I put the threshold as 1 byte.  So as you are loading the FIFO, the oscillator is already coming up.  The really nice thing about automode is the uC is only awake until the FIFO is filled and then can go right back to sleep.  The RFM69 takes care of getting the TX out and then puts the radio back to sleep since I define sleep as the base mode and TX as the intermediate mode with the FIFO threshold as the condition.  I hope to be done with my minimal lib this year.
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: Lukapple on July 30, 2017, 06:56:31 AM
Thanks for the explanation!
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: ChemE on July 30, 2017, 07:00:12 AM
Hmm, I might have found the setting mismatch causing the node to not transmit.  I had set automode to TX on rising edge of FIFO threshold but I'm not setting what that threshold is.  Try changing your definition of automode to this:

#define         AUTO_TRANSMITTER                        B00111011    // Enter = FIFO not empty; Exit = Packet Sent; Intermediate Mode = TX

This will force the node to TX as soon as the first byte hits the FIFO.  Also all settings on both the node and gateway must match other than automode and FIFO level.  The settings that I've been posting are 300kbps so that the radio broadcasts for 1/6th as long as the default library.  Felix's default bandwidth is 55.555kbps.  So you had a node speaking at 300 and a gateway listening at 55.
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: Darren on July 30, 2017, 10:01:46 AM
The Supercap or Hybrid Pulse Capacitor (HPC) will only charge to the voltage that is supplied to it.

A 5 volt solar cell never outputs 5 volts even in ideal situations.

The HPC is labelled 4.0 volts but outputs 3.6 volts. It's ideal for Moteinos.

Since the Moteino can operate down to 1.8 vdc the HPC can drop to this level and then be recharged.

The nice thing about HPC or Supercaps is that you don't have to worry about a charging circuit, about the cold or hot weather, nor do you have to worry about the input voltage being constant.

Titus brand, out of Louisville Kentucky, you can call Patrick or email him: [email protected]

Titus HPC1530 or the smaller version is HPC1520
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: Lukapple on July 30, 2017, 03:38:09 PM
Quote from: ChemE on July 30, 2017, 07:00:12 AM
Hmm, I might have found the setting mismatch causing the node to not transmit.  I had set automode to TX on rising edge of FIFO threshold but I'm not setting what that threshold is.  Try changing your definition of automode to this:

#define         AUTO_TRANSMITTER                        B00111011    // Enter = FIFO not empty; Exit = Packet Sent; Intermediate Mode = TX

This will force the node to TX as soon as the first byte hits the FIFO.  Also all settings on both the node and gateway must match other than automode and FIFO level.  The settings that I've been posting are 300kbps so that the radio broadcasts for 1/6th as long as the default library.  Felix's default bandwidth is 55.555kbps.  So you had a node speaking at 300 and a gateway listening at 55.

Ah, I see,
RegAutoModes, bits 7-5(EnterCondition): Interrupt condition for entering the intermediate mode: 001 → Rising edge of FifoNotEmpty

I'll try to modify my gateway node settings tommorow (my gateway is hard to reach ... somewhere on the attic).
Thanks!
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: Lukapple on July 31, 2017, 04:45:19 AM
ChemE,
another question about Power Reduction Register.
In your code, you halt some of the peripherials, that are not needed:
PRR = B10111101;  // halt other peripherials that are not needed

If I wan't to use "SendWithRetry" metod from RFM69.h lib, it doesn't work and if I coment out that PRR line, it works. Did you maybe disable some of the peripherials, that are needed for radio, by mistake?
Could you please tell me what PRR settings should I use, to make radio work?

Thanks!

Info about PRR from ATmega328p's datashet:
Bit 7 – PRTWI0: Power Reduction TWI0
Writing a logic one to this bit shuts down the TWI 0 by stopping the clock to the module. When waking up the TWI again, the TWI should be re initialized to ensure proper operation.
Bit 6 – PRTIM2: Power Reduction Timer/Counter2
Writing a logic one to this bit shuts down the Timer/Counter2 module in synchronous mode (AS2 is 0). When the Timer/Counter2 is enabled, operation will continue like before the shutdown.
Bit 5 – PRTIM0: Power Reduction Timer/Counter0
Writing a logic one to this bit shuts down the Timer/Counter0 module. When the Timer/Counter0 is enabled, operation will continue like before the shutdown.
Bit 3 – PRTIM1: Power Reduction Timer/Counter1
Writing a logic one to this bit shuts down the Timer/Counter1 module. When the Timer/Counter1 is enabled, operation will continue like before the shutdown.
Bit 2 – PRSPI0: Power Reduction Serial Peripheral Interface 0
If using debugWIRE On-chip Debug System, this bit should not be written to one. Writing a logic one to this bit shuts down the Serial Peripheral Interface by stopping the clock to the module. When waking up the SPI again, the SPI should be re initialized to ensure proper operation.
Bit 1 – PRUSART0: Power Reduction USART0
Writing a logic one to this bit shuts down the USART by stopping the clock to the module. When waking up the USART again, the USART should be re initialized to ensure proper operation.
Bit 0 – PRADC: Power Reduction ADC
Writing a logic one to this bit shuts down the ADC. The ADC must be disabled before shut down. The analog comparator cannot use the ADC input MUX when the ADC is shut down.
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: ChemE on July 31, 2017, 01:08:34 PM
Felix uses millis() to control the timouts in SendWithRetry.  Timer 0 controls the counter that millis() relies upon to function.  So you would want to change that bit to 0 so it stays on.  That should fix that issue.
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: Lukapple on August 01, 2017, 03:19:53 AM
Quote from: ChemE on July 31, 2017, 01:08:34 PM
Felix uses millis() to control the timouts in SendWithRetry.  Timer 0 controls the counter that millis() relies upon to function.  So you would want to change that bit to 0 so it stays on.  That should fix that issue.

It didn't help. I had to change bit 2, then it started to work. Thanks
Bit 2 – PRSPI0: Power Reduction Serial Peripheral Interface 0

Ok, now I've sketch ready. so this should work with 2x AAA or 2xAA (is there any difference) without removing LDO.
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: ChemE on August 01, 2017, 04:09:11 AM
Derp, yeah my fault.  I had turned off the SPI bus because the radio was already asleep and I wasn't using the radio again since I was just demonstrating the DS18B20.

Other than capacity no there is no electrical difference between 2xAA and 2xAAA.  You can keep the LDO as long as you use the Energizer Ultimate Lithium or a similar battery.  The battery chemistry is critically important because we need something that puts out more than 1.5V when it is fresh.  This chemistry puts out 1.8V when fresh and you can use almost all its capacity before the pair's voltage drops below 3.0V.  A normal alkaline battery would do terribly in this application.
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: Lukapple on August 03, 2017, 06:46:21 AM
Thanks for info.
I didn't know that those batteries are little harder to get (at least in our country). I had to order them online and now I'm waiting for package to arrive. I'll post the results and my product photo once I get those batteries.

My next project is to add another node, with DPD led display, which will display pool temperature :) (https://www.freetronics.com.au/products/dot-matrix-display-32x16-red#.WYL-sMaB01g)
Title: Re: DS18B20 - temperature on request, battery lifetime?
Post by: Lukapple on August 13, 2017, 04:23:27 PM
I've finally installed the temperature node to my pool.
Thank you guys for your help, expecially ChemE for taking time to experiment with the DS18B20 sensor and sharing his optimised code with us.
(http://shrani.si/f/1b/pl/30r2OgU9/img4379.jpg)