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

mode select switcher using counter not keeping previous mode
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
MassaM



Joined: 08 Jun 2019
Posts: 31

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

mode select switcher using counter not keeping previous mode
PostPosted: Thu Jul 11, 2019 3:21 pm     Reply with quote

Hello all again,

I put together a small single button multi mode switching test so it helps with inputs on if this is wrong and if not, how to get the cycling one mode at a time as in the previous mode starts the cycle.

The main reason of course is for reducing the buttons quantity to be used in special cases where there are lots of them already! Cool

The mode is switching properly, but in a forward auto cycling way which is a pain to wait and cycle through all over again for other modes from the beginning. Imagine if this grows beyond 3 modes as of now. Perhaps 8 modes in the final stages! Shocked

Screen shots to tell the story easier:

[url]
http://www.mediafire.com/view/ma877n1uaem9uv8/MODE_Initial_MODE_1.png
[/url]

[url]
http://www.mediafire.com/view/ih7qhvp2gkvuotb/MODE_0_to_1.png
[/url]

[url]
http://www.mediafire.com/view/9wd6fig9bfcnfk0/MODE_1_to_2.png
[/url]

[url]
http://www.mediafire.com/view/z839rl98c68tcs9/MODE_1_to_0.png
[/url]

And here is the code:

Code:

#include <16f877a.h>

#fuses XT, NOWDT, PUT, NOLVP, NOPROTECT, NOBROWNOUT

#use delay(clock=20000000)
#use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7)

// Mode switcher pin
#define MODE_SWITCHER PIN_A0

// Modes A, B and C
#define MODE_A 0
#define MODE_B 1
#define MODE_C 2

// Status LEDs On/Off
#define STATUS_RED 0b001   // Port E0 - Status LED for mode A Red On
#define STATUS_GREEN 0b010 // Port E1 - Status LED for mode B Green On
#define STATUS_BLUE 0b100  // Port E2 - Status LED for mode C Blue On

// Mode switcher handling
unsigned int millis; // miliseconds for counting press durations and mode selection
int previous_mode;   // track the previous mode at the switching time
int active_mode;     // the active mode
int1 mode_switcher_state;  // the state of mode switch

#int_TIMER0
void TIMER0_isr(void)
{
      set_timer0(100); // reset for 1ms overflow
               
      if(input(MODE_SWITCHER))
      {
         mode_switcher_state = 1;
         previous_mode = active_mode;         // not getting here
         millis = 0;
      }
      else if (!input(MODE_SWITCHER))
      {
         mode_switcher_state = 0;
         active_mode = previous_mode;         // not getting here
         millis++;
      }
     
     if(!mode_switcher_state){
     
         if(active_mode != MODE_A)
         {
            previous_mode = active_mode;
           
            if (millis > 10)  // if press held for 10 millis
              active_mode = MODE_A;
            else
              active_mode = previous_mode;
         }
         
         if(active_mode != MODE_B)
         {
            previous_mode = active_mode;

            if(millis > 40) // if press held for 40 millis
              active_mode = MODE_B;
            else
              active_mode = previous_mode;
         }
         
         if(active_mode != MODE_C)
         {
            previous_mode = active_mode;
           
            if(millis > 80) // if press held for 80 millis
              active_mode = MODE_C;
            else
              active_mode = previous_mode;
         }

     }
}

void doModeA()
{
   printf("active_mode %d **** millis %u\r\n", active_mode, millis);
   output_e(STATUS_RED); // Show Status Red when in Mode A
   
   // do other stuff for this mode
}

void doModeB()
{
   printf("active_mode %d **** millis %u\r\n", active_mode, millis);
   output_e(STATUS_GREEN); // Show Status Green when in Mode B
   
   // do other stuff for this mode
}

void doModeC()
{
   printf("active_mode %d **** millis %u\r\n", active_mode, millis);
   output_e(STATUS_BLUE); // Show Status Blue when in Mode C
   
   // do other stuff for this mode
}


void initAll()
{
   setup_counters(RTCC_INTERNAL, RTCC_DIV_256);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(global);
   
   active_mode = MODE_B;   // set initial mode to B = STATUS_GREEN
   
}

void main()
{
   initAll();
   
   while(TRUE)
   {
      printf("\r\nprevious_mode %d\r\n", previous_mode);
     
      switch(active_mode)  // main mode switching management
      {
         case MODE_A:
           doModeA();
         break;
         
         case MODE_B:
            doModeB();
         break;
               
         case MODE_C:
            doModeC();
         break;
    }
   }

}


Am sure there is something silly I am doing here which am unable to notice!

Your inputs are all appreciated in advance.
_________________
while(!dead)
{
keepLearning();
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jul 11, 2019 6:23 pm     Reply with quote

Quote:

#include <16f877a.h>

#fuses XT, NOWDT, PUT, NOLVP, NOPROTECT, NOBROWNOUT

#use delay(clock=20000000)

This shows you're using Proteus. You're not doing it for real.
MassaM



Joined: 08 Jun 2019
Posts: 31

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

PostPosted: Thu Jul 11, 2019 6:38 pm     Reply with quote

PCM programmer wrote:
Quote:

#include <16f877a.h>

#fuses XT, NOWDT, PUT, NOLVP, NOPROTECT, NOBROWNOUT

#use delay(clock=20000000)

This shows you're using Proteus. You're not doing it for real.


Yes indeed, it is on Proteus for now as per my posted screen shots.

Agreed that the simulation is not like the real thing, but just my testing on the simulation for the general feel of the button handling before I put all to breadboard.

Is it Proteus the problem, or the test code!? Cool

Edit: Added links below for your review.

This is the to be the final product:

http://www.mediafire.com/view/rqbyp9i7l53aw39/relay_controller_full.png

Youtube breadboard demonstration here:

https://www.youtube.com/watch?v=R96LOQxJpZk

Hope that helps.
_________________
while(!dead)
{
keepLearning();
}


Last edited by MassaM on Thu Jul 11, 2019 6:57 pm; edited 1 time in total
temtronic



Joined: 01 Jul 2010
Posts: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Jul 11, 2019 6:49 pm     Reply with quote

Proteus is known to be full of bugs, errors and fulty DRCs.
It simply cannot be trusted, as it even gets SIMPLE things wrong....

Your code can be made simpler, more efficient as you're only working with two states... ones and zeros.

Jay
MassaM



Joined: 08 Jun 2019
Posts: 31

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

PostPosted: Thu Jul 11, 2019 7:08 pm     Reply with quote

temtronic wrote:
Proteus is known to be full of bugs, errors and fulty DRCs.
It simply cannot be trusted, as it even gets SIMPLE things wrong....

Your code can be made simpler, more efficient as you're only working with two states... ones and zeros.

Jay


Agreed. Simulation fails miserably. But, its for the general brain storming and visual feedback/feel of the features in mind. A simulated visualization, perhaps useful in someways! Rolling Eyes

The major part of relay controller is already breadboarded and PIC programmed working great as demonstrated on my youtube video.
I added few links to my prior post to this reply. Please check.
_________________
while(!dead)
{
keepLearning();
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jul 12, 2019 1:53 am     Reply with quote

Quote:

The mode is switching properly, but in a forward auto cycling way which is
a pain to wait and cycle through all over again for other modes from the
beginning. Imagine if this grows beyond 3 modes as of now. Perhaps 8
modes in the final stages!

I don't know what you mean by forward auto cycling.

Your program is too complicated. I made a simple program.
Each time you press a button, it lights up the next LED. All other LEDs
are OFF. I don't know what you want. At least my program is
simple enough to understand (except maybe the macro part).
Code:

#include <16F877A.h>
#fuses HS, NOWDT, BROWNOUT, PUT, NOLVP
#use delay(clock=20M)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

//----------------------------
// The following macro calculates the Timer1 preload, so
// we don't have to do it.
#define FOSC getenv("CLOCK")  // Get PIC oscillator frequency
#if(FOSC < 21000000)          // Macro only supports max freq of 20 MHz
  #define TIMER0_PRELOAD (256 - (FOSC/4/256/100))
#else
  #error Oscillator frequency is too high:  FOSC
#endif
//----------------------------
// The button and LED pins are for my PicDem2-Plus board.

#define BUTTON_PIN  PIN_A4

#define RED_LED_PIN    PIN_B0
#define GREEN_LED_PIN  PIN_B1
#define BLUE_LED_PIN   PIN_B2

enum LED_STATE_VALUES{RED, GREEN, BLUE};
#define MAX_LED_STATE BLUE
#define MIN_LED_STATE RED

#define BUTTON_IDLE_STATE 1  // Button is active low


int8 button_pressed = FALSE;

//------------------------------
// The button pin is polled every 10ms in this interrupt
// routine. This assumes the "bounce" period for the
// button is less than 10 ms.  Usually this will be the
// case, except for very cheap, sloppy switches.

#int_timer0
void timer0_isr(void)
{
int8 current_value;
static int8 previous_value = BUTTON_IDLE_STATE;

set_rtcc(TIMER0_PRELOAD); // Reload Timer0 for 10ms rate

current_value = input(BUTTON_PIN);  // Read the button

// Look for a falling edge, which indicates the
// button has been pushed.
if((previous_value == 1) && (current_value == 0))
   button_pressed = TRUE;   

previous_value = current_value;  // Save current value for next time
}

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

//------------------------
void red_led_on(void)
{
output_high(RED_LED_PIN);
output_low(GREEN_LED_PIN);
output_low(BLUE_LED_PIN);
}

//------------------------
void green_led_on(void)
{
output_low(RED_LED_PIN);
output_high(GREEN_LED_PIN);
output_low(BLUE_LED_PIN);
}

//------------------------
void blue_led_on(void)
{
output_low(RED_LED_PIN);
output_low(GREEN_LED_PIN);
output_high(BLUE_LED_PIN);
}

//===========================
void main()
{
int8 led_state;

delay_ms(100);

timer0_init();

//printf("Timer0 preload = %u \n\r", TIMER0_PRELOAD);
//printf("RED = %u \n\r", RED);
//printf("GREEN = %u \n\r", GREEN);
//printf("BLUE = %u \n\r", BLUE);

led_state = GREEN;        // Initial LED to turn-on
button_pressed = TRUE;    // Force turn-on of initial LED

while(TRUE)
  {
   if(button_pressed == TRUE)
     {
      button_pressed = FALSE;   

      switch(led_state)
        {
         case RED:
           red_led_on();
           break;
         
         case GREEN:
           green_led_on();
           break;

         case BLUE:
           blue_led_on();
           break;
        }

      led_state++;
      if(led_state > MAX_LED_STATE)
         led_state = MIN_LED_STATE;
     }

  }


}
MassaM



Joined: 08 Jun 2019
Posts: 31

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

PostPosted: Fri Jul 12, 2019 5:07 am     Reply with quote

Thank you for taking time out to answer my question and write/post code, and I greatly appreciate the valuable information you have provided me with.

Also apologies for not being clear on what I am trying to achieve.

In simple terms, I need one single button that can shift between machine operating state aka modes of operation depending on the duration of button press and hold.

Let's say we have 3 Modes A, B & C where each of these modes are a totally different sets of controlling how the device functions.

Now, if I press and hold that one button for 10 Milli seconds, the PIC shifts the operation mode to Mode A where I do different set of functionality.

And in the same manner above, if I press and hold it down for more than 30 Milli seconds, the PIC shifts to Mode B, and if more than 90 Milli seconds, Mode C kicks in.

My code already is doing what I need and working alright, but, it reverts back to Mode A, then forward shifts to Mode B and then Mode C, aka cycles while the button is press held based on the counter durations mentioned.

What I like to achieve is:

If in any Mode at anytime, to have a press hold timer/counter on the single button to start the mode shift from that Active Mode, not revert back to A and then B and C as my code is doing now.

Basically, one button multi function depending on duration of button press measured using a timer/counter.

Hope above is clear, but please do let me know otherwise to explain further.
_________________
while(!dead)
{
keepLearning();
}
temtronic



Joined: 01 Jul 2010
Posts: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Jul 12, 2019 6:55 am     Reply with quote

In the FAQ or Q&A section of the manual...find this...

'How do I wait only a specified time for a button press?'

it is another way to do the 'timed button' operation.

There is a 'logic' problem with deciding length of 'button down'. You need to check if time is less than 10ms, or then less than 30ms then less than 100ms to capture the correct operation, I think....

Jay
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jul 12, 2019 9:54 am     Reply with quote

Quote:
Now, if I press and hold that one button for 10 Milli seconds, the PIC shifts the operation mode to Mode A where I do different set of functionality.

And in the same manner above, if I press and hold it down for more than 30 Milli seconds, the PIC shifts to Mode B, and if more than 90 Milli seconds, Mode C kicks in.

Do you honestly think you can hold a button for those precise amounts
of time ? Or is it actually not a button ? Is it really a pulse from some
un-named device ?
MassaM



Joined: 08 Jun 2019
Posts: 31

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

PostPosted: Fri Jul 12, 2019 10:13 am     Reply with quote

temtronic wrote:
In the FAQ or Q&A section of the manual...find this...

'How do I wait only a specified time for a button press?'

it is another way to do the 'timed button' operation.

There is a 'logic' problem with deciding length of 'button down'. You need to check if time is less than 10ms, or then less than 30ms then less than 100ms to capture the correct operation, I think....

Jay


Thank you for your feedback.

As you suggested, I looked in the FAQ ( http://www.ccsinfo.com/faq.php )
section for "time" and got two hits as below which neither help to achieve my required feature.

1- http://www.ccsinfo.com/faq.php?page=int_ext_button
2- http://www.ccsinfo.com/faq.php?page=ccs_timer0_interrupt

The 1st one is a PORT B interrupt and it does not meet the feature.
The 2nd one is couting in reverse from "HIGH_START 114", which is opposite of what I need and it's kind of a single event process triggered by and for separate buttons, if I am not mistaken!

I have also tested all timer based examples as well as the CCP1/2 capture examples of CCS-C, but they are PWM related and and overkill for my simple task.

Knowing that this forum is CCS, I have with due respect refrained from talking about other platforms such as Arduino or MikroC, but there is a library called "OneButton" in Arduino that does "Single Click", Double Click" and "Long Press" checking which is the exact thing I am trying to achieve with CCS.

I have also seen "PCM Programmer"'s Button.c which is an awesome library, but isn't fitting my One Button/Multi Function requirement.

Links to show further what I mean/require:

Clever Button which is Assembly based. I am a no assembly guy! Embarassed

https://www.youtube.com/watch?v=fpOnBKN8ZU8

Code link here:

http://www.pcbheaven.com/picpages/A_Clever_Button/

If any ASM savvy can port this to C, it's highly appreciated! Cool

With apologies in advance to CCS team, below is a MikroE example:
(Please feel free to delete this entire post if found it violating forum terms)

https://forum.mikroe.com/viewtopic.php?f=97&t=28092

Hope above helps explaining my request and not offensive to anyone.

Take care.
_________________
while(!dead)
{
keepLearning();
}
MassaM



Joined: 08 Jun 2019
Posts: 31

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

PostPosted: Fri Jul 12, 2019 10:22 am     Reply with quote

PCM programmer wrote:
Do you honestly think you can hold a button for those precise amounts
of time ? Or is it actually not a button ? Is it really a pulse from some
un-named device ?


Apologies. The running counter i meant, in the timer0_isr, if count is > 10 do A, if count > 30 do B and count > 80 do C as below.

Code:
#int_TIMER0
void TIMER0_isr(void)
{
   set_timer0(100); // reset for 1ms overflow
   
      if(input(MODE_SWITCHER))
      {
         mode_switcher_state = 1;
         millis = 0;
      }
      else if (!input(MODE_SWITCHER))
      {
         mode_switcher_state = 0;
         previous_mode = active_mode;
         millis++;         
      }
     
     if(!mode_switcher_state)
     {
     
         if(active_mode != MODE_A)
         {
            if (millis > 10)
              active_mode = MODE_A;
         }
         
         if(active_mode != MODE_B)
         {
            if(millis > 30)
              active_mode = MODE_B;
         }
         
         if(active_mode != MODE_C)
         {
            if(millis > 80)
              active_mode = MODE_C;
         }

     }
}

_________________
while(!dead)
{
keepLearning();
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jul 12, 2019 10:49 am     Reply with quote

Quote:
The running counter i meant, in the timer0_isr,

But previously you said:
Quote:

In simple terms, I need one single button that can shift between
machine operating state aka modes of operation depending on the
duration of button press and hold.


I've done all I can do to help you, by posting my sample program.
I can't do any more.
MassaM



Joined: 08 Jun 2019
Posts: 31

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

PostPosted: Fri Jul 12, 2019 10:59 am     Reply with quote

PCM programmer wrote:
Quote:
The running counter i meant, in the timer0_isr,

But previously you said:
Quote:

In simple terms, I need one single button that can shift between
machine operating state aka modes of operation depending on the
duration of button press and hold.


I've done all I can do to help you, by posting my sample program.
I can't do any more.


Great help as always and no worries. Thank you for your time! Smile

If I manage, I will share. It is going to be part of a tutorial on my youtube channel, and I always give credits. Cool
_________________
while(!dead)
{
keepLearning();
}
temtronic



Joined: 01 Jul 2010
Posts: 9081
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Jul 12, 2019 3:56 pm     Reply with quote

re:
Quote:
How do I wait only a specified time for a button press?

It's the 5th or 6th entry under the 'Common Questions & Answers' section of the manual.
I've used a variation of it for a 'short press' vs 'long press' of push buttons for a few years.
MassaM



Joined: 08 Jun 2019
Posts: 31

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

PostPosted: Fri Jul 12, 2019 7:38 pm     Reply with quote

temtronic wrote:
re:

'How do I wait only a specified time for a button press?'

It's the 5th or 6th entry under the 'Common Questions & Answers' section of the manual.
I've used a variation of it for a 'short press' vs 'long press' of push buttons for a few years.


I got the "CCS C Compiler Manual
PCB, PCM, PCH, and PCD" March 2019
from this link https://www.ccsinfo.com/downloads/ccs_c_manual.pdf
and its 622 pages but can't find anything as you mentioned? Do they have other manuals?
_________________
while(!dead)
{
keepLearning();
}
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 1, 2  Next
Page 1 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