There's GOT to be an easier way

I am relatively new to Ardunio, and I’m doing a project that uses manchester biphase. Right now, the data stream is 32 bits long and bits 9-24 control a pin each. The way I’m doing this so far is very inefficient and time consuming. Is there any way I could make this faster than using millions of if statements? Here’s the code:

#include <Manchester.h>
#define RX_PIN 8

void setup()
{
  man.setupReceive(RX_PIN, MAN_4800);
  man.beginReceive();
}



void loop() {
  if (man.receiveComplete()) {
  uint16_t m = man.getMessage();
  man.beginReceive(); //start listening for next message right after you retrieve the message
    //do something with your message here
    if (man.getMessage() == 00000000100000000000000011111101); {
      digitalWrite(13, HIGH);
    if (man.getMessage() == 00000000010000000000000011111101); {
      digitalWrite(12, HIGH);
    if (man.getMessage() == 00000000001000000000000011111101); {
      digitalWrite(11, HIGH);
    if (man.getMessage() == 00000000000100000000000011111101); {
      digitalWrite(11, HIGH);
    }
  }    
}
    }
  }
}

I’m using this library: Home - Arduino Manchester Encoding - Mchr3k

Use switch/case convert your binary # to hex (unsigned long), or don't ;)

http://www.arduino.cc/en/Reference/SwitchCase

Two bits for the same pin?

And the constant you specified should be converted as octal, giving unexpected values.

    if (man.getMessage() == 00000000001000000000000011111101); {
      digitalWrite(11, HIGH);
    if (man.getMessage() == 00000000000100000000000011111101); {
      digitalWrite(11, HIGH);

Basically the above code did never work, if feel that is different to "The way I'm doing this so far is very inefficient and time consuming. ".

Whandall: Two bits for the same pin?

And the constant you specified should be converted as octal, giving unexpected values.

    if (man.getMessage() == 00000000001000000000000011111101); {
      digitalWrite(11, HIGH);
    if (man.getMessage() == 00000000000100000000000011111101); {
      digitalWrite(11, HIGH);

Basically the above code did never work, if feel that is different to "The way I'm doing this so far is very inefficient and time consuming. ".

Thats a typo, the second 11 should be 10

Binary constants begin with "0b", octal with "0".

Your approach of decoding an entire message to control a single pin does not allow any message to switch more than one pin. That would be very inefficient.

jremington:
Binary constants begin with “0b”, octal with “0”.

Your approach of decoding an entire message to control a single pin does not allow any message to switch more than one pin. That would be very inefficient.

What do suggest I do?

Have a look at the bitRead function.

Or roll your own with a little bitshifting and bitmath.

// store the result in a variable if efficiency is what you're after
//  don't keep calling getMessage over and over
unsigned long val = man.getMessage();  

//Check to see if bit 9 is HIGH:
if((val >> 9) & 1){
   digitalWrite(9, HIGH);
}
else {
   digitalWrite(9, LOW);
}

or get really slick and do it in a for loop:

for (int i = 9; i < 25; i++){
   digitalWrite(i, (val << i) & 1);
}

OF course that assumes that bit 9 controls pin 9 and bit 10 controls pin 10. If not, just adjust by adding to i in the digitalWrite. If the pins aren’t in order like that then set up an array to hold the pin numbers and use i as an index.

int pins[] = {5, 7, 2, 12, 14, 16, 6};  // write out how many pins in the order they appear in that bitfield
for (int i=9; i<25; i++){
   digitalWrite(pins[i-9], (val >> i) &1);
}

Wow, so much to take in. Is there a way that I can read the entire data stream one time and control the pins from that one time of reading instead of doing each pin separately?

pianocorder_man: Wow, so much to take in. Is there a way that I can read the entire data stream one time and control the pins from that one time of reading instead of doing each pin separately?

No, it is unlikely that there is an intrinsic one-to-one mapping of payload bits to processor pins. But I'm 100% sure that you can do it efficiently with some relatively simple bit manipulation (as has been pointed out already).

Can this be explained more? I’m not sure I understand exactly:

int pins[] = {5, 7, 2, 12, 14, 16, 6};  // write out how many pins in the order they appear in that bitfield
for (int i=9; i<25; i++){
   digitalWrite(pins[i-9], (val >> i) &1);
}

Remember, there's a big difference between something being inefficient and something just taking a bunch of lines to code.

What part of that is vexing you? Hit the reference section and see if you can sort out the bitmath part.

pianocorder_man:
Can this be explained more? I’m not sure I understand exactly:

int pins[] = {5, 7, 2, 12, 14, 16, 6};  // write out how many pins in the order they appear in that bitfield

for (int i=9; i<25; i++){
  digitalWrite(pins[i-9], (val >> i) &1);
}

pins is an integer array with 7 elements

However, your for loop is going to run more than 7 times. Uh oh.

Look up one of the many tutorials on bitwise operations (eg this one)

But I’m wondering if @Delta_G’s for loop is quite correct even if you make the array the right length. If you assume human numbering system where bit 1 is on the left and bit 32 is on the right then surely you have to do ‘val >> (32-i)’ in order to get the ith bit into the same position as the 1?

Perhaps slightly easier to understand if you do

int pins[] = {5, 7, 2, 12, 14, 16, 6};  // write out how many pins in the order they appear in that bitfield
for (int i=9; i<25; i++){
   digitalWrite(pins[i-9], val & (1 << (31-i)) );
}

For example the string
‘00000000001000000000000011111101’
has the 11th bit set.

In order to test the 11th bit we create a bitmask like 1<<(32-11) .

1<<(32-11) in binary is
‘00000000001000000000000000000000’

So we apply the bitwise and operator & which compares the value of each bit in turn and only writes 1 in the positions where both numbers are 1

So if we do ‘val & (1<<(32-11))’ we get the result
‘00000000001000000000000000000000’

which, when fed into a function that expects a binary value, gets converted to one.

In comparison if we test the 10th bit
1<<(32-10)
‘00000000010000000000000000000000’

The 1’s dont line up so the result ‘val & (1<<(32-10)’ is
‘00000000000000000000000000000000’

which gets turned into a 0 when converted to binary.

ieee488: pins is an integer array with 7 elements

However, your for loop is going to run more than 7 times. Uh oh.

Yeah, read the comment. I left a bunch of numbers out because I didn't want to try to guess the OPs pin arrangement. The code here was for illustrative purposes. The OP said he has 24 pins. All he needs to do is fill in the rest of the pin numbers in the array.

rw950431: If you assume human numbering system where bit 1 is on the left and bit 32 is on the right then surely you have to do 'val >> (32-i)' in order to get the ith bit into the same position as the 1.

Typically bit 0 is the LSB (the one on the right end) and you count up to the MSB (bit 31 on the left). There's not a bit 32 in a 32 bit number. But the OP didn't make it very clear which bit maps to which pin so a little guesswork was involved. If you order the PIN numbers right in the array though then it doesn't matter. If it works backwards then reverse the order of the pins in the array.

Here's something else to consider: the last 8 bits indicate the end of that data frame for sync. What should I do with them in the programming? I almost need something that checks for valid sync before it continues to decode the rest.

"Almost"? I should say you do. Any time your communication protocol includes a checksum, parity, CRC or sync, you should check that first. It is a great protection against your robot running amok.

What would be a good way to set up the sync reader?

Bitwise Operators in C and C++: A Tutorial

Whandall: Bitwise Operators in C and C++: A Tutorial

Thanks for that, that is incredibly easy to understand and provides tons of useful information for this project :)