CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

A Clever Button
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
corgenius



Joined: 27 May 2015
Posts: 18

View user's profile Send private message

PostPosted: Sun Jul 26, 2015 10:19 am     Reply with quote

Hurrah, I understand the code completely!

Also I've tried to define all the missing parts and compile the code, and I got 3 errors : Expecting LVALUE such as a variable name or * expression (Lines 25, 29,59) and one error : A numeric expression must appear here (Line 43)

I've read about them in the PCW help menu but it doesn't make any sense because input(LAMP_BUTTON2) is a variable.

I will bold the 3 lines with LVALUE error and make italic the line with "numeric expression must appear here".
Code:
#include <12F675.h>
#FUSES INTRC_IO
#use delay(clock=4MHz)

#define LAMP_BUTTON2   PIN_A2
#define LAMP           PIN_A5                 
#define LAMP3          PIN_A1
#define button_pressed() (input(LAMP_BUTTON2)=SWITCH_NOT_PRESSED)
#define lamp_on() (output_high(LAMP))
#define lamp_off() (output_low(LAMP))
#define SWITCH_PRESSED      0          //  5V
#define SWITCH_NOT_PRESSED  1          //  0

//============================================================================================

void main()
{
output_high(LAMP3);                // STATUS - LED ON = MICROCONTROLER ON
enum {LOOK_FOR_BUTTON, WAIT_200, LAMP_500, IGNORE_STILL_ON} task;
int16 ticks;

    switch (task)
    {
    case LOOK_FOR_BUTTON:
        [b]if (button_pressed())[/b]
        {
           task=WAIT_200;
           ticks=200;
        }
        break;   
    case WAIT_200:
[b]        if (button_pressed()) [/b]
        {
            if (ticks)
                --ticks;
            else
            {
                //button has been pressed for 200 ticks
                ticks=500;
                task=LAMP_500;
            }
        }
    [i]    else  [/i]
            task=LOOK_FOR_BUTTON;
        break;
    case LAMP_500:
        if (ticks)
        {
            lamp_on(); //again I'd define this - haven't done so
            --ticks;
        }
        else
        {
            lamp_off(); //same comment
            task=IGNORE_STILL_ON;
        }
        break;
   case IGNORE_STILL_ON:
[b]        if (! button_pressed()) [/b]
            task=LOOK_FOR_BUTTON;
        break; //wait for the button to go off
   }//end of switch
}




Edit : I've found out were the mistake was.... the line #define button_pressed() (input(LAMP_BUTTON2)=SWITCH_NOT_PRESSED) was incorrect. The correct code is #define button_pressed() (input(LAMP_BUTTON2)==SWITCH_NOT_PRESSED)


Edit2: The code compiles, but, it doesn't do anything...the compiled code is:
Code:
#include <12F675.h>
#FUSES INTRC_IO
#use delay(clock=4MHz)

#define LAMP_BUTTON2   PIN_A2
#define LAMP           PIN_A5                 
#define LAMP3          PIN_A1
#define SWITCH_PRESSED      0          //  5V
#define SWITCH_NOT_PRESSED  1          //  0
#define button_pressed() (input(LAMP_BUTTON2)==SWITCH_NOT_PRESSED)
#define lamp_on()  output_high(LAMP)
#define lamp_off() output_low(LAMP)


//==============================================
void main()
{
output_high(LAMP3);                // STATUS - LED ON = MICROCONTROLER ON
enum {LOOK_FOR_BUTTON, WAIT_200, LAMP_500, IGNORE_STILL_ON} task;
int16 ticks;

    switch (task)
    {
    case LOOK_FOR_BUTTON:
        if (button_pressed())
        {
           ticks=20;
           task=WAIT_200;       
        }
        break;   
    case WAIT_200:
        if (button_pressed())
        {
            if (ticks>0)
                --ticks;
            else
            {
                //button has been pressed for 200 ticks
                ticks=100;
                task=LAMP_500;
            }
        }
        else 
            task=LOOK_FOR_BUTTON;
        break;
    case LAMP_500:
        if (ticks>0)
        {
            lamp_on(); //again I'd define this - haven't done so
            --ticks;
        }
        else
        {
            lamp_off(); //same comment
            task=IGNORE_STILL_ON;
        }
        break;
   case IGNORE_STILL_ON:
        if (!button_pressed())
            task=LOOK_FOR_BUTTON;
        break; //wait for the button to go off
   }//end of switch
}


Any ideas as why it doesn't do anything?

Regards,

Eugeniu
corgenius



Joined: 27 May 2015
Posts: 18

View user's profile Send private message

PostPosted: Sun Jul 26, 2015 1:58 pm     Reply with quote

Hurrahhhhh


I've managed to make it do exactly what I want Smile

Thank you for the support Ttelmah ! Please have a look at my code to see if everything looks alright:)


Regards,

Eugeniu



Code:
#include <12F675.h>
#FUSES INTRC_IO
#use delay(clock=4MHz)
             
#define LAMP3          PIN_A1
#define SWITCH_PRESSED      0          //  5V
#define SWITCH_NOT_PRESSED  1          //  0
#define button_pressed()          input(PIN_A2)==SWITCH_NOT_PRESSED
#define button_not_pressed()      input(PIN_A2)==SWITCH_PRESSED
#define lamp_on()                 output_high(PIN_A5)
#define lamp_on2()                 output_high(PIN_A4)
#define lamp_off()                output_low(PIN_A5)


//============================================================================================

void main()
{
output_high(LAMP3);                // STATUS - LED ON = MICROCONTROLER ON
enum {LOOK_FOR_BUTTON, WAIT_200, LAMP_500, IGNORE_STILL_ON} task;
int16 ticks;
While(true)
{
    switch (task)
    {
    case LOOK_FOR_BUTTON:
        if (button_pressed())
        {
           ticks=2000;
           task=WAIT_200;       
        }
        break;   
    case WAIT_200:
        if (button_pressed())
        {
            if (ticks>0)
                --ticks;
            else
            {
                //button has been pressed for 100 ticks
                ticks=1000;
                task=LAMP_500;
            }
        }
        else 
            task=LOOK_FOR_BUTTON;
        break;
    case LAMP_500:
        if (ticks>0)
        {
            lamp_on();
            delay_ms(5);
            --ticks;
        }
        else
        {
            lamp_off();
            ticks=300;
            task=IGNORE_STILL_ON;
        }
        break;
case IGNORE_STILL_ON:
     if (!button_pressed())
     {
          if (ticks>0)             
              --ticks;
        else
        {
           task=LOOK_FOR_BUTTON;
        }
           //wait for the button to go off
    }//end of switch
    break;
    }
    }
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19195

View user's profile Send private message

PostPosted: Sun Jul 26, 2015 2:05 pm     Reply with quote

It's looking a good start. Smile

Now if you want to get more complex (not necessary for your application), the 'tick' that makes the loop time can be done with a timer.
The advantage then is that the loop then takes 1mSec every time (assuming this is the time used). If a particular route through the code takes a fraction longer it doesn't change the timings.

Once you do that, and add more states to do anything else, you basically have the core of how people make the PIC do multiple jobs. Since the loop keeps looping you can handle multiple buttons, multiple lamps, whatever you want!.

The enum, with the switch, is called a 'state machine'. The code just moves through the states to do the various operations.

Have fun.
Petar_2010



Joined: 18 Nov 2018
Posts: 5

View user's profile Send private message

PostPosted: Mon Aug 19, 2019 9:36 am     Reply with quote

Hello,

I have a similar problem. I need to program a push-button with three states:
1 state: if the time of press is less than 1000ms the led must be permanent.
2 state: if the time of press is more than 1000ms the led must be flashing with 500ms on 500ms off.
3 state: another press - led off.
I've done states 1, 3 and 2, 3 separately and I tried to combine both but at the moment I don't have any success.

This is my code (states 1 and 3 without the time counter of 1000ms):
Code:

#include <16F1828.h>
#fuses NOMCLR        //Master Clear pin used for I/O           
#fuses BORV25        //Brownout reset at 2.5V

#use FIXED_IO( A_outputs=PIN_A0,PIN_A1,PIN_A2,PIN_A3,PIN_A4,PIN_A5 )
#use FIXED_IO( B_outputs=PIN_B4,PIN_B5,PIN_B6,PIN_B7 )
#use STANDARD_IO(C)

#use delay(internal=8MHz)

// DEFINE INPUT BUTTONS
#define BUTTON_1 PIN_C0

// DEFINE OUTPUT LEDS
#define LED_GREEN PIN_A0

int16 cont_green=0;

#int_timer2
void interm_green()
{
cont_green++;
if(cont_green==1600)
   {
    output_toggle(LED_GREEN);
    cont_green=0;
   }
}                   
//======================================================================
void main()
{
port_c_pullups(0xff);
output_a(0x00);

WHILE(true){
enable_interrupts(GLOBAL); //Habilita int. general
setup_timer_2(T2_DIV_BY_4,124,1);

if((input(BUTTON_1) == 0)){
   char count; count = 0;
   while(true){ //push-button pressed
      if((input(BUTTON_1) == 0)) delay_ms(10); //debounce
      if((input(BUTTON_1) == 0))
         count++;
      else
         count = 0;
      if(count == 1)
         break;
      delay_ms(10);
  }
                 
while(true){ //push-button loosed   
   if (input(BUTTON_1)) delay_ms(10); //debounce
   if(input(BUTTON_1))
      count++;
   else
      count = 0;
   if(count == 1)
      break;
   delay_ms(30);
}
output_toggle(LED_GREEN);

} //if green
} //while principal
} //void main

This is my code (states 2 and 3 without the time counter of 1000ms):
Code:

#include <16F1828.h>
#fuses NOMCLR        //Master Clear pin used for I/O           
#fuses BORV25        //Brownout reset at 2.5V

#use FIXED_IO( A_outputs=PIN_A0,PIN_A1,PIN_A2,PIN_A3,PIN_A4,PIN_A5 )
#use FIXED_IO( B_outputs=PIN_B4,PIN_B5,PIN_B6,PIN_B7 )
#use STANDARD_IO(C)

#use delay(internal=8MHz)

// DEFINE INPUT BUTTONS
#define BUTTON_1 PIN_C0

// DEFINE OUTPUT LEDS
#define LED_GREEN PIN_A0

int16 cont_green=0;

#int_timer2
void interm_green()
{
cont_green++;
if(cont_green==1600)
   {
    output_toggle(LED_GREEN);
    cont_green=0;
   }
}                   
//======================================================================
void main()
{
port_c_pullups(0xff);
output_a(0x00);

WHILE(true){
enable_interrupts(GLOBAL); //Habilita int. general
setup_timer_2(T2_DIV_BY_4,124,1);

if((input(BUTTON_1) == 0)){
char count; count = 0;
while(true){ //push-button pressed
   if((input(BUTTON_1) == 0)) delay_ms(10); //debounce
   if((input(BUTTON_1) == 0))
count++;
   else
      count = 0;
   if(count == 1)
      break; delay_ms(10);
  }
                 
while(true){ //push-button loosed
   if (input(BUTTON_1)) delay_ms(10); //debounce
   if(input(BUTTON_1))
      count++;
   else
      count = 0;
   if(count == 1)
      break; delay_ms(30);


int8 a1;
if(a1==0){
     a1=1;
     enable_interrupts(INT_TIMER2);}
  else {
     a1=0;
     disable_interrupts(INT_TIMER2);
     output_low(LED_GREEN);}     

} //if green
} //while principal
} //void main

Thank you for your comments.

Smile
allenhuffman



Joined: 17 Jun 2019
Posts: 537
Location: Des Moines, Iowa, USA

View user's profile Send private message Visit poster's website

PostPosted: Tue Aug 20, 2019 12:54 pm     Reply with quote

Interesting topic. Years ago, I was creating show control for a haunted house attraction using VenueMagic software. Initially, the place was wired up with pressure mats that could be used to trigger sounds and effects in various rooms.

Later, they needed to have a way to start and stop the attraction from the entrance. We wired a button into a pressure mat and then did exactly this -- short presses (people just walking by) did one thing, and long presses (the operator holding down the button for several seconds) did another. We called it the "Apple approach" because we were doing a bunch of stuff with one button.

Clever, indeed. Great suggestions and discussion here.
_________________
Allen C. Huffman, Sub-Etha Software (est. 1990) http://www.subethasoftware.com
Embedded C, Arduino, MSP430, ESP8266/32, BASIC Stamp and PIC24 programmer.
http://www.whywouldyouwanttodothat.com ?
MassaM



Joined: 08 Jun 2019
Posts: 31

View user's profile Send private message Visit poster's website

PostPosted: Fri Sep 20, 2019 6:06 pm     Reply with quote

Petar_2010 wrote:

I have a similar problem. I need to program a push-button with three states


Check my thread and go to 2nd page, maybe you can base your code on. Here:

Edit URL update to go to page 2 directly:

http://www.ccsinfo.com/forum/viewtopic.php?t=58126&postdays=0&postorder=asc&start=15
_________________
while(!dead)
{
keepLearning();
}
PrinceNai



Joined: 31 Oct 2016
Posts: 452
Location: Montenegro

View user's profile Send private message

PostPosted: Tue Sep 24, 2019 10:06 am     Reply with quote

Just because it's an interesting topic, I wrote a code that does what Petar_2010 wants to achieve.

1_switch.h

Code:

#include <18F46K22.h>
#device ADC=10

#FUSES NOWDT                    //No Watch Dog Timer
//#FUSES NOMCLR

#device ICD=TRUE
#use delay(internal=4000000)



1_switch.c

Code:

// LED is turned on with logical 0
// switch shorts to GND

#include <1_switch.h>

#define FOSC getenv("CLOCK")                                   // Get PIC oscillator frequency
// check if it is below or equal to 20MHz                 
#if(FOSC < 21000000)
  #define TIMER0_PRELOAD (256 - (FOSC/4/256/100))
#else
  #error Oscillator frequency is too high:  FOSC
#endif

#define  ENTER_switch   PIN_B0                                 // change to whatever suits you
#define LED PIN_C6

int8 ENTER_switch_is_down = FALSE;
int16 TimeCounter = 0;                                         // measures the time switch is pressed
enum {WAIT_PRESS, SWITCH_PRESSED, LED_ON};
int8 Read_Key = WAIT_PRESS;
int1 Blink = 0;
int8 BlinkCounter = 0;
int8 _Short = 0;

// ****************************************************************************

void timer0_init(void)
{
   setup_timer_0(T0_INTERNAL | T0_DIV_256 | T0_8_BIT);
   set_timer0(TIMER0_PRELOAD);
   clear_interrupt(INT_TIMER0);
   enable_interrupts(INT_TIMER0);
}

// ****************************************************************************

#INT_TIMER0                                                    // fires every 10ms
void  TIMER0_isr(void)
{
   set_rtcc(TIMER0_PRELOAD);                                   // set for next interrupt after 10ms
// debounce
// presumes that 0 is read when the switch is pressed
   int8 active_state_ENTER;
   int8 previous_state_ENTER;                                  // declare variables
   active_state_ENTER = input(ENTER_switch);                   // Read the button
   
   if((previous_state_ENTER == 1) && (active_state_ENTER == 0)){                       
      ENTER_switch_is_down = TRUE;                             // switch pressed, raise "ENTER PRESSED" flag             
   }                                                           // must be cleared in software
   
   previous_state_ENTER = active_state_ENTER;                  // Save current value for next time
   TimeCounter++;
   BlinkCounter++;
   if(BlinkCounter == 50){
      BlinkCounter = 0;
      Blink = !Blink;                                          // set the LED blinking rate of 500ms
   }
}

// ****************************************************************************

void main(){

   timer0_init();                                              // init timer0 for 10ms interrupt
   
// it works much more reliable with external pull-up   
   port_b_pullups(true);
   enable_interrupts(GLOBAL);

   while(TRUE){

// do the switch
      switch (Read_Key){
// ----------------------------------------------------------------------------
// wait for the switch to be pressed
         case WAIT_PRESS:{
            if(ENTER_switch_is_down){           // button pressed
               ENTER_switch_is_down = 0;        // clear flag
               TimeCounter = 1;                 // 10ms already passed
               Read_Key = SWITCH_PRESSED;       // measure for how long the key is pressed
            }         
            break;
         }
// ----------------------------------------------------------------------------
// switch was pressed, measure for how long
         case SWITCH_PRESSED:{                  // measure the time of the press
            if(input_state(ENTER_switch)){      // switch is off before 1s elapses           
               Read_Key = LED_ON;
               _Short = 1;                      // indicate short press
            }
            else{
               if(TimeCounter > 100){
                  Read_Key = LED_ON;            // switch pressed for more than 1s
                  _Short = 0;                   // indicate long press
               }
            }
            break;
         }
// ----------------------------------------------------------------------------
         case LED_ON:{                          // light the LED the way it has to be and wait for another key press to quit
// was switch pressed again to reset everything??         
            if(ENTER_switch_is_down){
               ENTER_switch_is_down = 0;
               output_high(LED);                // turn off the LED
               Read_Key = WAIT_PRESS;           // reset
               break;
            }
// short press, turn LED on
            if(_Short){
               output_low(LED);
            }

// long press, blink LED 500ms on, 500ms off
            else{
               if(Blink){
                  output_low(LED);
               }
               else{
                  output_high(LED);
               }
           
            }
            break;
         }         
// ------------------------- end cases ----------------------------------------     
      }        // switch brace
   
   }           // while true brace

}              // main brace

barbiani



Joined: 02 Feb 2013
Posts: 7

View user's profile Send private message

PostPosted: Thu Sep 26, 2019 11:24 pm     Reply with quote

Recalling another great post.

http://www.ccsinfo.com/forum/viewtopic.php?t=22145&highlight=button+double+click
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group