Multitasking library and example.

Santiago
2009-03-25
2013-05-30
  • Santiago

    Santiago - 2009-03-25

    I started to work with multasking afther reading viper7882 thread:
    https://sourceforge.net/forum/forum.php?thread_id=2055691&forum_id=629990

    I think multitasking is a very powerfull thing, but when you have 6 or 7 task running, the GCBasic code is a mess of variables, counters, flags, interrupts... etc.

    Then, for keep a simple GCBasic code i wrote a library for using multitasking in the easy way.
    This library can manage upto 8 tasks, but can grow to any number you want.
    The base-time is established to 10 ms to have a big gap-time to run long routines that can take a lot of clock-cicles. Anyway the base-time can also be changed.

    There is a "multitasking.h" file that contain the functions, and some notes about how it works and how to modify it.
    And a "multitask_example.gcb" : an example of use with some explanations; this example blinks 3 leds at different speeds, one blinks every 1s, other every 600 ms, and the third blinks in a period determined by the readed ADC value.

    You can download files here:

    https://sourceforge.net/project/showfiles.php?group_id=247157

    Any feedback will be apreeciated.

    Greetings.

     
    • Deepak Chatwani

      Deepak Chatwani - 2009-03-25

      Hello,

      I have downloaded multitasking library and it works perfectly.

      I am developing RGB LED controller using PWM with this library.

      Is it possible to use PWM with this library ?

      Pls. reply.

      Thank you very much for contribution with GCbasic.

      Regards,

      Deepak Chatwani

       
    • Santiago

      Santiago - 2009-03-25

      Hi Deepak. Thanks for the feedback.

      I think it should not be problem using hardware pwm, i tried it with multitasking, but not with this library.

      For short tasks it should not be problem, for long tasks sometimes is better using several short tasks than one long task, or using one long task with sub-tasks inside activated by flags: in the first cicle run first sub-task and activate second sub-task flag, in next cicle run second sub-task and activate third sub-task flag...

      The cuestion with multitasking is that sometimes it just doesn't work, or it work for some seconds (or even minutes) and then just stops... like a PC. This happend to me with many long tasks running at a time at very short time periods, then the pic just stalls; that's why i used a 10 ms base-time instead of 1 ms or less.
      The good thing is when the time needed to run all tasks is less than 10 ms.

      Sometimes it can be helpfull add an "offset" to tasks that have the same period; for example if you have several long tasks with a 100 ms period, you can avoid all the tasks to be executed is the same loop-cicle by setting an initial value to the task-counter, something like this:

      '------------------------ TASK's DEFINITIONS ----------------------------
      '------------------------------------------------------------------------

      #include <multitasking.h>

      #define Task1 led1      'Task subroutine
      time_Task1 = 10        'x10 ms = task will run every 100 ms
      cont_Task1 = 6 '60 ms offset

      #define Task2 led2
      time_Task2 = 10
      cont_task2 = 3

      #define Task3 led3
      time_Task2 = 10
      __________________________________________________________

      This three tasks will run with the same period (100 ms), but at different moments.

      What i do for testing purposes or even for definitive circuits is using a task as "life-led", that's a blinking led at a 500 ms toggle period, this way i know that multitasking is working and i can see that the running speed is as i expected (led on, every 1s).

      Multitasking can be very complex... then the goal is using an RTOS.

       
    • Santiago

      Santiago - 2009-03-25

      I forgot to say that you can use the library as a pwm generator, but perhaps for this you need to use a smaller base-time...

      If this is what you are talking about you need edit multitasking.h to have por example an 1 ms base-time; in the file there are some brief explanations about where are the lines to edit; if have some cuestion about this let me know...

      Greetings.

       
    • Santiago

      Santiago - 2009-06-01

      There is a new version of this multitasking library.

      Now is possible up to 16 tasks and 8 long-task (for long period tasks).
      LTasks, for long period: upto one hour with 4 Mhz clock and 65535 us base time; but depending on the base time and the used clock.

      Is also possible (needed indeed) to set the base time in your program so you can change it easily.

      Is possible to set the period of tasks in us, ms, s, instead of number of cicles.

      There is an example too.

      Download here:
      https://sourceforge.net/project/showfiles.php?group_id=247157

      These are the explanations included in the file:

      '_______________________________________________________________________
      '
      '

      'Notes:
      '
      '¡¡¡¡¡ this library will use Timer0, don't use it in your program !!!!!.
      '
      'Actually a maximum of 16 Tasks and 8 LTasks are supported.
      '
      'The base time must be defined:
      '
      '#define base_time value

      'where value is the desired value in us, for example:
      '
      '#define base_time 100      'for 100 us

      'Maximum base_time value with 20 MHz clock is 13107.
      'Maximum base_time value with 4 MHz clock is 65535.
      'Maximum base_time value with other clocks: 65535/ChipMhz/4.
      '
      '
      'The subroutine containing each task must be defined:
      '
      '#define Task1 Sub_name1
      '#define Task2 Sub_name2
      '#define LTask1 Sub_name3
      '
      '
      'The period of each Task must be defined:
      '
      '#define Task1_us 500            'Task1 period is 500 us
      '#define Task2_ms 10             'Task2 period is 10 ms
      '#define LTask1_s 1                'LTask1 period is 1 s
      '
      'In the previous example, Sub_name1 will be executed every 500 us,
      '   Sub_name2 every 10 ms and Sub_name3 every 1 S.
      '
      'Maximum value for Task period in us is: base_time*255
      '
      'For example, with a 100 us base_time,
      '   maximum value for Tasks is: 100*255 = 25500 us => 25 ms
      '
      'LTask is for long period tasks,
      '   a period is long or not depending on the base_time
      '   When the needed period > base_time*255 then you need a LTask
      '
      'Maximun value for LTask period in us is: base_time*65535
      '
      'For example, with a 100 us base_time,
      '   maximum value for LTasks is: 100*65535 = 6553500 us => 6553 ms => 6 s
      '
      '
      'Task will be executed with the command: Do_Taskx,
      '   for example  in a main loop:
      '
      'do
      '    Do_Task2
      '    Do_LTask1
      'loop
      '
      'or any other way... for example:
      '
      'do
      '    Do_Task2
      '    if PORTB.0 on then Do_LTask1  
      'loop
      '
      '
      'Is possible to execute a Task inside Interrupt subroutine:
      '
      '#define Run_Task1               'Run Task inside interrupt subroutine
      '
      '_______________________________________________________________________

       
    • Nobody/Anonymous

      This is interesting and seems better than Internet Lam – viper7882 code, because it is possible to run tasks outside interrupt. Keep going!

      I will try to contribute some ideas, asm and BASIC code for this project as soon as I have some time for this.

       
  • Nobody/Anonymous

    where is that library? can't find it. :-(

     
  • Santiago

    Santiago - 2009-10-26

    Example program:

        '----------------- CONFIGURE MICRO -------------------
        '------------------------------------------------

        #chip 16F876A, 4       

        #config HS_OSC, WDT_OFF, LVP_OFF, PWRTE_ON

        '---------------- TASK's DEFINITIONS -------------------
        '------------------------------------------------

        #include &lt;multitasking.h&gt;

        #define base_time 500       'base_time in us

        #define Task1 read_input
        #define Task1_us 500        'Task period in ms

        #define LTask1 led1         'Task subroutine
        #define LTask1_s 1          'task will run every 1 s
        #define Run_LTask1          'Run Task inside interrupt subroutine

        #define Task2 led2
        #define Task2_ms 100        'task will run every 100 ms

        #define Task3 led3          'we will have the time from ReadAD

        '--------------------- MAIN -----------------------

        '------------------------------------------------

        Dir PORTA.0 in
        Dir PORTB out

        do
            Do_Task1
            Do_Task3
            Do_Task2
        loop

        '------------------- TASK's SUBs ---------------------
        '------------------------------------------------
        Sub read_input
            time_Task3 = ReadAD(AN0)    'set led3 period to the AD value
        End Sub

        Sub led1
            PORTB = PORTB xor 1 'toggle led on bit 0
        End Sub

        Sub led2
            PORTB = PORTB xor 2 'toggle led on bit 1
        End Sub

        Sub led3
            PORTB = PORTB xor 4 'toggle led on bit 2
        End Sub

     
  • Santiago

    Santiago - 2009-10-27

    The previous example blinks 3 leds at diferent speeds: led1 at 1 Seg, led2 at 100 ms and led3 at a variable speed depending on ADC readed value.
    The good thing is that you can now add new tasks and the blinking leds will not be afected. They looks to work &quot;simultaneously&quot;.

    This is another example that use multitasking to generate pwm signals.
    It blinks one led (lifeled) at 500 ms  rate at RA0, and drive 8 leds using software pwm signals.
    This is a simple example, but i did a larger version controlling 64 leds directly (not a matrix) using shift registers.

        '----------------- CONFIGURE MICRO -------------------
        '------------------------------------------------
        #chip 16F627, 4        'modelo de pic y velocidad de reloj
        #config HS_OSC, WDT_OFF, LVP_OFF, PWRTE_ON

        '---------------- TASK's DEFINITIONS -------------------
        '------------------------------------------------
        #include &lt;multitasking.h&gt;

        #define niveles 20                          'light (pwm) levels

        #define base_time 1000                      'base_time in us

        #define Task1 rota_leds
        #define Task1_us 255*base_time              'Task period in us

        #define Task2 calc_output
        #define Task2_us base_time        

        #define Task7 pwm_period                    'pwm period for all leds
        #define Run_Task7                           'Run Task inside interrupt subroutine
        #define Task7_us niveles*base_time          'pwm period = resolution * base time

        #define LTask1 life_led                     'LTask is for long period tasks
        #define LTask1_ms 500                       'use LTask when period &gt; base_time*255

        '------------------- REGs DEFs ---------------------
        '------------------------------------------------
        #define total_regs  7
        #define registro    77 - total_regs

        '--------------------- MAIN -----------------------
        '------------------------------------------------
        TRISA = 0
        TRISB = 0

        for contador = 0 to total_regs
            FSR = registro + contador               'Store initial values
            INDF = (contador*contador)/3
           
            puerto = puerto xor 255                 'Blink leds
            wait 200 ms
        Next

        wait 500 ms

        do                  'Main Loop
            Do_Task1
            Do_Task2
            Do_LTask1
        loop

        '------------------- TASK's SUBs ---------------------
        '------------------------------------------------
        Sub rota_leds  
            for contador = 0 to total_regs
                FSR = registro + contador
                prev = INDF
                INDF = regprev
                regprev = prev
            Next
        End Sub

        Sub calc_output
                lectura = 0
                FSR = registro
                if INDF &gt; cont_Task7 then lectura.0 = 1
                FSR += 1
                if INDF &gt; cont_Task7 then lectura.1 = 1
                FSR += 1
                if INDF &gt; cont_Task7 then lectura.2 = 1
                FSR += 1
                if INDF &gt; cont_Task7 then lectura.3 = 1
                FSR += 1
                if INDF &gt; cont_Task7 then lectura.4 = 1
                FSR += 1
                if INDF &gt; cont_Task7 then lectura.5 = 1
                FSR += 1
                if INDF &gt; cont_Task7 then lectura.6 = 1
                FSR += 1
                if INDF &gt; cont_Task7 then lectura.7 = 1

                PORTB = lectura
        End Sub

        Sub pwm_period                   'this task is just needed to have the cont_Task7 counter
            nop
        End Sub

        Sub life_led
            PORTA = PORTA xor 1          'Blink led at RA0
        End Sub

    Here you can see the effect in a video:

      : http://piclinux.sourceforge.net/files/videos/rot-led.ogg &quot;Ktechlab-gcb simulation&quot;

     
  • Nobody/Anonymous

    I compiled an example PWMLEDS. Used assembly file with MPLAB and got:
    Error   C:\PROGRAM FILES\GCBASIC\EXAMPLES\PWMLEDS\PWMLEDS.ASM 417 : Symbol not previously defined (SYSCOMPLESSOREQUAL16)
    Commented out "call SYSCOMPLESSOREQUAL16", programmed PIC, works fine. Where this statement is coming from?
    Otherwise great job, very useful multitasking library, thanks.

     

Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks