Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 22:26 12 Nov 2025 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 : settick killing touch

Author Message
Quazee137

Guru

Joined: 07/08/2016
Location: United States
Posts: 600
Posted: 02:06pm 19 May 2019
Copy link to clipboard 
Print this post


I am trying out using settick as away to exit a timed menu.
What is happening is that if I let the timeout occur it locks out touch
and even the relay settick.

Here is stripped down code.

[CODE
'Backpack V1
'OPTION LCDPANEL ILI9341, RLANDSCAPE, 2, 23, 6
'OPTION TOUCH 7, 15

Option base 1
Colour RGB(black),RGB(green)

tirq=15 'touch irq pin 15
cntin=16 ' counter in on pin 16
relay=10 ' relay control pin 10


SetPin tirq, intl,touched
SetPin tirq, inth,untouched

Pin(relay)=1
SetPin relay,dout,oc
SetPin cntin,cin

here: 'where the trimmer bails out to

SetTick 0,here,2
CLS
Do

tc%=Pin(cntin)

Text 160,35,"Total",cm,,3
Text 160,60,Str$(tc%),c,,3
Text 10,100,"At some time touch",,,2
Text 10,125,"the LCD screen",,,2
If tflag Then Text 250,200,"TO",,,3
If penDown Then menu

itc=Int(tc%/500) 'relay on at every 500 counts

If (olditc<itc) Then
olditc=itc
Pin(relay)=0
Text 10,200,"relay on ",,,3
SetTick 5000,turnoff,1 'for test turn relay on for 5 sec's
EndIf

Loop

Sub turnoff
Pin(relay)=1
Text 10,200,"relay off",,,3
SetTick 0,turnoff,1
End Sub

Sub menu
tflag=1
SetTick 20000,here,2 ' if no touch then time out to lable here
CLS RGB(green)
Text 10,10,"20 sec timeout exit",,,2
Text 10,55,"if LCD not touched.",,,2
Text 10,120,"Waiting",,,3

Do:Loop Until PenUp
Do:Loop Until PenDown
CLS
Text 10,120,"PenDown",,,3
Do:Loop Until PenUp

SetTick 0,here,2
CLS
tflag=0
End Sub

Sub touched
tx=Touch(x):ty=Touch(y)
If tx=-1 Then Exit Sub
If ty=-1 Then Exit Sub
PenDown=1:PenUp=0
End Sub

Sub untouched
PenDown=0:PenUp=1
End Sub
]

I can have a count coming in and it will turn on the relay for 5 sec's
using a settick to turn it off.

If I touch the screen and only wait a few sec's and touch it again
before the time out kicks in things work as expected.

If I touch the screen and let it time out the count still updates
but the relay will lock on and touch stops working.

Any ideas what going on???


 
KeepIS

Guru

Joined: 13/10/2014
Location: Australia
Posts: 1945
Posted: 09:50pm 19 May 2019
Copy link to clipboard 
Print this post

[code]
here: 'where the trimmer bails out to

SetTick 0,here,2
[/code]


[code]
SUB here() 'where the trimmer bails out to
basic code
SetTick 0,here,2
END SUB
[/code]Edited by KeepIS 2019-05-21
NANO Inverter: Full download - Only Hex Ver 8.1Ks
 
CaptainBoing

Guru

Joined: 07/09/2016
Location: United Kingdom
Posts: 2171
Posted: 10:34pm 19 May 2019
Copy link to clipboard 
Print this post

Hi Quazee...

I think the problem is that you are using Here: as a lable when it should be a Sub to make the timer jump to it.

Not terribly relevant to your problem but it looks like you are suffering from the same thing I did a while back - all the setticks and their subs made for a confusing diagnostic.

That was the main driver behind the module I wrote to convert all this to a simple array of flags that you can test as and when you feel like it. Another being only 4 timers.

It makes the code so easy to read... stuff like:
Every 300,0 'Set time from the RTC every 5 minutes
Every 6,1 'calculate new PWM values every 6 seconds
Every 60,2 'Update the LCD display at minute intervals


and then all I have to test is the flag to know I have to do something... nothing firing behind my back, no dedicated subs (well, one - for the core timer thread), the time periods can be up to 2^61 "ticks" and it is expandable upto 63 timers... plus you can set the flags under code to make timer events happen as and when you wish:
FlagSet 0 'force clock set first time round
FlagSet 1 'force the PWM to be output for the first time round
FlagSet 2 'force the LCD update for the first time round


Then somewhere in the Main thread, I have stuff like this to service the timer that fired:
'time to update the LCD panel?
If FlagTest(2) then
FlagRes 2
DrawCurrentProfile
Colour 0
Move 25+(ptr*2),133:DrawR 0,100
EndIf


It all happens under control and completely synchronous to other tasks (timer subs don't kick off in the background in the middle of other tasks).

A timeout is so easy to do like this... you might say

AFTER 10,9' set a timer for 10 seconds

then in your code to check if the timeout has happend you simply test that flag

If FlagTest(9) Then Exit Do ' ran out of time

I never use anything else now.. really easy to understand statements, AFTER, EVERY & AT to set timers, REMAIN to stop a timer and DI & EI to temporarily suspend and re-enable all timers.

you can find the full write-up and code here
http://www.fruitoftheshed.com/MMBasic.AFTER-EVERY-REMAIN-Flexible-State-Machine-Timers-using-Semaphores.ashx

It is fairly blunt and there is scope for improvement but it works really well as written.

hth
Edited by CaptainBoing 2019-05-21
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9755
Posted: 11:08pm 19 May 2019
Copy link to clipboard 
Print this post

KeepIS is correct - you are missing an END SUB, and you can't call a LABEL for an interrupt, you must call a SUB.

Having said that, you tend to be breaking the #1 rule for interrupts: 'Thou shalt not hang about in interrupts.'

Remember that a SETTICK timer is still an interrupt, and all you REALLY should be doing inside interrupts, is setting flags and exiting. Let you main loop analyze those flags and do whatever is required.

I feel your pain, as I too made this EXACT mistake when learning how to correctly use interrupts, but you really must avoid putting the code you want to happen, inside the interrupt itself, as odd things can happen.

CaptainBoing is quite right in the way he is approaching it, and he PROBABLY did the same as you and I both, when he was learning interrupt programming, and put all the code in the interrupt.
But this is not a good idea, and it also does make debugging hard as he points out.

The IR command interrupt is a good one to study, as it works like that. When you press a button on the remote - which can be at any time - the interrupt just saves the value of the key, and returns the interrupt. This makes for a very fast interrupt, and the main code can examine the data and act. Example:

  Quote  '---------- IR REMOTE CONTROL KEY CODES: ------------
CONST POWER=2,TVPWR=170,SET=154,TVIN=26,VOLDN=234,VOLUP=106
CONST SETUP=194,APP=240,VOLDNYEL=8,VOLUPBLU=24
CONST HOME=136,GOBACK=152,MENU=50,MOUSE=0
CONST UPA=104,DOWNA=88,LEFTA=138,RIGHTA=10
CONST ONE=114,TWO=176,THREE=48,FOUR=82,FIVE=144
CONST SIX=16,SEVEN=98,EIGHT=160,NINE=32,ZERO=128
CONST MUTE=130,DEL=66,OK=200


  Quote  IR DEVICE,KEYP,IRINT 'Start IR remote control interrupt


...and...

  Quote  '--------- SUBROUTINES AND INTERRUPTS -----------
SUB IRINT 'IR remote control interrupt
IF DEVICE<>128 then 'Ignore other remote controls
BUTTON=0 'Ignore other remote control codes
ELSE
BUTTON=KEYP
'Valid remote control code, so save it and end the interrupt
ENDIF
End SUB


...and the main loop just examines the value of BUTTON:

  Quote   DO:Loop Until BUTTON 'Wait for another button press
Select CASE BUTTON 'Decide what button was pressed
CASE OK 'OK button was pressed...

...
...
...
  Quote   CASE ELSE
CPU RESTART 'Reboot system on any other key then OK
End Select
CASE ELSE 'Any other button press gets ignored
End Select


Smoke makes things work. When the smoke gets out, it stops!
 
Quazee137

Guru

Joined: 07/08/2016
Location: United States
Posts: 600
Posted: 11:08pm 19 May 2019
Copy link to clipboard 
Print this post



Why is touch not working after letting to 20 sec's run out?

There is only 2 setticks at play here.

Settick 1 handles the relay turn off and works fine till settick 2 is
allowed to time out. Then it blocks touch and settick 1 from working.

In the org code I had "settick 0,here,2" only right after the here: label
to turn it off as it is only needed to ensure when in the menu operations
for over 20 sec's it will bail out to here:


Still can not see why the touch not working after the 20 sec's.

 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9755
Posted: 11:16pm 19 May 2019
Copy link to clipboard 
Print this post

It is possibly linked to the fact you are running other code inside your interrupts. This can and has resulted in odd behaviour from the interpreter. I would re-write your code to just set flags and nothing else, have your main loop process those flags and see if the touch still freezes after those same 20 seconds. It could also be an undocumented bug - who knows. But before you can start to prove that, the interrupts need to be cleaned up so that you can say for sure, that it is not anything in there that could be causing something odd to happen.
Smoke makes things work. When the smoke gets out, it stops!
 
CaptainBoing

Guru

Joined: 07/09/2016
Location: United Kingdom
Posts: 2171
Posted: 11:18pm 19 May 2019
Copy link to clipboard 
Print this post

you are using "Here" as a label.

I suspect you have some weird confusion thing happening that is locking up your code or MMBasic.

As KeepIs pointed out, look at the lines:

here: 'where the trimmer bails out to

SetTick 0,here,2

that is wrong as Here isn't a Sub, the structure doesn't match how you did the turnoff (which is correct):
[code]
SetTick 5000,turnoff,1 'for test turn relay on for 5 sec's

...

Sub turnoff
..
End Sub
[/code]

Edited by CaptainBoing 2019-05-21
 
Quazee137

Guru

Joined: 07/08/2016
Location: United States
Posts: 600
Posted: 11:19pm 19 May 2019
Copy link to clipboard 
Print this post



this code shows all of the irq usage. just the setticks and touch.

touch does set flags that my main code uses.
 
CaptainBoing

Guru

Joined: 07/09/2016
Location: United Kingdom
Posts: 2171
Posted: 11:24pm 19 May 2019
Copy link to clipboard 
Print this post

convert "Here" to a SUB - it won't work any other way.

Settick *must* call a sub when it fires, it can't GOTOEdited by CaptainBoing 2019-05-21
 
Quazee137

Guru

Joined: 07/08/2016
Location: United States
Posts: 600
Posted: 11:26pm 19 May 2019
Copy link to clipboard 
Print this post



Ok I see now that settick is a call to a sub.

The way the manual shows it as if I can use a label to goto
no talk of it being a sub call needing a end sub.

Thanks now off to fix it.
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9755
Posted: 11:27pm 19 May 2019
Copy link to clipboard 
Print this post

[Quote=Quazee137]this code shows all of the irq usage. just the setticks and touch.

touch does set flags that my main code uses.[/Quote]

OK, good!

So, reverse-engineer your SETTICK code so it does the same.

SETTICK is an interrupt just as TOUCH is - treat it exactly the same way. At the moment, you are not. You are trying to execute bits of code inside the SETTICK interrupts. Calling a touch-interrupt from inside a SETTICK interrupt could possibly be what is causing your touch to freeze up. It can't process the touch interrupt, as it is still inside the SETTICK interrupt.
Smoke makes things work. When the smoke gets out, it stops!
 
Quazee137

Guru

Joined: 07/08/2016
Location: United States
Posts: 600
Posted: 02:29am 20 May 2019
Copy link to clipboard 
Print this post



I see I am making a loop with the settick 2 and maybe eating up the stack
with repeated calls.


My first run at setting the menu to use a timeout was with watchdog.
But watchdog clears the count value on the count pin.

Is there any way to reload/preset the count value of the cin pin?

The menu goes through many levels and at any level the user may not
complete it leaving me hung there. So I was looking for way to time
the menu operations as a whole. Exiting if timed out no mater where
the user was in the menu system.

Now back to rethinking how I can exit the menu system as a whole when
20 sec's has passed. I don't care where the user is in the menu system.
Only if user does not complete the selection.

As is now I'll have to test for an abort flag in each of the eight menus
and a few sub menus.

Such a simple idea but coding not so.

So maybe timer = 0 at menu start and test for timer>20001ms to exit sub menu

Thanks again.







 
KeepIS

Guru

Joined: 13/10/2014
Location: Australia
Posts: 1945
Posted: 05:25am 20 May 2019
Copy link to clipboard 
Print this post

I would think about a menu system that is non blocking, all sub menus are pass-through until a button press for the current sub menu state is pressed and acted on.

The Touch ISR will always return the Touch key value and that is its sole purpose. With a combination of touch down and touch up flags all intermediate Touch states can be ignored.

When a menu item had to run a procedure that is blocking, it should always check key status for abort and in some cases with machine movement control, a separate loop timer that times out if the action is not completed in the timer allocated time is needed. Any loop including the ones waiting for a timer to complete should be calling a main idle loop that checks for any user intervention. That main "idle loop" should have an in/out flag to stop any possibility or reentry code. Not needed in small programs, but with thousands and thousands of lines of code and complex machine states calling the same key control loop it's handy, if only for debugging. Edited by KeepIS 2019-05-21
NANO Inverter: Full download - Only Hex Ver 8.1Ks
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 4133
Posted: 06:59am 20 May 2019
Copy link to clipboard 
Print this post

To try to explain, I think one problem with the original code is that you need to exit from the SETTICK to label "here" using IRETURN (because "here" is not a SUB) - which the code does not do.

You will also be using a lot of internal stack, not to mention very possibly confusing MMBASIC's internals.

It's as if you think the interrupt has bailed your code out - but it hasn't. Instead, it has in effect called your "here" and is now nested running the code a second (or more!) time - all the time still inside an interrupt.

Unsurprisingly, it doesn't end well.

Some very helpful ways to fix it have already been posted so pick one you like :)

JohnEdited by JohnS 2019-05-21
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9755
Posted: 07:37am 20 May 2019
Copy link to clipboard 
Print this post

....and whichever one you DO pick up, PLEASE do not be discouraged.

GUI programming, and handling interrupts, is quite a bit different from your average A-to-B code, and at the start of grasping that concept, it CAN be quite confusing.

The thing to remember is: 'Flags are your friends.'

You can have hundreds of flags to control things, and they DON'T have to be binary flags either. You can make them any number that suits, and the main DO/LOOP can pick up on that.

The essential thing is to keep ALL interrupts AS SHORT AS POSSIBLE. Even MODERN OS coders would say the same. Think of it along the lines of:

CPU: Tra la-la-la la....
INT: Look at me!!!
CPU: OK, what do you want?
INT: DO THIS NOW!
CPU: OK, done, now.....tra-la-la-la....

Pseudo code, naturally, but you hopefully get the idea!

They need to be as simple and as short as possible, and return IMMEDIATELY so the CPU can concentrate on the main loop.
Smoke makes things work. When the smoke gets out, it stops!
 
Quazee137

Guru

Joined: 07/08/2016
Location: United States
Posts: 600
Posted: 08:03am 20 May 2019
Copy link to clipboard 
Print this post



In the past writing asm I would have gone to the label then disabled the
irq and popped the ireturn off the stack and kept going. Not clean but at
times was the fastest way to handle it.

MMBasic is so much faster to work with to get an idea out. Some times I
get into asm mode of thinking. And until I get around to working c
or even asm for the chip I am very happy to run into things like this.

Gota keep seeing how far I can push MMBasic so when it pushes back
I learn something.

I need a watchdog that can restart the program and not touch the vars or pins.
Maybe one I can set the reentry point like.

Watchdog XXXXXms,reentry label

Im not sure but the watchdog maybe hardware based as it is many micro's.

Thanks again to all. I adding new exiting to all menus.

 
CaptainBoing

Guru

Joined: 07/09/2016
Location: United Kingdom
Posts: 2171
Posted: 08:22am 20 May 2019
Copy link to clipboard 
Print this post

are you trying to use the watchdog to implement your timeout and dump you back out of x-layers deep in the menus?

If so, I would recommend you don't. Watchdog is intended to recover a locked-up system... it is a very blunt instrument... but then a hammer doesn't have to be smart! and you are seeing this when you lose your count.

Instead of positing ways to make watchdog do what you want, I would really urge you to work within the bounds of the system and do all this under program control.

When you call into your various menu-ing layers of your code, have the parent code (i.e. the bit that called the next bit) check the timeout flag immediately after the call and "ripple" back up out of the depths. This is also one of those times when the hated GOTO can be useful because you don't have any stack considerations and when the timeout occurs, no matter how deep you are you can just abandon everything and jump back to your default view.

Sometimes we can end up stabbing ourselves all over just to serve the God of Structured Programming with no benefit besides pretty code and a warm glow. I personally have no problem with a well-placed GOTO... I try not to use it for general loops etc. but in situations like this where I need to completely change my area of main focus within a program or just bail out, it serves me well.



 
Quazee137

Guru

Joined: 07/08/2016
Location: United States
Posts: 600
Posted: 08:50am 20 May 2019
Copy link to clipboard 
Print this post



Yes I have been avoiding using the goto and as you say sometimes its
the best way to get to a restart point.

I'll have to go back a week and look at my first run at this. I was using
goto's to reenter the main loop.It was a fast implementation of the idea.
I am now making more use of [exit sub] with a few flags.

Funny thing is the sub menus never reach the [end sub] they all use [exit sub].

Most of them are [select case] based that reads much easier than when I use
[if then else's] with goto's.

My main fault is trying to write minimum sized code (old coding habit) when
I have plenty of memory. This is just the water meter code. The 4-20mA to count
and count to 4-20 is still wip along with the PH and conductivity rewrites.

Flash:
4K ( 6%) Program (239 lines)
1K ( 1%) 6 Saved Variables (54 bytes)
8K (13%) Library
47K (80%) Free

RAM:
2K ( 4%) 26 Variables
0K ( 0%) General
48K (96%) Free
 
Quazee137

Guru

Joined: 07/08/2016
Location: United States
Posts: 600
Posted: 09:05am 20 May 2019
Copy link to clipboard 
Print this post

  CaptainBoing said   This is also one of those times when the hated GOTO can be useful because you don't have any stack considerations and when the timeout occurs, no matter how deep you are you can just abandon everything and jump back to your default view.


So if I am 8 sub levels in I don't need to [end sub] [exit sub] to cleanly leave them?

If so then maybe going back to using the goto's would be far less code. I can test
the timer is over run in the touch irqs and set the timeout flag there. Then in
the select case I add flag to the exit case.


Thanks off to try this out. I'll now have 5 versions Im testing. Fun stuff it is.


 
CaptainBoing

Guru

Joined: 07/09/2016
Location: United Kingdom
Posts: 2171
Posted: 09:57am 20 May 2019
Copy link to clipboard 
Print this post

I am the same.

Even as a professional programmer (which ended about 15 years ago when I moved more toward the architecture side) I still had the habit from my old assembler days of not squandering memory... and I still do it today. I have logging examples that use a tokenised form to get 170 lines of log in 2K of Flash complete with date/time log entry and an integer (counter). Another gets 288*5 integers into under 1.5K. I enjoy the challenge of making the seeming impossible work.

With your Subs, you have to exit them nicely, either with and End Sub or Exit Sub, you can't jump out of the middle of them, but if you have a flag that you set to indicate something went wrong, you can check that as soon as you get back to the parent code and if the flag is set it can Exit Sub... and so on until you reach the top. It won't take long either... something like this:

[code]
main:

FlagRes Timeout

sub1
If FlagTest(Timeout) then ... ran out of time

...<rest of your main>


'The Subs
'---------

Sub Sub1

Sub2
If FlagTest(Timeout) then Exit Sub ' check the timeout flag on return from sub2

<rest of Sub1>

End Sub


Sub Sub2

timer=0

Do
If timer>10000 Then Flagset TimeOut : Exit Sub ' a 10 second timeout based on the timer

...<rest of sub2 loop - activity must set timer=0 to prevent unexpected timeouts
so long as the user keeps doing stuff and you keep zeroing the timer the timeout will not
occur, only when they have been "silent" for 10 seconds since the last activity>

Loop

End Sub

[/code]

so Main calls Sub1, which calls Sub2 and whenever the Timeout flag gets set (whatever form it takes) we simply ripple back to Main where you can take action. All this uses zero interrupts. I know it sticks in the throat to do a tight loop checking for a condition, but on a microcontroller platform (I am excluding PiCromite here) you don't have to play nice with everything else so there is no problem. You could take this particular layering as far as you like and it will all just ripple back out so long as you test for the timeout flag after each call to a Sub.


 
Print this page


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

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025