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 CCS Technical Support

State machine problem
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
rems



Joined: 02 Feb 2012
Posts: 56

View user's profile Send private message

PostPosted: Wed Mar 28, 2012 10:46 am     Reply with quote

John P wrote:
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.


I appreciate your help. The reason it won't work is because of the nature of my switch. It is a custom made cage that holds a ball bearing. This is tilt switch that will sense motion. It will be mounted inside of a box. When the box is turned 6 different ways, the mcu will activate a switch to open it. The reason I need to use this custom cage is because if I used 6 separate tilt switches, more than one may be activated at a time (due to the physical nature of the box holding them ie. at any time some tilt switches will be in the horizontal position and may turn on or off at will.). If more than one is activated at a time, then my state machine will no longer work. The cage is my solution to this physical dilemma. The cage only allows the ball bearing to be in one of six places at a time. Due to the nature of the cage, it uses 4 custom posts (each one connected to a different pin of mcu) It is these posts that the ball bearing will connect together and thus connect 2 mcu pins together.

I am constrained to using 4 pins, no less and no more.

Why don't I simply make 2 posts gnd and the others as i/p's? Because then I would only make use of 2 possibilities and not the 6 I would like. eg
with a and b connected to mcu as i/p's
and c and d connected to gnd
if a connects to c then one postion sensed
if b connects to d then another position sensed
if a connects to d or b connects to c, then this is no different to mcu than first condition
furthermore, if a connects to b or c connects to d, then mcu wont even know it.
This all being said, I think I understand where you were going with the a, b, c & d. As of now I have been using my "scanface" function repeatedly if the test condition were true. You are telling me to use it when the condition is false. That is a great idea. I think that will help a lot. I'm going to try it right now.
Thanks
Ttelmah



Joined: 11 Mar 2010
Posts: 19546

View user's profile Send private message

PostPosted: Wed Mar 28, 2012 3:16 pm     Reply with quote

OK.
Tell us what the six connection patterns are. Call the 4 connections A,B,C,D. Then for the six positions tell us what combinations are connected.
A nice little table....
Realistically it sounds as if the whole scan could be done a lot more simply than you are trying to make it, but the exact sequence needed will depend on the patterns involved.

Best Wishes
rems



Joined: 02 Feb 2012
Posts: 56

View user's profile Send private message

PostPosted: Wed Mar 28, 2012 3:46 pm     Reply with quote

Ttelmah wrote:
OK.
Tell us what the six connection patterns are. Call the 4 connections A,B,C,D. Then for the six positions tell us what combinations are connected.
A nice little table....
Realistically it sounds as if the whole scan could be done a lot more simply than you are trying to make it, but the exact sequence needed will depend on the patterns involved.

Best Wishes


I believe you are correct about my solution being simpler than I think.
o/p i/p
1) A - B
2) A - C
3) A - D
4) B - C
5) B - D
6) C - D

Where A is set as o/p= low scanning B, C D ( B, C & D as i/p)
Then B is set as o/p= low scanning C & D ( A, C & D as i/p--including A as i/p even though not scanning for it so as to drop out of state machine if wrong position is sensed.)
Finally C is set as o/p= low scanning D ) A, B & C as i/p)

My cage has 6 positions. It holds a ball-bearing which will sit in one of six positions depending which side of the cage is face up. The cage is made up of 4 main posts. Depending which face of the cage is up will determine where the ball sits. Where the ball sits will determine which posts are connected to each other. That connection pattern is above.
For now, I am simulating my cage with the four pin dip switch as in the schematic.

The following code is a state machine that works for 6 separate switches. I need to merge this state machine with other code to scan the position of the cage.
Code:

void main()
{
int sw1=1,sw2,sw3,sw4,sw5,sw6;   // sw1=1 for starting first condition.

while(true)
   {
   
   if(input(butt1)==1&&sw1==1) //if butt 1 = 1 AND sw1=1(which it does to start) then
        sw2=1; //Allow second condition
       
   if(input(butt2)==1&&sw2==1)//if butt 2=1 AND sw2=1(it only will if butt 1 was pressed) then
        sw3=1; //Allow third condition
         
   if(input(butt3)==1&&sw3==1)   //if the three condition are obtained turn the led on.
       
        sw4=1;
       

   if(input(butt4)==1&&sw4==1)   //if the three condition are obtained turn the led on.
     
      sw5=1;
     
       

   if(input(butt5)==1&&sw5==1)   //if the three condition are obtained turn the led on.
      sw6=1;

   if(input(butt6)==1&&sw6==1)   //if the three condition are obtained turn the led on.
      {
      sw6=0;
      output_high(led); //turn led on
      }


   else if(input(butt6)==1&&sw6!=1) //if the algorithm is not executed wait for restart. (if butt 3=1 and sh3 does NOT =1 then )
      {
       sw1=0; //set all to zero
       sw2=0; //which ensures that only the proper combo(sequence) will activate
       sw3=0;
       sw4=0;
       sw5=0;
       sw6=0;
      }
 

I am continuing to try my best here. I really appreciate all the insight from everyone.
Ttelmah



Joined: 11 Mar 2010
Posts: 19546

View user's profile Send private message

PostPosted: Thu Mar 29, 2012 1:53 am     Reply with quote

OK.
Assuming A=B0, B=B1, C=B2, D=B3.
Code:

#use fast_io(b)
int8 scanpins(void) {
   int8 port_val;
   //Used so I/O operations don't change other pins.
   set_tris_b(0b11111110); //B0 only as output
   output_low(PIN_B0);
   delay_us(2); //Allow a fraction of time for the inputs to reflect output
   port_val=(input_b()>>1)|0b11111000;
   set_tris_b(0b11111101); //B1 only as output
   output_low(PIN_B1);
   delay_us(2);
   port_val=((input_b()<<1)|0b11100111))&port_val;
   set_tris_b(0b11111011);
   output_low(PIN_B2);
   delay_us(2);
   if (input(PIN_B3)==0) bit_clear(port_val,5);
   return(port_val);
}

Now you just call scanpins, and it returns a byte, with the bottom bit =0 for your first state, next bit=0 for the second etc..

Best Wishes
rems



Joined: 02 Feb 2012
Posts: 56

View user's profile Send private message

PostPosted: Thu Mar 29, 2012 6:57 am     Reply with quote

I see the beauty in this line " port_val=(input_b()>>1)|0b11111000;"
setting port_val to = whatever port b is = to.
port b will = what ever button is pressed because the ">>1" will shift through the entire port and be "ORED" with the 3 possible button presses.
That is awesome. I tried to do that in so many different ways that now make no sense compared to the sense that this makes.

And now I can just use "port_val" in my state machine.
Do I understand that correctly?
essentially, I needed 6 buttons from 4 and "port_val" comes to the rescue and says" USE ME, I can hold a value for your state machine"
Well sure, Thank you port_val, that would be great.
And Thank you Ttelmah

You actually made my head spin a little bit. I just learned so much more about programming.
using a function to control a variable
using that variable to return a value
using that value for something else
the simplicity of the tris register compared to doing it manually
an application for "bit masking" (I think that's what we call it when ORing a port with something else)

Have I understood properly?
Thank you again for your time. I will not waste the learning experience from this.
Ttelmah



Joined: 11 Mar 2010
Posts: 19546

View user's profile Send private message

PostPosted: Thu Mar 29, 2012 7:50 am     Reply with quote

I have no idea at all if it'll work!. Smile
It was posted 'off the cuff', based on what you gave about the connections, but you have spotted basically exactly what I was trying to do, and hopefully it'll lead to a good solution.
It shifts in each of the possible patterns from the 'wanted' bits, and combines them into one value it returns.
Since the last output, only returns one bit, it is quicker just to test this, and combine it with the five bits already generated.
I allow a couple of uSec, since the wires will have significant capacitance, and in the real world, you might want to add some 'debounce' to what happens.

Have fun.
rems



Joined: 02 Feb 2012
Posts: 56

View user's profile Send private message

PostPosted: Thu Mar 29, 2012 9:20 am     Reply with quote

I am having trouble understanding one part of the function
Code:

#use fast_io(b)
int8 scanfaces(void) {
   int8 port_val;
   //Used so I/O operations don't change other pins.
   set_tris_b(0b11111110); //B0 only as output
   output_low(PIN_B0);
   delay_us(2); //Allow a fraction of time for the inputs to reflect output
   port_val=(input_b()>>1)|0b11111000;
   set_tris_b(0b11111101); //B1 only as output
   output_low(PIN_B1);
   delay_us(2);
   port_val=((input_b()<<1)|0b11100111))&port_val;
   set_tris_b(0b11111011);
   output_low(PIN_B2);
   delay_us(2);
   if (input(PIN_B3)==0) bit_clear(port_val,5);
   return(port_val);
}
 

port_val=((input_b()<<1)|0b11100111))&port_val; // I get an error on this line...
It says I need a semi colon. What is "&port_val" doing?
Likewise, what does "if (input(PIN_B3)==0) bit_clear(port_val,5); " do?

I understand everything except those lines.
Ttelmah



Joined: 11 Mar 2010
Posts: 19546

View user's profile Send private message

PostPosted: Thu Mar 29, 2012 9:48 am     Reply with quote

port_val, arrives, with all bits '1', _except_ any of the low three bits that already may have found required patterns.
Then the new incoming value (C or D may be low), is masked so only those bits are taken, shifted left one to move them to bits 3 & 4, and then 'anded' with the previous result.
The problem is one too many close brackets. Line should be:

port_val=((input_b()<<1)|0b11100111)&port_val;

if (input(PIN_B3)==0) bit_clear(port_val,5);

Drops bit 5, if the last possible switch pattern is seen.

Best Wishes
John P



Joined: 17 Sep 2003
Posts: 331

View user's profile Send private message

PostPosted: Thu Mar 29, 2012 9:58 am     Reply with quote

That's not the way I visualized it. I think there should be successive tests for the various conditions, and if a test succeeds, you have your result and you can return from the function.

I've never seen much reason to use the input and output instructions. I just set and test port pins, so that's the way it's written. More untested code, worth what you're paying for it (and a line or two stolen from Ttelmah).

Code:

#use fast_io(b)
int8 scanfaces(void) {
  trisb |= 0b00011110;

  bit_clear(portb, 1);
  bit_clear(trisb, 1);
  delay_us(2); //Allow a fraction of time for the inputs to reflect output
  if (!bit_test(portb, 2))
    return(1);
  if (!bit_test(portb, 3))
    return(2);
  if (!bit_test(portb, 4))
    return(3);

  bit_clear(portb, 2);
  bit_set(trisb, 1);
  bit_clear(trisb, 2);
  delay_us(2); //Allow a fraction of time for the inputs to reflect output
  if (!bit_test(portb, 3))
    return(4);
  if (!bit_test(portb, 4))
    return(5);

  bit_clear(portb, 3);
  bit_set(trisb, 2);
  bit_clear(trisb, 3);
  delay_us(2); //Allow a fraction of time for the inputs to reflect output
  if (!bit_test(portb, 4))
    return(6);

  return(0);
}

Ttelmah



Joined: 11 Mar 2010
Posts: 19546

View user's profile Send private message

PostPosted: Thu Mar 29, 2012 10:06 am     Reply with quote

Yes, a good alternative, and gives much easier to use output.
However the first bit that needs to be low is B0, not B1. Just needs a fractional 'tweak' in the logic.

Best Wishes
rems



Joined: 02 Feb 2012
Posts: 56

View user's profile Send private message

PostPosted: Thu Mar 29, 2012 10:33 am     Reply with quote

I appreciate all the suggestions and insight. I am now trying to do something with all his information.
Thanks to both of you
John P



Joined: 17 Sep 2003
Posts: 331

View user's profile Send private message

PostPosted: Thu Mar 29, 2012 10:44 am     Reply with quote

I used portb 1-4 because that's the way Rems did it in his first message.
rems



Joined: 02 Feb 2012
Posts: 56

View user's profile Send private message

PostPosted: Thu Mar 29, 2012 10:47 am     Reply with quote

That's great..everything has been a great help
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