-1

OK, I'm working on a project where I want to have multiple toggle switches create a "code" to determine further actions. This is essentially 5-bit communication process that will create output with a 32-bit range of outcomes from 00000 to 11111.

I'm testing the method with three switches, so if the first and third switch are HIGH/on it will read 101. Second and third, 011 etc. I'm not versed enough to know if there is a better method here, but is there a better way to do this?

    // Define the pins being used
int pin_switch = 10;
int pin_switch2 = 11;
int pin_switch3 = 12;

// create int for 3-digit code
int code = 000;
 

void setup() 
{
    Serial.begin(9600); 
    pinMode(pin_switch, INPUT); 
    pinMode(pin_switch2, INPUT); 
    pinMode(pin_switch3, INPUT); 
}
 
void loop()
{

if pin_switch == HIGH;
    {code += 100;}

if pin_switch2 == HIGH;
    {code += 10;}

if pin_switch3 == HIGH;
    {code += 1;}

Serial.print(code);

// operate based on code output
if code == 101;
    {do 101 stuff}

if code == 001
    {do 001 stuff}

// reset code for next loop so numbers don't keep rising
code = 000;
}
1
  • 1
    Note: don't write leading zeros in a decimal number in C or C++ (or a bunch of other languages) - the numbers will be treated as octal rather than decimal which is very rarely what you want.
    – Mat
    Aug 23 at 15:55
2

It would be more convenient and less typing if you put all your switch pins in an array. That way you can loop over it to configure the ports and read them rather than copy/pasting the "same" code over and over.

The calculation of the resulting code is a classic "shift and add" loop. I put both the decimal version you seem to want and the more "usual" binary version in the snippet below.

The idea behind that sort of loop is:

  1. start with an empty (zero) code
  2. multiply the code by 10 (or left-shift once for binary)
  3. read a switch, add 1 to the code if it is HIGH
  4. go back to step 2 if there are more switches.

The value of the switches already read get "pushed" one slot to the left before reading the next switch, resulting in the code you want.

The order in which you list the ports in the array is important: the first port in the array will change the leftmost (most significant) digit/bit in the code.

const uint8_t switch_pin[] = { 10, 11, 12 };
const uint8_t num_switches = sizeof(switch_pin)/sizeof(switch_pin[0]);

void setup() {
  // Set all switch pins to input mode
  for (uint8_t i = 0; i < num_switches; ++i) {
    pinMode(switch_pin[i], INPUT);
  }
  Serial.begin(9600);
}

void loop() {
  int code = 0;
  // Read each switch and compute the code
  for (uint8_t i = 0; i < num_switches; ++i) {
    // If the code is supposed to be in decimal
    code = code * 10;
    code += digitalRead(switch_pin[i]);
    /* For a binary version, code only needs to be 8 bits long:
    code <<= 1;
    code |= digitalRead(switch_pin[i]);
    */
  }
  
  // Do stuff with the code
  Serial.println(code);
  delay(200);
}
2
  • Oh thank you Mat, I think Shift and Add is the terminology I was lacking! I think I do want to go Binary, I'm thinking I will expand this to five switches so the shifting aspect simplifies that in my mind. Looking at your code here: code <<= 1; How would I shift and add for the other parts of the code? The prior would output 010, right? Would I just need to do <<<=1; AND <<= 1 to get 110? Thank you for the help.
    – Mulcch
    Aug 23 at 15:56
  • 1
    If code is 1010, code <<= 1 (which is the same as code = code << 1) will result in 10100 (shift left, insert a zero at the right). The code |= 1; would "fill" the last position to 10101. code |= 0; would do nothing.
    – Mat
    Aug 23 at 16:07
2

Unfortunately your code is all over the place. You have to use C/C++ syntax, which you don't. Also you don't actually read any input.

  • if statements look like this:

      if(condition){
          my_code();
      }
    
  • if(pin_switch == HIGH) (corrected syntax) will always be false, since pin_switch is of value 10. Its just the pin number. To actually read the pin, you need to use digitalRead() like this:

      if(digitalRead(pin_switch) == HIGH)
    

    or even simpler

      if(digitalRead(pin_switch))
    
  • It seems that you want to manipulate the bits with code += 100;, but the compiler takes numbers as decimal. So you are adding 100 to code. Please look into the bitwise operators. Also: You can actually write numbers in binary or hex by using 0b101 or 0xF3 respectively (the values here are just examples). This also means, that int code = 000; is the same as int code = 0;.


To build the 3 digit code from input you could put them together via bitwise operators:

code = (digitalRead(pin_switch3) << 2) | (digitalRead(pin_switch2) << 1) | digitalRead(pin_switch);

Depending on your used Arduino and the used pins you can get this even easier. The pins are sorted into ports. Each port has a Special Function register, which holds the current state of the pins. You can mask away any unwanted pins and shift the number to be right justified. For example: On the Uno and Nano pins 2 to 7 belong to PORTD. So, if you use pins 2 to 4 for your 3 switches, you could get the code like:

code = (PIND & 0b00011100) >> 2;

This is a bit more difficult to understand, but it will help you later on, when pursuing Arduino more.


For deciding what action to do based on the code, it is normally easier to use a switch case statement:

switch(code){
    case 0b101:
        do_something();
        break;
    case 0b011:
        do_something_else();
        break;
}
3
  • Thank you! Yes my code was thrown together hastily from an example to test the method. Really appreciate the direction here, I'll dig into bitwise operators more!
    – Mulcch
    Aug 23 at 16:06
  • 1
    @Mulcch oops, corrected a small error. I used PORTD instead of PIND. The former is used to set the output state of a pin, the latter reflects the current input state.
    – chrisl
    Aug 23 at 16:22
  • Thanks for catching! I'm not sure I'll go that route, but really helpful to know about that.
    – Mulcch
    Aug 23 at 17:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.