All About Circuits Forum  

Go Back   All About Circuits Forum > Software, Microcomputing, and Communications Forums > Programmer's Corner

Notices

Programmer's Corner Discussion forum for all aspects of programming and software engineering. Any software programming language welcome: C, C++, C#, Fortran, Java, Matlab, etc.

Reply   Post New Thread
 
Thread Tools Display Modes
  #1  
Old 05-16-2014, 11:06 AM
TokTok TokTok is offline
New Member
 
Join Date: May 2014
Posts: 3
Default Simultaneous control of momentary LEDs

Hi all,

Apologies if this sound trivial but currently Iím stuck in terms of figuring out the logic to complete what I suspect is a fairly easy task.

Iím currently turning on my LEDs for a certain amount of time using the output_toggle() method as seen in my code below at the end of my post but Iíd like to move on to turning on another relay when Iíve got the first LED currently engaged. So essentially simultaneous operation of the LEDs is what Iím after.

Code:
#include<18F2580.h> 

#include <stdlib.h> 
#include <string.h> 

#fuses XT,PUT,NOBROWNOUT,NOWDT,NOPROTECT,NOLVP 
  
#use delay(clock=4000000) 
#use rs232(baud=19200, parity=N, xmit=PIN_C6, rcv=PIN_C7, STREAM=HWAREUART, ERRORS) 
#use rs232(baud=19200, parity=N, xmit=PIN_A4, Stream=PCSOFTWAREUART) 

#define REL_1 PIN_A1 
#define REL_2 PIN_A2 
#define REL_3 PIN_B0 
#define REL_4 PIN_B1 
#define REL_5 PIN_A5 

// 
void main() { 
   output_low(REL_1); 
   output_low(REL_2); 
   output_low(REL_3); 
   output_low(REL_4);    
   output_low(REL_5); 

while(1) { 
   int num, i; 

   for(i=0; i<5; i++) { 

       num = i; 
    
      if(num == 1) { 
         output_toggle(REL_1); 
         delay_ms(10000); 
         output_toggle(REL_1); 
      } else if(num == 2) { 
         output_toggle(REL_2); 
      } else if(num == 3) { 
         output_toggle(REL_3); 
         delay_ms(5000); 
         output_toggle(REL_3); 
      } else if(num == 4) { 
         output_toggle(REL_4); 
      }  else if(num == 5) { 
         output_toggle(REL_5); 
         delay_ms(2500); 
         output_toggle(REL_5); 
      } 
   } 
}
Select All
How does one go about this in an efficient way? As I come from a java background is there any threading within the CCS library?

My understanding is you could use timers which I tried below but no success:

Code:
#include<18F2580.h>

#include <stdlib.h>
#include <string.h>

#fuses XT,PUT,NOBROWNOUT,NOWDT,NOPROTECT,NOLVP
 
#use delay(clock=4000000) 
#use rs232(baud=19200, parity=N, xmit=PIN_C6, rcv=PIN_C7, STREAM=HWAREUART, ERRORS) 

#define LED_ONE PIN_B2 
#define LED_TWO PIN_B3

int push_btn_flag;
int millisecs, outs;

#int_timer0
void toggle_LED() {
   if(push_btn_flag == 1) {

	    // At this point in time in the interrupt service routineI would like to count down or up for 5 seconds in here so as to turn off LED_ONE after 5 seconds
	    output_toggle(LED_ONE);
	
		if(millisecs++ == 100) {
	    	output_toggle(LED_ONE);
			millisecs = 0;
		}

        push_btn_flag = 0;
   } else if(push_btn_flag == 2) {

      // At this point in time in the interrupt service routine I would like to count down or up for 10 seconds in here so as to turn off LED_ONE after 10 seconds
      output_toggle(LED_TWO);

		if(millisecs++ == 100) {
	    	output_toggle(LED_TWO);
			millisecs = 0;
		}

        push_btn_flag = 0;
   }
}

void main() {

   setup_timer_0(RTCC_EXT_L_TO_H|RTCC_DIV_16);

   enable_interrupts(int_timer0); 
   enable_interrupts(global); 

   output_low(LED_ONE);
   output_low(LED_TWO);

   // Here I essentially want to enable the user to play around with operating the LEDs SIMULTANEOUSLY
   // So say user presses PUSH_BTN_ONE essentially I want it that the push_btn_flag changes and
   // this causes the timer interrupt to start counting down or up based on a specified time i.e. 5 secs

   // Now in the interrupt service routine whilst the counting related to LED one is ongoing if the user were
   // to press PUSH_BTN_TWO then I would like in the interrupt service rountine the counting for LED_TWO 
   // to be started as the push_btn_flag would have been set to two.
   
   while(1) {
      if (input(PIN_B4) == 0){
         delay_ms(10);
         push_btn_flag = 1;
      } else if (input(PIN_A3) == 0){ 
         delay_ms(10);
         push_btn_flag = 2;
      }
   }
}
Select All
Edit:
Essentially below is how I would like to use a timer interrupt to provide me with my desired outcome:

Step 1 - In the main() function enable the global interrupts and the specific timer interrupt.

Step 2 - In the interrupt service routine function start watching out for changes i.e. on the push_btn_flag.

The value/state of the push_btn_flag will be changed in the main function when the user presses one of two momentary push button to operate the LEDs for a desired period of time.

So in the interrupt service routine if the push_btn_flag has been set to 1 then LED_ONE is turned on for a specific period of time. Now this specific period of time is what I need the timer ISR to count down and is what I'm stuck on.

The same applies with the turning on of a different LED when the push_btn_flag has been set to 2.

Step 3 - In the main() function watch out for the pressing of the push buttons as explained in step 2 which when pressed changes the push_btn_flag which the timer interrupt service routine is monitoring for change.

Note: My development environment is MPLAB IDE version 8.91.00.00 with my compiler being the CCS C PCWHD compiler version 4.1114.

Any help is appreciated.

TokTok.
Reply With Quote
  #2  
Old 05-16-2014, 12:53 PM
djsfantasi's Avatar
djsfantasi djsfantasi is offline
Senior Member
 
Join Date: Apr 2010
Location: Northeast US
Posts: 944
Blog Entries: 1
Default

Without using timer interrupts, one could calculate the end time of the delay for each push button and after checking the push button status, check to see if any of the delays have expired and toggle the LEDs/pins appropriately.

For example, see the following pseudo-code (it has not been compiled nor tested).

Code:
void main() { 
unsigned long end_LED_1;
unsigned long end_LED_2;
unsigned long end_LED_3;
unsigned long end_LED_4;
unsigned long end_LED_5;


   output_low(REL_1); 
   output_low(REL_2); 
   output_low(REL_3); 
   output_low(REL_4);    
   output_low(REL_5); 

while(1) { 
   int button; 

   for(button=0; button<5; button++) { 

      switch (button) {
      
	      case 1; {
		output_toggle(REL_1);
		end_LED_1 = millis()+10000;
		}
	      case 2; {
		output_toggle(REL_2);
		}      	
	      case 3: {
		output_toggle(REL_3);
		end_LED_3 = millis()+5000;
		}
	      case 4: {
		output_toggle(REL_4);
		]
	      case 5: {
		output_toggle(REL_5);
		end_LED_1 = millis()+2500;
		}      	

	if ( !(end_LED_1 == 0) AND (end_LED_1 <= millis()) {
	   output_toggle(REL_1);
	   end_LED_1 = 0;
	   }
	if ( !(end_LED_3 == 0) AND (end_LED_3 <= millis()) {
	   output_toggle(REL_3);
	   end_LED_3 = 0;
	   }
	if ( !(end_LED_5 == 0) AND (end_LED_5 <= millis()) {
	   output_toggle(REL_5);
	   end_LED_5 = 0;
	   }
	} 
    }
}
Select All
__________________
- Δj' fαπταi
Reply With Quote
  #3  
Old 05-16-2014, 02:24 PM
TokTok TokTok is offline
New Member
 
Join Date: May 2014
Posts: 3
Default

Hi djsfantasi,

Thanks for the idea but mills() which I understand in Arduino returns the number of milliseconds elapsed since the time the program started running isn't available in a PIC.

Any idea on PIC how to go about returning the number of milliseconds elapsed since the the program started running?

I'll around to see how this can be done on a PIC.
Reply With Quote
  #4  
Old 05-16-2014, 02:43 PM
ErnieM's Avatar
ErnieM ErnieM is offline
Senior Member
 
Join Date: Apr 2011
Location: Lon Guyland, Noo Yawk
Posts: 5,165
Default

Quote:
Originally Posted by TokTok View Post
Hi all
Hello there, and welcome to the forums!

Quote:
Originally Posted by TokTok View Post
Apologies if this sound trivial but currently Iím stuck in terms of figuring out the logic to complete what I suspect is a fairly easy task.
Completely untrivial. Getting a blinkie LED project to work is a good basis for larger projects.

Quote:
Originally Posted by TokTok View Post
How does one go about this in an efficient way? As I come from a java background is there any threading within the CCS library?
Yikes. did you say threading? Just as there is no crying in baseball there is NO threading in these PIC devices. Threading is an abstraction not physically realized in a single core device anyway.

In a PIC you are running bare metal, no operating systsm, just your code inside the core.

First off, while I'm familiar with PICs I havn't used the CCS C compiler in a few years, so I may be slightly off here, but with other C compilers it is generally undesirable to do any function calls from inside the ISR. That is because C must do a ton of work to make sure the ISR doesn't step on any variables the main code uses.

Just imagine if the main has called function A() when an interrupt triggers also calling A(). The internal state of the first call can be corrupted by the 2nd call there; some compilers notice this and actually give you two version of function A() to keep them seperate.

Next, the delays inside the ISR are bad indeed. An ISR should be short sweet to the point and done and out. Besides, if button A makes a 5 second delay during that time button B cannot be seen as the single thread is just waiting for the delay to finish.

I'm not quite sure what your buttons and states are, but generally a state machine (google that) can be worked out to handle these situations.

My default method of work is to set up a timer to bang into an ISR every 1 millisecond. In that routine I have a global variable say TickCount I just increment every time. I'll also put that routine to good use to debounce switch inputs by testing switches every 25 mS and ignoring anything that doesn't read the same 2x in a row.

Outside of the ISR TickCount itself can be used as a timer as long as you are careful using it: if longer then 8 bits it can change while you are using it.

There's lots of stuff for you to review here, but here's the short list to start you off.
__________________
ďFreedom is never more than one generation away from extinction. We didnít pass it to our children in the bloodstream. It must be fought for, protected, and handed on for them to do the same, or one day we will spend our sunset years telling our children and our childrenís children what it was once like in the United States where men were free.Ē
Reply With Quote
  #5  
Old 05-16-2014, 03:20 PM
djsfantasi's Avatar
djsfantasi djsfantasi is offline
Senior Member
 
Join Date: Apr 2010
Location: Northeast US
Posts: 944
Blog Entries: 1
Default

Quote:
Originally Posted by TokTok View Post
Hi djsfantasi,

Thanks for the idea but mills() which I understand in Arduino returns the number of milliseconds elapsed since the time the program started running isn't available in a PIC.

Any idea on PIC how to go about returning the number of milliseconds elapsed since the the program started running?
Missed that you were running this on a PIC. D'oh. That's where the timer interrupt is necessary. In your ISR, you would only increment a variable every millisecond, hence implementing your own "millis()" function.
__________________
- Δj' fαπταi
Reply With Quote
  #6  
Old 05-16-2014, 04:09 PM
TokTok TokTok is offline
New Member
 
Join Date: May 2014
Posts: 3
Default

@djsfantasi: Thanks. Thats exactly what I'm trying to figure out using the timers.

@ErnieM: Thansk for the welcome. I'll have a look at your suggestion and upload any issue.
Reply With Quote
  #7  
Old 05-16-2014, 06:13 PM
BobTPH BobTPH is offline
Senior Member
 
Join Date: Jun 2013
Posts: 432
Default

Quote:
Originally Posted by ErnieM View Post
Yikes. did you say threading? Just as there is no crying in baseball there is NO threading in these PIC devices. Threading is an abstraction not physically realized in a single core device anyway.
You do not need multiple cores to run multiple threads. I have a multi-threading kernel that works on midrange PICs. Each thread context is 5 bytes (plus of 2-bytes per level of call needed). I have used this in a project where multiplexing a display is done as a background thread, PWM to a tri-color LED is another thread, and the foreground thread is a user interface. Yes, it could have been done simply with interrupts, but I did this just for fun.

Bob
Reply With Quote
Reply   Post New Thread

Tags
, , , ,


Similar Threads
Thread Thread Starter Forum Replies Last Post
LED Light Therapy - Array of LEDs on PCB | How to? UncleGarage The Projects Forum 25 10-21-2012 09:16 PM
PWM control of an EBM-Pabst G1G170-AB05-20 fuzer_guy The Projects Forum 0 10-27-2011 11:15 PM
Control LED's with VB from serial port fletcher_ap Embedded Systems and Microcontrollers 2 02-25-2010 03:23 AM
control leds with picaxe software nyyankeehater Embedded Systems and Microcontrollers 1 10-21-2008 09:01 PM
momentary switches to control shifting hman333 The Projects Forum 11 11-29-2007 07:54 PM

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT. The time now is 03:42 AM.


User-posted content, unless source quoted, is licensed under a Creative Commons Public Domain License.
Powered by vBulletin
Copyright ©2000 - 2014, vBulletin Solutions, Inc.