# A challenge on Bit mapping

**URL:** <https://forum.arduino.cc/t/a-challenge-on-bit-mapping/1409612>\
**Category:** Networking, Protocols, and Devices\
**Created:** [October 16, 2025, 1:48am UTC](https://forum.arduino.cc/t/a-challenge-on-bit-mapping/1409612 "2025-10-16T01:48:45Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ardubit](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/ardubit/32/264049_2.png) [@Ardubit](https://forum.arduino.cc/u/Ardubit)\
**Post date:** [October 16, 2025, 1:48am UTC](https://forum.arduino.cc/t/a-challenge-on-bit-mapping/1409612/1 "2025-10-16T01:48:45Z")

</div>

I have a CAN message as below - it contains the status of 5 solenoids in Byte 0 and Byte 1. As I have shown a solenoid that is ON is represented by a bit combination of **01.** 00 is OFF. 10 or 11 is fault. So I just have to check for 01 or 00 and then if both are not matching declare fault.

0x18FF0308 = 55 01 00 00 00 00 00 00

First swap Byte 0 and Byte 1 and then form a 16 bit integer.

0x0155 = 00000001 01010101 ( All Solenoids ON )

One way is to do is a bit wise mask then AND for each solenoid and then decide . For instance for Solenoid 1 the mask will be 0x0001 and for Solenoid 2 it will be 0x0004 and so on.

Any other simple way ??

---

<div class="post-metadata">

**Author:** ![anon94801460](https://avatars.discourse-cdn.com/v4/letter/a/278dde/32.png) [@anon94801460](https://forum.arduino.cc/u/anon94801460)\
**Post date:** [October 16, 2025, 3:12am UTC](https://forum.arduino.cc/t/a-challenge-on-bit-mapping/1409612/2 "2025-10-16T03:12:26Z")

</div>

Is there an actual question in the above word salad?

---

<div class="post-metadata">

**Author:** ![horace](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/horace/32/1014299_2.png) [@horace](https://forum.arduino.cc/u/horace)\
**Post date:** [October 16, 2025, 6:47am UTC](https://forum.arduino.cc/t/a-challenge-on-bit-mapping/1409612/3 "2025-10-16T06:47:40Z")

</div>

> [@Ardubit](#):
>
> One way is to do is a bit wise mask then AND for each solenoid and then decide . For instance for Solenoid 1 the mask will be 0x0001 and for Solenoid 2 it will be 0x0004 and so on.

masking the bits as you indicate seems to be the simplest way  
as the CAN message is 8 bytes why not transmit the solenoid states in 5 separate bytes?

---

<div class="post-metadata">

**Author:** ![racpi](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/racpi/32/1126829_2.png) [@racpi](https://forum.arduino.cc/u/racpi)\
**Post date:** [October 16, 2025, 6:48am UTC](https://forum.arduino.cc/t/a-challenge-on-bit-mapping/1409612/4 "2025-10-16T06:48:27Z")

</div>

a bit field array

```arduino
struct RELAYS
{
uint16_t RELAY0: 2;
uint16_t RELAY1: 2;
…
uint16_t RELAY4: 2;
};

```

---

<div class="post-metadata">

**Author:** ![Ardubit](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/ardubit/32/264049_2.png) [@Ardubit](https://forum.arduino.cc/u/Ardubit)\
**Post date:** [October 16, 2025, 7:04am UTC](https://forum.arduino.cc/t/a-challenge-on-bit-mapping/1409612/5 "2025-10-16T07:04:23Z")

</div>

Yes would have been way simpler to do that … but the balance 6 bytes are reserved for some other info to be sent in future. So all this circus.

---

<div class="post-metadata">

**Author:** ![b707](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/b707/32/854321_2.png) [@b707](https://forum.arduino.cc/u/b707)\
**Post date:** [October 16, 2025, 8:01am UTC](https://forum.arduino.cc/t/a-challenge-on-bit-mapping/1409612/6 "2025-10-16T08:01:13Z")

</div>

> [@Ardubit](#):
>
> would have been way simpler to do that

Instead of applying a six separate bitmasks you could do it in a loop. But the way depends on the purpose. How do you plan to use the solenoid states after extraction them from the message?

---

<div class="post-metadata">

**Author:** ![J-M-L](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/j-m-l/32/766245_2.png) [@J-M-L](https://forum.arduino.cc/u/J-M-L)\
**Post date:** [October 16, 2025, 8:30am UTC](https://forum.arduino.cc/t/a-challenge-on-bit-mapping/1409612/7 "2025-10-16T08:30:20Z")

</div>

in which format do you store your CAN payload ( `55 01 00 00 00 00 00 00`) ? is that in a byte array ?

if it's in an array, let's says a 8 byte array, then you could write a function

```arduino
// Returns a byte where:
// bits 0-4 : solenoid ON/OFF (1 = ON, 0 = OFF)
// bits 5-7 : number of solenoids in fault
uint8_t getSolenoidStatus(const uint8_t* payload) {
  uint16_t val = (payload[1] << 8) | payload[0];
  uint8_t result = 0;
  uint8_t faultCount = 0;

  for (int i = 0; i < 5; i++) {
    uint8_t status = (val >> (i * 2)) & 0x03;
    if (status == 0x01)
      bitSet(result, i);
    else if (status != 0x00)
      faultCount++;
  }

  result |= (faultCount << 5);
  return result;
}

```

---

<div class="post-metadata">

**Author:** ![horace](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/horace/32/1014299_2.png) [@horace](https://forum.arduino.cc/u/horace)\
**Post date:** [October 16, 2025, 9:28am UTC](https://forum.arduino.cc/t/a-challenge-on-bit-mapping/1409612/8 "2025-10-16T09:28:55Z")

</div>

> [@Ardubit](#):
>
> but the balance 6 bytes are reserved for some other info to be sent in future

OK - using a loop

```cpp
void setup() {
  Serial.begin(115200);
  delay(2000);
  //byte data[]={0x55, 0x01, 0, 0, 0, 0, 0, 0};
  byte data[]={0x4B, 0x01, 0, 0, 0, 0, 0, 0}; // 0x4B = 01001011
  for(int i=0;i<4;i++) {
    byte test = (data[0] >> (i*2))& 0x3; // select 2 bits to test
    switch(test) {
      case 0: Serial.printf("switch %d, test %0x OFF\n", i, test); break;
      case 1: Serial.printf("switch %d, test %0x ON\n", 0, test); break;
      default: Serial.printf("switch %d, test %0x ERROR\n", i, test); break;    
    }
  }
}

void loop() {}

```

on an ESP32 displays

```arduino
switch 0, test 3 ERROR
switch 1, test 2 ERROR
switch 2, test 0 OFF
switch 0, test 1 ON

```

---

<div class="post-metadata">

**Author:** ![racpi](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/racpi/32/1126829_2.png) [@racpi](https://forum.arduino.cc/u/racpi)\
**Post date:** [October 16, 2025, 11:13am UTC](https://forum.arduino.cc/t/a-challenge-on-bit-mapping/1409612/9 "2025-10-16T11:13:50Z")

</div>

i like the power of bit fields and structures to handle packetized data

````arduino

```cpp
struct RELAYS {
  uint16_t RELAY0 : 2;
  uint16_t RELAY1 : 2;
  uint16_t RELAY2 : 2;
  uint16_t RELAY3 : 2;
  uint16_t RELAY4 : 2;
};

struct PACKET {
  RELAYS RELAY;
  byte STUFF[6];
};

PACKET pkt;

void setup() {
  Serial.begin(115200);
  //byte data[]={0x55, 0x01, 0, 0, 0, 0, 0, 0};
  byte data[] = { 0x54, 0x01, 11, 22, 33, 44, 77, 66 };
  memcpy((uint8_t*)&pkt, data, 8);
  Serial.println();
  Serial.printf("\nRelay-0\t%d\tStuff-0\t[%d]", pkt.RELAY.RELAY0, pkt.STUFF[0]);
  Serial.printf("\nRelay-1\t%d", pkt.RELAY.RELAY1);
  Serial.printf("\nRelay-2\t%d", pkt.RELAY.RELAY2);
  Serial.printf("\nRelay-3\t%d", pkt.RELAY.RELAY3);
  Serial.printf("\nRelay-4\t%d\tStuff-4\t[%d]", pkt.RELAY.RELAY4, pkt.STUFF[4]);
  Serial.printf("\n\t\tStuff-5\t[%d]", pkt.STUFF[5]);
}

void loop() {
  // put your main code here, to run repeatedly:
}

````

```arduino
ESP-ROM:esp32c3-api1-20210207

Relay-0 0 Stuff-0 [11]

Relay-1 1

Relay-2 1

Relay-3 1

Relay-4 1 Stuff-4 [77]

Stuff-5 [66]

```

```arduino

```

---

<div class="post-metadata">

**Author:** ![J-M-L](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/j-m-l/32/766245_2.png) [@J-M-L](https://forum.arduino.cc/u/J-M-L)\
**Post date:** [October 16, 2025, 11:23am UTC](https://forum.arduino.cc/t/a-challenge-on-bit-mapping/1409612/10 "2025-10-16T11:23:14Z")

</div>

> [@racpi](#):
>
> ```arduino
> struct PACKET {
> RELAYS RELAY;
> byte STUFF[6];
> };
> 
> ```

Did you mean union ?

(With the associated challenges in C++)

---

<div class="post-metadata">

**Author:** ![racpi](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/racpi/32/1126829_2.png) [@racpi](https://forum.arduino.cc/u/racpi)\
**Post date:** [October 16, 2025, 11:29am UTC](https://forum.arduino.cc/t/a-challenge-on-bit-mapping/1409612/11 "2025-10-16T11:29:36Z")

</div>

> [@J-M-L](#):
>
> Did you mean union ?

no , its a struc

---

<div class="post-metadata">

**Author:** ![J-M-L](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/j-m-l/32/766245_2.png) [@J-M-L](https://forum.arduino.cc/u/J-M-L)\
**Post date:** [October 16, 2025, 4:26pm UTC](https://forum.arduino.cc/t/a-challenge-on-bit-mapping/1409612/12 "2025-10-16T16:26:00Z")

</div>

Ok

Still, you are in undefined behavior territory according to the C++ standard. Bitfield layout and padding are implementation-defined, meaning the compiler decides how bits are arranged in memory, and this arrangement can vary across platforms or even compiler versions.

That being said, in practice, most compilers such as GCC and Clang on little-endian architectures produce the deterministic results you showed, so the code appears to work, but it is not portable and not guaranteed by the language.

---

<div class="post-metadata">

**Author:** ![racpi](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/racpi/32/1126829_2.png) [@racpi](https://forum.arduino.cc/u/racpi)\
**Post date:** [October 17, 2025, 2:04am UTC](https://forum.arduino.cc/t/a-challenge-on-bit-mapping/1409612/13 "2025-10-17T02:04:27Z")

</div>

> [@J-M-L](#):
>
> That being said, in practice, most compilers such as GCC and Clang on little-endian architectures produce the deterministic results you showed, so the code appears to work, but it is not portable and not guaranteed by the language.

i can see that being a major issue when the single specific implementation the code has been designed for, tested and proved to work on suddenly changes its platform and recompiles itself without user intervention.

i have never found a platform that I could not got this method to work on[eventually]

might need a bit of padding, attribute packing or order juggling , endianness conversion if one must.

---

<div class="post-metadata">

**Author:** ![J-M-L](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/j-m-l/32/766245_2.png) [@J-M-L](https://forum.arduino.cc/u/J-M-L)\
**Post date:** [October 17, 2025, 6:19am UTC](https://forum.arduino.cc/t/a-challenge-on-bit-mapping/1409612/14 "2025-10-17T06:19:20Z")

</div>

I guess for hobbyists it’s a personal decision. I know many companies where falling into Undefined Behavior is a no no.

Personally I’d rather stay « clean » when it’s easy to do so. The simple for loop I posted earlier is an example of how to extract some information from the payload easily.

---

<div class="post-metadata">

**Author:** ![racpi](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/racpi/32/1126829_2.png) [@racpi](https://forum.arduino.cc/u/racpi)\
**Post date:** [October 17, 2025, 7:54am UTC](https://forum.arduino.cc/t/a-challenge-on-bit-mapping/1409612/15 "2025-10-17T07:54:56Z")

</div>

> [@J-M-L](#):
>
> The simple for loop I posted earlier is an example of how to extract some information from the payload easily.

but it comes into its own if the data is modified and sent on

```arduino
struct RELAYS {
  uint16_t RELAY0 : 2;
  uint16_t RELAY1 : 2;
  uint16_t RELAY2 : 2;
  uint16_t RELAY3 : 2;
  uint16_t RELAY4 : 2;
};
// __attribute__ ((packed))
struct PACKET {
  RELAYS RELAY;
  byte STUFF[6];
};

PACKET pkt;

void setup() {
  Serial.begin(115200);
  //byte data[]={0x55, 0x01, 0, 0, 0, 0, 0, 0};
  byte data[] = { 0x54, 0x01, 11, 22, 33, 44, 77, 66 };
  memcpy((uint8_t*)&pkt, data, 8);
  Serial.println("ready");
  Serial.printf("\nRelay-0\t%d\tStuff-0\t[%d]", pkt.RELAY.RELAY0, pkt.STUFF[0]);
  Serial.printf("\nRelay-1\t%d", pkt.RELAY.RELAY1);
  Serial.printf("\nRelay-2\t%d", pkt.RELAY.RELAY2);
  Serial.printf("\nRelay-3\t%d", pkt.RELAY.RELAY3);
  Serial.printf("\nRelay-4\t%d\tStuff-4\t[%d]", pkt.RELAY.RELAY4, pkt.STUFF[4]);
  Serial.printf("\n\t\tStuff-5\t[%d]", pkt.STUFF[5]);
  pkt.RELAY.RELAY0 = 3;
  pkt.STUFF[5] = 77;
  pkt.STUFF[4] = 66;
  memcpy(data, (uint8_t*)&pkt, 8);
  Serial.printf("\ndata[0x%02x,0x%02x,%d,%d,%d,%d,%d,%d]", data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
}

void loop() {
  // put your main code here, to run repeatedly:
}

```

```arduino
ESP-ROM:esp32c3-api1-20210207
ready

Relay-0	0	Stuff-0	[11]
Relay-1	1
Relay-2	1
Relay-3	1
Relay-4	1	Stuff-4	[77]
		Stuff-5	[66]
data[0x57,0x01,11,22,33,44,66,77]

```

---

<div class="post-metadata">

**Author:** ![J-M-L](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/j-m-l/32/766245_2.png) [@J-M-L](https://forum.arduino.cc/u/J-M-L)\
**Post date:** [October 17, 2025, 8:12am UTC](https://forum.arduino.cc/t/a-challenge-on-bit-mapping/1409612/16 "2025-10-17T08:12:21Z")

</div>

> [@racpi](#):
>
> but it comes into its own if the data is modified and set on

I don't understand what that means ...

---

<div class="post-metadata">

**Author:** ![racpi](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/racpi/32/1126829_2.png) [@racpi](https://forum.arduino.cc/u/racpi)\
**Post date:** [October 17, 2025, 8:16am UTC](https://forum.arduino.cc/t/a-challenge-on-bit-mapping/1409612/17 "2025-10-17T08:16:22Z")

</div>

i mean the data can be easily created or modified using easy to understand meaningful names ready to be transmitted or retransmitted  
eg

```arduino
struct RELAYS {
  uint16_t heater_fan : 2;
  uint16_t demister: 2;
  uint16_t washer : 2;
  uint16_t high_beam: 2;
  uint16_t reverse_lamp : 2;
};

```

---

<div class="post-metadata">

**Author:** ![J-M-L](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/j-m-l/32/766245_2.png) [@J-M-L](https://forum.arduino.cc/u/J-M-L)\
**Post date:** [October 17, 2025, 8:23am UTC](https://forum.arduino.cc/t/a-challenge-on-bit-mapping/1409612/18 "2025-10-17T08:23:29Z")

</div>

I don't understand...

basically my function

```arduino
// Returns a byte where:
// bits 0-4 : solenoid ON/OFF (1 = ON, 0 = OFF)
// bits 5-7 : number of solenoids in fault
uint8_t getSolenoidStatus(const uint8_t* payload) {
  uint16_t val = (payload[1] << 8) | payload[0];
  uint8_t result = 0;
  uint8_t faultCount = 0;

  for (int i = 0; i < 5; i++) {
    uint8_t status = (val >> (i * 2)) & 0x03;
    if (status == 0x01)
      bitSet(result, i);
    else if (status != 0x00)
      faultCount++;
  }

  result |= (faultCount << 5);
  return result;
}

```

does conceptually what you do here

> [@racpi](#):
>
> ```arduino
> byte data[] = { 0x54, 0x01, 11, 22, 33, 44, 77, 66 };
> memcpy((uint8_t*)&pkt, data, 8);
> 
> ```

I provide a result (as you do in pkt) which you can use then to extract and print information from. The information I extracted is the status — ON / OFF of each solenoid and the count of faulty states (so that if that count is not 0, you know you can't trust the status bits but you can't tell in one byte which one was wrong)

so if you get a payload from CAN, you pass it to the function and you keep the resulting bye as your system state.

---

<div class="post-metadata">

**Author:** ![racpi](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/racpi/32/1126829_2.png) [@racpi](https://forum.arduino.cc/u/racpi)\
**Post date:** [October 17, 2025, 8:54am UTC](https://forum.arduino.cc/t/a-challenge-on-bit-mapping/1409612/19 "2025-10-17T08:54:48Z")

</div>

> [@J-M-L](#):
>
> does conceptually what you do here

indeed but you are assuming the data is only to be read. what if you want to create the data or modify it for transmission

i gave my last two posts more detail ,sorry

---

<div class="post-metadata">

**Author:** ![racpi](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/racpi/32/1126829_2.png) [@racpi](https://forum.arduino.cc/u/racpi)\
**Post date:** [October 17, 2025, 9:14am UTC](https://forum.arduino.cc/t/a-challenge-on-bit-mapping/1409612/20 "2025-10-17T09:14:48Z")

</div>

as an aside, I do this a lot. identical structures can exist on a 8bit pic chip and an esp32 for instance, if you are transferring data between them its so easy . the concept works for every c compiler I have come across xc8,xc16,xc32,gcc,mickroc, sourceboost etc. even python, node-red, javascript have similar methods too, it makes transfer of data between platforms simple in my view. if you know how the compiler allocates memory for your platform its not difficult

[Next page](https://forum.arduino.cc/t/a-challenge-on-bit-mapping/1409612.md?page=2)
