Using bit math with larger than bits

Hello all,

I'm working on a program to turn relays on/off (for christmas lights ect.) and I am using bit math to make it simple. I have the example below working. Each "menu selection" will cycle through the bytes and turn on/off the relays according to the bits. (Because there can be up to 32 cycles per menu, the first bit is 1 to show that it is not a null entry.)

I have this working for 6 relays, and want to expand up to 16 relays. However, something like B11010100111101010 doesn't work (probably because it's not a byte..).

Is there a solution? How can I make an integer in binary format and still use the bitmath?

byte RelaySequence[menuSelections][32] = {  //up to 32 cycles per menu
  {                                   //menu selection 1
    B1100000,
    B1000000                    }
  ,
  {                                  //menu selection 2
    B1110000,
    B1011000,
    B1001100,
    B1000110,
    B1000011,
    B1100001       }
}

http://arduino.cc/en/Reference/LowByte

You just need to select the size that gives you the right number of bits (for your application) if you want to manipulate it as a number:

  • (unsigned) byte or uint8_t - 8 bits
  • (unsigned) int or uint16_t - 16 bits
  • (unsigned) long or uint32_t - 32 bits

Of course you can still use your array of bytes and combine them into int/long just before you need to use them if that makes more sense form a programming point of view.

Also note that the numbers Bnnnnnnnn are defined in the Arduino header file (not really sure why). Standard C/C++ allows you to define binary numbers by 0bnnn..nn (simlar to hex numbers being 0xnnnn). This definintion does not depend on any header file and allows arbitrary length bit strings. You still need to respect that the bits have to fit in your variable, though.

Perhaps you could make your question less vague.

How many (max) relays per sequence entry.
What is the (max) length of a sequence.

... anything else you think will help take out the guess work as to WHAT you are trying to accomplish using MORE EXACT WORDING.

Here is a set of helper macros I have ported for use in my code.
These will allow you to use up to 32 bits.

/* 
    Binary constant generator macro 
    By Tom Torfs - donated to the public domain 
    All macro's evaluate to compile-time constants
*/ 

/* 
    HEX__(n)

        Turn a numeric literal into a hex constant ( avoids problems with leading zeroes ).
        8-bit constants max value 0x11111111, always fits in unsigned long 
*/ 

#define HEX__(n) 0x##n##LU 

/* 8-bit conversion function */ 
#define B8__( x ) ( ( x & 0x0000000FLU ) ? 1 : 0 ) + ( ( x & 0x000000F0LU ) ? 2 : 0 ) + ( ( x & 0x00000F00LU ) ? 4 : 0 ) + ( ( x & 0x0000F000LU ) ? 8 : 0 ) + ( ( x & 0x000F0000LU ) ? 16 : 0 ) + ( ( x & 0x00F00000LU ) ? 32 : 0 ) + ( ( x & 0x0F000000LU ) ? 64 : 0 ) + ( ( x & 0xF0000000LU ) ? 128 : 0 )

/* for upto 8-bit binary constants */ 
#define B8( d ) ( ( uint8_t ) B8__( HEX__( d ) ) ) 

/* for upto 16-bit binary constants, MSB first */ 
#define B16( dmsb, dlsb ) ( ( ( uint16_t ) B8( dmsb ) << 8 ) + B8( dlsb ) ) 

/* for upto 32-bit binary constants, MSB first */ 
#define B32( dmsb, db2, db3, dlsb ) ( ( ( uint32_t ) B8( dmsb ) << 24 ) + ( ( uint32_t ) B8( db2 ) << 16 ) + ( ( uint32_t ) B8( db3 ) << 8 ) + B8( dlsb ) )

Use them like this:

uint8_t u_8BitData  = B8(01010101); //85
uint16_t u_16BitData = B16(10101010,01010101); //43605
uint32_t u_32BitData = B32(10000000,11111111,10101010,01010101); //2164238933

Could use in your code like this:

int RelaySequence[menuSelections][32] = {  //up to 32 cycles per menu
  {                                   //menu selection 1
    B16( 1100000, 1100000 ),
    B16( 1000000, 1000000 )                    }
  ,
  {                                  //menu selection 2
    B16( 1110000, 1110000 ),
    B16( 1011000, 1011000 ),
    B16( 1001100, 1001100 ),
    B16( 1000110, 1000110 ),
    B16( 1000011, 1000011 ),
    B16( 1100001, 1100001 )       }
}

John_S:
However, something like B11010100111101010 doesn't work (probably because it's not a byte..).

I would wean myself off these rather annoying defines:

#define B101101 45
#define B0101101 45
#define B00101101 45
#define B101110 46
#define B0101110 46
#define B00101110 46
#define B101111 47
#define B0101111 47
#define B00101111 47
#define B110000 48
#define B0110000 48
#define B00110000 48
#define B110001 49
#define B0110001 49
#define B00110001 49
#define B110010 50
#define B0110010 50
#define B00110010 50
#define B110011 51
#define B0110011 51

Just use what the compiler actually supports:

0b11010100111101010

As in:

void setup ()
{
  Serial.begin (115200);
  
  long i = 0b11010100111101010;
  
  Serial.println (i);
}
void loop () {}

Output:

109034

See? It works. :wink:

I'm working on a program to turn relays on/off (for christmas lights ect.)

Christmas lights AND electro-convulsive therapy?
In May?

Skip binary for anything long than about five bits; do what the grown-ups do and learn hex.

Thanks all, I will give it a try. Hopefully it's ready by christmas...