bool array binary to int conversion [Solved #7 and #9]

So I'm taking user input from a four dip-switches and storing the bit values in a bool array, and then converting that to int/hex.
This should make it more clear

String user_in()
{
  bool in_bits[4] = {digitalRead(BIT0),digitalRead(BIT1),digitalRead(BIT2),digitalRead(BIT3)};
  int value = 0;
  int i = 0;
  while(i < 4)
  {
    value = value + (in_bits[i]*(pow(2,i)));
    i++;
  }
  return String(String(in_bits[3])+" "+String(in_bits[2])+" "+String(in_bits[1])+" "+String(in_bits[0])+" = "+String(value, HEX));
}

now here is the issue:
It works fine till 0011 which it shows as 3, But it also shows 0100 as 3 which should be 4. And from that point on all values are n-1, ie 1000 = 7 instead of 8.

Now I know that the logic is sane as my c code compiled using gcc works just as expected.

#include <stdio.h>
#include <math.h>
#include <stdbool.h>
int main()
{

bool in_bits[4] = {0,0,1,0};
int value = 0;
int i = 0;
while(i<4)
{
 value = value + (in_bits[i]*(pow(2,i)));
 i++;
}

printf("%d", value);

}

Any Ideas what might be going on here?

How are the inputs wired ?
Do you have pulldown resistors in place or are the inputs floating at an unknown voltage ?

What do you see if you print tha values pf the digitalRead()s ?

Why use Strings when there are more efficient ways to do what you are doing ?

I assume that you have deliberately chosen not to use the standard setup()/loop() arrangement and have also chosen not to call the Arduino init() function

UKHeliBob:
How are the inputs wired ?
Do you have pulldown resistors in place or are the inputs floating at an unknown voltage ?

What do you see if you print tha values pf the digitalRead()s ?

Why use Strings when there are more efficient ways to do what you are doing ?

I assume that you have deliberately chosen not to use the standard setup()/loop() arrangement and have also chosen not to call the Arduino init() function

  1. The switches are connected to CD40106B CMOS Hex Schmitt-Triggers Inverter for external debouncing, there are resistors in place.
  2. digitalRead values are sane.
  3. Just testing atm not the final code
  4. I am using the standard setup()/loop() arrangement, I have just pasted the function itself that is called from within loop() as Serial.println(user_in()). setup just contains pinmode(n, INPUT);

Please post a complete program that demonstrates the problem.

At the moment we have no idea which pins are being used, for example.

UKHeliBob:
Please post a complete program that demonstrates the problem.

At the moment we have no idea which pins are being used, for example.

I don't see how knowing the exact pin number helps but here you go:

#define BIT0 13
#define BIT1 12
#define BIT2 11
#define BIT3 10
#define NEXT 9
#define RTRN 8
 
void setup() {
  // put your setup code here, to run once:

  pinMode(BIT0, INPUT);
  pinMode(BIT1, INPUT);
  pinMode(BIT2, INPUT);
  pinMode(BIT3, INPUT);
  pinMode(NEXT, INPUT);
  pinMode(RTRN, INPUT);

  Serial.begin(9600);

}

String user_in()
{
  bool in_bits[4] = {digitalRead(BIT0),digitalRead(BIT1),digitalRead(BIT2),digitalRead(BIT3)};
  int value = 0;
  int i = 0;
  while(i < 4)
  {
    value = value + (in_bits[i]*(pow(2,i)));
    i++;
  }
  return String(String(in_bits[3])+" "+String(in_bits[2])+" "+String(in_bits[1])+" "+String(in_bits[0])+" = "+String(value, HEX));
}

void loop() {

  Serial.println(user_in());


}

Output

0 1 0 0 = 3

In case you thing the input pins are an issue
this has the same result:

bool in_bits[4] = {0,0,1,0};

I don't see how knowing the exact pin number helps but here you go:

You would if you had used pins 0 and/or 1 for instance

value = value + (in_bits[i]*(pow(2,i)));
    i++;
  }
  return String(String(in_bits[3])+" "+String(in_bits[2])+" "+String(in_bits[1])+" "+String(in_bits[0])+" = "+String(value, HEX));
}

Madness, using pow, insanity using String.

pow() returns a float. So every other variable in your arithmetic is implicitly cast to a float too.

At some point pow() will introduce a bit of rounding error (because pow is for floats so works by approximation) which is fine if everything stays a float.

But you're then stuffing that result into an integer type, So even if the result is 3.99-recurring that gets truncated to 3.

Rewrite the routine so it doesn't use pow(). Use a bit shift operator instead.

Rewrite the routine so it doesn't use pow(). Use a bit shift operator instead.

and eliminate the Strings while you are at it.

GypsumFantastic:
pow() returns a float. So every other variable in your arithmetic is implicitly cast to a float too.

At some point pow() will introduce a bit of rounding error (because pow is for floats so works by approximation) which is fine if everything stays a float.

But you're then stuffing that result into an integer type, So even if the result is 3.99-recurring that gets truncated to 3.

Rewrite the routine so it doesn't use pow(). Use a bit shift operator instead.

this worked: value = value + (in_bits_*(2<<(i-1)));_
> UKHeliBob:
> and eliminate the Strings while you are at it.
As I said, it was just for testing, not the final code :slight_smile:

When i == 0 you shift -1 times left. Behaviour of negative shifts are undefined, and might work or not.

Instead of shifting bit 2 "i-1" times, just shift bit 1 "i" times.

value = value + in_bits[i] << i;

value = value | in_bits[i] << i;

value += in_bits[i] << i;

value |= in_bits[i] << i;

Instead of shifting bit 2 "i-1" times,

The value 2 is actually bit 1 (21 == 2)

That is correct.

Don't know what I was thinking of :wink:

AWOL:
Madness, using pow, insanity using String.

Rather pointless using an int to count to 4, too.