Union bite array to decimal value

Hi All,

I’ve been googling and trying to figure out how to convert (i.e. serialPrint) the value of an array to decimal.

In a nutshell here is a simplified sample of the code:

int point1;
int point2;
int point3;
int point4;
int point5;
int point6;
int point7;
int point8;

union { 
  byte configs [8] = {1,0,0,0,0,0,0,1}; // this will be replaced by what the slave has sent via i2c from another arduino.
} slaveDataUnion;


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

void loop() {

  point8 = slaveDataUnion.configs [0];
  point7 = slaveDataUnion.configs [1];
  point6 = slaveDataUnion.configs [2];
  point5 = slaveDataUnion.configs [3];
  point4 = slaveDataUnion.configs [4];
  point3 = slaveDataUnion.configs [5];
  point2 = slaveDataUnion.configs [6];
  point1 = slaveDataUnion.configs [7];


  Serial.print(point1);
  Serial.print(point2);
  Serial.print(point3);
  Serial.print(point4);
  Serial.print(point5);
  Serial.print(point6);
  Serial.print(point7);
  Serial.println(point8);
// Now need to print the decimal value.... :o 

}

so far so good… BUT… I also need to see a decimal value of what the binary value above is.

Forgive me if it is a stupid question but my head hurts already and after days of fiddling with it I might just not see the forest 'cause of the trees! :slight_smile:

Any help will be greatly appreciated.

Thanks guys/gals

Does this help. I added a bit to get the decimal value of the byte. Is this what you meant?

int point1;
int point2;
int point3;
int point4;
int point5;
int point6;
int point7;
int point8;

union
{
   byte configs [8] = {1, 0, 0, 0, 0, 0, 1, 1}; // this will be replaced by what the slave has sent via i2c from another arduino.
} slaveDataUnion;

byte decimalValue = 0;  //****** added

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

void loop()
{
   // lets slow it down so we can see the prints
   static unsigned long timer = 0;
   unsigned long interval = 500;
   if (millis() - timer >= interval)
   {
      timer = millis();
      
      point8 = slaveDataUnion.configs [0];
      point7 = slaveDataUnion.configs [1];
      point6 = slaveDataUnion.configs [2];
      point5 = slaveDataUnion.configs [3];
      point4 = slaveDataUnion.configs [4];
      point3 = slaveDataUnion.configs [5];
      point2 = slaveDataUnion.configs [6];
      point1 = slaveDataUnion.configs [7];

      Serial.print(point1);
      Serial.print(point2);
      Serial.print(point3);
      Serial.print(point4);
      Serial.print(point5);
      Serial.print(point6);
      Serial.print(point7);
      Serial.println(point8);

      // Now need to print the decimal value.... :o
      
      // I guessed that the MSB is slaveDataUnion.configs [0]
      for (int n = 0; n < 8; n++)
      {
         bitWrite(decimalValue, n, slaveDataUnion.configs [7 - n]);
         // if my guess is wrong
         // bitWrite(decimalValue, n, slaveDataUnion.configs [n]);        
      }
      Serial.print("Decimal value  ");
      Serial.println(decimalValue, DEC);
   }
}
  byte decimalValue = 0;
  for (int bit = 0; bit < 8; bit++)
  {
    bitWrite(decimalValue, bit, slaveDataUnion.configs[bit]);
  }

You don’t say what order the bits are held in the array so you may need to adjust the for loop but this will do what you asked

Using bit sifting and masking would be neater but bitWrite() is easy to use

or if you want to do maths:

 byte decimalValue = 0;
for (int bit = 0; bit < 8; bit++) decimalValue = 2 * decimalValue + slaveDataUnion.configs[bit]; // if bit 0 is MSB

If you are receiving the points separately - you could also benefit from a hack (out of language spec but works with GCC in your Arduino context) and use bitfields in your union.

union __attribute__((packed)) {
  struct __attribute__((packed)) {
    uint8_t point1: 1;
    uint8_t point2: 1;
    uint8_t point3: 1;
    uint8_t point4: 1;
    uint8_t point5: 1;
    uint8_t point6: 1;
    uint8_t point7: 1;
    uint8_t point8: 1;
  } points;
  uint8_t byteValue;
} slaveDataUnion = {1, 0, 0, 1, 0, 0, 1, 1};

void setup() {
  Serial.begin(115200);
  Serial.print(F("Size of slaveDataUnion = ")); Serial.println(sizeof(slaveDataUnion));
  Serial.println();

  Serial.print(F("point1 = "));  Serial.println(slaveDataUnion.points.point1);
  Serial.print(F("point2 = "));  Serial.println(slaveDataUnion.points.point2);
  Serial.print(F("point3 = "));  Serial.println(slaveDataUnion.points.point3);
  Serial.print(F("point4 = "));  Serial.println(slaveDataUnion.points.point4);
  Serial.print(F("point5 = "));  Serial.println(slaveDataUnion.points.point5);
  Serial.print(F("point6 = "));  Serial.println(slaveDataUnion.points.point6);
  Serial.print(F("point7 = "));  Serial.println(slaveDataUnion.points.point7);
  Serial.print(F("point8 = "));  Serial.println(slaveDataUnion.points.point8);

  Serial.println();
  Serial.print(F("Direct read = 0b")); Serial.print(slaveDataUnion.byteValue, BIN);
}

void loop() {}

Again, that’s a hack as the language state that you should not read slaveDataUnion.byteValue if you have been using the slaveDataUnion.points structure to initialize the union. But it does work :slight_smile:

Why do you use a union for a simple 8 element byte array?

Unions are structs that place all there elements at the same address,
it is not very useful for a single element.

You can make use of a union like so

struct TheBits {
  byte bit0 : 1;
  byte bit1 : 1;
  byte bit2 : 1;
  byte bit3 : 1;
  byte bit4 : 1;
  byte bit5 : 1;
  byte bit6 : 1;
  byte bit7 : 1;
};

union Together {
  TheBits bits;
  byte value;
} test;

void setup() {
  Serial.begin(250000);
  test.bits.bit6 = 1;
  Serial.println(test.value);
}
void loop() {}
64

Whandall:
You can make use of a union like so...

yeah, was having the same idea - cf above (typing as you were posting). Only challenge is that this is out of language spec (but does work)

You guys Rock!!!! You bunch are just MAGIC!!!! Plenty of digital Beers to you all!

@groundFungus, Your solution worked perfectly. Many many thanks for your fast reply.

To all others who responded, my sincere appreciation for your kind input and generosity of sharing your knowledge.

Best regards from Namibia

Whandall:
Why do you use a union for a simple 8 element byte array?

Unions are structs that place all there elements at the same address,
it is not very useful for a single element.

You can make use of a union like so

struct TheBits {

byte bit0 : 1;
 byte bit1 : 1;
 byte bit2 : 1;
 byte bit3 : 1;
 byte bit4 : 1;
 byte bit5 : 1;
 byte bit6 : 1;
 byte bit7 : 1;
};

union Together {
 TheBits bits;
 byte value;
} test;

void setup() {
 Serial.begin(250000);
 test.bits.bit6 = 1;
 Serial.println(test.value);
}
void loop() {}





64

Ahhh yes..... (grin)..... because in the final code there will be more datatypes and stuff in the union.

Chilli_Paste:
Ahhh yes..... (grin)..... because in the final code there will be more datatypes and stuff in the union.

don't you think you want a struct then and not a union??

Whandall:
Unions are structs that place all there elements at the same address,

At the same time?

Theoretically they are only guaranteed to work for one interpretation at a time,
factually the different interpretations work in parallel IIRC.

Whandall:
Theoretically they are only guaranteed to work for one interpretation at a time,
factually the different interpretations work in parallel IIRC.

That means that we can't do the following though 3F9D70A4 is the correct binary32 formatted value for 1.23.

union
  {
    float x = 1.23;
    byte myByte[4] = {0xA4, 0x70, 0x9D, 0x3F}; //LSB first
  }myData;

We have to do either one of the following two:

 union
 {
   float x = 1.23;
   byte myByte[4];
 }myData;

OR

 union
 {
   float x;
   byte myByte[4] = {0xA4, 0x70, 0x9D, 0x3F}; //LSB first
 }myData;

Why do you think that has to be pointed out?
I see no connection to anything I have claimed.

It seems you can not assign to two interpretations of the same memory via initialization,
which absolutely makes sense to me, I would have never even tried that.

J-M-L:
don't you think you want a struct then and not a union??

Good point there. I will keep that in mind. I truthfully cannot say why I decided to use a union.
I am a male..... I press buttons until it works :slight_smile: :slight_smile: :slight_smile:

That means that we can't do the following though 3F9D70A4 is the correct binary32 formatted value for 1.23.

union

{
   float x = 1.23;
   byte myByte[4] = {0xA4, 0x70, 0x9D, 0x3F}; //LSB first
 }myData;

Why would you want to and even if you could do it what should happen if the values assigned conflicted with each other ?

Whandall:
Theoretically they are only guaranteed to work for one interpretation at a time,
factually the different interpretations work in parallel IIRC.

yes - I usually add __attribute__((packed), gives a bit of comfort the compiler won't play too much with data alignment and data structure padding and go for a condensed memory usage.