PDA

View Full Version : What's the best code loop-structure to handle multiple tasks without interruption?



OldMarty
- 13th July 2016, 05:47
Hi All,

I'm looking for help on the best way to structure code that has multiple tasks happening, while not interrupting or slowing the overall operation at any given time.
For example, i want to drive 16 LEDs using a 4x4 (Multiplexed) matrix (4 rows x 4 columns)
The LEDs in the matrix will be often changing states and/or flashing in various patterns.

The LED status and flash speeds will be dependent on settings of various pots and switches wired to the PIC.
The LED patterns vary from switching approx 10-20 times per second down to say once per second, while other LEDs are just static ON or off.
Of course the 'ON' LEDs need to look like they're stable, not flickering due to the speed of the matrix scanning being interrupted by the code going to process a pot-change etc.

In my past attempts (long ago), while my projects have worked overall, i suffer too much interruption to the LEDs while adjusting pots and setting external switches to alternate values.
So, in all, i need to master how i use loops to monitor/switch everything cleanly. Are there preferred ways to do this?
My loops in the past have always revolved around goto's & gosubs, i've never ventured into using DO loops or WAITs, WENDs etc...maybe this is what i'm lacking?

I haven't provided code for my example, as this is just an open question about general structure and loop techniques (rules of thumb) that people use for speed efficiency.
Before you ask, it's now slow hardware or slow chips, it's *me* not structuring my looping and I/O monitoring correctly.

Any suggestions are greatly welcomed, i can only learn what i've been doing wrong all these years lol ;-)

Regards,
Marty.

richard
- 13th July 2016, 07:55
You can always drive the leds like this charlieplex [12 led] example . the multiplexer is an interrupt driven background task that only uses about
2% of the processing time [if I remember correctly]. the isr could be done in asm if speed critical





'************************************************* ***************
'* Name : charlieplex.pbp *
'* Author : richard *
'* Notice : *
'* : *
'* Date : *
'* Version : 16f1825 @3.3 volts *
'* Notes : *
'* : *
'*
'************************************************* ***************

#CONFIG
__config _CONFIG1, _FOSC_INTOSC & _CP_OFF & _WDTE_ON & _PWRTE_ON & _MCLRE_ON & _CLKOUTEN_OFF
__config _CONFIG2, _PLLEN_ON & _LVP_OFF
#ENDCONFIG

DEFINE OSC 32

include "dt_ints-14.bas"
Include "REENTERPBP.bas"


asm
INT_LIST macro
INT_HANDLER TMR1_INT, _TOCK, PBP ,YES

endm
INT_CREATE
ENDASM




@timer1 =TMR1L
leds var word
tmp var byte
x var byte
timer1 VAR WORD EXT
timer1=15543
T1CON=$31
@ INT_ENABLE TMR1_INT
OSCCON=$70
ANSELA=0
ANSELC=0


mainloop:
leds=1365
pause 1000
leds=2730
pause 1000
goto mainloop





TOCK:
T1CON.0=0
timer1=timer1+64536
T1CON.0=1
if leds.0[x] then
lookup x,[12,12,9,9,3,3,5,5,6,6,10,10],tmp
TRISC =(TRISC&$f0)|tmp
lookup x,[ 2, 1,4,2,8,4,8,2,8,1 ,4, 1],tmp
latC =(latC&$f0)|tmp
endif
x=x+1
if x=12 then x=0
@ INT_RETURN

OldMarty
- 13th July 2016, 08:18
I guess what i'm really asking is how to setup my loop(s) in an order from most-used tasks (update LEDs) to least-used tasks (read pots/switches) and process them all in a way that keep it running smooth and not flickering.

This is for ALL my coding in future projects, not just limited to a LED chaser as per my initial example.

I want to master "correct structure" to keep my code running efficiently. (please don't suggest C or asm, it's my structure that needs to be revised, not the platform i program with, my coding will STILL be crappy & flickery in C or asm lol)

richard
- 13th July 2016, 08:34
produce some code and post it for comment

tumbleweed
- 13th July 2016, 10:30
...LEDs need to look like they're stable, not flickering due to the speed of the matrix scanning being interrupted by the code going to process a pot-change etc.

You might be looking at this the wrong way around and have the stuff you're doing in the interrupt and the main loop backwards.

I usually reserve using interrupts for events that must be done at a high priority, and leave the not so important things that aren't as time sensitive and can wait a bit for handling in the main loop.

For example, the matrix scanning would be done by a timer ISR running fast enough to do the scanning w/out producing any flickering (like Richard's charlieplexing routine)
All the other stuff would be done by polling in the main loop ie looking for key press, reading knobs, etc. That way no matter what your main loop is doing the matrix scanning always gets done when it needs to.

OldMarty
- 13th July 2016, 15:06
You might be looking at this the wrong way around and have the stuff you're doing in the interrupt and the main loop backwards.

I usually reserve using interrupts for events that must be done at a high priority, and leave the not so important things that aren't as time sensitive and can wait a bit for handling in the main loop.

For example, the matrix scanning would be done by a timer ISR running fast enough to do the scanning w/out producing any flickering (like Richard's charlieplexing routine)
All the other stuff would be done by polling in the main loop ie looking for key press, reading knobs, etc. That way no matter what your main loop is doing the matrix scanning always gets done when it needs to.


Yes, perhaps i was looking at it all "backwards" hence my overall question of how people prefer to keep busy code running smoothly ;-)

Jerson
- 13th July 2016, 15:50
Co-operative multi-tasking is the way to do it. Every task that you want to execute has to execute in a RTC(run to completion) manner. You should write tasks in such a way that no single task ever blocks(hogs the CPU). Every person may implement this differently. Most will prefer the super-loop structure of task management in tiny embedded systems. Medium / large embedded systems can afford the use of RTOSes since they have sufficient memory to handle such overheads.

A good way would be to read up on ProtoThreads and see how they mangle C to implement the super-loop task management. Wikipedia might help for information on co-operative multitasking.

Art
- 13th July 2016, 16:21
There are a bunch of PBP commands which cause delay which you can’t use, Pause being a good example,
or at least not with a high value behind it :D
and some commands that need to be used a particular way which is always contrary to the manual,
in a manner that only deals with bytes at a time. Any serial command is a good example of that.

For the LED display I don’t think any of these enter into it.
Assuming just a loop, your program would be something like:



Set up an initial graphic frame
cycle:
Draw the frame to the LED display
Delay to display the frame to the User
Read input from buttons/interface
Process the next frame based on input and/or the program
goto cycle


As the program progresses it may be the last step increases time to execute,
and the deliberate delay can be shortened or eliminated.
For an LED display it may or may not be helpful to use a timer for the framerate,
but that doesn’t really relate to your question.

OldMarty
- 14th July 2016, 04:46
Thanx so much for everyones input, something for me to consider and learn mroe about, i'd never even heard of co-opeartive multitasking, let along how to implement it in a pic/picaxe lol. (more reading for me).

Overall, to simplify my initial question/example, I wanted to know what preferred methods programmers use when it comes to nesting loops and how to interlace them in order of importance, like loop 1 (main) is the housekeeping loop, loop2 is the led matrix data, loop 3 and 4 read posts & switches, then a preferred structure of how loop1,2,3&4 would nest together for fastest (least interruptions) code operation.

I'm feeling Co-op multitasking is perhaps the best solution to consider? unless there's a general rule of thumb about nesting loops nicely to share time with eachother?

Thanx again,
Marty.