Convert BCD to decimal for switch case

Hi, I want to read four pin state and convert them to decimal so that i can use them with switch statements to control a relay. For ex, If the pins read 0001 , (do something) If the pins read 0101, (do something)

I need to take inputs on pins ranging from 0001 to 1100 matching each case to a certain task. I tried using else if, but the program gets very big. Is there any simpler way to do this?

Give us a starting place, please share the code you have.

Well, i am sorry. I don't know where to start. I read all the inputs and stored on different variables. But how to store them in a single "long" variable to use switch case.. Is there anyway i can group the variables in one "long" variable?

Is the variable only 0000 thru 1001 or can it be 10011001 ? You say BCD is it otherwise? Give us a range?

The range is from 0001 to 1100 Each value corresponding to an action.

int motopin = 11;
int i0 = 7;
int i1 = 6;
int i2 = 5;
int i3 = 4;
int 0state;
int 1state;
int 2state;
int 3state;

void setup() 
{
delay(2000);
pinMode(motopin, OUTPUT);
pinMode(i0, INPUT);
pinMode(i1, INPUT);
pinMode(i2, INPUT);
pinMode(i3, INPUT);

0state = digitalRead(i0);
1state = digitalRead(i1);
2state = digitalRead(i2);
3state = digitalRead(i3);


//I want a code here that maps the variables received to corresponding cases
//for ex if the read input is 0100 on the four pins i want the "case 3" to be activated
//
//
//
//

 switch (range) 
 {
  case 0:    // Do something
    break;
  case 1:    // Do something
    break;
  case 2:    // Do something
    break;
  case 3:    // Do something
    break;
    
    //...
    //...
    //..
    //..
  case 12:    // Do something
    break;
    
  } 

}

void loop() 
{

}

This is the code i could come up with,. Any help would be greatly appreciated..

If there is only one BCD digit why not use the BCD values directly in the SWITCH statement?

If there is more than one BCD digit (eg two digits of 0010 and 0011 representing decimal 23) then just multiply them out by powers of ten and add them together. EG 0010 * decimal 10 + 0011.

If it is BCD how can the highest value be 1100 which is 12?

...R

Reading bits on a port: http://arduino.cc/en/Reference/PortManipulation#.Uy8Y-PLnbcc Masking bits: http://playground.arduino.cc/Code/BitMath#.Uy8ZZvLnbcc Switch case: http://arduino.cc/en/Reference/SwitchCase#.Uy8ZwfLnbcc Here is a start:

unsigned char var;
void setup()
{
  pinMode(8,INPUT_PULLUP);
  pinMode(9,INPUT_PULLUP);
  pinMode(10,INPUT_PULLUP);
  pinMode(11,INPUT_PULLUP);
  Serial.begin(9600);
}

void loop()
{
  var = PINB & 0b00001111;  // read bits 8 thru 13 and mask the top 4 bits
  Serial.println(var,BIN);
  delay(500); //slow things down a bit

  switch (var)
  {
  case 0:
  Serial.println("input is 0");
    break;
  case 1:
  Serial.println("input is 1");
    break;
   case 2: 
  Serial.println("input is 2");
    break;
  case 3:
  Serial.println("input is 3");
    break;
//etc.
  case 15:
  Serial.println("input is 15");
  break;
  
  default: 
    // if nothing else matches, do the default
    // default is optional
  break;
  }
}

EDIT: PIND maps to Arduino digital pins 0 to 7 (UNO)

vijayrex: Is there anyway i can group the variables in one "long" variable?

You can access individual bits within a variable, and Arduino provides the bitWrite() convenience function to simplify this. If you wanted, it would be easy to put your digital input states into an array and use a FOR loop to read each element in the array and set the corresponding bit in a result variable. Since you only have four inputs, you would only need a byte variable to hold the result, although you could use a larger variable if you want to. In any case, you could then use a switch case statement to handle each resulting value. If each unique combination of input states corresponded to a different command, this would be a reasonable way to handle them.

You can check out this post of mine on a 4x4 keypad interface using a BCDA output 74c922 chip. It shows how I did the code using an Interrupt and how I read the code. The IDE program file is attached . http://forum.arduino.cc/index.php?topic=211548.0

This works for plain binary, which is what you appear to be using, but not BCD.

value = 0;
value = value + (digitalRead(pin8));  //Most significant bit
value = (value*2) + (digitalRead(pin7));  
value = (value*2) + (digitalRead(pin6));  
value = (value*2) + (digitalRead(pin5));   //Least significant bit

Value will hold a number 0 to 15 or, in your case, 0 to 12.

Thanks for the amazing ideas...

Robin2 Its not actually a BCD, i am its binary numbers from 0000 to 1100 that's the only range i need because there are only 12 control inputs

LarryD Thanks for the code, now i got a general idea.. You're a genius... If i want to run this code only once, can i put all the contents of "voidLoop" in "voidsetup"?

PeterH Array idea is great, I wonder why i didn't think about it.

Henry_best I wonder if i can use your code in "LarryD" code where we acquire inputs.

Setup is ok

Edit: Crossroads is the teacher.

Thank you very much,. I will post the results soon..

Here’s a couple of other versions of the keypad code. One uses PIND (Port D input), the other uses CASE. You have to substitute
your own values in the array if they are different from the ones I used. The way that works is it reads the port and shifts it because
the pins I was using were offset from a normal PIND read. then, based on the value read, the corresponding result would be read from the array. That allows you to redefine any key to be any value. The case is a little different.You would probably have to modify that a little to . It’s too complicated to explain why I used those values. I present it only for it’s value as an example of that format.

Matrix_4x4_16_key_encoder_LCD_CASE_ok.ino (4.96 KB)

Matrix_4x4_16_key_kypd_to_74c922_encoder_ic_PIND_ARRAY_PORTD.ino (1.13 KB)

vijayrex: Its not actually a BCD, i am its binary numbers from 0000 to 1100 that's the only range i need because there are only 12 control inputs

I humbly apologize for wasting my time.

How about a more accurate title next time ?

...R

LarryD Thank you very much,. The code works great. I just have a silly doubt. Just incase if i have to use the last four digits instead of var = PINB & 0b00001111; Here we are masking the ports B4, B5, B6, B7 what if i want to mask the lower Bits B0, B1, B2, B3 and use the input from top four bits.

I am just curious to know if there is a way var = PINB & 0b11110000; or just changing the code to this will work?

Also if i want to introduce a Delay of 5 hours in one of the cases can i use (18000000) in the delay. I don't mind the arduino waiting in the delay code.

Robin, I am really sorry for wasting your time.. :disappointed_relieved:

The good thing about software is you can test things out for yourself. Note: the top bits (6,7) of PORTB, UNO, are not connected to i/o pins. PORTB bit 0 is connected to UNO pin 8 while bit 5 is connected to pin 13. So if you what to use the top 4 "Pins" this is bits 2, 3, 4 and 5. Bits 6 and 7 are not usable. val = PINB & 0b11000011; For this example, switch case changes, you need to be looking at: 4,8,12,16,20,24,28,32,36,40 etc. 60 for the 16 possible combinations.

18000000UL I've got in the habit of adding UL to things that need to be unsigned long.

Edit: Learn to make delays with the millis() function.