Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 19:05 18 May 2024 Privacy Policy
Jump to

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.

Forum Index : Microcontroller and PC projects : Function Vs Sub.

Author Message
Phil23
Guru

Joined: 27/03/2016
Location: Australia
Posts: 1664
Posted: 01:06am 19 May 2016
Copy link to clipboard 
Print this post

I mentioned this code in another post.

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

OneWire Write PinTmp, 1, 10, &H55,&H28,Ts1,Ts2,Ts3,Ts4,Ts5,Ts6,Ts7,&HBE
OneWire Read PinTmp, 2, 2, LTemp, HTemp

'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 Zealand
Posts: 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

OneWire Write PinTmp, 1, 10, &H55,&H28,Ts1,Ts2,Ts3,Ts4,Ts5,Ts6,Ts7,&H44

... etc ...

End Function

(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: Australia
Posts: 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 Zealand
Posts: 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 Zealand
Posts: 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: Australia
Posts: 1664
Posted: 12:43pm 19 May 2016
Copy link to clipboard 
Print this post

  robert.rozee said  
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

OneWire Write PinTmp, 1, 10, &H55,&H28,Ts1,Ts2,Ts3,Ts4,Ts5,Ts6,Ts7,&H44

... etc ...

End Function



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

OneWire Write PinTmp, 1, 10, &H55,&H28,Ts1,Ts2,Ts3,Ts4,Ts5,Ts6,Ts7,&H44

... etc ...

End Function
[/code]

Does that look feasible?

Thanks

Phil.Edited by Phil23 2016-05-20
 
robert.rozee
Guru

Joined: 31/12/2012
Location: New Zealand
Posts: 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: Australia
Posts: 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: Australia
Posts: 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

OneWire Write PinTmp, 1, 10, &H55,&H28,Ts1,Ts2,Ts3,Ts4,Ts5,Ts6,Ts7,&HBE
OneWire Read PinTmp, 2, 2, LTemp, HTemp

'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]

ONE.WIRE Reset seems to be not needed.

Others who commented & understand it more than me might have feedback.

Love it, Just 12 lines of code & a nice block of named Serial#'s.

Thanks

Phil.
 
Phil23
Guru

Joined: 27/03/2016
Location: Australia
Posts: 1664
Posted: 03:24pm 21 May 2016
Copy link to clipboard 
Print this post

  robert.rozee said   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.

cheers,
rob :-)


So is SUB PerimeterAndArea(x,y,P2,A2) a good or bad coding example?

[Code]
'Test Function
Option Explicit
Dim Float x,y,Perimeter2,Area2

x=2.0 : y=3

Print "X="; x
Print "Y="; y
Print "Perimeter"; Perimeter(x,y)
Print "Area "; Area(x,y)

PerimeterAndArea(x,y,Perimeter2,Area2)

Print
Print "Perimeter"; Perimeter2
Print "Area "; Area2


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 Zealand
Posts: 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
 
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2024