This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

How do I set pin high for specific time after input pin momentary press

'Howdy Everybody,

 

I am finally getting some time to work on my gate opener inteface controller.

 

I am having a hard time figuring out how to set a pin high for a desired time after a input pin signal has been recieved. 

 

{
if ((P2IN & REMOTE) ==0)   //P2.0 input from gate opener second channel contact
    P2OUT |= BYPASS;  // output high on P2.2 
    _delay_cycles(500000);

    if ((POSITION) =0 //make bypass stay high until P2.1 goes low
       P2OUT &= ~BYPASS;
       _delay_cycles(500000)
}     

Will this work? 

 

The whole system is

If there is a momentary input on P2.0 it will make an output on P2.2 until P2.1 returns to low for more than a half second. the timer is set at 1 mhZ 

Thanks !  hopefully my codee writing skills will get better. 

  • Use ‘{‘ and ‘}’ to clearly indicate what the ‘if’ should do when the comparison returns valid (or invalid).
    Your second ‘if’ is wrong and not complete.

    Create a ‘base’ timer of about 10mS and use this to de-bounce your inputs, poll the input until you read at least 10 times the same level than your input is valid.

    Use the same timer for your delays instead of using ‘delay_cycles’.
  • Thank you Leo,

    I am going to see if I can get a bit further on it tonight. Shift swap is not helping!
  • Jake,

    doesn't this one

    if ((POSITION) =0 //make bypass stay high until P2.1 goes low

    give you some kind of warning because there is missing a bracket? Futhermore testing for a value is done by

    if( POSITION == 0 )

    and not by

    = 0

    which is for assigning a value. And your comment //make bypass stay high until P2.1 goes low does not match with the action

    P2OUT &= ~BYPASS;

    but I don't know your code, so maybe that is simply commented misleading.

    Dennis

  • #include <msp430g2553.h>
    
    /*
     *Gate controller ad on
     *Functions short input from remote second channel will enable bypass and status LED until gate close input is received
     *Functions 2 second press of bypass will place gate in locked position disabling all gate functions until 2 second input is received again
     *Gate status information to be sent to PC via wifi, open and closed status, along with obstruction sensor bypass and locked condition
     */
    
    #define REMOTE BIT0 //P2.0
    #define POSITION BIT1 // P2.1
    #define BYPASS BIT2 // P2.2
    #define LOCKED BIT3 // P2.3
    #define LOCKLED BIT4 //2.4
    #define STATUS_LED BIT0 //P1.0
    #ifndef TIMER0_A1_VECTOR
    #define TIMER0_A1_VECTOR    TIMERA1_VECTOR
    #define TIMER0_A0_VECTOR    TIMERA0_VECTOR
    #endif
    
    void main(void) {
        WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
        CCTL0 = CCIE;                             // CCR0 interrupt enabled
        TACTL = TASSEL_2 + MC_1 + ID_3;           // SMCLK/8, upmode
        CCR0 =  10000;                     // 12.5 Hz
    
    P2OUT = 0;            // reset all outputs
    P2IN &= ~REMOTE;      // P2.0 input from gate remote second channel
    P2IN &= ~POSITION;    // P2.1 input from gate controller for position high open/ low closed
    P2OUT &= ~BYPASS;     // P2.2 output high to obstruction sensor bypass relay
    P2OUT &= ~LOCK;       // P2.3 output high to gate lock relay
    P2OUT &= ~LOCKLED;    // P2.4 output high to gate lock status LED
    P2REN |= REMOTE;
    P2REN |= POSITION;
    P2REN |= BYPASS;
    P2REN |= LOCK;
    P2REN |= LOCKLED;
    P2IES |= REMOTE;
    P2IFG &= ~POSITION;    // clear flags
    P2IE |= REMOTE;        // enable interrupts
    P1OUT &= ~BIT0;
    P1DIR |= BIT0;
    
    // timer TA0, used to monitor the bypass input
       TA0CCR0 = 0;                        // full cycle
       TA0CTL = TASSEL_2 + MC_1 + ID_3;    // SMCLK/8, upmode
    
       __bis_SR_register(GIE);    // LPM0 with interrupt
    
         while (1)
        	 ;
    }
    
    // Remote input interrupt service routine
    #pragma vector= TIMER0_A0_VECTOR
    __interrupt void TIMER_A0(void){
    
           if (P2IN & REMOTE) {        // Bypass pin high after remote input received NEED TO DEBOUNCE SWITCH
               TA0CCTL0 &= ~CCIE;     // disable timer
               TA0CCR0 = 0;
               P2IFG = 0;             // enable interrupt
               P2IE |= (BYPASS & STATUS_LED);
        	   P2IFG &= ~POSITION;    // Clear interrupt when gate closes
    }
    	}
    
    

  • I am attempting to make it when I get a REMOTE input, it will trigger the interrupt which will make BYPASS AND STATUS_LED high, and reset the interrupt when POSITION goes high. It loaded without blowing up on me, but it wont function. Any tips to get it rolling or a better way to approach this? thanks!

    Jake
  • Well I have gotten a bit further into this but now attempting to use an interrupt I am running into this

    #1111-D pragma vector can only be applied to a function definition, not "Port_1" (declared at line 55)

    I think I need a #define line up at the top of the code for it but I can not seem to figure it out.

    Thanks everyone!!

    #include <msp430g2553.h>
    
    /*
     *Gate controller ad on
     *Functions short input from remote second channel will enable bypass and status LED until gate close input is received
     *Functions 2 second press of bypass will place gate in locked position disabling all gate functions until 2 second input is received again
     *Gate status information to be sent to PC via wifi, open and closed status, along with obstruction sensor bypass and locked condition
     */
    
    #define REMOTE BIT2 //P1.3
    #define POSITION BIT3 // P1.4
    #define BYPASS BIT4 // P1.5
    #define LOCKED BIT5 // P1.6
    #define LOCKLED BIT6 //P1.7
    #define STATUS_LED BIT0 //P1.0
    #ifndef TIMER0_A1_VECTOR
    #define TIMER0_A1_VECTOR    TIMERA1_VECTOR
    #define TIMER0_A0_VECTOR    TIMERA0_VECTOR
    #define PORT1_VECTOR
    #endif
    
    void main(void) {
    WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
    TA0CCTL0 = CCIE;                             // CCR0 interrupt enabled
    TA0CTL = TASSEL_2 + MC_1 + ID_3;           // SMCLK/8, upmode
    TA0CCR0 =  10000;                     // 12.5 Hz
    P1OUT &= 0x00;            // reset all outputs
    P1IN &= ~REMOTE;      // P1.3 input from gate remote second channel
    P1IN &= ~POSITION;    // P1.4 input from gate controller for position high open/ low closed
    P1OUT &= ~BYPASS;     // P1.5 output high to obstruction sensor bypass relay
    P1OUT &= ~LOCK;       // P1.6 output high to gate lock relay
    P1OUT &= ~LOCKLED;    // P1.7 output high to gate lock status LED
    P1REN |= REMOTE;
    P1REN |= POSITION;
    P1REN |= BYPASS;
    P1REN |= LOCK;
    P1REN |= LOCKLED;
    P1IES |= REMOTE;       // interrupt hi/lo edge
    P1IFG &= ~POSITION;    // clear flags
    P1IE |= REMOTE;        // enable interrupt
    P1DIR |= STATUS_LED;   // status led direction out
    _BIS_SR(CPUOFF + GIE);          // Enter LPM0 w/ interrupt
    
    
         while (1)
         {}
    }
    // Timer A0 interrupt service routine
    #pragma vector=TIMER0_A0_VECTOR
    __interrupt void Timer_A (void)
    {
    
    // Port 1 interrupt service routine
    #pragma vector=PORT1_VECTOR
    __interrupt void Port_1(void)
    {
       P2OUT ^= (BYPASS & STATUS_LED);         // MAKE BYPASS AND LED HIGH
       P2IFG &= ~POSITION;                     // RESET INT UPON POSITION HIGH
    }
    

  • You are defining ‘PORT1_VECTOR’ as NULL (empty). This will be read as: ‘#pragma vector=Port_1’.
  • I finally have some time to try this again! I wish I could find someone locally that I could get some tutoring on this. 

    I do not get an error, but it says encountered a problem loading file........................could not open file

    So I have something wrong that it is not happy with, is there something that you see that is causing me the problem?

    Thank you for the help!

    #include "RTC.h"
    #include "msp430g2553.h"
    void main(void)
    {
    	WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
    	P1DIR |= 0x01; // Set P1.0 to output direction
    	TA0CCR0 = 32768 - 1;
    	TA0CTL = TASSEL_1 + MC_1; // ACLK, upmode
    	TA0CCTL0 |= CCIE; // enable CCRO interrupt
    	_EINT();
    	P1OUT &= 0x00;               // Shut down everything
    	P1DIR &= 0x00;
    	P1DIR |= BIT0 + BIT6;        // P1.0 and P1.6 pins output the rest are input
    	P1REN |= BIT3;                   // Enable internal pull-up/down resistors
    	P1OUT |= BIT3;                   //Select pull-up mode for P1.3
    	P1IE |= BIT3;                       // P1.3 interrupt enabled
    	P1IES |= BIT3;                     // P1.3 Hi/lo edge
    	P1IFG &= ~BIT3;                  // P1.3 IFG cleared
    	while (1)
    	{
    		LPM3; // enter LPM3, clock will be updated
    		P1OUT ^= 0x01; // do any other needed items in loop
    		_NOP(); // set breakpoint here to see 1 second int.
    	}
    }
    // Timer A0 interrupt service routine
    #pragma vector=TIMERA0_VECTOR
    __interrupt void Timer_A(void)
    {
    	incrementSeconds();
    	LPM3_EXIT;
    }
    // Port 1 interrupt service routine
    #pragma vector=PORT1_VECTOR
    __interrupt void Port_1(void)
    {
    	if(P1IN & BUTTON);		// Start timer when button is high
    	incrementSeconds(2);    // count 2 seconds as long as button is high
    	P1OUT |= BIT6;		    // Set output high after 2 seconds has elapsed
    	incrementSeconds(60);	// count 60 seconds after output is high
    	P1IFG &= ~BIT6;         // Clear IFG, reset P1.6 low the output will go back low after 60 seconds elapsed
    }
    

  • Jake,

    Leo Bosch passed away November the 15th, 2015

    -- Lichen Wang
  • I did not know, may he rest in peace.

    Thank you Mr. Wang
  • I have tried a few different ways to knock out this challenge.  I can not seem to get to the finish on this or get closer.

    If(BUTTON & P1IN)

    Start interrupt

    Run timer 2 seconds

    Make output high

    Run timer 60 seconds

    reset interrupt

    This was my latest attempt.  I wish they still had the MSP430 face to face work shops!  Either that or find a tutor down here to get me past some of the hurdles.  

    The below code attempt is showing a handful of errors, it does not like having the incrementSeconds in the interrupt or to use pragma.

    I have gone past the point of confusion. 

    Thanks in advance everybody!

    #include "RTC.h"
    #include "msp430g2553.h"
    #define BUTTON BIT3  // P1.3 Button on MSP430G2553
    #define LEDR   BIT6  // P1.6 LED 
    void main(void)
    {
    	WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
    	P1DIR |= 0x01; // Set P1.0 to output direction
    	TA0CCR0 = 32768 - 1;
    	TA0CTL = TASSEL_1 + MC_1; // ACLK, upmode
    	TA0CCTL0 |= CCIE; // enable CCRO interrupt
    	_EINT();
    	P1OUT &= 0x00;               // Shut down everything
    	P1DIR &= 0x00;
    	P1DIR |= BIT0 + BIT6;        // P1.0 and P1.6 pins output the rest are input
    	P1REN |= BIT3;                   // Enable internal pull-up/down resistors
    	P1OUT |= BIT3;                   //Select pull-up mode for P1.3
    	P1IE |= BIT3;                       // P1.3 interrupt enabled
    	P1IES |= BIT3;                     // P1.3 Hi/lo edge
    	P1IFG &= ~BIT3;                  // P1.3 IFG cleared
    	while (1)
    	{
    		LPM3; // enter LPM3, clock will be updated
    		P1OUT ^= 0x01; // do any other needed items in loop
    		_NOP(); // set breakpoint here to see 1 second int.
    	}
    }
    // Timer A0 interrupt service routine
    #pragma vector=TIMERA0_VECTOR
    __interrupt void Timer_A(void)
    {
    	incrementSeconds();
    	LPM3_EXIT;
    }
    // Port 1 interrupt service routine
    #pragma vector=PORT1_VECTOR
    __interrupt void Port_1(void)
    {
    	if(P1IN & BUTTON);		// Start timer when button is high
    	incrementSeconds(2);    // count 2 seconds as long as button is high
    	P1OUT |= LEDR;		    // Set output high
    	incrementSeconds(60);	// count 60 seconds after output is high
    	P1IFG &= ~LEDR;         // Clear IFG, reset P1.6 low
    }

  • jake freese said:
    {
    if ((P2IN & REMOTE) ==0)   //P2.0 input from gate opener second channel contact
        P2OUT |= BYPASS;  // output high on P2.2 
        _delay_cycles(500000);
    
        if ((POSITION) =0 //make bypass stay high until P2.1 goes low
           P2OUT &= ~BYPASS;
           _delay_cycles(500000)
    }     

    Will this work? 

    No, that will not work.

    First, you made some obvious mistakes in the conditions of your second "if" statement. I can fix that.

    Second, the indentations of your lines suggested to me some "grouping". But the c compiler will ignore indentations and misunderstand you. I can fix that too. Do you agree with the following fixed version?

    {
      if ((P2IN & REMOTE) ==0)   //P2.0 input from gate opener second channel contact
      {
        P2OUT |= BYPASS;  // output high on P2.2
        _delay_cycles(500000);
    
        if ((P2IN & POSITION) ==0) //make bypass stay high until P2.1 goes low
        {
           P2OUT &= ~BYPASS;
           _delay_cycles(500000);
        }
      }
    }

     

  • Thanks guys, still no luck. Who thought making a software time delay relay would be such a challenge. I think I am going to just order a PLC today and use it instead.

**Attention** This is a public forum