Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Multitasking

Status
Not open for further replies.
many thanks to all that helping me out. I am going to try each approaches.

Anyway, to answer Mike question. For the throttle trigger, Actually I want to simulate "Braking" signal for a car light. It is 50% initial brightness, and when the pulse is more than 1.6ms (braking signal), it is in 100% brightness. But here I just make the LEDs flash in a sequence (for example only) then it is just applicable.

My problem is still, difficult to have both flashing modes for steering and throttle triggers run at the same time (well not at the same time, but almost the same time). A solution to this is to use 2 PICs but it is hardware approach, since I want to study and learn PIC Programming, would really learn, then it should not be that way. Many thanks to all.

Kind regards,

Kelvin
 
mrfunkyjay said:
My problem is still, difficult to have both flashing modes for steering and throttle triggers run at the same time (well not at the same time, but almost the same time).

Kevin,
This is not a problem. The computer works very fast.

The code Mike and I posted are very nearly the same. The difference is that when an LED is on, Mike toggles it each time through the main loop. My code runs the main loop faster and turns the LED on or off based on the value of counter. Both work. Mikes example includes the code to turn both the direction and throttle LEDs on at the same time. I only showed you how to do the steering, but the throttle code is easy and follows the steering as it did in Mikes.

I did not look at your code for GetPulse.

My strong suggestion is to get the code working for the steering. Once that works it will be easy to add the additonal code for the throttle.

To better understand the code walk throught the code writting down the value of each variable as it changes.

EDIT: Once you get this working we can show you how to light and LED at half intensity :)
 
Last edited:
thanks 3v0 for your explanation, I appreciate it so much :)

Now I used the code from Mike, I changed a little bit in Delay. Here what I get.

both LED function - Steering and Throttle run simultaneously, good that I saw difference compared to the first source code before. The thing is they kinda lag.

To explain it further, let's say I have a blinking rate for steering lights as 1s ON then 1s OFF until forever. When I send a throttle signal to it (while steering lights are still blinking), the steering lights kinda lagging. I am not sure about the period of flashing but it seems double or less. 2s ON then 2s OFF.

Well, for your code, 3v0, it seems that I have miscalculated the counter or something in timing issue. I got my LEDs for steering not blinking at all, or perhaps, it blinked, but it was too fast. Something wrong with the setting.

I use 20Mhz ext osc and I read somewhere to calculate the amount of delay you want to have, simply divide the freq OSC by 4, count the period by T=1/f and lastly multiply by the instruction cycle. If I noticed here, to calculate the instruction cycle, it is just another way around. For your case 3v0, the thing that I did not really understand is the usage of 8bit counter here. I know it has range of 0-255. and simply half of it would be 127. But I just don't really get the logic of count>0x7f you wrote before. Hmm I mean, atm I used Delay10KTCYx(n), which n range from 0-255 to add delays. Hmm, I would be extremely happy if you would explain. Thanks in advance!

Regards,

Kelvin
 
My answers are in bold.
thanks 3v0 for your explanation, I appreciate it so much :)

Now I used the code from Mike, I changed a little bit in Delay. Here what I get.

both LED function - Steering and Throttle run simultaneously, good that I saw difference compared to the first source code before. The thing is they kinda lag.

To explain it further, let's say I have a blinking rate for steering lights as 1s ON then 1s OFF until forever. When I send a throttle signal to it (while steering lights are still blinking), the steering lights kinda lagging. I am not sure about the period of flashing but it seems double or less. 2s ON then 2s OFF.

If you mean that there is a delay between when you move the stick and when the lights indicate the change try making the delay smaller. The LEDs may seem to stay on because they are flashing fast with a small delay. In Mikes code the sample rate and the blink rate are the same.

Well, for your code, 3v0, it seems that I have miscalculated the counter or something in timing issue. I got my LEDs for steering not blinking at all, or perhaps, it blinked, but it was too fast. Something wrong with the setting.

I use 20Mhz ext osc and I read somewhere to calculate the amount of delay you want to have, simply divide the freq OSC by 4, count the period by T=1/f and lastly multiply by the instruction cycle. If I noticed here, to calculate the instruction cycle, it is just another way around.
Delay10KTCYx(n) delays multiples of 10,000 Tcy.
The osc is 20,000,000. The instruction rate is 4 time slower or 5,000,000. The period is 1/(instruction rate) or 0.0000002. Then (0.0000002 * 10,000) is .002 seconds. So n is (delay_in_seconds/.002). Hope I got that right :) If you want to blink once per second use a delay of about ((1/256)/.002). (1/256) because you need to go through the loop 256 times for one blink. The actual blink rate will be a little slower because it takes time to execute the code, most the sample.


For your case 3v0, the thing that I did not really understand is the usage of 8bit counter here. I know it has range of 0-255. and simply half of it would be 127. But I just don't really get the logic of count>0x7f you wrote before. Hmm I mean, atm I used Delay10KTCYx(n), which n range from 0-255 to add delays. Hmm, I would be extremely happy if you would explain. Thanks in advance!

(count>0x7F) evaluates to a 0 for count less then 7F and 1 for count equal or greater to 7F.

So instead of

Code:
    if (count>0x7F)
    {
        LATBbits.LATB0 = 1;
    }
    else
    {
        LATBbits.LATB0 = 0;
    }
I can write the single line.
Code:
LATBbits.LATB0 = (count>0x7F);


My code will measure the pulse and set the LEDs 255 times for each LED blink (on/off). Use this simple code to test the blink rate.
Code:
unsigned char count;  // make count a byte
count = 0;
while(1)
{
    LATBbits.LATB0 = (count>0x7F);
    count++;
    delay(some value)
}
Get that working and set the delay to blink the led at the rate you want.

Use that delay in the code I posted earlier and you should get the right blink rate.



Regards,

Kelvin
 
Okay, it is working. Hmm, this thing is great. A new way to blink LEDs. Hmm. thanks for sharing :D I set it to (2) and the blinking rate is acceptable.
 
Hmm I have tried to decrease the delays, but it seems that the "lag" still there. If you mentioned computer is fast, then could it be, my Ext OSC is damaged?? Should I try changing to new one?
 
Hmm I have tried to decrease the delays, but it seems that the "lag" still there. If you mentioned computer is fast, then could it be, my Ext OSC is damaged?? Should I try changing to new one?

I doubt it. But you may not have setup the config right and are still using the internal one. Do you delays make sense or are they way too long for the numbers you input ?

How fast are you blinking the LEDs and how long is the lag (in seconds please)

Remember that Mikes code only samples as fast as you blink the LEDs.

EDIT:
Try setting the OSCCON = 0x00;
You actualy only need to set the SCS0 and SCS1 bits to zero but setting the entire register to 0 will work too. Or use the debugger and see i SCS0 and SCS1 are already zero. They enable the use of the external crystal when set to 0. I think that is the default but am not sure.
 
Last edited:
My code now:
Code:
#include <p18f4520.h>
#include <delays.h>

#pragma config OSC = HS
#pragma config WDT = OFF
#pragma config LVP = OFF

#define L_LED LATBbits.LATB0
#define R_LED LATBbits.LATB1

int i, iPulse1, iPulse2;

/*Counts the length of a pulse on Pin RA1*/
int GetPulse1(){
    T1CON=0b00000000;			/*Init timer1*/
    TMR1L=0;
    TMR1H=0;
    TRISAbits.TRISA1=1;			/*Make this pin as an input*/
    while(PORTAbits.RA1==1); 	/*Make pin low*/
    while(PORTAbits.RA1==0);	/*While pin is high*/
    T1CONbits.TMR1ON=1;			/*Start timer0*/
    while(PORTAbits.RA1==1);	/*When pin is low*/
    T1CONbits.TMR1ON=0;			/*Stop timer0*/
    return TMR1H*256+TMR1L;		/*return 16bit timer value*/
}

/*Counts the length of a pulse on Pin RA2*/
int GetPulse2(){
	T3CON=0b00000000;			/*Init timer3*/
	TMR3L=0;
	TMR3H=0;
	TRISAbits.TRISA2=1;			/*Make this pin as an input*/
	while(PORTAbits.RA2==1);	/*Make pin low*/
	while(PORTAbits.RA2==0);	/*While pin is high*/
	T3CONbits.TMR3ON=1;			/*Start timer0*/
	while(PORTAbits.RA2==1);	/*When pin is low*/
	T3CONbits.TMR3ON=0;			/*Stop timer0*/
	return TMR3H*256+TMR3L;		/*return 16bit timer value*/
}

void main(void)
{
TRISA = 0b00000111; /*Initialize RA0 as Input Port to read PWM Signal*/
TRISB = 0b00000000; /*Initialize Port B as Output Port to flash LEDs*/
ADCON1 = 15; /*Digital Input*/
PORTB = 0;
	while(1)
	{
		L_LED = 0;
		R_LED = 0;
		iPulse1=GetPulse1();
		if(iPulse1<7000){		/*If the Pulse Width is less than 1.4ms*/
			R_LED = 0;
			Delay10KTCYx(200);
			L_LED = ~L_LED;			/*Blinks left LED*/
			Delay10KTCYx(150);
		}
		if(iPulse1>8000){	/*If the Pulse Width is more than 1.6ms*/
			L_LED = 0;
			Delay10KTCYx(200);
			R_LED = ~R_LED;			/*Blinks right LED*/
			Delay10KTCYx(150);
		}

		iPulse2=GetPulse2();
		if (iPulse2 < 6000)
		{	
			for(i=0;i<1;i++)
			{
				LATBbits.LATB2 = 1;
				Delay10KTCYx(50);
				LATBbits.LATB2 = 0;
				Delay10KTCYx(50);
				LATBbits.LATB3 = 1;
				Delay10KTCYx(50);
				LATBbits.LATB3 = 0;
				Delay10KTCYx(50);
				LATBbits.LATB4 = 1;
				Delay10KTCYx(50);
				LATBbits.LATB4 = 0;
				Delay10KTCYx(50);
				LATBbits.LATB5 = 1;
				Delay10KTCYx(50);
				LATBbits.LATB5 = 0;
				Delay10KTCYx(50);
			}
		}
		if (iPulse2 > 8000)
		{
			for(i=0;i<1;i++)
			{
				LATBbits.LATB2 = 1;
				Delay10KTCYx(30);
				LATBbits.LATB2 = 0;
				Delay10KTCYx(30);
				LATBbits.LATB3 = 1;
				Delay10KTCYx(30);
				LATBbits.LATB3 = 0;
				Delay10KTCYx(30);
				LATBbits.LATB4 = 1;
				Delay10KTCYx(30);
				LATBbits.LATB4 = 0;
				Delay10KTCYx(30);
				LATBbits.LATB5 = 1;
				Delay10KTCYx(30);
				LATBbits.LATB5 = 0;
				Delay10KTCYx(30);
			}
		}
	}
}

From this, I can say the blinking LEFT and RIGHT LEDs are operating nice (if I don't trigger the throttle at all).

It is like a normal BLINK signal for real cars.

When I press the throttle, somehow it lags like twice. So if I have it blinking like 1..0..1..0..1..0..1.. now when I press the throttle:
1....0....1....0....1....

Previously, before I post anything in this forum, I had a source code that tell my Microcontroller to do this thing, but it was a failure and when I press the throttle after holding the steering, both of them not blinking at the same time.

Sorry for my english since it is not my mother tongue, learn it only at school. Thanks anyway for guiding me along, thanks2. :)

Kelvin
 
Last edited:
It is about what I would expect with your code.

Code:
			Delay10KTCYx(50);
				LATBbits.LATB2 = 0;
				Delay10KTCYx(50);
				LATBbits.LATB3 = 1;
				Delay10KTCYx(50);
				LATBbits.LATB3 = 0;
				Delay10KTCYx(50);
				LATBbits.LATB4 = 1;
				Delay10KTCYx(50);
				LATBbits.LATB4 = 0;
				Delay10KTCYx(50);
				LATBbits.LATB5 = 1;
				Delay10KTCYx(50);
				LATBbits.LATB5 = 0;
				Delay10KTCYx(50);

You are delaying 50*8*10,000 instruction cycles every time you use the throttle. That has got to slow things down.... The delays in the left right code do not belong there either. You should have only ONE delay per loop. Mike had his at the top, I had mine at the bottom. Both work.

Use the code mike provided for the throttle.

Code:
unsigned char Mask = 0b00000100;     //
...

  if (Pulse2 > 16000)                // if Pulse2 > 1.6 msecs
    { LATB &= ~Mask;                   // turn off previous LED
      if (Mask == 0b00100000)          // if RB5 (end of sequence)
        Mask = 0b00000100;             // reset mask for RB2
      else                             // else
        Mask <<= 1;                    // shift Mask bit left
      LATB |= Mask;                    // turn on new LED
    }
    else                               // if Pulse2 < 1.6 msecs
    { LATB &= 0b00000011;              // clear RB2..RB5 LEDs
      Mask = 0b00000100;               // reset mask for RB2
    }
 
Okay!!!!!!!!! It is working, thanks a lot!!

Btw, now for simulating the braking signal, hmm, how to put this.

Initial condition:
50% brightness LED
iPulse2 > 9000:
100% brightness LED

Any comments? Thanks!!! :D
 
done

Gentlemen, it is done. I have added some little codes as my LEDs will all go OFF when it is in STANDBY MODE if I could say. :D:D:D

If anyone want to help me with braking lights, WELCOME. I am very pleased to know how, THANKS SO MUCH FELLAS!! :D:D

Code:
#include <p18f4520.h>
#include <delays.h>

#pragma config OSC = HS
#pragma config WDT = OFF
#pragma config LVP = OFF

#define L_LED LATBbits.LATB0
#define R_LED LATBbits.LATB1

int i, iPulse1, iPulse2;

unsigned char Mask = 0b00000100;

/*Counts the length of a pulse on Pin RA1*/
int GetPulse1(){
    T1CON=0b00000000;			/*Init timer1*/
    TMR1L=0;
    TMR1H=0;
    TRISAbits.TRISA1=1;			/*Make this pin as an input*/
    while(PORTAbits.RA1==1); 	/*Make pin low*/
    while(PORTAbits.RA1==0);	/*While pin is high*/
    T1CONbits.TMR1ON=1;			/*Start timer0*/
    while(PORTAbits.RA1==1);	/*When pin is low*/
    T1CONbits.TMR1ON=0;			/*Stop timer0*/
    return TMR1H*256+TMR1L;		/*return 16bit timer value*/
}

/*Counts the length of a pulse on Pin RA2*/
int GetPulse2(){
	T3CON=0b00000000;			/*Init timer3*/
	TMR3L=0;
	TMR3H=0;
	TRISAbits.TRISA2=1;			/*Make this pin as an input*/
	while(PORTAbits.RA2==1);	/*Make pin low*/
	while(PORTAbits.RA2==0);	/*While pin is high*/
	T3CONbits.TMR3ON=1;			/*Start timer0*/
	while(PORTAbits.RA2==1);	/*When pin is low*/
	T3CONbits.TMR3ON=0;			/*Stop timer0*/
	return TMR3H*256+TMR3L;		/*return 16bit timer value*/
}

void main(void)
{
TRISA = 0b00000111; /*Initialize RA0 as Input Port to read PWM Signal*/
TRISB = 0b00000000; /*Initialize Port B as Output Port to flash LEDs*/
ADCON1 = 15; /*Digital Input*/
PORTB = 0;

while(1)
{
Delay10KTCYx(150);
iPulse1 = GetPulse1();
if (iPulse1 < 7000)                  // if Pulse1 < 1.4ms
	{
	R_LED = 0;                       // turn off right LED
	L_LED = ~L_LED;                  // toggle left LED @ 2 Hz
	}
if (iPulse1 > 8000)                  // if Pulse1 > 1.6ms
	{
	L_LED = 0;                       // turn off left LED
	R_LED = ~R_LED;                  // toggle right LED @ 2 Hz
	}
iPulse2 = GetPulse2();
if (iPulse2 < 6000)                  // if Pulse2 < 1.4ms
	{
	LATB &= ~Mask;                   // turn off previous LED
	if (Mask == 0b00100000)          // if RB5 (end of sequence)
		Mask = 0b00000100;           // reset mask for RB2
	else                             // else
		Mask <<= 1;                  // shift Mask bit left
		LATB |= Mask;                // turn on new LED
	}
if (iPulse2 > 9000)                  // if Pulse2 > 1.8ms
	{
	LATB &= ~Mask;                   // turn off previous LED
	if (Mask == 0b00000100)          // if RB2 (end of sequence)
		Mask = 0b00100000;           // reset mask for RB5
	else                             // else
		Mask >>= 1;                  // shift Mask bit right
		LATB |= Mask;                // turn on new LED
	}
if (iPulse1 >= 7001 && iPulse1 <= 7999) //Steering Standby Mode
	{
	L_LED = 0;
	R_LED = 0;
	}
if (iPulse2 >= 6001 && iPulse2 <= 8999) //Throttle Standby Mode
	{
	LATBbits.LATB2 = 0;
	LATBbits.LATB3 = 0;
	LATBbits.LATB4 = 0;
	LATBbits.LATB5 = 0;
	}
}
}

Btw how to set faster blink for the throttle? which parameters should I play with?

Best regards,

Kelvin Susanto
 
Last edited:
Congrats'. I think you've got it, including condition tests that I missed in my example when the controls are sitting in the middle positions.

Regards, Mike
 
Last edited:
To use less then full brightness with a LED you need to turn it on and off rapidly. One way to do this is Pulse Width Modulation. We can do that without getting fancy.

The following code illustrates how you can do this without too much trouble.

Code:
unsigned byte prcnt, brightness;
prcnt = 0;
while(1)
{
   LATBbits.LATB0 = (prcnt < brightness);
  
   prcnt++;
   if (prcnt>99)
   {
       prcnt = 0;
   }
}
You can have fun with this
Code:
unsigned byte prcnt, brightness;
prcnt = 0;
while(1) 
   for (brightness=0; brightness<100; brightness++)
   {
      LATBbits.LATB0 = (prcnt < brightness);
  
      prcnt++;
      if (prcnt>99)
      {
          prcnt = 0;
      }
   }

You first idea will be to put more loops inside your code to do the dimming. Do not. What you need to do is to change you code so that it works like this.

Code:
unsigned byte prcnt, brightness;

while(1) 
{
   for (prcnt=0; prcnt<100; prcnt++)
   {
      // do not sample every time through the loop 
      if (prcnt == 0)
      {
           iPulse1=GetPulse1();
           if (iPulse1 < 7000)                  // if Pulse1 < 1.4ms
           {
	R_LED = 0;                       // turn off right LED
	L_LED = ~L_LED;                  // toggle left LED @ 2 Hz
	}
            if (iPulse1 > 8000)                  // if Pulse1 > 1.6ms
	{
	L_LED = 0;                       // turn off left LED
	R_LED = ~R_LED;                  // toggle right LED @ 2 Hz
	}
       }
      
      // do not sample every time through the loop 
      if (prcnt == 0)
      {
           iPulse2=GetPulse2();
           if (iPulse2>9000)
           {
              brightness = 100;
           }
           else 
           {
               brightness = 50;
           }  
      }

      // every time we check to see if we need to turn of LED
      LATBbits.LATB4 = (prcnt < brightness); // on while prctn < brightness

      prcnt++;
      if (prcnt>99)
      {
          prcnt = 0;
      }
      delay(??);
   }
}



Okay!!!!!!!!! It is working, thanks a lot!!

Btw, now for simulating the braking signal, hmm, how to put this.

Initial condition:
50% brightness LED
iPulse2 > 9000:
100% brightness LED

Any comments? Thanks!!! :D
 
Excellent example!!!

Actually, read the pulse widths on '0' and toggle the turn signal LEDs on '0' and '50'? No, never mind, it doesn't matter...
 
Last edited:
Some good suggestions above but, be aware that (each of) the GetPulse routine(s) could wait 20mS before returning. It may be simpler to have the variable LED fed by two pins and use two resistors and only switch 1 pin to output at any time.

Mike.
 
That's why I suggested collecting pulse width values as a background task. I didn't push it however because interrupt processing can be a bit overwhelming for newcomers and I also thought that a variable 20 to 40 msecs wouldn't affect the timing that much with the relatively long delays we were talking about. Now that we're considering shorter loop delays, it could be a factor.

Mike
 
so u guys suggested here to use 3v0's code? I want to try it anyway tommorow, since I am out of office right now (student working for a company).

@Mike, K8LH:

the thing I didnt really catch is
LATB &= ~Mask;
and
LATB |= Mask;

Explaining those things would relieve some stresses. LOL. Thx.
 
That's why I suggested collecting pulse width values as a background task. I didn't push it however because interrupt processing can be a bit overwhelming for newcomers and I also thought that a variable 20 to 40 msecs wouldn't affect the timing that much with the relatively long delays we were talking about. Now that we're considering shorter loop delays, it could be a factor.

Mike

The code I provided only samples when the loop counter is zero, there are 99 loop iterations between each sample. It could be changed to sample the streering at 0, the throttle at 33, and the brake at 66 sort of thing. Maybe he was using same input for throttle and brake, no matter. By sizing the per iteration delay and number of iterations one can get a lot of flexiablity in the spacing between samples.

I am not against using interrups but agree on not using them here.
 
Status
Not open for further replies.

Latest threads

Back
Top