OneWire in Due

Is there any way to fix to the delayMicroseconds() issue? or is this something we have to hope the folks at arduino will fix for us? I am using the Ds18b20's for a brewery system and have moved to the due recently and don't want to backtrack to change the sensors

Hi all,

I tried the the OneWire 2.2 with IDE 1.5.1r2. Two of four DS1820 sensors give me no readings ("No more addresses" in the DS18x20 Example sketch), the other two produce no valid temperature readings:

ROM = 10 D1 A2 54 2 8 0 57
  Chip = DS18S20
  Data = 1 FF FF FF FF FF FF FF FF FF  CRC=C9
  Temperature = -0.50 Celsius, 31.10 Fahrenheit

It is probably the delayMicroseconds problem Paul mentioned in his post.

With the new IDE 1.5.2 (Arduino Forum) all four sensors are unable to be read ("No more addresses").
It's kind of weird...

Have someone else tried 1.5.2 with OneWire yet?

Leo

Update: the OneWire Library with changes by alvesjc and mantoui works with both 1.5.1r2 and 1.5.2. I'm able to read all 4 sensors.

Hi Paul,

I just finished diff-and-try session with the library version OneWire_preview22_17jan13.zip and the version from this thread (with changes by alvesjc and mantoui).
The critical point seems to be the write_bit() function and the interrupt handling combined with delayMicroseconds() calls in this function (both have been mentioned in this thread already).
As soon as I excluded delayMicroseconds calls from noInterrupts()/interrupts() sections in the write_bit() function, the library worked.

Here is the changed version of write_bit():

void OneWire::write_bit(uint8_t v)
{
	IO_REG_TYPE mask=bitmask;
	volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg;

	if (v & 1) {
		noInterrupts();
		DIRECT_WRITE_LOW(reg, mask);
		DIRECT_MODE_OUTPUT(reg, mask);	// drive output low
		interrupts();
		delayMicroseconds(10);
		noInterrupts();
		DIRECT_WRITE_HIGH(reg, mask);	// drive output high
		interrupts();
		delayMicroseconds(55);
	} else {
		noInterrupts();
		DIRECT_WRITE_LOW(reg, mask);
		DIRECT_MODE_OUTPUT(reg, mask);	// drive output low
		interrupts();
		delayMicroseconds(65);
		noInterrupts();
		DIRECT_WRITE_HIGH(reg, mask);	// drive output high
		interrupts();
		delayMicroseconds(5);
	}
}

It's the only change I made on the library.

I'm running a test with all the sensors installed in my house heating control, I have 9 DS1820 for temperature sensing and some DS2408 and DS2413 for relay switching.
All of them are working (so far) as they usually do with my old Arduino Mega. I'll post test results tomorrow.

Leo

Interrupts are disabled for a very good reason. There's absolutely no way OneWire will return to the buggy pre-2.0 days where interrupts could lengthen the timing and cause random communication errors.

Ok, I understand that (I do know what are interrupts for and why they are disabled in time critical sections). I do not understand why delayMicroseconds acts differently depending on interrupts being disabled or enabled. Declaration of delayMicrosections for SAM is quite simple (from wiring.c):

void delayMicroseconds( uint32_t us )
{
    uint32_t start = micros();
    while ((micros() - start) < us)
        ;
}

It did not change since 1.5.1r2.

Do you have an idea, what the solution could be?

Leo

PS if I can contribute in any way, let me know.

leonid_leonid:

[quote author=Paul Stoffregen link=topic=141030.msg1115802#msg1115802 date=1360682994]
Interrupts are disabled for a very good reason. There's absolutely no way OneWire will return to the buggy pre-2.0 days where interrupts could lengthen the timing and cause random communication errors.

Ok, I understand that (I do know what are interrupts for and why they are disabled in time critical sections). I do not understand why delayMicroseconds acts differently depending on interrupts being disabled or enabled. Declaration of delayMicrosections for SAM is quite simple (from wiring.c):

void delayMicroseconds( uint32_t us )
{
    uint32_t start = micros();
    while ((micros() - start) < us)
        ;
}

It did not change since 1.5.1r2.

Do you have an idea, what the solution could be?

Leo

PS if I can contribute in any way, let me know.
[/quote]

So the problem must be somewhere behind the micros the function delayMicroseconds is realy open so the problem musst be somewhere there

 uint32_t micros( void )
{
uint32_t ticks ;
uint32_t count ;

SysTick->CTRL;
do {
  ticks = SysTick->VAL;
  count = GetTickCount();
} while (SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk);

return count * 1000 + (SysTick->LOAD + 1 - ticks) / (SystemCoreClock/1000000) ;
}

its in the wiring.c

Markus_L811:
So the problem must be somewhere behind the micros the function delayMicroseconds is realy open so the problem musst be somewhere there

Right, micros() must have a problem with noInterrupts().

I tried to change delayMicroseconds() to make it independent from micros(). Here is the code:

#define CYCLES_PER_USEC 84 // Arduino Due has 84 MHz clock
#define CYCLES_PER_LOOP 6  // one iteration of the loop takes 6 cycles
#define OVERHEAD_CONST 18  // could someone with an osci please verify this constant?
void delayMicroseconds( uint32_t us )
{
  if(us==1) return;
  int j;
  //one iteration of this loop takes 6 cycles on Arduino Due compiled with IDE 1.5.2
  for(j=0;j<us*(CYCLES_PER_USEC/CYCLES_PER_LOOP)-OVERHEAD_CONST;j++)
  {
    asm volatile("mov r0, r0"); // just NOP 
    asm volatile("mov r0, r0");  
  }
}

This change worked with the original version of OneWire (OneWire_preview22_17jan13.zip)

This patch is not pretty but it proves that the problem is in the micros().

Tomorrow I'll try to understand, why micros() has a problem with noIterrupts().

Thank you all, guys, for debugging this one.

I've pushed a patch that makes delayMicrosecond() independent from micros().

Paul, I've borrowed the implementation from the Teensy core, if you don't mind!
I've only slightly changed it:

  • the "bne" instruction to "bge" to allow delays of 0uS
  • changed the calculation of "n" (multiply seems to use 1 cycle as the shift and
    makes the formula generic)

@leonid_leonid
sorry, I didn't looked at the forum thread with your implementation!

Hi all.

I'm back in Due.

I've compiled IDE from the latest info in Git, so I'll give a try on the latest lib from Paul later today.

Hello World!

Sometime today, I'll be receiving my Arduino Due, and one of my active Arduino projects is using OneWire. After reading through all of the posts, I'm confused on what to do with my current OneWire library. Should I patch it, replace it, or make a new OneWire library parallel to the current one I'm using?

My Project: Arduino Mega 2560: Digital Temperature using DS18B20 and 7-Segments LEDs

I've removed the serial debugging code and simplified my sketch that works on my Arduino Mega 2560 clone.

From this Forum, I've downloaded OneWire.zip and OneWire_preview22_17jan13.zip.

Your best chance is OneWire 2.2 with the latest nightly build of Arduino.

Yes that works just changing a few files and the new OneWire lib from Paul and the Due is working correctly.

As discussed earlier in this thread, the delayMicroseconds() function does not work correctly with interrupts disabled in IDE version 1.5.2.

Since the last post several months ago, IDE versions 1.5.3 and 1.5.4 have been released, and supposedly the delayMicroseconds() function was corrected for version 1.5.3.

I have just tried using both versions 1.5.3 and 1.5.4, but now the OneWire library no longer works. The first step for data transfer, the reset signaled by pulling the line low, is not occurring. Looking at the signal on an oscilloscope I can confirm that the line is never pulled low. It seems like the DIRECT_WRITE_LOW function is no longer working.

Anybody know why? Seems like there must have been some library changes in version 1.5.3 that broke this functionality.

Thanks,

Dominic

It definitely was working in 1.5.2 and the github code in late February (2013).

Paul,
I tried downloading the "nightly build" from the Arduino website download page, but that seems to be the latest available nightly build.

Is there a way that I can download the old nightly builds from February?

Thanks,

Dominic

Yes, it's possible to use git to obtain the source from any point in Arduino's history. You'll only get the source code, so you'll need to build it yourself (easy on Linux & Mac, requires setting up lots of stuff for Windows).

I'm not an expert with git & github. You'll need to look for info online (there is a lot of info on may sites), or find someone who's more knowledgeable about git to help you.

Thank you for your quick reply Paul!

Dominic

Just wanted to let everyone in this thread know that it is working great for me!

I am using Arduino 1.5.5 IDE under Mac OS X
Using OneWire_preview22_17jan13.zip library

Thanks guys! :slight_smile:

Dear Dominic ,

I appreciate what you have done. I was trying to find the SdFatHsmci library zip. I was unable to find library in github or here.

Please let us know where we can download that library.

Thanks