OneWire in Due

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

I've been running the OneWire code that I posted in the ZIP file in a previous post for over 12 hours with no errors pulling data from three DS18B20's.

I have not been able to incorporate mantoui's updated read_bit function but I will do that later tonight when I'm home.

ROM = 28 A0 CE 49 3 0 0 55
  Chip = DS18B20
  Data = 1 A3 1 4B 46 7F FF D 10 CE  CRC=CE
  Temperature = 26.19 Celsius, 79.14 Fahrenheit
ROM = 28 F6 C3 49 3 0 0 25
  Chip = DS18B20
  Data = 1 A2 1 4B 46 7F FF E 10 D8  CRC=D8
  Temperature = 26.12 Celsius, 79.03 Fahrenheit
ROM = 28 6B C7 49 3 0 0 C1
  Chip = DS18B20
  Data = 1 A3 1 4B 46 7F FF D 10 CE  CRC=CE
  Temperature = 26.19 Celsius, 79.14 Fahrenheit
No more addresses.

I noticed in the Examples folder there is also a sketch for a DS2408 which is an 8 channel addressable switch. I have a number of those lying around so I may be able to test the sketch later against one and let you know the results.

Does Due have a tone() function yet? If so, please output an infinite duration 15 kHz tone on a pin during the test.

I believe the tone functions are still not ported.

alvesjc:

[quote author=Paul Stoffregen link=topic=141030.msg1067752#msg1067752 date=1357937038]
Does Due have a tone() function yet? If so, please output an infinite duration 15 kHz tone on a pin during the test.

I believe the tone functions are still not ported.
[/quote]

I'm not sure what this has to do with onewire thread, but I have a proof-of-concept tone(), see tone1.ino in

I've been working with OneWire today. I included the #defines for Due.

It seems to work on a couple sensors, but most of my 10 test sensors them do not work. They all respond with a presence pulse, but then return 0xFF for every byte including the checksum.

So I started troubleshooting. I believe I've tracked the problem to a possible bug in delayMicroseconds(). I'm using Arduino IDE 1.5.1.

Here is a very simple test program, which does a reset and then sends a single byte (skip is 0xCC).

#include <OneWire.h>

OneWire ds(10); // on pin 10

void setup() {
}

void loop() {
ds.reset();
ds.skip();
delay(10);
}

Here is the actual waveform:

On the top trace you can see the entire sequence. On the bottom is a zoomed in view of the first 4 bits after the reset. The time scale is 30 us/div. OneWire sends LSB first, so this is two 0s followed by two 1s.

The first 0 bit is incorrect. OneWire called delayMicroseconds(65), but as you can see on the trace, the time was only 30 us. The next zero bit is generated by the exact same code, where the delay actually is 65 us. Well, it's actually closer to 67 us, but a 2 us error is ok. But the first pulse being less than 60 us is not ok. The datasheet says the chip will sample the voltage between 15 to 60 us after the falling edge, so a 30 us pulse works with some chips, but not others (most my 10 test samples apparently sample after 30 us).

Here is the same code, with the same sensor and same oscilloscope setup, running on a Teensy 3.0 board.

Both of the zero bits have a 65 us wide low pulse.

I'm getting ready to publish OneWire 2.2. Here's a preview version:

http://www.pjrc.com/teensy/beta/OneWire_preview22_17jan13.zip

If anyone has any feedback regarding how OneWire 2.2 should look, please speak up ASAP!

Unfortunatly, can't test it... argh...

Paul,

I'm having problems reading from multiple DS18B20's with your 2.2 preview library.

Fresh copy of arduino-1.5.1r2-windows, and downloaded just your 2.2 preview library, and I run the DS18x20_Temperature sketch with three of the DS18B20's attached to Due pin 54 (Analog line 0) and I get the following:

No more addresses.

No more addresses.

No more addresses.

If I pull two of the sensors out it starts returning results although sometimes it returns results like the following:

ROM = 28 F6 C3 49 3 0 0 25
Chip = DS18B20
Data = 0 FF FF FF FF FF FF FF FF FF CRC=C9
Temperature = 4095.94 Celsius, 7404.69 Fahrenheit

or

ROM = 28 F6 C3 49 3 0 0 25
Chip = DS18B20
Data = 1 50 5 4B 46 7F FF C 10 1C CRC=1C
Temperature = 85.00 Celsius, 185.00 Fahrenheit

I'm using the ADK2012 device (with the google-provided IDE), which is very similar to an Arduino Due. When I include the pre-release 2.2 version linked above into a project and compile, I get errors like this:

OneWire.cpp: In constructor 'OneWire::OneWire(uint8_t)':
OneWire.cpp:123: error: base operand of '->' has non-pointer type 'const PinDescription'
OneWire.cpp:124: error: base operand of '->' has non-pointer type 'const PinDescription'

Removing the 2 lines it's complaining about allows it to compile, but unsurprisingly, it doesn't actually work.

I'm new enough to all this that I don't have a good handle on how to get started debugging this. Any ideas?

(I asked this on stackoverflow too: http://stackoverflow.com/q/14669607/114917)