dallas 1 wire.. does it matter which pin I define?

This forum is for posts that might be considered off-topic but that may be useful or interesting to members. Examples include posts about electronics or programming in general, other microcontrollers or interesting devices, useful websites, etc.
Post Reply
cadillackid
Posts: 35
Joined: 22 August 2009, 16:34 PM

dallas 1 wire.. does it matter which pin I define?

Post by cadillackid »

on a ZX-328n does it matter which pin I define as my dallas 1 wire pin? and can I define more than one pin as a 1 wire pin?

I am going to have 3 temperature sensors on the controller... and I know I can chain them, however im trying to make it easy if a sensor goes bad i dont have to deal with code that finds out the new sensor's address, I can just hook it up and go...

if I want to run them parasitically do I just need to set my DQ pin as zxinputtristate after my 1 wire command? or will the ZX release the line after the 1 wire command and the pullup can hold it high for the conversion?
-Christopher
dkinzer
Site Admin
Posts: 3122
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Re: dallas 1 wire.. does it matter which pin I define?

Post by dkinzer »

cadillackid wrote:on a ZX-328n does it matter which pin I define as my dallas 1 wire pin? and can I define more than one pin as a 1 wire pin?
Any I/O pin will work and you can use as many as you wish.
cadillackid wrote:if I want to run them parasitically do I just need to set my DQ pin as zxinputtristate after my 1 wire command?
The 1-wire command will leave the output in zxInputTriState mode so you needn't do anything.

The sample code below may be useful as a starting point. The reported values correlate well with a nearby digital thermometer when the DS18S20 is powered. However, in parasitic mode the reported values seem to be several degrees high. I don't know why this occurs but it could be an issue with the timing.

Code: Select all

' This code is intended for the DS18S20 temperature chip. The
' code assumes the presence of a single device on the 1-wire bus.

Const owPin as Byte = 14  ' the pin to which the DQ line is connected

Sub Main()
  Dim temp as Single
  Do
    temp = readTemp()
    Debug.Print "The temperature is "; Fmt(temp, 1); "*C";
    Debug.Print ", "; Fmt((temp + 40.0) * (9.0 / 5.0) - 40.0, 1); "*F"
    Call Delay(1.0)
  Loop
End Sub

'
'' readTemp
'
' Request a temperature conversion and read the result.  The
' return value is in degrees Centigrade.
'
Function readTemp() as Single
  Dim b as Byte
  Dim data(1 to 9) as Byte

  ' initialize the 1-wire interface (return value is the "presence" bit)
  b = Reset1Wire(owPin)

  Call Delay(0.750)
  ' initiate a conversion
  data(1) = &Hcc    ' "skip ROM" command
  data(2) = &H44    ' conversion command
  Call Put1WireData(owPin, data, 2)
  
  ' delay to allow for the conversion
  Call Delay(0.750)

  ' send another reset pulse
  b = Reset1Wire(owPin)

  ' prepare to read the data
  data(1) = &Hcc    ' "skip ROM" command
  data(2) = &Hbe    ' "read scratchpad" command
  Call Put1WireData(owPin, data, 2)

  ' read the data
  Call Get1WireData(owPin, data, 9)

  ' compute the temperature
  Dim ival as Integer Alias data(1)
  readTemp = CSng(ival) / 2.0
End Function
- Don Kinzer
cadillackid
Posts: 35
Joined: 22 August 2009, 16:34 PM

Post by cadillackid »

interesting you mention the correlation between parasite and Vdd power.. I have a mixture in my home automation system and have noticed that they vary quite a bit even in similar vicinity... .. so I looked through my setup and sure enough the variances come from ones that are powered versus parasite... i think I'll just power them all... its pretty easy to do...

the biggest issue ive ever had with these sensors even in my basic stamp was setting the resolution from 12 bit to 9 bit... somehow I never can get the hang of just sending the 2 bits to it that are required so it never takes... I end up hooking them to a program on a PC through a DS9097u and setting resolution that way.....

have you ever changed resolution on them?

for HVAC apps 9 bit is good enough and they are faster in that mode....
-Christopher
dkinzer
Site Admin
Posts: 3122
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

cadillackid wrote:have you ever changed resolution on them?
I don't believe that the DS18S20, which I've used, is configurable; it's fixed at 9-bit resolution.
- Don Kinzer
kranenborg
Posts: 57
Joined: 27 July 2009, 14:20 PM
Location: Groningen, The Netherlands
Contact:

Post by kranenborg »

The DS18B20 can be configured at any resolution between 9 - 12 bits

/Jurjen
cadillackid
Posts: 35
Joined: 22 August 2009, 16:34 PM

Post by cadillackid »

the DS18B20 are the ones I use and are configurable resolution... I buy them from Crystalfontz.. they are already on a whip and have connectors attached... much easier for me than having to fab up whips onto the TO-92 package... of course they ship as 12 Bit and I want them at 9 bit...

I probably have 30 of these things in service around my House... some of them have been out in the rain for close to 5 years without fail(I dip them in clear fingernail polish.. seals but doesnt insulate)...

-Christopher
cadillackid
Posts: 35
Joined: 22 August 2009, 16:34 PM

Post by cadillackid »

how long does a reset1wire usually take?

do I need to wait 750 milliseconds before issuing the conversion command?
is that time so that the bus can stabilize back at its high pullup state?

im going to use the 9 bit mode so I wont likely wait .750 seconds for a conversion... however jusdt wondering about the reset..
-Christopher
dkinzer
Site Admin
Posts: 3122
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

cadillackid wrote:how long does a reset1wire usually take?
Reset1Wire() consumes about 1mS. An additional delay may be required, depending on your device, for it to become ready to respond to read/write operations. The datasheet for the DS18S20, for example, doesn't mention any required delay after a reset before read/write operations may take place.
cadillackid wrote:do I need to wait 750 milliseconds before issuing the conversion command? is that time so that the bus can stabilize back at its high pullup state?
The datasheet for the DS18S20 indicates that the maximum time required for a conversion is 750mS. That's why the example code delays that long before reading the result. I believe that there is a way to determine when the conversion is complete. If so, implementing that would allow the defined delay to be eliminated.
- Don Kinzer
cadillackid
Posts: 35
Joined: 22 August 2009, 16:34 PM

Post by cadillackid »

Ok so im a little bit confused here... it "LOOKS" like my 1 wire is working but im getting some wierd values and not understanding part of the code....

so here is a snippet of the code im running..

Code: Select all

  c = reset1wire(supplypin) 
  call delay (0.1)
  
  if c=0 then
	supply(1)=&Hcc
	supply(2)=&H44
	call put1wiredata(supplypin,supply,2)
	debug.print "Supply Air Sensor Present"
  ' delay to allow for the conversion
    Call Delay(0.750)
	
  ' prepare to read the data
  c = reset1wire(supplypin)
  supply(1) = &Hcc    ' "skip ROM" command
  supply(2) = &Hbe    ' "read scratchpad" command
  Call Put1WireData(supplypin, supply, 2)

  ' read the data
  Call Get1WireData(supplypin, supply, 9)


  ' compute the temperature
  Dim ival as Integer Alias supply(1)
  debug.print "raw data:";supply(1)
  supplyairc = CSng(ival) / 2.0 
  debug.print "supply temp:";supplyairc

	
  Else
	debug.print "No Supply Air Sensor"
	supplyairc=99.9
  end if
I have 1 sensor connected and powered to my ZX board....

here is the output I get from the above program:

Code: Select all


>Getting temp
                                                                 
Supply Air Sensor Present
                                                     
raw data:19
                                                                   
supply temp:137.5

this sensor is still in its factory default of 12 bit config i havent changed it.. when i convert the "19" to degrees F its in the right vicinity of being correct... within a degree so I know im reading the sensor... but why am I getting the 137.5?? and what does that part of the code do? im confused?

also trying to figure out how I will read negative numbers.... (these are heatpumps and the freon line temps will go below freezing in defrost cycles)
dkinzer
Site Admin
Posts: 3122
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

cadillackid wrote:but why am I getting the 137.5?? and what does that part of the code do?
The code needs to be changed for the DS18B20 because the values it returns have different meaning than for the DS18S20.

For the DS18S20, the temperature value is returned in the first two of the nine scratchpad bytes. This value is a signed 16-bit value that expresses the temperature in units of 0.5*C. Consequently, +25*C will be represented as the value 50 while -10*C will be represented as -20. The example code (reproduced in part below) exploits the Alias feature of ZBasic to allow the first two bytes of the data in the buffer to be treated as a 16-bit Integer value. The second line in the excerpt below then converts the value from units of 0.5*C to 1*C.

Code: Select all

	' compute the temperature
  Dim ival as Integer Alias data(1)
  readTemp = CSng(ival) / 2.0
I looked at the datasheet for the DS18B20 briefly and I believe that the code for it should read as shown below. The reasoning here is that the temperature value for the DS18B20 has units of 1/16th *C. Because of this difference, the reported temperature was too high by a factor of 8.

Code: Select all

	' compute the temperature
  Dim ival as Integer Alias data(1)
  readTemp = CSng(ival) / 16.0
cadillackid wrote:also trying to figure out how I will read negative numbers.
The datasheet indicates that the returned value is a 16-bit signed value so representing negative temperature levels is no problem. You should modify your code to output both bytes of the raw temperature data rather than only the low byte.

Code: Select all

  ' compute the temperature
  Dim ival as Integer Alias supply(1)
  debug.print "raw data:";ival
  supplyairc = CSng(ival) / 16.0
  debug.print "supply temp:";supplyairc
- Don Kinzer
dkinzer
Site Admin
Posts: 3122
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

Also note that if you change the resolution you also need to change the conversion formula:

Code: Select all

t = CSng(ival) / 16.0 ' 12-bit mode
t = CSng(ival) / 8.0  ' 11-bit mode
t = CSng(ival) / 4.0  ' 10-bit mode
t = CSng(ival) / 2.0  '  9-bit mode
- Don Kinzer
cadillackid
Posts: 35
Joined: 22 August 2009, 16:34 PM

Post by cadillackid »

that makes total sense and my value (though the temp seems low) is working better now... I just cant seem for the life of me to get the resolution changed to 9 bits... this is the code im trying to do it with... but seems my config register never "takes"

Code: Select all


  f = reset1wire(supplypin) 
  call delay (0.1)
  
  if f=0 then
	supplyres(1)=&Hcc	'skip ROM 
	supplyres(2)=&H4e   'write 0's to the scratchpad on the chip
	supplyres(3)=75		'set the Th and Tl registers
	supplyres(4)=70
	supplyres(5)=31     'set the config register at 31 which sets resolution to 9 bits
    call put1wiredata(supplypin,supplyres,5)
	debug.print "Supply Air Sensor Present"
  ' delay to allow for the writing
    Call Delay(0.200)
	
  ' send a reset to the device after writing
  f = reset1wire(supplypin)

  ' prepare to read the data
  supplyres(1) = &Hcc    ' "skip ROM" command
  supplyres(2) = &Hbe    ' "read scratchpad" command
  Call Put1WireData(supplypin, supplyres, 2)

  ' read the data just for "sequence sake"
  Call Get1WireData(supplypin, supplyres, 9)
  call delay(0.2)

  f = reset1wire(supplypin)

  ' prepare to copy the data to EEPROM
  supplyres(1) = &Hcc    ' "skip ROM" command
  supplyres(2) = &H48    ' "copy scratchpad" command
  Call Put1WireData(supplypin, supplyres, 2)


debug.print "Supply air resolution Changed"	
  Else
	debug.print "No Supply Air Sensor"
  end if
yes its a little messy but its test code so go easy on me....

here is the reading I get when I take a conversion after the above code and write out the scratchpade..

Code: Select all

>Getting temp
                                                                 
Supply Air Sensor Present
                                                     
raw data:282
                                                                  
supply temp:17.625
                                                            
config register127
                                                            
th register78
                                                                 
tl register70
                                                                 
 
my config register is still 127 instead of 31 indicating those 2 resolution bits never got set....
have you ever changed res?
-Christopher
cadillackid
Posts: 35
Joined: 22 August 2009, 16:34 PM

Post by cadillackid »

Ok i found the problem...

it looks like doing 1 wire in one task or subroutine while there is outputcaptureex or inputcaptureex going on causes issues.. im guessing with timer0....

when I set it up to suspend the routine that talks to the A/C units while I set the resolution it worked like a champ..

I also had noticed that doing conversions was real hit or miss..

so now I just have the routine that talks to the HVAC units call the 1 wire routine after it is done capturing data from the A/C unit so that only 1 wire OR capturing / outputting is going on, not both at the same time.. and all is good..
-Christopher
dkinzer
Site Admin
Posts: 3122
Joined: 03 September 2005, 13:53 PM
Location: Portland, OR

Post by dkinzer »

cadillackid wrote:it looks like doing 1 wire in one task or subroutine while there is outputcaptureex or inputcaptureex going on causes issues.. im guessing with timer0....
The problem is not with Timer0, which is used for the RTC, but with Timer1 which is used for all timed I/O routines.

Unfortunately, the calling sequence for some of the I/O routines has no provision for returning a success/failure code and if the timer that is needed is already being used the routine may just return with no indication of there being a problem. You can work around this issue by making sure that the timer is available before issuing the call. For example:

Code: Select all

  Call LockTask()
  If (Semaphore(Register.Timer1Busy)) Then
    Register.Timer1Busy = False
    'invoke I/O routine here that uses Timer1
  End If
  Call UnlockTask()
An alternate implementation of this idea, which loops until the timer can be used, is shown below.

Code: Select all

  Do
    Call LockTask()
    If (Semaphore(Register.Timer1Busy)) Then
      Register.Timer1Busy = False
      'invoke I/O routine here that uses Timer1
      Call UnlockTask()
      Exit Do
    Else
      Call Sleep(0)  ' this will unlock the task
    End If
  Loop
This code would work for ZX devices that use Timer1 for the I/O timing. It would need to be modified for other ZX devices. See the table Timer Usage by CPU Type in the System Library Manual for information on which timer is used for various ZX devices.
- Don Kinzer
cadillackid
Posts: 35
Joined: 22 August 2009, 16:34 PM

Post by cadillackid »

this all makes sense now.. I guess I thought a timer was a read only property that a routine would use to get timing for I/O..

so I assumed that all I/O could occur simultaneously and on multiple pins at once...

I was running a task that talked to the HVAC unit using inputcapture and outputcapture..

I was running a task that set the value of a digital Pot using shiftout

I was running a task that talked to the dallas 1 wire temp sensors...

all were separate tasks running alongside each other..

the main program was what handled serial I/O to the host controller and adjusted variables which the tasks used in their various functions...

I can now see they were all stomping on each other because each needed exclusive use of the timer...

I realized after re evaluating, that I dont need lightning speed nor do I need multi-tasking for each separate I/O function...

so I simply have a single task that handles All I/O and each I/O item is called sequentially after the previous one finishes... the air conditioning unit likes a minimum of 100 ms after each exchange, and there is no maximum.. I can unplug the line for 5 minutes to the A/C unit and then reconnect and it doesnt care it will talk back to me when I talk to it..

so I do all my I/O sequentially and it all works like a champ...

I played around with locking and unlocking tasks and seemed like everytime I ended up in my ZX locking up or a task somewhere in oblivian where it quit responding.. so thats when I went to the sequemtial approach..
-Christopher
Post Reply