DS18B20

Everything about programming the platform and using the Waspmote API
chriswater
Posts: 33
Joined: Tue May 05, 2015 2:59 pm

Re: DS18B20

Post by chriswater » Tue Jul 25, 2017 11:19 am

Dear libelium-dev

Yes I tested that and it didn't help.
As I have written in my post, the only thing that helped was to modify wiring.c.

Code: Select all

/* Delay for the given number of microseconds.  Assumes a 16 MHz clock. 
 * Disables interrupts, which will disrupt the millis() function if used
 * too frequently. */
void delayMicroseconds(unsigned int us)
{
	// make conversion to simulate a 8MHz clock
	unsigned int us_aux = us;
	
	if( us > 3)
	{
		us_aux*=1.8;
	}
	else
	{
		us_aux*=2;
	}
	
	uint8_t oldSREG;

	// calling avrlib's delay_us() function with low values (e.g. 1 or
	// 2 microseconds) gives delays longer than desired.
	//delay_us(us);

#if F_CPU >= 16000000L
    // for the 16 MHz clock on most Arduino boards

	// for a one-microsecond delay, simply return.  the overhead
	// of the function call yields a delay of approximately 1 1/8 us.
	if (--us_aux == 0)
		return;

	// the following loop takes a quarter of a microsecond (4 cycles)
	// per iteration, so execute it four times for each microsecond of
	// delay requested.
	us_aux <<= 2;

	// account for the time taken in the preceeding commands.
	us_aux -= 2;
#else
    // for the 8 MHz internal clock on the ATmega168

    // for a one- or two-microsecond delay, simply return.  the overhead of
    // the function calls takes more than two microseconds.  can't just
    // subtract two, since us is unsigned; we'd overflow.
	if (--us_aux == 0)
		return;
	if (--us_aux == 0)
		return;

	// the following loop takes half of a microsecond (4 cycles)
	// per iteration, so execute it twice for each microsecond of
	// delay requested.
	us_aux <<= 1;
    
    // partially compensate for the time taken by the preceeding commands.
    // we can't subtract any more than this or we'd overflow w/ small delays.
    us_aux--;
#endif

	// disable interrupts, otherwise the timer 0 overflow interrupt that
	// tracks milliseconds will make us delay longer than we want.
	oldSREG = SREG;
	cli();

	// busy wait
	__asm__ __volatile__ (
		"1: sbiw %0,1" "\n\t" // 2 cycles
		"brne 1b" : "=w" (us_aux) : "0" (us_aux) // 2 cycles
	);

	// reenable interrupts.
	SREG = oldSREG;
}
to

Code: Select all

/* Delay for the given number of microseconds.  Assumes a 16 MHz clock. 
 * Disables interrupts, which will disrupt the millis() function if used
 * too frequently. */
void delayMicroseconds(unsigned int us)
{
	// make conversion to simulate a 8MHz clock
	unsigned int us_aux = us;
	
	/*
	if( us > 3)
	{
		us_aux*=1.8;
	}
	else
	{
		us_aux*=2;
	}
	*/
	us_aux*=2; 
	
	uint8_t oldSREG;

	// calling avrlib's delay_us() function with low values (e.g. 1 or
	// 2 microseconds) gives delays longer than desired.
	//delay_us(us);

#if F_CPU >= 16000000L
    // for the 16 MHz clock on most Arduino boards

	// for a one-microsecond delay, simply return.  the overhead
	// of the function call yields a delay of approximately 1 1/8 us.
	if (--us_aux == 0)
		return;

	// the following loop takes a quarter of a microsecond (4 cycles)
	// per iteration, so execute it four times for each microsecond of
	// delay requested.
	us_aux <<= 2;

	// account for the time taken in the preceeding commands.
	us_aux -= 2;
#else
    // for the 8 MHz internal clock on the ATmega168

    // for a one- or two-microsecond delay, simply return.  the overhead of
    // the function calls takes more than two microseconds.  can't just
    // subtract two, since us is unsigned; we'd overflow.
	if (--us_aux == 0)
		return;
	if (--us_aux == 0)
		return;

	// the following loop takes half of a microsecond (4 cycles)
	// per iteration, so execute it twice for each microsecond of
	// delay requested.
	us_aux <<= 1;
    
    // partially compensate for the time taken by the preceeding commands.
    // we can't subtract any more than this or we'd overflow w/ small delays.
    us_aux--;
#endif

	// disable interrupts, otherwise the timer 0 overflow interrupt that
	// tracks milliseconds will make us delay longer than we want.
	oldSREG = SREG;
	cli();

	// busy wait
	__asm__ __volatile__ (
		"1: sbiw %0,1" "\n\t" // 2 cycles
		"brne 1b" : "=w" (us_aux) : "0" (us_aux) // 2 cycles
	);

	// reenable interrupts.
	SREG = oldSREG;
}
With the code "us_aux*=1.8;" the reading/writing to the DS18B20 was not working, most probably because that initiates a floating point operation. I was able to reproduce that and measured the timing with an oscilloscope.

Kind regards

libelium-dev
Posts: 27967
Joined: Mon Sep 28, 2009 1:06 pm

Re: DS18B20

Post by libelium-dev » Thu Jul 27, 2017 9:41 am

Hi,

We have done some test and we have checked that the delayMicroseconds() function works better with the modifications than with the current function. We are going to do more test and we will change this in the next API release.

Regards

luukh
Posts: 31
Joined: Mon Mar 09, 2015 9:29 pm
Location: Arcadia, Australia
Contact:

Re: DS18B20

Post by luukh » Tue Aug 29, 2017 1:25 pm

Hi All,

Just a confirmation that Chris' theory seems to provide a solution to this issue (in my case).

I have a setup of 2 brand new PnS Agri Pro units (with V1.2 boards, not V1.5). Both units have 1 sensirion, 1 DS18B20 and 1 soil moisture probe connected. The units run identical firmware. What I've noticed, when running both units over 3 days taking measurements at 15 minute intervals, is that 1 of the units gave me many "-1000" readings on the DS18B20. I looked a little closer at that anomaly and noticed that for some reason, when the temperature dropped below 12 degrees C the probe read "-1000". As soon as the temperature rose and came up over 12 degrees C, the probe gave a correct reading again. The temperature variation expected was a fairly natural temperature cycle reading cooler temps overnight than during the day.

This issue was also easily simulated with a cup of ice and hot water, using one of the IDE examples. 1 Unit read perfectly, the other read constant -1000 on temperature drops below 12 degrees C.

FYI, I am using API V23 (knowing it is quite different from V25 or V28 in many areas of the library). So I tried some of the suggested code changes mentioned in this post, but none seemed to have an effect or correct the reading, bar the suggestion Chris Water proposed. I.e. removing the floating calculus out from the function, thereby not negatively affecting the timing of the delayMicroseconds function. That change somehow made the both units read the DS18B20 values properly.

I can't explain why only one unit would be affected by this issue and not the other, as they are identical H/W (well I have to assume that, as I have not opened the boxes). So I can only put it down to either a borderline timing issue, or possible an issue with a batch of probes. I will swap the probes to rule out a probe issue, but I thought I'd share this with you before I forget :)

Happy to have other people's thoughts go over it.
Luuk

luukh
Posts: 31
Joined: Mon Mar 09, 2015 9:29 pm
Location: Arcadia, Australia
Contact:

Re: DS18B20

Post by luukh » Wed Aug 30, 2017 9:23 am

FYI, today I confirmed the probes. When I swapped the probes on the 2 identical Agri Pro units, the -1000 temp reading issue transfers from one to the other. Ie. Hardware .... same, firmware ... same. I've only swapped the probes.

Making the changes as suggested by Chris makes both DS18B20 probes read the temp properly.

Cheerio,
Luuk

libelium-dev
Posts: 27967
Joined: Mon Sep 28, 2009 1:06 pm

Re: DS18B20

Post by libelium-dev » Wed Aug 30, 2017 9:32 am

Hi,

OneWire library (used to read the DS18B20 sensor) is very sensitive, changes of microseconds inside it can affect. We did a slight change in the delayMicroseconds() function in order to it will be more accurate.

You can try changing the current function for

Code: Select all

void delayMicroseconds(unsigned int us)
{
	// make conversion to simulate a 8MHz clock
	unsigned int us_aux = us;
	
	if( us > 150)
	{
		us_aux*=1.8;
	}
	else
	{
		us_aux*=2;
	}
	...
	...
Regards

luukh
Posts: 31
Joined: Mon Mar 09, 2015 9:29 pm
Location: Arcadia, Australia
Contact:

Re: DS18B20

Post by luukh » Thu Aug 31, 2017 2:30 am

Hi Dev,

I changed the code to the one you suggested. This change works too (of course). Ie. Libelium's change applies the proposed change by Chris for smaller microsec values, however still provides better accuracy for larger microsec values.

Thanks,
Luuk

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest