Arduino Forum

Products => Arduino Due => Topic started by: alvesjc on Jan 06, 2013, 04:03 am

Title: OneWire in Due
Post by: alvesjc on Jan 06, 2013, 04:03 am
Hi.

I've been porting the onewire lib to work in Due.

I've it working well in my program, but would be nice if some more people would test it also.

Library is attached.

I've built a test sketch with the function I'm using to read the temperature. Sketch as follows:

Code: [Select]

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

#include <OneWire.h>

OneWire  ds(54);  // data bus on pin A0

//DS18B20
float celsius;
unsigned int raw_temp;
boolean conversioninprogress=false;
byte data[12];
byte addr[8];
unsigned long tempconvmillis;
unsigned long waitforesultmillis;

float read_temp()
{
  if (!conversioninprogress)
  {
    ds.reset();
    delay(1);
    ds.skip();
    delay(1);
    ds.write(0x44,0);         // start conversion, with parasite power off at the end
    conversioninprogress=true;
    waitforesultmillis=millis();
  }
 
  if (((millis()-waitforesultmillis) > 1000) && conversioninprogress) 
  // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
  {
    byte i;
    byte present = 0;
    present = ds.reset();
    delay(1);
    ds.skip();
    delay(1);   
    ds.write(0xBE,0);         // Read Scratchpad
   
    delay(1);
   
    for ( i = 0; i < 9; i++) {           // we need 9 bytes
      data[i] = ds.read();
    }
    // convert the data to actual temperature
 
    raw_temp = (data[1] << 8) | data[0];
   
    unsigned char t_mask[4] = {0x7, 0x3, 0x1, 0x0};
    byte cfg = (data[4] & 0x60) >> 5;
    raw_temp &= ~t_mask[cfg];
 
    conversioninprogress=false;
    celsius = (float)raw_temp / 16.0;
  }
  tempconvmillis=millis();
  return celsius;
}
void setup()
{
  Serial.begin(115200);
}
void loop()
{
  if ((millis()-tempconvmillis) > 2000)
  Serial.println(read_temp());
}


Regards,

Joao
Title: Re: OneWire in Due
Post by: kcore on Jan 08, 2013, 06:05 am
alvesjc,

I tried the library but wasn't able to get it working with my DS18B20 and my Due.  In the serial monitor after dropping your library in the Arduino\Libraries folder I ran you sketch and get the following:

4095.94
4095.94
4095.94
4095.94

If I hold the temp sensor with my finger the numbers don't change a bit, which they obviously should.

I have it wired like the following on my Due but with the data line going to Due line A0 to the middle of the DS18B20 and a 4.7k resistor going from the middle pin to the 5v line.

Sorry bud, I really want this library to work because it's one of the only hold backs keeping me from using the Due instead of the Uno/Leonardo which I have verified good working code on.
(http://dangerousprototypes.com/wp-content/media/2011/07/DS18S20-Arduino-300x177.png)
Title: Re: OneWire in Due
Post by: alvesjc on Jan 08, 2013, 12:17 pm
Hi Kcore.

Thank you for testing.

It's working already for me and one coleague, what IDE are you using? We are bought using testing IDE compiled from git.

One thing important I forgot to mention, and is related to IDE version. This lib is set to use ODSR register, meaning this, that you MUST have OWER register set to 1.

This has been fixed in the IDE currently in git, can you compile it and repeat the test please?

There is also other way, in onewire.h, you have the following code for SAM3x.

Code: [Select]

#elif defined(__SAM3X8E__)
#define PIN_TO_BASEREG(pin)             (&(digitalPinToPort(pin)->PIO_PER)) //to get Base PORT address
#define PIN_TO_BITMASK(pin)             (digitalPinToBitMask(pin))
#define IO_REG_TYPE uint32_t
#define IO_REG_ASM
#define DIRECT_READ(base, mask)         (((*(base+15)) & (mask)) ? 1 : 0) /*(Pio Offset: 0x003C) Pin Data Status Register */
#define DIRECT_MODE_INPUT(base, mask)   ((*(base+5)) = (mask)) /*(Pio Offset: 0x0014) Output Disable Register */
#define DIRECT_MODE_OUTPUT(base, mask)  ((*(base+4)) = (mask)) /*(Pio Offset: 0x0010) Output Enable Register */
#define DIRECT_WRITE_LOW(base, mask)    ((*(base+14)) &= ~(mask)) /*(Pio Offset: 0x0038) Output Data Status Register */
#define DIRECT_WRITE_HIGH(base, mask)   ((*(base+14)) |= (mask)) /*(Pio Offset: 0x0038) Output Data Status Register */
//#define DIRECT_WRITE_LOW(base, mask)    ((*(base+13)) = (mask)) /*(Pio Offset: 0x0034) Clear Output Data Register */
//#define DIRECT_WRITE_HIGH(base, mask)   ((*(base+12)) = (mask)) /*(Pio Offset: 0x0030) Set Output Data Register */
#include "pgmspace.h"


Replace it with the following lines:

Code: [Select]

#define DIRECT_WRITE_LOW(base, mask)    ((*(base+14)) &= ~(mask)) /*(Pio Offset: 0x0038) Output Data Status Register */
#define DIRECT_WRITE_HIGH(base, mask)   ((*(base+14)) |= (mask)) /*(Pio Offset: 0x0038) Output Data Status Register */
//#define DIRECT_WRITE_LOW(base, mask)    ((*(base+13)) = (mask)) /*(Pio Offset: 0x0034) Clear Output Data Register */
//#define DIRECT_WRITE_HIGH(base, mask)   ((*(base+12)) = (mask)) /*(Pio Offset: 0x0030) Set Output Data Register */


with:

Code: [Select]

//#define DIRECT_WRITE_LOW(base, mask)    ((*(base+14)) &= ~(mask)) /*(Pio Offset: 0x0038) Output Data Status Register */
//#define DIRECT_WRITE_HIGH(base, mask)   ((*(base+14)) |= (mask)) /*(Pio Offset: 0x0038) Output Data Status Register */
#define DIRECT_WRITE_LOW(base, mask)    ((*(base+13)) = (mask)) /*(Pio Offset: 0x0034) Clear Output Data Register */
#define DIRECT_WRITE_HIGH(base, mask)   ((*(base+12)) = (mask)) /*(Pio Offset: 0x0030) Set Output Data Register */


This way you will be using CODR and SODR to clear and set the bit in the port. This is independent of OWER, and probably solve your problem.

Can you test it again please?

Unfortunately, I have burned my Due yesterday with a electrical hazard, and I can't do any more testes meanwhile...

Thank you.

BR,

Joao
Title: Re: OneWire in Due
Post by: kcore on Jan 09, 2013, 06:35 am
alvesjc,

I'm running my Due with arduino-1.5.1r2 on Windows.

I modified the OneWire.h file like you said it seems to work now.  I'm getting the following in the serial window:

Code: [Select]
0.00
24.94
24.94
24.94
24.94
26.87
26.87
30.19
30.19
31.44
31.44
32.06
32.06


Those numbers are when I was just touching the DS18B20 with my finger so they look about right to me.

I did notice I wasn't able to get valid temps from the example that I'm using below.  It's from the examples folder in the library you uploaded, any idea why?

Code: [Select]
#include <OneWire.h>

// OneWire DS18S20, DS18B20, DS1822 Temperature Example
//
// http://www.pjrc.com/teensy/td_libs_OneWire.html
//
// The DallasTemperature library can do all this work for you!
// http://milesburton.com/Dallas_Temperature_Control_Library

OneWire  ds(54);  // on pin 54 which is A0 for the Arduino Due

void setup(void) {
  Serial.begin(9600);
}

void loop(void) {
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;
 
  if ( !ds.search(addr)) {
    Serial.println("No more addresses.");
    Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }
 
  Serial.print("ROM =");
  for( i = 0; i < 8; i++) {
    Serial.write(' ');
    Serial.print(addr[i], HEX);
  }

  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
      return;
  }
  Serial.println();

  // the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
      Serial.println("  Chip = DS18S20");  // or old DS1820
      type_s = 1;
      break;
    case 0x28:
      Serial.println("  Chip = DS18B20");
      type_s = 0;
      break;
    case 0x22:
      Serial.println("  Chip = DS1822");
      type_s = 0;
      break;
    default:
      Serial.println("Device is not a DS18x20 family device.");
      return;
  }

  ds.reset();
  ds.select(addr);
  ds.write(0x44,1);         // start conversion, with parasite power on at the end
 
  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
 
  present = ds.reset();
  ds.select(addr);   
  ds.write(0xBE);         // Read Scratchpad

  Serial.print("  Data = ");
  Serial.print(present,HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  Serial.print(" CRC=");
  Serial.print(OneWire::crc8(data, 8), HEX);
  Serial.println();

  // convert the data to actual temperature

  unsigned int raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // count remain gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    if (cfg == 0x00) raw = raw << 3;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
    // default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0;
  Serial.print("  Temperature = ");
  Serial.print(celsius);
  Serial.print(" Celsius, ");
  Serial.print(fahrenheit);
  Serial.println(" Fahrenheit");
}


In the serial output window I get the following:

Quote
ROM = 28 6B C7 49 3 0 0 C1
  Chip = DS18B20
  Data = 1 FF FF FF FF FF FF FF FF FF  CRC=C9
  Temperature = 4095.94 Celsius, 7404.69 Fahrenheit
No more addresses.


Touching the sensor doesn't do anything and the numbers for Celsius and Fahrenheit don't change - They look a little bit hot to me...  :smiley-roll-sweat:

Let me know, I can do more testing for you and hopefully we can get a working library that everyone can run.  Thanks for your help.
Title: Re: OneWire in Due
Post by: alvesjc on Jan 09, 2013, 08:58 pm
Hi Kcore.

Thank you for your time testing.

Ok, those are good news!

This leaves me more confident. I Had to tweak the timings in read and write timeslots, and I was affraid that i might be just tweaking the lib for my own probes or probe cable length, etc.

That proves the opposite.

Regarding the original example, I have the same problem, I only get FFFFF. I don't have any clue about that, but I suspect that might be something about the probe discovery process. In my test, I just skip that, because I'm addressing only one prob.

I've left that aside to first conclude if the actual code work with every prob.

We are now 3 with working due with onewire.

Unfortunately, I can't continue to test why it doesn't work with example, has i told before, I've accidentally burned my due...

My suggestion now, is to transport the discovery process to the function that works and test it( and removing ds.skip() ).

If more people joins this effort, maybe we can get to a final library faster.

My test function was first built a very long time ago based on that example, it should work...

Let us know if you move forward with this! ;)

Regards,

João
Title: Re: OneWire in Due
Post by: mantoui on Jan 10, 2013, 06:43 pm
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

Code: [Select]

    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
Title: Re: OneWire in Due
Post by: alvesjc on Jan 10, 2013, 07:08 pm
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.



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! ;)
Title: Re: OneWire in Due
Post by: mantoui on Jan 10, 2013, 07:12 pm
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.
Title: Re: OneWire in Due
Post by: alvesjc on Jan 10, 2013, 07:22 pm
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
Title: Re: OneWire in Due
Post by: mantoui on Jan 10, 2013, 07:29 pm
my select() in OneWire.cpp follows.  I'll let you be master of your library source.  thanks

Code: [Select]

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
    }
}


Title: Re: OneWire in Due
Post by: AWOL on Jan 10, 2013, 07:34 pm
Code: [Select]
void OneWire::select( uint8_t rom[8])
{
    int i;  // overkill
...
    for( i = 0; i < 8; i++) {
}
Title: Re: OneWire in Due
Post by: alvesjc on Jan 10, 2013, 07:34 pm
Ok, thanks.

I'll ask my friend to test this also. ;)

regards,

Joao
Title: Re: OneWire in Due
Post by: alvesjc on Jan 10, 2013, 07:36 pm

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



Sorry, I don't understand what you mean!
Title: Re: OneWire in Due
Post by: mantoui on Jan 11, 2013, 02:20 am
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.

Code: [Select]

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
}
Title: Re: OneWire in Due
Post by: kcore on Jan 11, 2013, 03:53 am
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.
Title: Re: OneWire in Due
Post by: pjrc on Jan 11, 2013, 11:09 am
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?

Title: Re: OneWire in Due
Post by: AWOL on Jan 11, 2013, 11:28 am
Quote
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.
Title: Re: OneWire in Due
Post by: alvesjc on Jan 11, 2013, 01:15 pm

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.

Code: [Select]

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...
Title: Re: OneWire in Due
Post by: alvesjc on Jan 11, 2013, 01:17 pm

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!!!
Title: Re: OneWire in Due
Post by: alvesjc on Jan 11, 2013, 01:23 pm

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?




Hi!

Glad you're back! ;)

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
Title: Re: OneWire in Due
Post by: alvesjc on Jan 11, 2013, 01:24 pm

Quote
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
Title: Re: OneWire in Due
Post by: mantoui on Jan 11, 2013, 02:02 pm
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.

Code: [Select]

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;
}
Title: Re: OneWire in Due
Post by: alvesjc on Jan 11, 2013, 02:04 pm
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. ;)
Title: Re: OneWire in Due
Post by: pjrc on Jan 11, 2013, 04:57 pm

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


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.
Title: Re: OneWire in Due
Post by: alvesjc on Jan 11, 2013, 05:39 pm
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
Title: Re: OneWire in Due
Post by: kcore on Jan 11, 2013, 09:39 pm
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.

Code: [Select]
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.
Title: Re: OneWire in Due
Post by: pjrc on Jan 11, 2013, 09:43 pm
Does Due have a tone() function yet?  If so, please output an infinite duration 15 kHz tone on a pin during the test.
Title: Re: OneWire in Due
Post by: alvesjc on Jan 11, 2013, 10:25 pm

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.
Title: Re: OneWire in Due
Post by: mantoui on Jan 11, 2013, 10:38 pm


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.


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

 
Title: Re: OneWire in Due
Post by: pjrc on Jan 17, 2013, 08:47 pm
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).

Quote

#include <OneWire.h>

OneWire  ds(10);  // on pin 10

void setup() {
}

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


Here is the actual waveform:

(http://www.pjrc.com/teensy/beta/arduino_due_timing_bug.png)

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.

(http://www.pjrc.com/teensy/beta/arduino_due_timing_bug2.png)

Both of the zero bits have a 65 us wide low pulse.
Title: Re: OneWire in Due
Post by: pjrc on Jan 18, 2013, 12:43 am
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!
Title: Re: OneWire in Due
Post by: alvesjc on Jan 18, 2013, 01:54 am
Unfortunatly, can't test it... argh...
Title: Re: OneWire in Due
Post by: kcore on Jan 24, 2013, 03:17 am
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:

Quote
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:

Quote
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

Quote
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
Title: Re: OneWire in Due
Post by: PaulMcMillan on Feb 03, 2013, 06:03 am
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:

Code: [Select]

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)
Title: Re: OneWire in Due
Post by: pjrc on Feb 06, 2013, 01:37 am

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:


Did you try compiling on Arduino 1.5.1?

Maybe you can copy whatever's ADK2012 is missing from Arduino 1.5.1?

Of course, without fixing delayMicroseconds(), it's unlikely to work reliably.
Title: Re: OneWire in Due
Post by: brendon_lecomte on Feb 10, 2013, 06:43 am
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
Title: Re: OneWire in Due
Post by: leonid_leonid on Feb 11, 2013, 01:50 pm
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 (http://arduino.cc/forum/index.php?topic=147531.0 (http://arduino.cc/forum/index.php?topic=147531.0)) 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.
Title: Re: OneWire in Due
Post by: leonid_leonid on Feb 12, 2013, 03:26 pm
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():
Code: [Select]

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
Title: Re: OneWire in Due
Post by: pjrc on Feb 12, 2013, 04:29 pm
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.
Title: Re: OneWire in Due
Post by: leonid_leonid on Feb 13, 2013, 10:13 am

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):
Code: [Select]

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.
Title: Re: OneWire in Due
Post by: Markus_L811 on Feb 13, 2013, 11:40 am


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):
Code: [Select]

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.


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

Code: [Select]
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
Title: Re: OneWire in Due
Post by: leonid_leonid on Feb 13, 2013, 03:03 pm


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:
Code: [Select]

#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().
Title: Re: OneWire in Due
Post by: cmaglie on Feb 13, 2013, 03:55 pm

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)

https://github.com/arduino/Arduino/commit/7f7637c782fc0c028f0539d27b99f930ee30baa5

@leonid_leonid
sorry, I didn't looked at the forum thread with your implementation!
Title: Re: OneWire in Due
Post by: alvesjc on Mar 14, 2013, 03:15 pm
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.
Title: Re: OneWire in Due
Post by: Kuya Marc on Apr 01, 2013, 07:05 am
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 (http://www.element14.com/community/blogs/mirandasoft/2013/03/28/arduino-mega-2560-digital-temperature-using-ds18b20-and-7-segment-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.
Title: Re: OneWire in Due
Post by: pjrc on Apr 01, 2013, 09:47 am
Your best chance is OneWire 2.2 with the latest nightly build of Arduino.
Title: Re: OneWire in Due
Post by: Markus_L811 on Apr 18, 2013, 10:13 am

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.
Title: Re: OneWire in Due
Post by: DominicG on Sep 12, 2013, 06:11 pm
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
Title: Re: OneWire in Due
Post by: pjrc on Sep 12, 2013, 09:58 pm
It definitely was working in 1.5.2 and the github code in late February (2013).
Title: Re: OneWire in Due
Post by: DominicG on Oct 08, 2013, 10:22 pm
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
Title: Re: OneWire in Due
Post by: pjrc on Oct 08, 2013, 10:28 pm
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.
Title: Re: OneWire in Due
Post by: DominicG on Oct 08, 2013, 10:38 pm
Thank you for your quick reply Paul!

Dominic
Title: Re: OneWire in Due
Post by: armandohg on Dec 14, 2013, 08:05 pm
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!  :)
Title: Re: OneWire in Due
Post by: omkardokur on Sep 10, 2014, 08:26 pm
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