Can I use a relational operator in avr programming??

Go To Last Post
14 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello, here's my problem, I am using 4 input pins from portB...PB0 to PB4, I am connecting these 4 to 4 float switches. Switch1 to PB0, then Switch2 to PB1, switch3 to PB2 and switch4 to PB3. My expected output is in the following snippet(only)

char msg1[] = {"The water is in level 1."};
char msg2[] = {"The water is in level 2."};
char msg3[] = {"The water is in level 3."};
char msg4[] = {"The water is in level 4."};
char msg5[] = {"No switch is on."};

if (PINB & 0x01) //if level 1 switch is on*/
sendout(msg1);	//send serial output indicate level1
		
else if (PINB & 0x03)//if level 1 and 2 switches are on*/
sendout(msg2); //send serial output indicate level2 
		
else if (PINB & 0x07) /*if level 1, 2, and 3 switches are on*/
sendout(msg3); //send serial output indicate level3 
		
else if(PINB & 0x0F)   /*if level 1,2,3, and 4 switches are on*/
sendout(msg4); //send serial output indicate level4

else
sendout(msg5); 

But it is not working the way I expect it because (PINB & 0x01) will also be true if switch 1 and switch 2 is on(PINB = 00000011), so it will output sendout(msg1), but the expected is msg2.

I think, the best way is to use an equality operator( ==) in the if else statement. So, I used that like this

if (PINB == 0x01) //if level 1 switch is on*/
sendout(msg1);	//send serial output indicate level1

else if (PINB == 0x03)//if level 1 and 2 switches are on*/
sendout(msg2); //send serial output indicate level2 
		
else if (PINB == 0x07) /*if level 1, 2, and 3 switches are on*/
sendout(msg3); //send serial output indicate level3 
		
else if(PINB == 0x0F)   /*if level 1,2,3, and 4 switches are on*/
sendout(msg4); //send serial output indicate level4

else
sendout(msg5);

but my output is msg5(no switches are on).

Really need a help..

I will appreciate your help! Thanks in advanced!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What is happening on PB4..7? Also hardware issues come into play - how are your inputs wired and do you have pull up resistors? To see what is really happening on pinb, use the function itoa() to give a human readable value that you can output the serial port.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Also, you can rearrange your if/else if/else ( reverse the order ) so that it always only sends the highest level -- as it stands, it will always send the lowest level. Either way could be correct, you have to decide.

This is, of course, assuming active-high switches which are possible but unusual.

It all comes down to precisely what result you want.

Martin Jay McKee

As with most things in engineering, the answer is an unabashed, "It depends."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So your switches are wired so they are "1" when the water is above them?

I think all you need then, is to reverse the order of your tests, and possibly AND the port with 0x0F to be sure the high bits aren't confusing anything:

 if ((PINB & 0x0F) == 0x0F) sendout(msg4)
 else if ((PINB & 0x0F) == 0x07) sendout(msg3)
 else if ((PINB & 0x0F) == 0x03) sendout(msg2)
 else if ((PINB & 0x0F) == 0x01) sendount(msg1)
 else sendout(msg5);

Looking at it again, all you should need to do is and the PINB with 0x0F and your code should work the order you did it.

Disclaimer: You'll want to be sure the compiler doesn't complain about anything I've typed. I usually include lots more {} to be sure the compiler knows what I mean.

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
 if ((PINB & 0x0F) == 0x0F) sendout(msg4)
 else if ((PINB & 0x0F) == 0x07) sendout(msg3)
 else if ((PINB & 0x0F) == 0x03) sendout(msg2)
 else if ((PINB & 0x0F) == 0x01) sendount(msg1)
 else sendout(msg5);

It doesn't need to be this complicated. This will work:

 if (PINB & 0x08) sendout(msg4)
 else if (PINB & 0x04) sendout(msg3)
 else if (PINB & 0x02) sendout(msg2)
 else if (PINB & 0x01) sendount(msg1)
 else sendout(msg5); 

Assuming that you know that the lower pins are high whenever a higher pin is high.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think you should save the result of the level detection in a variable, perhaps called lowercase pinb, and then tell the humans about it with a sendout in a separate step.

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

But it is not working the way I expect it because (PINB & 0x01) will also be true if switch 1 and switch 2 is on(PINB = 00000011), so it will output sendout(msg1), but the expected is msg2.

For future reference, you can test whether the masked bits from a port/variable match a "trigger" mask:

if ( (PINB & 0x01) == 0x01)
   { action 1 }
else if ( (PINB & 0x03) == 0x03)
   { action 2 }
...

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Or

if ((PINB & 0x01) != 0)

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But again, that will work only if you test the bits in the correct order. Lee's solution will work no matter the order of testing. Where Lee's would fail is if there is a hardware failure. If the sensor on bit 0 fails and get stuck on 0, all tests would fail. My solution of testing only the single bit would fail only on the bit 0 test, but would still work on all the others. Which you would choose would therefore depend on your hardware design and how you want the program to deal with potential errors. Of course in both you could test for unexpected values to detect and handle error conditions.

Another way of handling this is a switch statement:

switch(PINB)
{
   case 0x00:
      sendount(msg5);
      break;
   case 0x01:
      sendount(msg1);
      break;
   case 0x03:
      sendount(msg2);
      break;
   case 0x07:
      sendount(msg3);
      break;
   case 0x0F:
      sendount(msg4);
      break;
   default:
      sendount(msgError);
}

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Where Lee's would fail is if there is a hardware failure.

??? The >>test<< wouldn't fail. Agreed that one should use defensive coding practices, especially when there are real devices (e.g. movement, heat, etc.) out there.

In this case there could indeed be a test for a missing float switch.

A comment from one of my apps, where an "action" bit needs to be by itself:

Quote:
Door DTC but not yet CLOSING ((current_aux & (MASK_CLOSING | MASK_DTC)) == MASK_DTC

This app appears to be a set of float switches, in lieu of a level sensor. In an industrial app, I might have a dozen or so "action" inputs. During design the customer will outline features to be carried out based on these action/status conditions. That rough specification is often incomplete, and sometimes conflicting. I'll typically make some type of chart or spreadsheet or state machine or even real ;) methods like a Karnaugh map. Then one tries to consider all the "what if" conditions--e.g. motion to an endpoint based on encoder counts. Motion commanded and encoder counts not changing? What should be done? Drop-dead timeouts when the endpoint not reached. Those two are more subtle than the simple "encoder loss of feedback/no comms connection.

At this point I often find the matrix of action inputs and operational states and "trips" is overwhelming and confusing. Show it to the customer, and the response is often "this is too complex" even though it is exactly what the customer specified. :) So then I try to look for patterns in the fault trips and the recovery actions, and then implement a simpler, consistent trip response/recovery. There always seem to be "specials", though.

Back to the topic: While indeed my code will usually look at "action" bits in a priority order, it isn't unusual for me the have a few "else if ((current_aux & (MASK_CLOSING | MASK_DTC)) == MASK_DTC)" in a full app.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Again, you're assuming that the top half of PINB reads all zeros. I think that's the OP's actual problem.

Koshchi wrote:
But again, that will work only if you test the bits in the correct order. Lee's solution will work no matter the order of testing. Where Lee's would fail is if there is a hardware failure. If the sensor on bit 0 fails and get stuck on 0, all tests would fail. My solution of testing only the single bit would fail only on the bit 0 test, but would still work on all the others. Which you would choose would therefore depend on your hardware design and how you want the program to deal with potential errors. Of course in both you could test for unexpected values to detect and handle error conditions.

Another way of handling this is a switch statement:

switch(PINB)
{
   case 0x00:
      sendount(msg5);
      break;
   case 0x01:
      sendount(msg1);
      break;
   case 0x03:
      sendount(msg2);
      break;
   case 0x07:
      sendount(msg3);
      break;
   case 0x0F:
      sendount(msg4);
      break;
   default:
      sendount(msgError);
}

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Again, you're assuming that the top half of PINB reads all zeros

But that's just

switch(PINB & 0x0F) 

in that case.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Again, you're assuming that the top half of PINB reads all zeros. I think that's the OP's actual problem.
Untrue. The OP was masking out the upper 4 bits in every test, so they could not possible affect the result. The OP's problem was testing the bits in the incorrect order: at all levels (except level 0), the first if would always be true and therefore never getting to any of the other if's.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh. Sure enough. Perhaps I'm too ADD to participate in a thread more than 3 posts long

If you don't know my whole story, keep your mouth shut.

If you know my whole story, you're an accomplice. Keep your mouth shut.