|
|
View previous topic :: View next topic |
Author |
Message |
rems
Joined: 02 Feb 2012 Posts: 56
|
State machine problem |
Posted: Tue Mar 27, 2012 7:33 pm |
|
|
I am using a PIC16F887, MPLAB and CCS C.
I am making a combination switch that senses the combo via motion. Due to the nature of certain physical aspects, I need to treat 4 pins as 6 switches. This is why I have the function "scanfaces". It allows me to switch what is i/p and o/p. Basically, I make one pin o/p set low and the other 3 pins are i/p's. Then I make a different pin o/p set low with the rest as i/p's.
I have had luck with the state machine in the bottom of the program when I used 6 different switches. In that case, I used 6 pins, all as i/p's and it worked fine. But now, I'm trying to merge the "scanfaces" function with the state machine and am having a lot of difficulty. I want the led to turn on only when the combo is sensed. As you can see, pins B3 & B4 are shared by different o/p configurations and I think this is part of the problem. I need a way to make them more unique.
Does anyone have any ideas?
Here is my code
Code: |
#include <16F887.h>
#fuses INTRC_IO //use internal oscillator
#fuses NOWDT //No watch dog timer
#fuses PUT//
#fuses BROWNOUT//reset chip if voltage falls
#fuses MCLR//master clear enabled
#fuses NOLVP
#use delay(clock=8000000)
#define resbutt pin_B5 //restart 'c' condition
#define led pin_D4 //if condition is obtained turn on led
#define sleepbutt pin_D7
/*****************************************************************Declare a function that will SCAN the custom switch*******************/
void scanfaces (void)
{
OUTPUT_low(pin_B1); // Configuring cage to sense faces
input(pin_B2);
input(pin_B3);
input(pin_B4);
OUTPUT_low(pin_B2); // Configuring cage to sense second 3 i/p's
input(pin_B3);
input(pin_B4);
OUTPUT_low(pin_B3); // Configuring cage to sense last i/p
input(pin_B4);
}
void main()
{
int sh1=1,sh2,sh3,sh4,sh5,sh6; // sh1=1 for starting first condition.
while(1){
scanfaces();
if(!input(pin_B2)==1&&sh1==1) //if pin_B2 = 0 AND sh1=1(which it does to start) then
sh2=1; //Allow second condition
scanfaces();
if(!input(pin_B3)==1&&sh2==1)//if pin_B3=0 AND sh2=1(it only will if butt 1 was pressed) then
sh3=1; //Allow third condition
scanfaces();
if(!input(pin_B4)==1&&sh3==1)
sh4=1;
scanfaces();
if(!input(pin_B3)==1&&sh4==1)
sh5=1;
scanfaces();
if(!input(pin_B4)==1&&sh5==1)
sh6=1;
scanfaces();
if(!input(pin_B4)==1&&sh6==1) //if the six condition are obtained turn the led on.
{
sh6=0;
output_high(led); //turn led on
scanfaces();
}
else if(!input(pin_B4)==1&&sh6!=1) //if the algorithm is not executed wait for restart. (if pin_B4=0 and sh6 does NOT =1 then )
{
sh1=0; //set all to zero
sh2=0; //which ensures that only the proper combo(sequence) will activate
sh3=0;
sh4=0;
sh5=0;
sh6=0;
}
if(input(resbutt)==1) //restart entering sequence of buttons. if reset button pushed
{
output_low(led); //led will turn off
sh1=1; //allow condition start again
}
}
} |
|
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Wed Mar 28, 2012 2:25 am |
|
|
I don't get what you are trying to do.
Some kind of schematic might help.
Mike |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19494
|
|
Posted: Wed Mar 28, 2012 2:59 am |
|
|
Yes, a circuit of the scanning would help.
However just looking at the code, can't see that 'scanfaces' is ever going to work. As it stands, it sets B1, 2, and 3 _all low_, and leaves just B4 as an input.
You need to remember that things are sequential, and happen very fast on a computer. So it starts setting B1 low, then setting B2, B3, and B4 as inputs (actually this can all be done with one instruction - this is exactly what the TRIS statement is for.....). Then only a couple of uSec latter B2 is set as an output, with B3 and B4, once again set as inputs (they already are - things are remembered....), then B3 is set as an output, and B4, once again set as input. At this point, B1, B2, and B3, are _all_ driving low, and only B4 is an input.
Then the routine is existed, and the first test done. At this, B2, is changed to being an input, and immediately read. probably won't work, since it takes _time_ for signals to change.
The similar pattern is then repeated for the other pins....
As a comment, the logic of the code layout also doesn't help understanding. After the 'if' tests, scanfaces is indented, which is normally used as a signe to say 'this is only executed if the test is true', but in fact it is only the single line after the 'if' that if dependant on the test.
It is also 'odd', that you drive the lines 'low', yet seem to test for 'high' as a button made combination.
Post a circuit.
Best Wishes |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9220 Location: Greensville,Ontario
|
|
Posted: Wed Mar 28, 2012 5:23 am |
|
|
You should lookup 'Charlieplexing'....though most use it for outputs, I've used it for input as well.You can get 6 inputs from 3 pins. |
|
|
John P
Joined: 17 Sep 2003 Posts: 331
|
|
Posted: Wed Mar 28, 2012 9:03 am |
|
|
Seems pretty trivial. You can get 4 switches where (I'm calling the lines a, b, c and d, nothing to do with port names) a and b cross c and d, and 2 more where a could cross b and c could cross d. Then you can get 4 more where each of a-d can connect to Gnd. If you use pins with internal pullups, there's no need for any external components except the switches. If you can't trust the user to avoid pushing multiple switches, you might need to test for that.
Wouldn't Charlieplexing need diodes? There's no point in using added parts. |
|
|
rems
Joined: 02 Feb 2012 Posts: 56
|
|
Posted: Wed Mar 28, 2012 9:04 am |
|
|
Ttelmah,
Thank you, I completely understand your pointers. I was afraid "scanfaces" was happening so fast that it wasn't working. Wow, I didn't realize that the first line after the if is the only one valid for the test condition. That explains a lot. Since my original post, I actually split up "scanfaces" into 3 separate functions.
Code: |
void scanfaces1 (void)
{
OUTPUT_low(pin_B1); // Configuring cage to sense faces
input(pin_B2);
input(pin_B3);
input(pin_B4);
}
void scanfaces2 (void)
{
OUTPUT_low(pin_B2); // Configuring cage to sense second 3 i/p's
input(pin_B3);
input(pin_B4);
}
void scanfaces3 (void)
{
OUTPUT_low(pin_B3); // Configuring cage to sense last i/p
input(pin_B4);
}
|
My goal is to separate the function to make it so B4 isn't the only i/p essentially. Then I used the following if statements to operate them
Code: |
void main()
{
int sh1=1,sh2,sh3,sh4,sh5,sh6; // sh1=1 for starting first condition.
scanfaces1();
while(1){
if(!input(pin_B2)==1&&sh1==1) //if pin_B2 = 0 AND sh1=1(which it does to start) then
sh2=1; //Allow second condition
scanfaces1();
if(!input(pin_B3)==1&&sh2==1)//if pin_B3=0 AND sh2=1(it only will if butt 1 was pressed) then
sh3=1; //Allow third condition
if(!input(pin_B4)==1&&sh3==1)
sh4=1;
output_high(pin_D2);
scanfaces2();
if(!input(pin_B3)==1&&sh4==1) {
sh5=1;
output_high(pin_D3);
scanfaces2();
}
if(!input(pin_B4)==1&&sh5==1){
sh6=1;
output_low(pin_C4);
scanfaces3();
}
if(!input(pin_B4)==1&&sh6==1) //if the six condition are obtained turn the led on.
{
sh6=0;
output_high(pin_C5);
scanfaces3();
}
else if(!input(pin_B4)==1&&sh6!=1) //if the algorithm is not executed wait for restart. (if pin_B4=0 and sh6 does NOT =1 then )
{
sh1=0; //set all to zero
sh2=0; //which ensures that only the proper combo(sequence) will activate
sh3=0;
sh4=0;
sh5=0;
sh6=0;
}
|
Can I simply put multiple statements on the same line that follows the if statement separated by a comma? Or how can I execute multiple "tasks" with on if statement test?
As far as I know, I do test for "low". The "!" does that. But maybe you are referring to the fact that I say " ==1" after. I was experimenting with "==0" and it didn't work. Maybe that part isn't needed at all? After my experiments, I concluded that "==1" basically says "if true" and "==0" says "if false". I'm not sure, but I'll try to take it out.
I don't know how to post the circuit, so Ill draw it below
code:
Code: |
#include16F887.h
__________
|
|--B1----|------10k----------------------VCC
| |
| |
|--B2----|------|------10K---------------VCC
mcu | | |
| | |
|--B3----|------|------|------10K--------VCC
| | | |
| | | |
|--B4----|------|------|------|---10K----VCC
| | | | |
| | | | |
__________| | | | |
| | | |
| | | |
\ \ \ \
\ \ \ \
\ \ \ \
| | | |
_____1______2______3______4_____
|
That is the best I can do with my keyboard. The "10k's" are external pull-ups. I know I can use internal but that will be after I figure everything else out. The weird looking thing at the bottom is a 4 pin dip switch with one complete side shorted together. This is how I connect 2 mcu pins together at a time to "sense". My intention is that for eg. in the first cycle, "1" will be close when "B1" is set as o/p=low. at the same time, pins_2, 3 & 4 will be i/p's. Now when I close either "2, 3 or 4" on the switch, the mcu can sense what is happening. This is how I am using four pins of mcu to "see" 6 switches.
Does this help?
I appreciate the advice you have already given. Any additional direction would be fantastic.
Thanks again
Last edited by rems on Wed Mar 28, 2012 9:10 am; edited 3 times in total |
|
|
rems
Joined: 02 Feb 2012 Posts: 56
|
|
Posted: Wed Mar 28, 2012 9:06 am |
|
|
WOW, my schematic did not look like that when I drew it in the text box before I posted.
++++++++++++++++++++
Schematic fixed by Mod.
How to do:
- Edit text not in forum, but in Windows NotePad (monospaced font).
- Copy & Paste into forum post.
- Enclose in Code Block.
- Preview for correctness.
- Forum Moderator
++++++++++++++++++++ |
|
|
rems
Joined: 02 Feb 2012 Posts: 56
|
|
Posted: Wed Mar 28, 2012 9:11 am |
|
|
I will look into charlieplexing as well. Thank you for that. |
|
|
John P
Joined: 17 Sep 2003 Posts: 331
|
|
Posted: Wed Mar 28, 2012 9:17 am |
|
|
If you want to waste components and your time to wire them up, go ahead. |
|
|
rems
Joined: 02 Feb 2012 Posts: 56
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19494
|
|
Posted: Wed Mar 28, 2012 9:33 am |
|
|
This is where {} brackets come in.
Everything inside a pair of these, is (logically) treated as a single statement. So:
Code: |
if (fred)
this;
that;
//executes 'this' if fred is true, but 'that' is always executed
if (fred) {
this;
that;
theother;
}
more;
//executes 'this', 'that' and 'theother' if fred is true
//then 'more' is always executed
|
',' has a slightly different meaning. If you have something that uses a value:
if (fred,dick)
or
val=fred,dick;
Then both 'fred', and 'dick' are evaluated, and the value returned by 'dick' is the one used.
Best Wishes |
|
|
John P
Joined: 17 Sep 2003 Posts: 331
|
|
Posted: Wed Mar 28, 2012 9:39 am |
|
|
Re the schematic, you can eliminate the resistors. Then consider what you can achieve if you don't just use switches to connect the pins to Gnd, but also to each other. |
|
|
rems
Joined: 02 Feb 2012 Posts: 56
|
|
Posted: Wed Mar 28, 2012 9:49 am |
|
|
John P wrote: | Re the schematic, you can eliminate the resistors. Then consider what you can achieve if you don't just use switches to connect the pins to Gnd, but also to each other. |
I will be getting rid of the resistors in place of internal pullups. The switch doesn't connect anything to ground. The switch is intended to only connect pins together. It is my hope that one of those pins will be set as o/p=low, while the other three are i/p's. The o/p=low will be there ground. In that scenario, I have 3 "switches" of 6 taken care of. I then need to make a different pin as o/p=low and the rest as i/p's to take care of 2 more switches. Then I need to do it a third and last time to take care of the final "switch". In the end, 4 pins that act as 6 switches. |
|
|
rems
Joined: 02 Feb 2012 Posts: 56
|
|
Posted: Wed Mar 28, 2012 9:51 am |
|
|
Ttelmah wrote: | This is where {} brackets come in.
Everything inside a pair of these, is (logically) treated as a single statement. So:
Code: |
if (fred)
this;
that;
//executes 'this' if fred is true, but 'that' is always executed
if (fred) {
this;
that;
theother;
}
more;
//executes 'this', 'that' and 'theother' if fred is true
//then 'more' is always executed
|
',' has a slightly different meaning. If you have something that uses a value:
if (fred,dick)
or
val=fred,dick;
Then both 'fred', and 'dick' are evaluated, and the value returned by 'dick' is the one used.
Best Wishes |
Okay great. That answers other questions I had as well. I get it now. Thank you. |
|
|
John P
Joined: 17 Sep 2003 Posts: 331
|
|
Posted: Wed Mar 28, 2012 10:23 am |
|
|
Here's what I think the schematic should be:
http://dl.dropbox.com/u/28291527/sws.jpg
First you would set all 4 outputs low, with the TRIS bits set high (pins hi-Z) and the pullups turned on.
Then set a as the active output, and see if b, c or d go low.
If not, set b as the active output, and see if c or d go low.
If not, set c as the active output, and see if d goes low.
If not, nothing is pressed.
If you had switches to ground as well, you'd insert an initial step where you'd check for anything pulled low while all the TRIS bits were high, before doing anything else.
Actually, if you use connections to Gnd, you could do this job with only 3 pins. 3 switches would connect between the pins (using b, c and d) and 3 would go between each of the pins and Gnd. I don't see why that wouldn't work. |
|
|
|
|
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
|