How to divide a byte into 8 boolean variables

Hello programmers,
I have looked around and I have read and read. The question has been asked several times but each person is doing something slightly different from what I am trying to do.

I am receiving a byte of data from a port expander. Each bit of that byte is connected to an input of the MCP23017 chip. I am able to receive the byte ok, but what I'd like to do is to take the received byte and separate into 8 boolean variables so that I can act on them each independently.

/*
 * accepting inputs from MCP23017 I2c port expander
 * 
 */
#include "Wire.h"
byte inputs=0; //variable to save incoming byte from MCP23017
//below are variables to break apart above byte to be able to act on independently
boolean bit0=0; 
boolean bit1=0; 
boolean bit2=0; 
boolean bit3=0; 
boolean bit4=0; 
boolean bit5=0; 
boolean bit6=0; 
boolean bit7=0; 


void setup() {
  Serial.begin(9600);
  Wire.begin();
  

} //end of setup

void loop() {

Wire.beginTransmission(0x20); //start talking to MCP23017
Wire.write(0x12); //set chip pointer to A half of MCP23017
Wire.endTransmission();//end conversation
Wire.requestFrom(0x20,1);//request 1 bytes worth of info from A side of MCP23017
inputs=Wire.read(); //store the byte from MCP23017 into the variable "inputs"


 //something is done here to take the byte stored in "inputs" break it down into the above 8 boolean variables
 // my guess is:
  bit0=bitRead(inputs,0); 
  bit1=bitRead(inputs,1);
  bit2=bitRead(inputs,2);
  bit3=bitRead(inputs,3); 
  bit4=bitRead(inputs,4); 
  bit5=bitRead(inputs,5); 
  bit6=bitRead(inputs,6); 
  bit7=bitRead(inputs,7); 


//take inputs that have been separated into individual bits and act on each one individually
if (bit0==true){/*go for a walk*/}
if (bit1==true){/*make macaroni and cheese*/}
if (bit2==true){/*fix the car*/}
if (bit3==true){/*mow the lawn*/}
if (bit4==true){/*watch TV*/}
if (bit5==true){/*clean the garage*/}
if (bit6==true){/*organize my desk*/}
if (bit7==true){/*turn on the radio and dance*/}
  else {/*sit here and stare at this problem until i die*/}

  
}//end of loop

your assistance is greatly appreciated
amachinetech

Use bitRead() or a logical mask to detect the state of individual bits in a byte.

Mask example:

if (byte & (1<<7) ) Serial.print("High bit is set");

This:

if (bit0==true){/*go for a walk*/}

can be replaced with

if (bit0){/*go for a walk*/}

or

 if (bitRead(inputs,0)) {/*go for a walk*/} 

How about using an array of function pointers ?
A small example

typedef void (*functionPtrs)(void);

functionPtrs funcs[3] = { &zero, &one, &two };

void setup()
{
    byte inputs = 0b00000101;
    Serial.begin(115200);
    for (int b = 0; b < 3; b++)
    {
        if (bitRead(inputs, b))
        {
            funcs[b]();
        }
    }
}

void loop()
{
}

void zero()
{
    Serial.println("zero");
}

void one()
{
    Serial.println("one");
}

void two()
{
    Serial.println("two");
}

That's the beauty of coding. :expressionless:

Here you don't need to unpack the bits at all, using what @jremington reveals

    if (inputs & (1 << 4)) {/*watch TV*/}

But.

Anytime you find yourself making things whose name differ only because you've appended a digit, like bit0, bit1 and so forth, you should see it as a sign that array variables might make things easier.

So put array variables on your list of things to learn and know about.

If you haven't, put for loops on that list also.

Together they will let you say things in a compact manner, greatly flexible compared to dealing with many of discretely named variables.

HTH

a7

1 Like

I need some help explaining this line and what it is doing.
To me it looks like we are looking at the entirety of the byte at a time but then selecting only one bit of it, but I don't understand how it is doing what it is doing.

if (look at inputs ( we want 1 bit, look at the 4th bit ) {/watch tv/}

the part I dont get is what << is doing. That is a bitshift. I am not following how the question is asked "if this is true" in this line. This is an area of the IDE I have not tread before

amachinetech

Also upon reading the bitshift reference it says that the values that are moved disappear out of existence. Does this also mean that I can use this line to read one bit but because I have shifted it part of it was destroyed in the process and now I need to refresh the byte to have a complete data set to look at with the next question. or am I overcomplicating it (most likely)
amachinetech

1 << 4 results in 0x10.
ANDing that with the value of input results in a non-zero value (i.e. logical TRUE) if the correspond bit in input is set

Seems like you are getting there with your own steam.

Try this

if (inputs & 0x8) {/*watch TV*/}

using hex. 0x8 is just bit 3. The expression does not change inputs.

1 << 4 is just one bit shifted left four places. The earlier expression where that is used to grab a specific bit of inputs also does not change inputs.

Ppl write it as 1<< 4, that is recognized and idiomatic way of talking about one bit, someplace in a bit. Here the bit 4 places to the left.

I've never seen, but

1 << 0

woukd just be 1, same as 0x1, and talking about the least significant bit in the byte, bit 0.

HTH

a7

@alto777

OK I think I have it.
inputs doesn't change so I should be able to:

if (inputs & (1 << 4)) {/watch TV/} //true so it executes
if (inputs & (1 << 3)) {/mow the lawn/} //for this example this is false so nothing is done
if (inputs & (1 << 7)) {/turn on the radio and dance/} // this one is true so it executes

so I should be able to query the byte in any random order with the stipulation that "&" is looking for "if this is true" yes?

now how would I state it if I wanted to ask a "if this was false" query?
amachinetech

For example, taking inverse of "If this was true" condition:

if (! (inputs & (1 << 4)))

Please, illustrate with a numerical example how the argument of the above if() structure stands true.

Is the line below can be considered as "numerical example"?

if (0xFF & (1 << 7)) 
1 Like

a byte is brought in from the port expander and saved to the variable "inputs". That byte would look like "B10110001"

so in this example from the port expander: input 0 is on, inputs1,2,3, are all off, 4 and 5 are on, 6 is off, 7 is on.

So I should be able to ask:
"look at the byte inputs, specifically look at bit 7, if it is true (on) then {/turn on the radio and dance/}

if(inputs &(1 << 7))) {/turn on the radio and dance/}

and if I want to ask a "if this false" question then I would structure it thus:

if( ! (inputs &(1 << 7))) {/turn on the radio and dance/}

Thats how I see it. Yes?

amachinetech

2 Likes

resonable

Thank all of you for explaining this to me. Have a great week
amachinetech

...but attracts a lot of flak about type punning.

Fixed that for ya'. :wink:

And I have to add it tests your luck from day to day, compiler version to compiler version &c.

"It works" is insufficient. "It has always worked for me", well, good for whomever.

And anyone dealing with bits should know more than what has been revealed so far on this thread anyway.

a7

1 Like

I deleted it

You could structure it otherwise, for example

if ( (inputs & (1 << 7)) == 0) { //test for bit 7 false or zero

@jremington
could this:
if ( (inputs & (1 << 7)) == 0) { //test for bit 7 false or zero}

also be written:
if ( (inputs & (1 << 7)) == false) { //test for bit 7 false or zero}

and the inverse:

if ( (inputs & (1 << 7)) == 1) { //test for bit 7 true or one}
or
if ( (inputs & (1 << 7)) == true) { //test for bit 7 true or one}

amachinetech