Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 09:14 01 Aug 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 : MM feature request

     Page 1 of 2    
Author Message
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 5089
Posted: 11:55am 01 Feb 2019
Copy link to clipboard 
Print this post

@Geoff, Matherp,

I've been working with Arduino, MicroMite (and Maximite) and Picaxe for years.
But only recently I discovered that the PICAXE can do multitasking.

I was working on a (more or less real time) control function, and had to add human controls (keys, leds, display). I decided for the first time to use multitasking (this picaxe (18M2) knows up to 4 tasks). And it worked wonderfull. Even when I added delays for key debounce in the keyboard scan task, the fast main control loop did not show any iregularities (well...minor ones...).

I know Micromite basic can achieve similar functionality since it can work with interrupts, and interrupts on timers, but it is not quite as simple as having multitasking. MMbasic is also far more powerfull, so it is possible this cannot be implemented easily.

I am posting this since I was stunned by the fact that it was soo simple to abstract functions without having to worry about real time issues. It would be great if MMbasic could offer such comfort.

as far as I understand on picaxe multitasking
- the picaxe interpreter switches tasks the moment it finalizes one basic command, so the task switching is depending on the complexity of the command, and the time it takes to execute.
- there are excemptions for some commands: timed delays, RS232 communication (buffers?). It is documented that timed delays become more inaccurate.
- tasks can be started, suspended, resumed, and restarted
- the picaxe does not support local variables. all is global.

Can MMbasic become MMMbasic ? (MicroMiteMultitasking)....

Volhout







PicomiteVGA PETSCII ROBOTS
 
viscomjim
Guru

Joined: 08/01/2014
Location: United States
Posts: 925
Posted: 12:22pm 01 Feb 2019
Copy link to clipboard 
Print this post

I am not really familiar with picaxe, but the 18M2 is just an 8 bit 16F1847 with a single core running at a max speed of 32mhz, so I don't know how they are doing parallel processing. The only way I can image this working is using a "state machine" type of way. I have used THIS type of logic with the timer function on the MM before and this "simulates" multi tasking using different timed intervals to switch between different operations. This method may be the way picaxe is doing it "behind the scenes"? Not sure, but a theory. This can also be done with MMbasic. Of couse, MM can also process interrupts and handle serial comms, PWM, etc. while continuing to run the main program.Edited by viscomjim 2019-02-02
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3292
Posted: 12:27pm 01 Feb 2019
Copy link to clipboard 
Print this post

Aaaggghhh!! That is quite a feature.

It is not possible on the 28 and 44-pin Micromites (not enough flash) but I will think about it for the MM+. Multitasking is not easy, for example, what if two different tasks are trying to execute the same loop at the same time? Then you need interprocess communications (semaphores, etc), wait on events, etc... not easy.

I am guessing that the PICAXE implements a very limited version of multitasking. That would be easier, For example, it would be easy to simply have four program pointers and switch between them in round robin style and leave the BASIC programmer to figure out the issues. But would it be really useful?

Hmmm...
Geoff Graham - http://geoffg.net
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 4044
Posted: 12:56pm 01 Feb 2019
Copy link to clipboard 
Print this post

No doubt it would be useful.

It will also simplify some programming needs and the code.

Without proper semaphores etc sooner or later various people will hit bugs that will be "hard" to find, until they grasp why those things are needed.

With semaphores etc sooner or later someone will rediscover deadlocks.

Still, sounds worth adding. Good luck with suitable warnings or just provide URLs to articles about semaphores etc.

You're likely to need one (MMBasic) stack per task but with enough extra RAM that's just a detail.

Quite which task you take an interrupt in may be interesting especially if it's whichever one happens to be active i.e. it varies...

John
 
CaptainBoing

Guru

Joined: 07/09/2016
Location: United Kingdom
Posts: 2170
Posted: 01:14pm 01 Feb 2019
Copy link to clipboard 
Print this post

I suspect the multi-tasking isn't really as it won't be event driven with the processor sitting parked (i.e. halted) and only bursting into life when something comes along. You still have a loop of some sort executing. Happy to be wrong.

There may be time-slicing (which is just about the only way to do it with a single core) but even then the processes are not truly running simultaneously, it's just switching rapidly between different sections of code... did a similar thing on a bespoke Z80 kernel back end of the 80's. Unless the tasks are doing something where there is a lot of waiting involved (like serial I/O) then the two tasks will take the same time to run sequentially as in parallel (actually a bit longer as there is switching overhead). Again, happy to be wrong.

If you have an immediate need, consider state machine methodology. This way you have a lean main loop that just services flags/pins and calls separate subs to do the work (bonus: it makes it a doddle to debug your stuff). When done well (by which I mean don't be tempted to make your service/main loop do anything except service your stimuli), it can end up "looking" like m/t quite convincingly. As an example; at a very low level, proper serial I/O routines do this by not waiting for characters to go before sending the next one (I #*%$! hate code like that). They load a register then either poll or get interrupted by a flag saying "ready for the next". You call the sub to load the next char from the buffer. If you consider a 9600 baud link can take a milli-second per character - if you are just waiting around that is a massive waste of compute.

my 2p
Edited by CaptainBoing 2019-02-02
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 5089
Posted: 01:33pm 01 Feb 2019
Copy link to clipboard 
Print this post

@JohnS,

Yes, you definitely need semaphores in your basic code.
If you are altering data in one task, you need a flag (semaphore) to indicate new data is available, since the other task could use invalid data (worst case: while the data is being changed, so it is neither old nor new).

So the one who writes the code must be aware of that. In my case it was very straightforward: the keyboard task set's a semaphore when it has a a new key, the main task clears the semaphore when it accepts the key.

But imagine how you would do this same piece of code in a "linear" basic program. Matrix scanning a keyboard with deboucing -and- a control loop for a PID. You would almost have to integrate the keyboard scan into the control loop. Or a pretty complex timed interrupt routine...for the PID algorythm (because the PID is more time critical than the keyboard scan).

No doubt the interpreter also needs semaphores, and probably every task needs it's own stack. But it could very well be that they use exctly what Geoff hinted. A program pointer list that the interpreter cycles through.



PicomiteVGA PETSCII ROBOTS
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 4044
Posted: 01:37pm 01 Feb 2019
Copy link to clipboard 
Print this post

  Volhout said   @JohnS,

Yes, you definitely need semaphores in your basic code.
If you are altering data in one task, you need a flag (semaphore) to indicate new data is available, since the other task could use invalid data (worst case: while the data is being changed, so it is neither old nor new).

So the one who writes the code must be aware of that. In my case it was very straightforward: the keyboard task set's a semaphore when it has a a new key, the main task clears the semaphore when it accepts the key.

But imagine how you would do this same piece of code in a "linear" basic program.

You just use a state machine along the lines of ones which people have even posted from time to time.

John
 
lizby
Guru

Joined: 17/05/2016
Location: United States
Posts: 3378
Posted: 02:13pm 01 Feb 2019
Copy link to clipboard 
Print this post

  Geoffg said  For example, it would be easy to simply have four program pointers and switch between them in round robin style and leave the BASIC programmer to figure out the issues. But would it be really useful?

Hmmm...

This is basically what the picaxe "multi-tasking" does. Nothing is parallel; the multiple tasks are executed round robin style. The 18M2 has multiple "slots" which may have separate programs (with shared variables). I'm not sure whether a slot gets to execute for a certain period of time or one command at a time before the next slot program pointer is used.

PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 5089
Posted: 02:17pm 01 Feb 2019
Copy link to clipboard 
Print this post

Hi JohnS,

Always happy to learn about state machines, so please explain.

Let's assume we want to generate a 50Hz square wave that we can stop and start with 2 buttons. This is more or less exactly the picbasic code. I know MMBasic has PWM's that can handle it, so has the picaxe, this is just to explain how simple it is to abstract two processes. Would be a lot harder in a state machine I guess.


start0
do
if stop=1 then
out=low
else
out=low
delay 10
out=high
delay 10
end if
loop

start1
do
if stopkey=1 then
stop=1
do
delay 50
loop until stopkey=0
if startkey=1 then
stop=0
do
delay 50
loop until startkey=0
delay 50
loop


This code is not documented, but it is not very difficult to understand. Happy to explain if required.
By some stupid reason the indenting disappeared....Edited by Volhout 2019-02-03
PicomiteVGA PETSCII ROBOTS
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 4044
Posted: 02:26pm 01 Feb 2019
Copy link to clipboard 
Print this post

OK, so I used google and about the first thing it got was this

Or for the general idea this

A multi-tasking MMBasic will obviously run somewhat slower and use more RAM but on the bigger CPUs those wont matter. Clearly up to Geoff to decide what he wants and feels is appropriate. Quite a lot of the internals will need rewrites but many are trivial.

(On the basis this is pseudo-multi-tasking i.e. one thread switched across multiple tasks, rather than using a multi-CPU and a thread per CPU. I don't think there's a rush to go the whole hog.)

JohnEdited by JohnS 2019-02-03
 
MicroBlocks

Guru

Joined: 12/05/2012
Location: Thailand
Posts: 2209
Posted: 04:09pm 01 Feb 2019
Copy link to clipboard 
Print this post

I go around all of it by using events with timer ticks and interrupts.
Sure it is not multitasking but it comes close enough.

Timings should never be done by using delays but rather with timer ticks.


Simplest form is to update a counter each time a timer tick happens, and with each value of that counter call a specific function.
You can then have one to hundreds of "tasks" depending on your needs.



Edited by MicroBlocks 2019-02-03
Microblocks. Build with logic.
 
CaptainBoing

Guru

Joined: 07/09/2016
Location: United Kingdom
Posts: 2170
Posted: 04:51pm 01 Feb 2019
Copy link to clipboard 
Print this post

@Volhout

for the problem you have, the state machine would look something like the below... note how the main loop does nothing but respond to stimuli. SUBs become true sub-programs and are responsible for the work... everything communicates with everything else by setting flags (semaphores) or some other stimulus.


Main:
Do
If Button1 Then OutputStart
If Button2 Then OutputStop
Loop


Sub OutPutStart
PWM 1, 50, 50 ' Freq=50Hz, 1A=50%
End Sub

Sub OutputStop
PWM 1, STOP
End Sub



The temptation to look at the above is to ask "why no just put the 'active' bits of the code in the If statements?" - that is a factor of the simplicity of the task. What the FSM approach does is apply a container approach...even the above is not strictly FSM - a better version would be... (also notice also the order you put the flag processing decides also the priority - if you hold both buttons down the process is stopped)


Main:
Do
If Button1 Then Flag=1
If Button2 Then Flag=0


If Flag=1 Then OutputStart
If Flag=0 Then OutputStop

Loop



Sub OutPutStart
PWM 1, 50, 50 ' Freq=50Hz, 1A=50%
End Sub

Sub OutputStop
PWM 1, STOP
End Sub



The reason being that any part of your code can start or stop the output simply by setting the flag. The button press (and it's detection) serve only to set the flag... anything could conceivably set that flag, not just a button... a character received on the serial port, another Sub... and it all gets handled by the main loop - nothing is allowed to call an "active" piece of code apart from the main loop - if you want something doing, you have to set the semaphore and let the service loop deal with it.

I do this all the time, Here's a section of code from one of my projects which uses the service loop to switch the external hardware. I do this because it suits - the early section of the loop checks for messages in a serial comms channel and processes the flags, the latter part acts on them:



...
Case "U" 'door up
q$= "Answering Door Up"
DoorUpRequest
IntLightSetAuto
ExtLightSetAuto

... and the associated subs...


Sub DoorUpRequest
If (FlagTest(DoorUp)=0) And (FlagTest(DoorUpMoving)=0) Then 'if we are not already moving UP
Release
FlagSet DoorUpMoving
After DoorMovePeriod,DoorMoveTimer
Else
q$= "Ignored (flags)"
Endif
End Sub

Sub IntLightSetAuto
FlagRes IntLightON
FlagRes IntLightOFF
FlagSet IntLightAUTO
FlagRes ExtLightFLASH
End Sub

Sub ExtLightSetAuto
FlagRes ExtLightOR
If FlagTest(DoorDown) Then
FlagRes ExtLightONEnable
FlagSet ExtLightOFF
Else
FlagRes ExtLightOFF
FlagSet ExtLightONEnable
EndIf
End Sub


... and then in the main/service loop... just one, bit...

'process states
'door moving states
If FlagTest(DoorUpMoving) Then
Pin(DoorUp)=DoorActive
EndIf


notice how none of the subs do anything but set semaphores for each other. Only the main loop does anything "active" - like actually switching things on or off

This might all look a bit long winded but it pays dividends because as you add functionality to a larger project, you write the sub that does the logic (and sets the flags to communicate with other sections of your prog) and it doesn't knock anything else out of place. Then you only have to test a single flag in Main to decide if you have to do something. and no Spaghetti code! all in nice neat little piles.

The approach might not suit small projects but I find it is worth the effort because even little jobs tend to grow organically and if you follow this method, all you have to do is write the sub and then process a flag to trigger it.

Also I would recommend you have flags for every state i.e. a separate flag for on and another for off - I like to deal with absolutes but it doesn't suit everyone.

Edited by CaptainBoing 2019-02-03
 
vegipete

Guru

Joined: 29/01/2013
Location: Canada
Posts: 1132
Posted: 07:07pm 01 Feb 2019
Copy link to clipboard 
Print this post

Years ago I did some programming on a Rabbit processor (sort of Z80ish) using Dynamic C. This variation of C had a sort of multi-tasking built in. I found the user's manual multi-tasking chapter here which might offer some ideas or suggestions.
Visit Vegipete's *Mite Library for cool programs.
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 4044
Posted: 07:54pm 01 Feb 2019
Copy link to clipboard 
Print this post

Given the choice I'd always use multiple tasks rather than a state machine and so in the past have more than once put together a small OS - small enough to be handy but quick to write.

However, whereas I'm a full-time software guy, the attraction of BASIC is that it can be used by just about anyone. So, if it gets multi-tasking it probably ought to be something simple to understand. No doubt Geoff can do such a thing if he wishes.

John



 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 5089
Posted: 08:11pm 01 Feb 2019
Copy link to clipboard 
Print this post

All,

Previous post contained something that looks like picaxe code, but was I could remember doind while riding a train and typin on a mobile phone.

This is working code (just for completeness).
I think it got some people thinking.
I do understand stete machines a bit better now, so will try to master it.

But simplicity....

' symbol declaration
symbol bStop = b0
symbol bOut = B.0
symbol bStopKey = pinB.1
symbol bStartKey = pinB.2

' task 0 : generate 50Hz square wave
' or do other real time stuff
start0:
do
if bStop=1 then
low bOut
else
low bOut
pause 10
high bOut
pause 10
end if
loop

' task 1 : completely unrelated check keys
' debounce (blocking) without affecting task 0
start1:
do
if bStopKey=1 then
bStop=1
do
pause 50
loop until bStopKey=0
end if

if bStartKey=1 then
bStop=0
do
pause 50
loop until bStartKey=0
end if
pause 50
loop


imagine writing code for a game.....

start0:
do
play music
loop

start1:
do
check_for_collisions
loop

start2:
do
read keyboard or game paddle
loop

start3:
do
process movements
update screen
loop


Edited by Volhout 2019-02-03
PicomiteVGA PETSCII ROBOTS
 
CircuitGizmos

Guru

Joined: 08/09/2011
Location: United States
Posts: 1427
Posted: 08:49pm 01 Feb 2019
Copy link to clipboard 
Print this post


  A very capable, generous, and smart man said  
So, with any new feature I consider:
- Will a significant number of people use it?
- Can it be done using the current features of MMBasic?
- Does it fit with the "look and feel" of the BASIC language?
- Will it be really useful?



I personally think that with good programming practices and skill "multitasking" is already in MMBasic.

I can't imagine the bugs that this might introduce.

Micromites and Maximites! - Beginning Maximite
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9610
Posted: 09:45pm 01 Feb 2019
Copy link to clipboard 
Print this post

Interesting idea. Those for it will always have plenty of reasons why it should be included, and those against will have similar reasons - you can't win.

I do have to kinda agree with CG above though. The OP mentions the PICAXE using a slot to do the keypad thing. Well, that is easy-peasy to do in MMBASIC via the KEYPAD command interrupt. It will scan the keypad matrix in the background and generate an interrupt whenever a key is pressed. All you have to do in the interrupt, is read the value of the key and return from the interrupt - all pretty quick and seamless, and certainly no need to scan the matrix within your main loop or anything.

I am certainly not an expert coder, so there may be things I am perhaps not seeing in my interpretation of things.
Smoke makes things work. When the smoke gets out, it stops!
 
JohnL
Senior Member

Joined: 10/01/2014
Location: Seychelles
Posts: 128
Posted: 10:17pm 01 Feb 2019
Copy link to clipboard 
Print this post

https://www.freertos.org/

Free rtos has been around for ages and is very mature and solid, does not need much overhead, obviously will not fit in small micromites. Used by heaps of other microcontroller platforms.

If I was Geoff I would have considered splitting MMbasic into separate underlying OS, doing all the hardware and system servicing, then Basic interpreter on top as a programming language. This may mean starting with clean sheet of paper, but if done correctly would offer more flexibility and other possibilities.
 
flip
Senior Member

Joined: 18/07/2016
Location: Australia
Posts: 114
Posted: 10:29pm 01 Feb 2019
Copy link to clipboard 
Print this post

I posted a simple multi-tasking program back in Simple Multi-Tasker

It's just a demo and very rough and slow...you can tab between windows, type text in them and press Function keys along bottom of screen to start scroller...have since made improvements but no means ready for posting...
regards Phil
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 4044
Posted: 10:35pm 01 Feb 2019
Copy link to clipboard 
Print this post

Something as simple as multi-tasking doesn't need an entire OS.

Though it could also be a way to get semaphores etc. And some more things like task with different priorities.

It's possible to argue that the existing interrupt features can (and sometimes do) get people into trouble so maybe it would be better to multi-task.

At some point it stops being a simple easily understood variant of Basic I expect. (Maybe it stopped already?)

John
 
     Page 1 of 2    
Print this page
The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025