View previous topic :: View next topic |
Author |
Message |
rems
Joined: 02 Feb 2012 Posts: 56
|
What control statement can I use? |
Posted: Sat Feb 18, 2012 12:29 pm |
|
|
I am using a PIC16F887, CCS with Mplab and pickit 2.
I want to turn an led on, only after a combination of pins have been enabled.
The following is my partial pseudo code
Pseudo code
6 switch combination to control led
led connected to pin 10
combo is 123456
is pin 1 hi
yes> check pin 2
no> go back to sleep
is pin 2 hi
yes> check pin 3
no> go back to sleep
is pin 3 hi
yes> check pin 4
no> go back to sleep
is pin 4 hi
yes> check pin 5
no> go back to sleep
is pin 5 hi
yes> check pin 6
no> go back to sleep
is pin hi
yes> enable pin 10
no> go back to sleep
I am not asking for the C code needed. I only want some direction if possible. I am all set up and can control leds no problem. Here's what I have so far.
Code: |
void main()
{
while(1)
{
if (input(pin_E0)){
if (input(pin_E1)){
Output_high(pin_D4);
}
}
}
}
}
|
This code turns the led on, only when both pins are on at the same time. I want it to work so that the first pin goes HI and then the program checks the second pin, regardless of the first pin anymore.
Is this where I should use a "case-switch-break" statement?
Any suggestions? |
|
|
SherpaDoug
Joined: 07 Sep 2003 Posts: 1640 Location: Cape Cod Mass USA
|
|
Posted: Sat Feb 18, 2012 1:33 pm |
|
|
This is a classic application of a software construct called a "State Machine". Here is a description of how that works:
http://en.wikipedia.org/wiki/State_machine
Look at figure 4 of the link above to see just how it applies.
It is a very powerful tool every programmer should learn about. _________________ The search for better is endless. Instead simply find very good and get the job done. |
|
|
rems
Joined: 02 Feb 2012 Posts: 56
|
|
Posted: Sat Feb 18, 2012 1:53 pm |
|
|
Great...I'm going to take a look right now...
Thank you so much |
|
|
rems
Joined: 02 Feb 2012 Posts: 56
|
|
Posted: Thu Feb 23, 2012 9:47 am |
|
|
I've looked at this "state machine" and it looks like exactly what I need. However, after long searching the CCS help files, I am unable to find anything that looks like this.
Is there a way to make a "case-break" into this? Or an "if-else"?
Or does it need to be done in a more rigorous fashion?
Such as:
PSEUDO
create a variable C
When C=6, output ledpin HI
C=1 to start
then I make series of if-else statements such as:
Code: |
if (input(pin_E0)) {
increment C
}
|
Something like the above...I'll just try to "run" with the above and see how it goes..
I would still appreciate maybe a specific direction that may seem obvious to everyone but me.... |
|
|
rems
Joined: 02 Feb 2012 Posts: 56
|
|
Posted: Thu Feb 23, 2012 10:04 am |
|
|
This is what I have so far...Right now I am just trying a 2 pin combo...
Code: |
void main()
{
int C;
C==0;
while(1)
{
if (input(pin_E0)) {
C++;
}
if (input(pin_D1)) {
C++;
}
if (C==2) {
Output_high(pin_D4);
}
}
}
|
When E0 goes HI, I expect C to increment and when D1 goes HI, I expect C to increment again. Then the final is when C=2, I expect my o/p ledpin to go hi.
Problem is that the led pin goes hi when ever pinE0 or pinD1 go HI. There seems to be no incrementation of C and if there is, then my program certainly isn't waiting for C to = 2 before it o/p's my led pin to HI.
ie. When I make pinE0 HI----LED turns on regardless of pinD1
and When pinD1 goes HI----LED also turns on regardless of pinE0
What am I doing wrong? |
|
|
ezflyr
Joined: 25 Oct 2010 Posts: 1019 Location: Tewksbury, MA
|
|
Posted: Thu Feb 23, 2012 11:23 am |
|
|
Hi,
What is the initial value of C? This statement C==0; is not correct.
Keep in mind that your while loop is executing very quickly, and C increments well beyond 2 as soon as either E0 or D1 goes high. The LED lights when C = 2, but then stays on because there is no code to turn it off.
You probably want some code to increment C once per button press. You'll also want to add some code to limit when the LED is lit. Finally, you'll benefit enormously by using an output pin to send diagnostic messages using printf to aid in debugging.
John |
|
|
rems
Joined: 02 Feb 2012 Posts: 56
|
|
Posted: Thu Feb 23, 2012 11:38 am |
|
|
I see what you mean. C will continue to increment while the pin is HI. Furthermore, the pin will stay HI because nothing is turning it off. I do realize the program runs very quick and C will be a very big number in no time.
I was trying to make the initial value of C equal to zero..Maybe just C=0; would be better?
I really like the idea of using printf statements to aid in debugging. I can use them to very the value of C and adjust my program accordingly.
Thank you for this great advice... |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
State machine |
Posted: Thu Feb 23, 2012 11:46 am |
|
|
Of course it does.
You cannot be certain of your initial value for C. C=0 forces C to zero NOT C==0.
What you are seeing is EXACTLY what you have told your PIC to do.
Your code is going round a loop very quickly (~us) looking at each switch in turn. When you press either button you are incremencting C every time it encounters either high button. At some point C==2 will be true and the LED will be lit.
You are NOT creating a state machine.
From what you said you want:-
(1) You ONLY test first button when C==0.
(2) Then ONLY test second button when C==1.
There are loads of ways to do what you want.
Mike |
|
|
rems
Joined: 02 Feb 2012 Posts: 56
|
|
Posted: Thu Feb 23, 2012 12:04 pm |
|
|
I realize I have not created a state machine. That is why I am trying to...I just want to make a combination of pins turn an led on. And only that combo in order. I am far away from that and am just experimenting. I need to figure out how to only increment C(my variable) once.
I want C to = 1 when first button pushed.
Then C to = 2 when second button pushed.
Only in that order as well.
If 2nd button is pushed first, I want C to stay = to zero.
When C = 2 then I want led to light....
I want to eventually make it 6 buttons, for a 6 pin combo...But that will come later....
I will keep trying..
Thank you for pointing out my fault though...I have changed my code to read C=0 and not C==0.
Thanks |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
Do NOT use goto's |
Posted: Thu Feb 23, 2012 12:41 pm |
|
|
The usual beginners way is to jump from one section of code to another with goto commands. (Where each section represents one of the states.)
I strongly implore NOT to go down that route. It's terribly bad practice and leads to what is commonly know a spaghetti code.
Suppose you wanted to use "rems" as a password.
You could create and character array where the characters are 'r' , 'e' , 'm' , 's'. So index zero character is 'r', index one is 'e' etc.
Then:-
(1) Set an index to zero.
(2) Wait for a character from your RS232 link.
(3) You are looking for a character which matches the index character.
(4) If the character matches your index character you increment the index, or if the character does not match you reset the index to zero.
(5) Repeat (2) (3) (4) until your index goes past maximum.
You can do all of the above in a while loop.
Mike |
|
|
rems
Joined: 02 Feb 2012 Posts: 56
|
|
Posted: Thu Feb 23, 2012 12:50 pm |
|
|
Yes, I do not want to get into the bad practice of GOTO statements. I took a "C" class in school and at least took that tidbit of info with me...
I think I understand what you are telling me and will experiment in that direction....
Thank you |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
Switches |
Posted: Thu Feb 23, 2012 1:40 pm |
|
|
I would try to work with RS232 first then migrate to switches.
When you use switches you will need to deal with things like debouncing which is not an issue with the RS232. You've already had switch handling problems.
I presume you want 1231 to restart the sequence so that ONLY 123456 is accepted.
Just a thought!
Best wishes.
Mike |
|
|
rems
Joined: 02 Feb 2012 Posts: 56
|
|
Posted: Thu Feb 23, 2012 1:51 pm |
|
|
Very good point about the switches. I am aware of de-bouncing issues and realize I will need to consider it when the time comes. I will take your advice and leave switches out of the "equation" for now.
You assume correct. 1231 should reset and 123456 should be a valid "unlock"
I will admit that I don't fully understand. I know rs232 is a serial cable. I am not using one. I am using a pickit 2 with usb cable.
By RS232, do you just mean communicate with my pic thru my keyboard via rs232 to my PIC? Or my USB in my case? Or do you mean something completely different?
Either way, I am looking into it..
Thanks for all your help |
|
|
rikotech8
Joined: 10 Dec 2011 Posts: 376 Location: Sofiq,Bulgariq
|
|
Posted: Thu Feb 23, 2012 2:21 pm |
|
|
First excuse my bad english.
Here is a code i made for you. I hope it would be useful.
Code: |
#include <Device.h>
#use delay(crystal=4M)
#define butt1 pin_b1 //button 1
#define butt2 pin_b2 //button 2
#define butt3 pin_b3 //button 3
#define resbutt pin_b4 //restart 'c' condition
#define led pin_b5 //if condition is obtained turn on led
void main()
{
int sh1=1,sh2,sh3; // sh1=1 for starting first condition.
while(true)
{
if(input(butt1)==1&&sh1==1)
sh2=1; //Allow second condition
if(input(butt2)==1&&sh2==1)
sh3=1; //Allow third condition
if(input(butt3)==1&&sh3==1) //if the three condition are obtained turn the led on.
{
sh3=0;
output_high(led);
}
else if(input(butt3)==1&&sh3!=1) //if the algorithm is not executed wait for restart.
{
sh1=0;
sh2=0;
sh3=0;
}
if(input(resbutt)==1) //restart entering sequence of buttons.
{
output_low(led);
sh1=1; //allow condition start again
}
}
}
|
You can perform this algorithm with four or more input buttons.
Best wishes! |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
RS232 |
Posted: Thu Feb 23, 2012 3:01 pm |
|
|
Sorry. But I am rather old. I can remember a time before the invention of the transistor.
I was assuming an RS232 communicating directly from a PC to PIC (maybe via a USB to RS232 device). I.e. a comms terminal.
So, you type in your password, and the LED lights when you type in the correct sequence of characters.
In a previous reply you seemed happy to use RS232 to monitor your PIC activity. I.e. PIC sending data to a PC. I rather took it for granted that the reverse process PC to PIC would also be available.
Mike |
|
|
|