Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.
It's what I've ended up with for reading multiple DS18B20's.
The original source was from Pmather, a Sub that called a couple of other Subs.
I made it into a Function, but I'm still not clear on what better in this situation, being a Function or being a Sub routine.
I currently call the function with a sensor number, being the array position, but ultimately I's like to call it & pass an actual sensor name, probsably have to be in a separate array.
Can anyone explain which would be the more appropriate choice for this code?
Function or Sub & why.
Thanks
Phil.
[Code]
DATA &H24,&H72,&H4A,&H07,&H00,&H00,&H1B 'Sensor1
DATA &HC9,&H5D,&H4B,&H07,&H00,&H00,&H60 'Sensor2
DATA &H46,&HB9,&H4A,&H07,&H00,&H00,&HE4 'Sensor3
'Load Serial#'s into Array
For I = 1 to TsNum 'sensor # count
For J = 1 to 7 'id byte count
Read Ts(J,I) 'read the data in the array
Next J
Next I
..
..
..
Function ReadTemp(TsNum As Integer) As Float
OneWire Reset PinTmp
'Read Sensor Using Serial Numbers from Array Data.
Ts1=Ts(1,TsNum):Ts2=Ts(2,TsNum):Ts3=Ts(3,TsNum):Ts4=Ts(4,TsNum):Ts5=Ts(5,TsNum):Ts6=Ts(6,TsNum):Ts7=Ts(7,TsNum)
OneWire Write PinTmp, 1, 10, &H55,&H28,Ts1,Ts2,Ts3,Ts4,Ts5,Ts6,Ts7,&H44
'Check sensor is ready
Timer=0 : Status=0
Do
If Timer > 1000 Then Error "Sensor Error"
OneWire Read PinTmp, 4, 1, Status ' Conversion status
Loop Until Status = 1
'Calculate the temp in C
ReadTemp=((HTemp And &b111) * 256 + LTemp) / 16
If HTemp And &b1000 Then ReadTemp=-ReadTemp ' adjust if negative
End Function [/code]
robert.rozee Guru
Joined: 31/12/2012 Location: New ZealandPosts: 2294
Posted: 01:57am 19 May 2016
Copy link to clipboard
Print this post
firstly, a function returns a value, whereas a subroutine does not - the only way for a subroutine to return a result is to either change the value of a passed in parameter, or to change the value of a global variable.
see the following example:
Do
Input X
Print square1(X), ' X*X returned from function
square2 (X, RESULT)
Print RESULT, ' X*X returned in variable RESULT
square3(X)
Print XTIMESX ' X*X saved in variable XTIMESX
Loop
Function square1(X)
square1 = X * X
End Function
Sub square2(X, XX)
XX = X * X
End Sub
Sub square3(X)
XTIMESX = X * X
End Sub
secondly, using an array to hold the serial numbers seems a tad complicated. the following code snippet may be simpler:
DO
PRINT ReadTemp(&H24724A0700001B)
LOOP
Function ReadTemp(TsSerial As Integer) As Float
OneWire Reset PinTmp
Ts1=(TsSerial >> 48) and &hFF
Ts2=(TsSerial >> 40) and &hFF
Ts3=(TsSerial >> 32) and &hFF
Ts4=(TsSerial >> 24) and &hFF
Ts5=(TsSerial >> 16) and &hFF
Ts6=(TsSerial >> 8) and &hFF
Ts7=(TsSerial) and &hFF
(in the above i may well have the order of address bytes reversed, the code is untested)
and is the line OneWire Reset PinTmp necessary? is the reset not accomplished by the flag=1 in OneWire Write PinTmp, 1, 10, &H55,&H28...?
cheers,
rob :-)
Phil23 Guru
Joined: 27/03/2016 Location: AustraliaPosts: 1664
Posted: 02:25am 19 May 2016
Copy link to clipboard
Print this post
Thanks Rob,
The examples clear up the Function/Sub issue, I think.
So a Function can only return a single value? Right?
While a Sub could change multiple variables, either passed or global?
Not quire sure I understand the lines
[Code]
Ts1=(TsSerial >> 48) and &hFF
Ts2=(TsSerial >> 40) and &hFF
etc....
[/code]
the >> ? is that a binary extraction? And'd with 1111 1111? (FF).
Thanks
Phil
robert.rozee Guru
Joined: 31/12/2012 Location: New ZealandPosts: 2294
Posted: 02:39am 19 May 2016
Copy link to clipboard
Print this post
a function can indeed only return a single value. if you have multiple results to return then you need to return them as changes to passed variables. both these methods are considered ok, depending upon how many results you wish to return.
changing global variables is generally considered a bad practice, as it can become difficult to see at a glance what the full effect of calling a function or subroutine is, without loooking closely at the code within the function/subroutine. in some circles global variables are also considered bad things.
Ts2=(TsSerial >> 40) and &hFF
this shifts TsSerial 40-bits to the right, then chops off everything in the result except the lower 8 bits. for example:
&h123456789ABCDEF >> 40 results in &h12345
then &h12345 and &hFF chops off the '123', giving &h45
this is a means of neatly chopping a 64-bit integer into a number of 8-bit bytes.
cheers,
rob :-)Edited by robert.rozee 2016-05-20
robert.rozee Guru
Joined: 31/12/2012 Location: New ZealandPosts: 2294
Posted: 02:58am 19 May 2016
Copy link to clipboard
Print this post
here is an example combining all the above:
> list
serial% = &h23456789ABCDEF
For B = 6 To 0 Step -1
Print Hex$(byte(serial%, B)),
Next B
Print
End
Function byte(I%, index)
byte = (I% >> (index * 8)) And &hFF
End Function
> run
23 45 67 89 AB CD EF
>
we use the user created function byte(I%, index) to extract 7 of the 8 individual bytes from the serial number. you may do it this way if you were doing a great many byte extractions from integers in different places in your code.
cheers,
rob :-)Edited by robert.rozee 2016-05-20
Phil23 Guru
Joined: 27/03/2016 Location: AustraliaPosts: 1664
Posted: 12:43pm 19 May 2016
Copy link to clipboard
Print this post
Hi Robert,
The example you give tend to lend it's self more to my final aim.
[Code]
TsCur=&H24724A0700001B 'Sensor1 Water Temp
TsInp=&HC95D4B07000060 'Sensor2 Panel Input Temp
TsOut=&H46B94A070000E4 'Sensor3 Panel Output Temp
DO
PRINT "Water Temp ="; ReadTemp(TsCur)
LOOP
Function ReadTemp(TsSerial As Integer) As Float
OneWire Reset PinTmp
Ts1=(TsSerial >> 48) and &hFF
Ts2=(TsSerial >> 40) and &hFF
Ts3=(TsSerial >> 32) and &hFF
Ts4=(TsSerial >> 24) and &hFF
Ts5=(TsSerial >> 16) and &hFF
Ts6=(TsSerial >> 8) and &hFF
Ts7=(TsSerial) and &hFF
Joined: 31/12/2012 Location: New ZealandPosts: 2294
Posted: 03:57am 20 May 2016
Copy link to clipboard
Print this post
it all looks ok. the only thing to mind is that Ts1-Ts7 may be in the reverse order. i've not checked the code, so if you have any problems, first try reversing the order!
and once you have it working, try commenting out the line OneWire Reset PinTmp to see if it is indeed necessary.
cheers,
rob :-)
Phil23 Guru
Joined: 27/03/2016 Location: AustraliaPosts: 1664
Posted: 01:56pm 21 May 2016
Copy link to clipboard
Print this post
Thanks Robert,
Only tested it by printing Ts1-7 outputs & seems you have it the right way round.
I think using your approach will make the code tighter & easier to follow.
Compressed the 7 lines down to 2....
[Code]
Function ReadTemp(TsSerial As Integer) As Float
'OneWire Reset PinTmp
Ts1=(TsSerial >> 48) and &hFF : Ts2=(TsSerial >> 40) and &hFF : Ts3=(TsSerial >> 32) and &hFF
Ts4=(TsSerial >> 24) and &hFF : Ts5=(TsSerial >> 16) and &hFF : Ts6=(TsSerial >> 8) and &hFF : Ts7=(TsSerial) and &hFF
'
Print Ts1,Ts2,Ts3,Ts4,Ts5,Ts6,Ts7
Pause 1000
'... etc ...
End Function
[/code]
Thanks
Phil
Phil23 Guru
Joined: 27/03/2016 Location: AustraliaPosts: 1664
Posted: 02:47pm 21 May 2016
Copy link to clipboard
Print this post
Thanks Robert,
Works like a dream & makes the much more workable.
[Code]
'List of DS18B20's on the Bus.
Dim Integer TsCur=&H24724A0700001B 'Sensor1 Water Temp
Dim Integer TsInp=&HC95D4B07000060 'Sensor2 Panel Input Temp
Dim Integer TsOut=&H46B94A070000E4 'Sensor3 Panel Output Temp
..
..
..
TmpCur=ReadTemp(TsCur)
TmpInp=ReadTemp(TsInp)
TmpOut=ReadTemp(TsOut)
..
..
..
Function ReadTemp(TsSerial As Integer) As Float
Ts1=(TsSerial >> 48) and &hFF : Ts2=(TsSerial >> 40) and &hFF : Ts3=(TsSerial >> 32) and &hFF
Ts4=(TsSerial >> 24) and &hFF : Ts5=(TsSerial >> 16) and &hFF : Ts6=(TsSerial >> 8) and &hFF : Ts7=(TsSerial) and &hFF
OneWire Write PinTmp, 1, 10, &H55,&H28,Ts1,Ts2,Ts3,Ts4,Ts5,Ts6,Ts7,&H44
'Check sensor is ready
Timer=0 : Status=0
Do
If Timer > 1000 Then Error "Sensor Error"
OneWire Read PinTmp, 4, 1, Status ' Conversion status
Loop Until Status = 1
Function perimeter(a,b) As Float
Perimeter=(a+b)*2
End Function
Function Area(a,b)
Area=a*b
End Function
Sub PerimeterAndArea(x,y,P2,A2)
P2=(x+y)*2
A2=x*y
End Sub
[/code]
Thanks.
robert.rozee Guru
Joined: 31/12/2012 Location: New ZealandPosts: 2294
Posted: 07:55pm 21 May 2016
Copy link to clipboard
Print this post
PerimeterAndArea(x,y,Perimeter2,Area2) is an acceptable example of returning two results from a subroutine, given the limitations of the syntax of basic. purists might argue that using the two separate functions perimeter(a,b) and Area(a,b) is a more elegant solution, however one does need to allow a little pragmatism into the mix; sometimes it is necessary to use a few lines of 'ugly' code to achieve a programming task in a timely and efficient fashion.
the most important thing is that if you go back to your code 6 months later, you (or someone else) can still figure out how it works and what it is doing. to this end, it is a good idea to use plenty of comments within the code to explain what you are doing and how things work. MMedit is an excellent tool in this regard, as it allows you to maintain comments within the original source code, while stripping them out when uploaded to the micromite.
cheers,
rob :-)
disclaimer: have never used MMedit myself, and often break all the rules i preach!Edited by robert.rozee 2016-05-23