ATSAMD21G18A One wire library

Go To Last Post
10 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello, I'm using the ds18B20 with ATSAMD21G18A. All examples I can see use the one wire library. Is there any equivalent for SAMD boards? If not how would I go about creating my own one wire library, any tips on where to start?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

In my experience, the easiest and most reliable approach is to use a 1-Wire master IC like the DS2482. It is possible to implement a 1-Wire master without a dedicated 1-Wire master chip though.

 

In order to get reliable 1-Wire communication you will need some external components even if you don't use a dedicated 1-Wire master. In particular, the DS18B20 requires a stronger pull-up than more basic 1-Wire devices as it requires extra current to take a temperature reading or program the EEPROM. See this tutorial for more details on 1-Wire devices that require extra power.

 

This tutorial describes how to use a UART to implement a 1-Wire master. It includes some example designs for the required hardware which can range from a single resistor between the TX and RX pins (possibly not sufficient to supply the current for the DS18B20) to implementing a discrete open drain buffer. If you need a particularly long distance 1-Wire link, this tutorial discusses some of the details you will need to consider and has an appendix that offers some alternative driver circuit implementations. If you want to get really fancy there is a reference design here for a more advanced driver design.

 

If you don't want to use a UART, it is also possible to implement 1-Wire in software. Maxim has an application note describing how it can be accomplished, including some example code, here.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

wildernessbagel wrote:
the (sic) one wire library

I'm sure there are many 1-Wire libraries - which one, specifically, are you referring to?

 

Maxim give you source code - all you have to do is add your specific timing function.

 

See https://www.avrfreaks.net/commen... for key documents ...

 

samueldewan wrote:
DS18B20 requires a stronger pull-up than more basic 1-Wire devices as it requires extra current to take a temperature reading

Only if you're running it in the so-called Parasite Power mode?

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the detailed response, i really appreciate the resources you provided, hopefully that will be enough. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I meant this library I tried to use it as a base and translate it to code compatible with SAMD21. Is something like that even possible without rewritting the whole thing? Btw any ideas where to find PIN_TO_BITMASK(pin); PIN_TO_BASEREG(pin); they are both defined in OneWire_direct_gpio.h as (portInputRegister(digitalPinToPort(pin))) and (digitalPinToBitMask(pin)) but this is where the trail ends and i can't figure out what they are supposed to do. If you guys think it's better to start anew using this code as a base I'll go down that road. 
 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

wildernessbagel wrote:
I meant this library

So PJRC ?

 

https://www.pjrc.com/about/about_us.html

 

have you tried asking them: https://forum.pjrc.com/ ?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I haven't but now I will :D thanks for the info.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok so I got a bit of help over on the other forum however I'm still doing something wrong. 

 

This is the original code I'm trying to change. 

void OneWire::begin(uint8_t pin)
{
	pinMode(pin, INPUT);
	bitmask = PIN_TO_BITMASK(pin);
	baseReg = PIN_TO_BASEREG(pin);
#if ONEWIRE_SEARCH
	reset_search();
#endif
}

Here are the definitions for SAMD21 for PIN_TO_BITMASK and PIN_TO_BASEREG.
 

#define PIN_TO_BASEREG(pin)             portModeRegister(digitalPinToPort(pin))
#define PIN_TO_BITMASK(pin)             (digitalPinToBitMask(pin))

And finally this is defined as: 

#define digitalPinToPort(P)      (&(PORT->Group[g_APinDescription[P].ulPort]))
#define digitalPinToBitMask(P)   (1 << g_APinDescription[P].ulPin)

I changed the code to look like this: 

#define digitalPinToPort(P)      (&(PORT->Group[0]))
#define digitalPinToBitMask(P)   (1 << 8)
//#define analogInPinToBit(P)    ()
#define portOutputRegister(port) (&(port->OUT.reg))
#define portInputRegister(port)  (&(port->IN.reg))
#define portModeRegister(port)   (&(port->DIR.reg))

#define PIN_TO_BASEREG(pin)             portModeRegister(digitalPinToPort(pin))
#define PIN_TO_BITMASK(pin)             (digitalPinToBitMask(pin))


#define IO_REG_TYPE uint32_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
#define DIRECT_READ(base, mask)         (((*((base)+8)) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask)   ((*((base)+1)) = (mask))
#define DIRECT_MODE_OUTPUT(base, mask)  ((*((base)+2)) = (mask))
#define DIRECT_WRITE_LOW(base, mask)    ((*((base)+5)) = (mask))
#define DIRECT_WRITE_HIGH(base, mask)   ((*((base)+6)) = (mask))
#define pgm_read_byte(addr) (*(const uint8_t *)(addr))


void OneWire::begin(uint8_t pin)
{
	PORT->Group[0].DIRCLR.reg = (1 << pin);									// set pin as input
	bitmask = PIN_TO_BITMASK(pin);
	baseReg = PIN_TO_BASEREG(pin);
}

So I hardcoded #define digitalPinToPort(P) (&(PORT->Group[0])) and #define digitalPinToBitMask(P) (1 << 8) to pin 8 since that's the data pin I am using, I'll try to make it more modular however I just want to get it working first. Are there any obvious mistakes? 
 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You haven't said what problem(s) you're having with that code.

 

What debugging have you done to see what's going on?

 

Do you have an oscilloscope to see what's happening on the wire?

 

A nice feature of 1-WireTM is that the timing between bits (timeslots) is not critical - so you can break at the end of a bit to look at the timing, etc, without breaking the comms ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok so I got a scope and an arduino Uno to test the sensor. When I use arduino the code works and I have the following data on the scope (I tried uploading a picture but I can't the data is not that relevant anyways tho). 

However when I run my version of the code the pin only stays high and only sometimes (maybe for half a second) the correct data is shown.

I figured out that in the first code I posted, I wasn't setting the pin as input correctly. It should have been done like this: 
 

PORT->Group[0].PINCFG[pin].reg=(uint8_t)(PORT_PINCFG_INEN) ;
PORT->Group[0].DIRCLR.reg = (uint32_t)(1<< pin);

Now the code can't find the sensor, when I use the function from the Arduino-Temperature-Control-Library

sensors.getTempCByIndex(0);

I get 0 and it should be 1 (on arduino uno it works correctly).
The only things I'm not sure about are their nointerrupts functions which are defined as: 

#define noInterrupts() {portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;portENTER_CRITICAL(&mux)
#define interrupts() portEXIT_CRITICAL(&mux);}

insted of this I simply used: 
 

#define interrupts()    __enable_irq()
#define noInterrupts()  __disable_irq()

Outside of this I think I changed everything to be compatible with SAMD21 correctly.