Discussion about the ZBasic language including the System Library. If you're not sure where to post your message, do it here. However, do not make test posts here; that's the purpose of the Sandbox.
I'm altering my race car lap timing program to use a magnetic pickup present in most circuits rather than the IR beacon and detector I used previously. The IR is prone to interference from other beacons, people knocking it out of alignment, range issues and last but not least me forgetting to take it home !
I have a sensor that i tested at a circuit last weekend and have wired this to pin 4 on a 328n which is defined as zxinputpullup, which the switch takes low when a magnet is detected.
The detection part works fine. The task below correctly detects the change of state but never prints 'cont'. The aim of the routine is to provide half a second of hysterysis to the global trigger variable. BCN_INT is defined as zero for a 328n and the task has a 170 byte stack.
apart from the frowned upon use of a goto - what is going wrong ?
Sub BeaconDetectTask()
IR: 'Loop looking for beacon
debug.print "wait trig"
Call WaitForInterrupt(zxPinFallingEdge,BCN_INT)
debug.print "Trig"
by_BeaconDetected=0
Sleep (0.5)
debug.print "cont"
by_BeaconDetected=1
goto IR
End Sub
Boy, I don't see anything wrong between printing "trig" and printing "cont".
I take it you ARE getting the "trig" printed?
Replace the goto with a do or while(true) loop. It might be nice to have a way to exit the loop so you might use a while(global boolean variable) loop. This or another process can then change the boolean to break the loop.
Then remove the sleep() function. It ought to print "trig" and "cont" back to back. Does that happen?
Sub BeaconDetectTask()
'Loop looking for beacon
do
debug.print "wait trig"
Call WaitForInterrupt(zxPinFallingEdge,BCN_INT)
debug.print "Trig"
'by_BeaconDetected=0
'Sleep (0.5)
debug.print "cont"
'by_BeaconDetected=1
loop
End Sub
and i get debug output of :-
Trig
cont
wait tri
yes there is a missing g, and if i leave in the variable setting then more letters are missing, suggesting its a timing issue. then i also fail to get any more triggers - the main program is still running but i get no more triggers.
as an experiment i wrote a stand alone test prog to mimic this code and it worked perfectly so there is an interaction going on with other parts of my code but at the moment not sure what this could be. there is a lot of pin io going on to drive the lcd but other than that its all fairly normal.
i'll dig some more but any pointers much appreciated.
pjc30943 wrote:EDIT: I see now that you mentioned it was a task.
What else is running? Is another task also using debug.print without a semaphore?
Good question. I always look to Don to tell me about the vagaries of debug.print and how it will block tasks (or not) and so on.
One thing you might try is to increase the task stack just to prove that the problem is not a stack overrun. If you have the space, try doubling it and see if it still misbehaves.
FFMan wrote:yes there is a missing g, and if i leave in the variable setting then more letters are missing, suggesting its a timing issue.
This symptom could be the result of stack corruption or a bug (in your code or ours) that inadvertently leaves interrupts disabled.
This type of problem is difficult to diagnose. It is usually difficult to create a simplified test case that exhibits the problem but worth the effort. If you can create a simplified test case that requires no external input (or some easy-to-reproduce external input sequence) that will go a long way toward determining the root cause of the problem.
although the program is quite large, the actual code running when the problem is evident is quite very simple. i suspect some interaction with the io writing to the lcd and i'll start by commenting out this code and go from there. the lcd code does lock the task momentarily.
i'll have a play this evening and post results back.
looking at the lcd code i see it has a block that locks the task, toggles some pins and then has a Pause(0.002), toggles some pins and unlocks the task.
The documentation states that pause prevents other tasks running. This didn't seem to be an issue when using IR and InputCapture, but that has now been replaced with WaitforInterrupt, perhaps there is some interaction there.
ok - a few checks and changes made and it doesn't get any clearer but here is what I have found:-
I have the 2 functions shown below. If the line
Call LCD_Plot(Cstr(by_Ret) & Cstr(timer),0,0)
is left in its original form:-
Call LCD_Plot(Cstr(by_Ret) ,0,0)
the process fails to complete the 'cont' debug and fails to retrigger. If i have the display line with the timer it works fine and retriggers etc as expected. I tried adding 50 bytes to the stack but this didn't help.
function Read_Beacon() as byte
if bo_TestMode=true then
Read_Beacon= GetPin(TRG_Pin)
'debug.print "~";
else
Read_Beacon=by_BeaconDetected
end if
end function
'Display beacon state to user
Sub Beacon_Test()
dim by_Ret as byte
Call LCD_Clear
Call LCD_Plot("Beacon:",0,0)
Call LCD_Plot("Exit>",1,255)
Do while UserInput(false)=0
by_Ret=Read_Beacon
Call LCD_Plot(Cstr(by_Ret) & Cstr(timer),0,0) '0,12
loop
end sub
interestingly if i replace the cstr(timer) addition with a constant such as:-
Call LCD_Plot(Cstr(by_Ret) & "a",0,0)
i still see the issue. From programming way back would it be true to say the compiler creates a new variable if a non-constant is concatenated, whereas by adding nothing, or another constant the compiler is passing by reference and this is causing the issue and perhaps this is because this variable is a return from a previous function call and passed by reference itself ? a wild guess really....
I can work round it using this 'fix', and in the main operational code (as opposed to this routine which is for the user to test the beacon), there isn't an issue anyhow.
FFMan wrote:i[W]ould it be true to say the compiler creates a new variable if a non-constant is concatenated, whereas by adding nothing, or another constant the compiler is passing by reference
No. Both the CStr(by_Ret) and the CStr(timer) calls return allocated strings (assuming that the parameter is not a compile-time constant). With the string concatenation operator (&), the two strings are combined into a single allocated string which is then passed to the called subroutine (where it is ultimately deallocated). Even if you concatenate a constant string to the result of CStr(by_Ret), the result is still an allocated string (again, assuming that by_Ret is not a compile-time constant.
The problem could be related to the concatenation operation or to the freeing of the concatenated string. We haven't seen any issues recently with operations like this but there still could be something unusual going. Tracking down the problem will be difficult (perhaps impossible) without a working example that manifests the issue.