Hi!
Trying to control relay's with Netmedia LCD+. ZBasic doc says it's not recommended to pass value to task's ByRef. Code below works if I pass a value ByREf in an ordinary Sub but not in a task. Tried to preserve the RelayStatus value in a tmpRelayStatus variable but still not working. Could anyone give me a hint how to get Byref to work in a task. Tried to solve the problem by reading the doc's/forum but I'm stucked. Any help would be appreciated
Regards Hucke
[/code]
test.bas
'***************************''''
'
'
'
'
'
Sub Main
RelaysALL_OFF' set relay's off and initialize 'tmpRelayStatus' to &H00
Do
'#### DON't WORK
CallTask SwitchRelay(tmpRelayStatus,3,1),RelayStack
CallTask SwitchRelay(tmpRelayStatus,4,1),RelayStack
'#### WORKING
call SwitchRelay(tmpRelayStatus,2,1)
call SwitchRelay(tmpRelayStatus,1,1)
Loop
End Sub
' Relay_1.Bas
'
' Public Sub Relays_OFF()- turn OFF ALL relays
' Sub SwitchRelay(ByRef RelayStatus as Byte, ByVal RelayNumber as Byte)
'
'Call RelaysALL_OFF() in Sub Main to set all relay's off as default and to set 'tmpRelayStatus'
Public RelayMsg(0 to 7) As String
Public RelayStack(1 To 73) As Byte
Public tmpRelayStatus As Byte 'to hold value of RelayStatus
'********************************************************************************************
Sub SwitchRelay(Byref RelayStat as Byte,ByVal RelayNumber as Byte,ByVal tmpStatus As Byte)
' Turns ON/OFF specified relay 1-8
If RelayNumber > 8 Then
Exit Sub
End If
Select Case tmpStatus
Case 1'On
Call PutBit(RelayStat, RelayNumber-1, 1)
Case 0'Off
Call PutBit(RelayStat, RelayNumber-1, 0)
End Select
Call PutByte_3(&H12)
Call PutByte_3(RelayStat XOR &Hff)
Relay_Msg(RelayStat)
Call Delay(0.0)
End Sub
Public Sub RelaysALL_OFF()
Dim RelayStatus As Byte
RelayStatus = &H00
Call PutByte_3(&H12) ' relay command
Call PutB_3(RelayStatus XOR &Hff) ' turn OFF all relay's
Call Relay_Msg(RelayStatus)
tmpRelayStatus = RelayStatus
End Sub
Public Sub Relay_Msg(ByRef RelayStatus As Byte)
Dim X As Integer
Dim Y As Integer
Dim TmpBitStatus As Byte
Dim tmpMsg As String
Dim tmpPos As Byte
RelayMsg(0) = "Pump = "
RelayMsg(1) = "Chlor = "
RelayMsg(2) = "VP = "
RelayMsg(3) = "Sun = "
RelayMsg(4) = "Light1 ="
RelayMsg(5) = "Light2 ="
RelayMsg(6) = "Light3 ="
RelayMsg(7) = "Light4 ="
tmpPos = 0
For X = 0 To 7
TmpBitStatus = GetBit(RelayStatus, X)
tmpMsg = RelayMsg(X) & Cstr(TmpBitStatus)
If tmpPos > 79 Then
tmpPos = 0
End If
LCDSetCursorPosition(tmpPos)
PutStr_3 tmpMsg
tmpPos = tmpPos + 10
Next
End Sub
Calling ByRef in Task's
I think Tom misunderstood your question. Here is a working test program that passes parameters by reference to a task.
The compiler issues the warning as documented in CallTask about passing parameters by reference (ByRef) and the code produces the expected output of
I am not sure exactly what the problem is that you are having. Can you describe a little more what is failing and where? Reading the code it looks like you could simply use a module level variable. Here is the same example as above rewritten with a module level variable.
Code: Select all
Dim taskStack(1 to 100) as Byte
Public Sub Main()
Dim tmpRelayStatus as Byte
tmpRelayStatus = &H00
Debug.Print "Outside task "; tmpRelayStatus
CallTask RelayTask(tmpRelayStatus), taskStack
Call Sleep(1.0)
Debug.Print "Outside task "; tmpRelayStatus
Do ' loop forever
Loop
End Sub
Public Sub RelayTask(ByRef relayStatus as Byte)
Debug.Print "Inside task "; relayStatus
relayStatus = &H55
Debug.Print "Inside task "; relayStatus
Do ' loop forever
Loop
End Sub
Code: Select all
Outside task 0
Inside task 0
Inside task 85
Outside task 85
Code: Select all
Dim relayStatus as Byte
Dim taskStack(1 to 100) as Byte
Public Sub Main()
relayStatus = &H00
Debug.Print "Outside task "; relayStatus
CallTask RelayTask(), taskStack
Call Sleep(1.0)
Debug.Print "Outside task "; relayStatus
Do ' loop forever
Loop
End Sub
Public Sub RelayTask()
Debug.Print "Inside task "; relayStatus
relayStatus = &H55
Debug.Print "Inside task "; relayStatus
Do ' loop forever
Loop
End Sub
Mike Perks
For me, the only rule of thumb is the more general case very issue that the compiler warned about when using ByRef variable passing. That issue is sharing of resources between processes, RAM being one of them.hakha4 wrote:By the way. Are there any thumb roles for when to use delay/pause in Task's .I thougt one of the advantages with task's was that the procedure finish before next call is launched.
You have to be very careful about how you share all this stuff because another process may become active when the other proces was in the middle of doing something and got suspended by a task switch. If you assume that a certain process runs to completion without interruption (i.e. it is "atomic"), then sometimes you will have some very odd and hard-to-figure-out problems.
By passing values "ByVal", the task has its own variable, and is not dependent on other tasks behaving in any specific manner. Go ahead and pass by reference, but be careful!
-Tony
On the contrary, unless you take special steps to prevent it, a procedure may be "paused" to allow another task to run at almost any time. That's why you need to think carefully about how data is shared between tasks when you code your application.hakha4 wrote:I thougt one of the advantages with task's was that the procedure finish before next call is launched.
The reason for the recommendation (and the warning) is that, if not done correctly, the task can end up using a pointer to a variable that no longer exists. This can happen if a task in invoked using a reference to a local variable of a procedure when that procedure terminates (and thus causes the local variable to vanish) prior to the task using the reference.hakha4 wrote:ZBasic doc says it's not recommended to pass value to task's ByRef.
If you pass a module-level variable to the task, it will exist as long as the program is running so the variable's lifetime is not an issue. You can use the #pragma warning directive to suppress the warning if you know for certain that what you're doing is OK. In retrospect, there may be a way to modify the compiler so that it doesn't issue the warning if the variable passed by reference is defined at the module level.
- Don Kinzer