Is There An Easier Way

I use the following code to read 4 GPIO pins to an unsigned decimal number (0 through 15).

Smack_Intensity_Value = (digitalRead(Smack_Intensity_Pin_B4) * 8) + 
                            (digitalRead(Smack_Intensity_Pin_B3) * 4) + 
                            (digitalRead(Smack_Intensity_Pin_B2) * 2) + 
                             digitalRead(Smack_Intensity_Pin_B1);

Is there an easier way to convert 4 GPIO pins to a decimal number?`

Have a look at the pinned post about how to use the forum.

int pins[8] =
{
    Smack_Intensity_Pin_B4, 8,
    Smack_Intensity_Pin_B3, 4,
    Smack_Intensity_Pin_B2, 2,
    Smack_Intensity_Pin_B1, 1
};

int Smack_Intensity_Value = 0;
for (int i = 0; i < 4; i++)
{
    Smack_Intensity_Value += digitalRead(pins[i*2]) * pins[i*2+1];
}

Looks right to me. Didn't test. Not sure about the easier part tho :wink:

Sorry about that. What forum should I use and how to transfer this post to that proper forum?

  • You can read a port all at once, UNO, PORTB reads D8 thru D13.

myDecimalNumber = PINB;  // I.E. X/X/D13/D12/D11/D10/D9/D8

2 Likes

I would use shifts instead of multiplies, but the compiler will probably do that anyway.

EDIT:
And OR instead of add.

It was more about source code wiring and serial output, but too late now, your problem is solved.

shorten to:
(uncompiled / untested)

int pins[4] = {
   Smack_Intensity_Pin_B1,
   Smack_Intensity_Pin_B2,
   Smack_Intensity_Pin_B3,
   Smack_Intensity_Pin_B4,
};

int Smack_Intensity_Value = 0;
for (int i = 0; i < 4; i++) {
    Smack_Intensity_Value |= digitalRead(pins[i]) << i;
}

Note that I swapped the order of the pins.

That would also work, but I was going for a more general purpose approach. On a second glance, I think OP was just trying to read half an 8-bit port at once.

Looks like @LarryD had the right idea.

1 Like

+1

Additional text

Note that this makes the code processor/board-specific...

  • Yes, this is for the, UNO (and similar) controller.

You can read a port all at once, UNO, PORTB reads D8 thru D13.

myDecimalNumber = PINB; // I.E. X/X/D13/D12/D11/D10/D9/D8

I think I should mention the board I am using is the ItsyBitsy 32u4-3V.

Thank you all for sharing your wisdom with me :slight_smile:

Here is the code I came up with:::

const uint8_t Smack_Intensity_Pin_B4 = 18; 
const uint8_t Smack_Intensity_Pin_B3 = 19;
const uint8_t Smack_Intensity_Pin_B2 = 20;
const uint8_t Smack_Intensity_Pin_B1 = 21;

Smack_Intensity_Value = 0b00000000;
bitWrite(Smack_Intensity_Value, 0, digitalRead(Smack_Intensity_Pin_B1));
bitWrite(Smack_Intensity_Value, 1, digitalRead(Smack_Intensity_Pin_B2));
bitWrite(Smack_Intensity_Value, 2, digitalRead(Smack_Intensity_Pin_B3));
bitWrite(Smack_Intensity_Value, 3, digitalRead(Smack_Intensity_Pin_B4));

I would use the regestor method but I do not have experience and do not know how.

You could do slightly better with something like this.

Smack_Intensity_Value = 0b00000000;
Smack_Intensity_Value |=  digitalRead(Smack_Intensity_Pin_B1); 
Smack_Intensity_Value |= (digitalRead(Smack_Intensity_Pin_B2) <<1);
Smack_Intensity_Value |= (digitalRead(Smack_Intensity_Pin_B3) <<2);
Smack_Intensity_Value |= (digitalRead(Smack_Intensity_Pin_B4) <<3);

This reads the pins and shifts the pin value to the bit position you want in the answer and ORs it in. It is sort of your original code except the multiplies are replaced by bit shifts and the adds are replaced with ORs.

Your last set of code does more work because the bitWrite() does a compare on the value and set the bits on or off. This is unnecessary because you start with the bits off and only need to turn bits on.

Why do you think this is "easier" than your original formulation.

I would ask what you mean by "easier" and if you think any of the formulations suggested in this thread are "easier"?

I think I used the wrong wording to explain what I was asking for.
I am not new to coding but want to learn the advanced Arduino code/functions to streamline the code.
oldcurmudgeon suggestion is what I was looking for, it is simple and runs faster.

If you used pins B0 ~ B3, you could write:

Smack_Intensity = PINB & 0x0F;

I do not understand your last reply.
What is "PINB"?

PINB returns the states of the PORTB pins.
Serial.println(PINB & 15);

Should print the decimal value of pins B0, B1, B2, B3.

Serial.println(PINB & 0F,HEX);

Should print the binary value of pins B0, B1, B2, B3.

OOPS! Should have been:

Serial.println(PINB & 15,BIN);