Flashing Three LED's

ronsimpson

Joined Oct 7, 2019
4,703
I don't know what your point is
The computer does not think in mSs. It might think how many instructions it takes to do a job. In this case it thinks in interrupts. I see software people converting in to and out of mS several times to get an answer. Just think in interrupts. Don't think "I am at 293.596mS". Think "this LED has been on for "5 ticks" or 5 interrupts, what should I do?
 

ApacheKid

Joined Jan 12, 2015
1,762
I'm trying to write general non blocking code logic for three LED, Not for specific uC and compiler. #There are 3 LED, numbered 1, 2 and 3.

Description of problem
  • Flash LED 1 once for 200 ms time period every 250 ms
  • Flash LED 2 once for 400 ms time period every 500 ms
  • Flash LED 3 once for 600 ms time period every 750 ms
Timer interrupt generates every 10 ms

Here is my planning with pseudocode. I'm stuck with LED flashing function logic and I don't have any idea how do it
C:
LED1
LED2
LED3

#define  True          1
#define  SET           1
#define  RESET         0
#define  OFF           0
#define  CLEAR         0

void main ()
{ // main start from here
    LED1 = OFF ;
    LED2 = OFF ;
    LED3 = OFF ;

    unit8_t Time_Flag = CLEAR;

    unit8_t LED1_Deadline_Time =  CLEAR ;
    unit8_t LED2_Deadline_Time =  CLEAR ;
    unit8_t LED3_Deadline_Time =  CLEAR ;

    while ( True )
    { // while Loop start from here
      if (Time_Flag == SET)
      {
        if ( LED1_Deadline_Time == 200 )  // Always check deadline time for LED1 if match
        {
            LED1_Flashing();
            LED1_Deadline_Time = RESET;
        }

        LED1_Deadline_Time++;

        if ( LED2_Deadline_Time == 400 )  // Always check deadline time for LED2 if match
        {
            LED2_Flashing();
            LED2_Deadline_Time = RESET;
        }

        LED2_Deadline_Time++;

        if ( LED3_Deadline_Time == 700 ) // Always check deadline time for LED1 if match
        {
            LED3_Flashing();
            LED3_Deadline_Time = RESET;
        }

        LED3_Deadline_Time++;
      }

      Time_Flag = CLEAR ;

    } //while Loop End here

}// main End here

// interrupt every 10ms
void ISR_Timer_Interrupt ()
{
    if ( T1IF = SET )
    {
        Time_Flag = SET;
        T1IF = CLEAR;
    }
}
I think you are right to try to solve the problem in a kind of abstract way, without too much specifics about this or that CPU etc.

One way to approach this is to pretend there is only one LED, if we can solve the problem for one then perhaps three is just a matter of doing the same thing.

My intuition here say that we have a real timer - the 10 mS one - and then devise a "virtual" timer that represents the details for LED events and then setup three (or maybe six) of these "virtual" timers.

Then on every real timer interrupt we scan through the list of virtual timers, each one representing one of the LEDs, this is kind of how a small OS might do this.

The virtual timer can just be a structure and we can have a list or even just an array of these. The problem also suggest that when a virtual timer expires the code that runs when it expires, could create a new virtual timer or perhaps enable another.

So for LED1 you want "Flash LED 1 once for 200 ms time period every 250 ms".

This is a timer - call it TimerA, setup to "wait" for 250 mS, I see this as being a non repeating timer.
At the end of 250 mS the handler for the expiration lights an LED and activates another timer TimerB with 200 mS period, again, no concept of auto repetition.
At the end of 200 mS the handler for the expiration shuts off the LED and activates TimerA with a 250 mS period.

This will run continuously and if the code handles one it can handle many, three being no issue, what a timer expiry does is is secondary to this overall design.

But am I understanding the time correctly? you want LED1 to be OFF for 250 mS then ON for 200 mS then OFF for 250 mS...

Forget about the details how we'd implement a "virtual" timer for now, just pretend it is available and solve the problem - conceptually - using the idea, if the solution seems solid then you can worry about how to actually implement the virtual timer.

(I'm regarding your 10 mS timer as being analogous to an OS clock and the virtual timers as software abstractions like for example a Timer in .Net for example).
 

ApacheKid

Joined Jan 12, 2015
1,762
So far as the implementation goes I am tempted to see it as a small API, perhaps:

1. CreateVirtualTimer
2. EnableVirtualTimer
3. DisableVirtualTimer
4. ResetVirtualTimer

For example.

We'd then create six of these (two per LED), then we'd enable three and be done.

As each of the three reaches its timeout (determined by the 10 mS handler code that scans the list) it will reset another timer, activate/deactivate the LED, enable that other timer.

Thus the timers are paired, one counts down, then expires, does something with its LED and resets and enables another timer, the pair of timers basically then play ping-pong, back and forth, over and over and the main code does none of the fiddling around with counting etc. Each timer lives in a very simple world, have I expired yet? no, do nothing, yes, change LED state, reset (I mean reinit) the other timer, enable that other timer. Here that timer is concerned only with setting an LED ON, it cares not about OFF, that for another timer to worry about!
 
Last edited:

Thread Starter

Sparsh45

Joined Dec 6, 2021
143
My intuition here say that we have a real timer - the 10 mS one - and then devise a "virtual" timer that represents the details for LED events and then setup three (or maybe six) of these "virtual" timers.

Then on every real timer interrupt we scan through the list of virtual timers, each one representing one of the LEDs, this is kind of how a small OS might do this.
Exactly my next target is six LEDs. There are two important things to remember.
  • Deadline for each LED
  • Execution Time (Flashing time of LED)

The program checks every 10ms which LED to pay attention. The program turns the LEDs on/off as needed

The virtual timer can just be a structure and we can have a list or even just an array of these. The problem also suggest that when a virtual timer expires the code that runs when it expires, could create a new virtual timer or perhaps enable another.
can you explain it a bit more for me. we have three timers which are incremented inside the ISR.

What is your idea how would you use all timers when it is list or array?

It would great help if you can post any code to understand your idea as i have done in my initial post
 
Last edited:

click_here

Joined Sep 22, 2020
548
If I understand click_here’s code correctly, in the short non-blocking code, the value of TICK should be set to TRUE. The rest is MCU specific
That's correct

It relies on a timer interrupt which sets "Tick" to true.


The best way of doing this using only interrupts is to find a PIC with 3 timers.

However, if you wanted to do this using one timer interrupt, I suggest a lookup table.

The period of each LED is
200mS + 250mS = 450mS
400mS + 500mS = 900mS
600mS + 750mS = 1350mS

The smallest amount of time that they all divide into is 2700mS.

2700mS/450mS = 6
2700mS/900mS = 3
2700mS/1350mS = 2

So every 2700mS the cycle starts again.

To represent 10mS, I am going to use "centi-seconds" cS - "Centi" means 1/100th. This is to fit into your 10mS interrupt requirement, or 1cS :)

So, how many bits of data would you need to cover the 270cS (2700mS)?

To make things tighter, but not too difficult, I'd recommend using a nibble (4 bits) for each state for the LEDs

So the first byte would have 2 cS in it...

0b00000000 -> 0b0000 & 0b0000

And each bit represents an LED state (with room for a 4th LED). The reason that I left that 4th bit there is so that it alligns better with the bytes.

0b00100011 would be 2 different centi-seconds
1cS -> 0b0011 -> LED3=off, LED2=on, LED1=on
2cS -> 0b0010 -> LED3=off, LED2=on, LED1=off

This means that you could do it with 270/2 = 135bytes.

And every cS you would just iterate through the table until you got to the 270 nibble and start again.


Would I recommend doing it this way? Well... no!

The reason is that the logic of the program is tightly dependent on those 3 periods. If any of them changed, it would mean a lot of work to get it up and going again. Where as using the method that I gave earlier it is just a simple change to the const int.
 

Thread Starter

Sparsh45

Joined Dec 6, 2021
143
Perhaps my biggest mistake is choosing an LED example for understanding multitasking that is creating confusion.

Let's assume that we have multiple tasks and each task has its own period. Each task needs to be completed within the time limit. Each task has a priority that should be followed.

multitasking example.jpg
I took this example from the internet

I assume 1ms system tick

LCM of the time period of all tasks is 12ms

12ms/4ms = 3
12ms/6ms = 2
12ms/12ms = 1

Maybe this will be a simple example to understand multitasking with a timer interrupt
 

ericgibbs

Joined Jan 29, 2010
21,452
Let's assume that we have multiple tasks and each task has its own period. Each task needs to be completed within the time limit. Each task has a priority that should be followed.
hi S45,
Be aware that multitasking is not related to none blocking coding.

Many MCU's have 'inbuilt' Low and High priority Interrupt, software controlling hardware
E

As a side study, look up RTOS.
 

ApacheKid

Joined Jan 12, 2015
1,762
Exactly my next target is six LEDs. There are two important things to remember.
  • Deadline for each LED
  • Execution Time (Flashing time of LED)

The program checks every 10ms which LED to pay attention. The program turns the LEDs on/off as needed


can you explain it a bit more for me. we have three timers which are incremented inside the ISR.

What is your idea how would you use all timers when it is list or array?

It would great help if you can post any code to understand your idea as i have done in my initial post
I'll draft some code in C, this is not going to be tested or specific to an MCU - but it will explain the design better for you.
 

Thread Starter

Sparsh45

Joined Dec 6, 2021
143
I'll draft some code in C, this is not going to be tested or specific to an MCU - but it will explain the design better for you.
Thanks for your valuable time. I will be happy to see your logic but write the logic for the description in post #28 instead of the LED because that example make more sense to me.
 

MrChips

Joined Oct 2, 2009
34,832
The pseudo code I posted in post #14 will work for any number of LEDs.
This is not a multitasking example.
Perhaps my biggest mistake is choosing an LED example for understanding multitasking that is creating confusion.

Maybe this will be a simple example to understand multitasking with a timer interrupt
Perhaps if you want to experiment with multitasking you should start a new thread.
 

Thread Starter

Sparsh45

Joined Dec 6, 2021
143
The pseudo code I posted in post #14 will work for any number of LEDs.
This is not a multitasking example.
I think both examples are multitasking examples I wonder why you don't consider the second example as multitasking example?

@MrChips Please explain reason ?

What's definition of multitasking for you ?

I call it multitasking when there is more than one task running on the micro.

Perhaps if you want to experiment with multitasking you should start a new thread.
OK, I'll do it
 

ericgibbs

Joined Jan 29, 2010
21,452
I call it multitasking when there is more than one task running on the micro.
Hi S45,
Please don't consider my posts as picky, but you must be more precise with your declarations.

What would you define as : more than one task running on the micro.

E
 

ApacheKid

Joined Jan 12, 2015
1,762
There is some ambiguity (to me!) in the details.

When this system begins are all LEDs initially OFF?

Also what does "every 250 mS" mean exactly? does this represent what's expected?

1640626181271.png

Think of the blue indicating that some handler runs briefly every 250 mS.

Think of red meaning the LED goes on for 200 mS then goes off, in this case it goes off 50 mS before the next run of the handler.

Just want to make sure I understand what's expected...
 

Thread Starter

Sparsh45

Joined Dec 6, 2021
143
There is some ambiguity (to me!) in the details.

Just want to make sure I understand what's expected...
That's why i told you to follow example in post #28

if you still want to ask for LED, Then please refer table given in post #19. If you still have any questions then feel free to ask me
 

ApacheKid

Joined Jan 12, 2015
1,762
That's why i told you to follow example in post #28

if you still want to ask for LED, Then please refer table given in post #19. If you still have any questions then feel free to ask me
OK I never noticed that table and other post.

So we want a 50% duty cycle for each LED, on and off periods always the same for each LED.
 

ApacheKid

Joined Jan 12, 2015
1,762
OK here's the kind of thing I was talking about, the GitHub code is here.

I could refine it more and make it more general but you should be able to see what I was driving at.

Notice the task data structure contains a pointer to a function to handle the timer expiry.

This is C code, it compiles under Visual Studio as C17 but of course I have not tested it but I'm sure it can be made to work with just a small effort if it doesn't already.

If you wanted the on/off time to be non-symmetrical then it can be done easily, you'd just have separate tasks for handling on->off and off->on.
 
Last edited:

Thread Starter

Sparsh45

Joined Dec 6, 2021
143
OK I never noticed that table and other post.

So we want a 50% duty cycle for each LED, on and off periods always the same for each LED.
post #19 Table

Initially all LEDs are ON.

When 10 interrupts occur only the LED1 changes its state. Earlier it was ON but now it will be turn off but the rest will remain as they were.

When 20 interrupts occur
LED 1 and LED 2 change their state LED 1 was OFF before so now it will ON and LED 2 was ON so It will be OFF now

When 30 interrupt occur LED 1 and LED 3 change their state
LED 1 was ON before so now it will OFF
LED 2 was ON before so now it will OFF

Now you must have got the idea that LED 1 changes the state after every 10 interrupt. LED 2 changes the state after every 20 interrupt and LED 3 changes the state after every 30 interrupt
 
Top