|
|
View previous topic :: View next topic |
Author |
Message |
MassaM
Joined: 08 Jun 2019 Posts: 31
|
mode select switcher using counter not keeping previous mode |
Posted: Thu Jul 11, 2019 3:21 pm |
|
|
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!
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!
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
|
|
Posted: Thu Jul 11, 2019 6:23 pm |
|
|
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
|
|
Posted: Thu Jul 11, 2019 6:38 pm |
|
|
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!?
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: 9221 Location: Greensville,Ontario
|
|
Posted: Thu Jul 11, 2019 6:49 pm |
|
|
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
|
|
Posted: Thu Jul 11, 2019 7:08 pm |
|
|
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!
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
|
|
Posted: Fri Jul 12, 2019 1:53 am |
|
|
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
|
|
Posted: Fri Jul 12, 2019 5:07 am |
|
|
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: 9221 Location: Greensville,Ontario
|
|
Posted: Fri Jul 12, 2019 6:55 am |
|
|
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
|
|
Posted: Fri Jul 12, 2019 9:54 am |
|
|
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
|
|
Posted: Fri Jul 12, 2019 10:13 am |
|
|
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!
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!
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
|
|
Posted: Fri Jul 12, 2019 10:22 am |
|
|
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
|
|
Posted: Fri Jul 12, 2019 10:49 am |
|
|
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
|
|
Posted: Fri Jul 12, 2019 10:59 am |
|
|
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!
If I manage, I will share. It is going to be part of a tutorial on my youtube channel, and I always give credits. _________________ while(!dead)
{
keepLearning();
} |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Fri Jul 12, 2019 3:56 pm |
|
|
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
|
|
Posted: Fri Jul 12, 2019 7:38 pm |
|
|
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();
} |
|
|
|
|
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
|