OneWire in Due

I tested your lib and sketch on linux with IDE 1.5.1 (didn't compile with 1.5). I edited OneWire.h as suggested. Sketch worked. Also tested with no delay(1); -- still worked.

I tested the Examples>OneWire>DS18x20_Temperature. It would work if I replaced ds.select(addr); with ds.skip(); With delay(1);'s it worked each query. With no delay(1); every other query would return Data with FFs

     ROM = 28 86 42 5B 3 0 0 84
        Chip = DS18B20
        Data = 1 82 1 4B 46 7F FF E 10 70  CRC=70
        Temperature = 24.12 Celsius, 75.43 Fahrenheit
        No more addresses.

In a later experiment, I got the Example to work by adding delay(1);'s in the ds.select() function in OneWire.cpp

Hi Mantoui.

Ok, so if I understand right the delays are needed for your usage also, right?

The only way to get stable readings for long run was with that delays. My function worked without them, but it returns FFF from time to time!

With the delays, I had it running for more then 48hours without a failure.

mantoui:
I tested the Examples>OneWire>DS18x20_Temperature. It would work if I replaced ds.select(addr); with ds.skip(); With delay(1);'s it worked each query. With no delay(1); every other query would return Data with FFs

Can you clarify this a bit more?

Thank you for joining! :wink:

your sketch, seemed to work consistently with or without delay(1);

the Examples was bad every other query without the delay(1) using ds.skip()

I got Examples to work by adding delay(1) between every write in the select() function in OneWire.cpp,
and no delay(1) in the Examples sketch

I had also tried delayMicroseconds in select() with no luck, so I switched to delay(1); but presumably something
shorter than a millisecond might work ... sort of hit and miss.

Ok ok, nice.

So I think that this confirms that the DUE is too fast for the probe.

What I just don't understand, is why it works fine with chipkit....

Can you post your changed onewire.cpp here?

maybe we get more people testing your changes.

Thanks

my select() in OneWire.cpp follows. I'll let you be master of your library source. thanks

void OneWire::select( uint8_t rom[8])
{
    int i;

    write(0x55);           // Choose ROM
    delay(1); // thd

    for( i = 0; i < 8; i++) {
        write(rom[i]);
        delay(1);  // thd
    }
}
void OneWire::select( uint8_t rom[8])
{
    int i;  // overkill
...
    for( i = 0; i < 8; i++) {
}

Ok, thanks.

I'll ask my friend to test this also. :wink:

regards,

Joao

AWOL:

void OneWire::select( uint8_t rom[8])

{
    int i;  // overkill
...
    for( i = 0; i < 8; i++) {
}

Sorry, I don't understand what you mean!

I rewrote write_bit() in OneWire.cpp to match (more or less) what was working on the maple. This seems to work for me without any delay(1);! Works on both the little ds18b20 sketch and the Examples>OneWire>DS18x20_temperature.

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_MODE_OUTPUT(reg, mask);	// drive output low
		DIRECT_WRITE_LOW(reg, mask);
		delayMicroseconds(5);
//		DIRECT_WRITE_HIGH(reg, mask);	// drive output high
		DIRECT_MODE_INPUT(reg, mask);	// let pin float, pull up will raise
		delayMicroseconds(60);
		//interrupts();
	} else {
		//noInterrupts();
		DIRECT_MODE_OUTPUT(reg, mask);	// drive output low
		DIRECT_WRITE_LOW(reg, mask);
		delayMicroseconds(60);
		DIRECT_MODE_INPUT(reg, mask);	// let pin float, pull up will raise
		//DIRECT_WRITE_HIGH(reg, mask);	// drive output high
		//interrupts();
	}
	delayMicroseconds(10); // 10uSec recovery time
}

Great job gentlemen!

I combined mantoui's updated OneWire::write_bit function along with the changes made by alvesjc and I'm now able to run the DS18x20_Temperature right out of the box.

This effort should go a long way in getting other people moved over to the Due because so many projects have requirements to read temperatures and interact with other one wire devices.

Thanks for all your help in getting this working.

I've put all the stuff in a zip file for others to test without having to edit the files.

OneWire.zip (14.9 KB)

I'd like to merge this change into OneWire.

I'm current the de-facto maintainer of OneWire, but only because it was essentially abandoned when I picked it up and fixed the many bugs. If anyone else really wants the position, it's open....

Long-term, is the ODSR (presumably will work starting with 1.5.2) or CODR and SODR approach the best way?

Quote from: AWOL on 10-01-2013, 19:34:01
Code:

void OneWire::select( uint8_t rom[8])
{
int i; // overkill
...
for( i = 0; i < 8; i++) {
}

Sorry, I don't understand what you mean!

Using a sixteen bit variable to count to eight is overkill.
Use "char" or "byte" - you'll save precious space.

mantoui:
I rewrote write_bit() in OneWire.cpp to match (more or less) what was working on the maple. This seems to work for me without any delay(1);! Works on both the little ds18b20 sketch and the Examples>OneWire>DS18x20_temperature.

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_MODE_OUTPUT(reg, mask); // drive output low
DIRECT_WRITE_LOW(reg, mask);
delayMicroseconds(5);
// DIRECT_WRITE_HIGH(reg, mask); // drive output high
DIRECT_MODE_INPUT(reg, mask); // let pin float, pull up will raise
delayMicroseconds(60);
//interrupts();
} else {
//noInterrupts();
DIRECT_MODE_OUTPUT(reg, mask); // drive output low
DIRECT_WRITE_LOW(reg, mask);
delayMicroseconds(60);
DIRECT_MODE_INPUT(reg, mask); // let pin float, pull up will raise
//DIRECT_WRITE_HIGH(reg, mask); // drive output high
//interrupts();
}
delayMicroseconds(10); // 10uSec recovery time
}

Ok, nice!!!

I had something similar, but without the 10 uSec in the end. Unfortunatly I can't test it... arghh...

kcore:
Great job gentlemen!

I combined mantoui's updated OneWire::write_bit function along with the changes made by alvesjc and I'm now able to run the DS18x20_Temperature right out of the box.

This effort should go a long way in getting other people moved over to the Due because so many projects have requirements to read temperatures and interact with other one wire devices.

Thanks for all your help in getting this working.

I've put all the stuff in a zip file for others to test without having to edit the files.

Great great news!!!

Thank you again for joining this ride!!!

Hi!

Glad you're back! :wink:

So many people already complained about onewire, so I thought you're just gone of the Arduino world and took the initiative to try to make this work for everyone in this great new platform.

I has needing this lib for my project, so I started to dig on this.

You're most welcome to include the changes in your git!

Best regards,

Joao

AWOL:

Quote from: AWOL on 10-01-2013, 19:34:01
Code:

void OneWire::select( uint8_t rom[8])
{
int i; // overkill
...
for( i = 0; i < 8; i++) {
}

Sorry, I don't understand what you mean!

Using a sixteen bit variable to count to eight is overkill.
Use "char" or "byte" - you'll save precious space.

Ohh, got it, thank you!

int's in mega are a lot diferent in size from due, but even in mega it's overkill anyway.

Regards,

Joao

Though read_bit() seemed to be working, I modified it as well to match the maple version. The two sketches seemed to work with the slimmer version. NO delay(1)'s required.

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

	DIRECT_MODE_OUTPUT(reg, mask);
	DIRECT_WRITE_LOW(reg, mask);
	delayMicroseconds(5);
	DIRECT_MODE_INPUT(reg, mask);	// let pin float, pull up will raise
	delayMicroseconds(5);
	r = DIRECT_READ(reg, mask);
	delayMicroseconds(60);
	return r;
}

Ok, nice.

But do a long run test, leave it running for a few hours logging to serial.

I' had it running with other timers, but would have failures from time to time, some of them were very spaced in time. :wink:

alvesjc:
I' had it running with other timers, but would have failures from time to time, some of them were very spaced in time. :wink:

I can believe that. Several of the code fragments above have the interrupt disable removed. If an interrupt occurs during a bit read or write, it will lengthen the timing. On ARM, the problem is probably less, because the process is so much faster, especially with interrupt overhead (the context is saved by hardware, utilizing a separate bus, rather than by code in the interrupt routine). This was one of the 2 major bugs before I made version 2.0.

Hi Paul.

They weren't removed, I've disabled the interrupts in start, and enabled again in the end of each function.

You may check the first version published.

Regards,

Joao