Switching between 3 sections of code using rotary switch and digital inputs

Im using my 6 analog inputs from my Arduino Uno already in my project. what is the most efficient way to go about jumping back and forth between 3 small sections of code inside the void loop using digital pins and a rotary 3 position switch.

Basically my code loops an equation and its output is based on an analog input. Im trying to implement where I turn the rotary switch it will change to a slightly different equation but continue on with the majority of the code until I turn it back or to a different position( a different position being a slightly different altered equation).

I want to try and figure it out on my own before posting code but my previous attempts havent been working out. Im just looking for a basic direction as of now.

I couldn't quite figure out how to set up a case statement using 3 different digital pin inputs as the variable.

Is there a different method that I should research? Or am I on the right track?

any help is appreciated.

Maybe not a case for the case statement 8) but if rather?

I'd try something like this. Pull the digital pins high with the internal pullups. Then pull the selected one to ground with the switch and your if block checks to see which if any is low.

JimboZA: Maybe not a case for the case statement 8) but if rather?

I'd try something like this. Pull the digital pins high with the internal pullups. Then pull the selected one to ground with the switch and your if block checks to see which if any is low.

This is exactly what I was looking for thank you! Would this be set up as an if, else if, else

or three ifs (one for each pin high state)

I was thinking if, else if, else. (Provided you can guarantee one of the 3 positions is switched in..... If there's any chance that none of the digital pins is selected, then you you would need to cover that with a fourth option: if (pinA is on), else if (pinB is on), else if (pinC is on), else (none is on.))

Separate ifs would work, but the else if thing is there to make the coding simpler.

one of the switches will always be on. so if, else if, else it is.

Ill give this a go and see if it checks out

Don't forget the pullups, either enabled in code or with external ones. Without them you'll have floating pins of no known state...

Switch:case will work fine also.

void loop(){
:
:
:
// code variation time
// read three inputs
selection = PORTD & B00111000; // read port D, bits 3,4,5 for example.  1 of them will always be in this example
switch (selection){
case 1:
// code
break;
case 2:
// code
break;
case 4:
// code
break;
}
// back to normal processing
:
:

change the case numbers to 3 (011), 5 (101) , 6 (110) it the switch will pull an input low instead.

rperez88: one of the switches will always be on.

If it's a make-before-break type then one will always be "on", but during a change two are. If it's a break-before-make type then none is "on" between a change.

[quote author=Runaway Pancake link=topic=164448.msg1228359#msg1228359 date=1367684450]

rperez88: one of the switches will always be on.

If it's a make-before-break type then one will always be "on", but during a change two are. If it's a break-before-make type then none is "on" between a change. [/quote]

Good point, being a selector switch it's a break before make? There will be brief moment when none of the switches are on if I understand you correctly.

CrossRoads: Switch:case will work fine also.

void loop(){
:
:
:
// code variation time
// read three inputs
selection = PORTD & B00111000; // read port D, bits 3,4,5 for example.  1 of them will always be in this example
switch (selection){
case 1:
// code
break;
case 2:
// code
break;
case 4:
// code
break;
}
// back to normal processing
:
:

change the case numbers to 3 (011), 5 (101) , 6 (110) it the switch will pull an input low instead.

Is port D which ever digital pin im using as the input? You code comments say bits 3,4,5 but after your code in the text you say to change case 3,5, and 6. Sorry, just want to make sure i have a handle on everything your saying.

Can i take three slightly altered versions of my void loop and put them in 3 different cases? if so, do I need to put the function definitions in each case as well? or leave them at the bottom after the entire case statement?

Here is the mapping from the Ports/bits to their software names: PORTD is D7,D6,D5,D4,D3,D2,D1,D0. PORTB is not connected, not connected, D13,D12,D11,D10,D9,D8 PORTC is not connected, not connected, D19,D18,D17,D16,D15,D14 (or A5,A4,A3,A2,A1,A0)

You can use port manipulation to read the whole port at one time, or use digitalRead(D5), digitalRead(D4), digitalRead(D3) to read them one at a time.

I realize as I type this up that my case #s are not correct: They should be: xx001xxx xx010xxx xx100xxx the x's are forced to be 0 by the & statement: selection = PORTD & B00111000;

if we shift that right 3 bits, the case statement are correct: selection = (PORTD & B00111000) >>3;

so now reading the threes switches will result in 3 bits of non-zero data, with 1 always high, or 1 always low, and the case numbers will result in: xxxxx001 = 1 with only 1 high xxxxx010 = 2 xxxxx100 = 4

or xxxxx110 = 6 with only 1 low xxxxx101 = 5 xxxxx011 = 3

with x always being 0, but shown as x here to make it clear where the good data is.

You have differentiate between the digital pins and the software result.

Regarding the make before break, or make after break, that may result in the switches reading back something other than 1 of the conditions above - you can add a test for that, and use the previous valid condition again until a new valid condition is read.

CrossRoads: Here is the mapping from the Ports/bits to their software names: PORTD is D7,D6,D5,D4,D3,D2,D1,D0. PORTB is not connected, not connected, D13,D12,D11,D10,D9,D8 PORTC is not connected, not connected, D19,D18,D17,D16,D15,D14 (or A5,A4,A3,A2,A1,A0)

You can use port manipulation to read the whole port at one time, or use digitalRead(D5), digitalRead(D4), digitalRead(D3) to read them one at a time.

I realize as I type this up that my case #s are not correct: They should be: xx001xxx xx010xxx xx100xxx the x's are forced to be 0 by the & statement: selection = PORTD & B00111000;

if we shift that right 3 bits, the case statement are correct: selection = (PORTD & B00111000) >>3;

so now reading the threes switches will result in 3 bits of non-zero data, with 1 always high, or 1 always low, and the case numbers will result in: xxxxx001 = 1 with only 1 high xxxxx010 = 2 xxxxx100 = 4

or xxxxx110 = 6 with only 1 low xxxxx101 = 5 xxxxx011 = 3

with x always being 0, but shown as x here to make it clear where the good data is.

You have differentiate between the digital pins and the software result.

Regarding the make before break, or make after break, that may result in the switches reading back something other than 1 of the conditions above - you can add a test for that, and use the previous valid condition again until a new valid condition is read.

So if im using this:

if we shift that right 3 bits, the case statement are correct:
selection = (PORTD & B00111000) >>3;

so now reading the threes switches will result in 3 bits of non-zero data, with 1 always high, or 1 always low, and the case numbers will result in:
xxxxx001 = 1  with only 1 high
xxxxx010 = 2
xxxxx100 = 4

My rotary switch inputs would be D0,D1, and D2?

why wouldn't I just do: selection = (PORTD && B00000111)? why do I need to bit shift?

Can i take three slightly altered versions of my void loop and put them in 3 different cases? if so, do I need to put the function definitions in each case as well? or leave them at the bottom after the entire case statement?

Sure, you could use D0,D1,D2 - except D0, D1 are the serial interface. I try to keep them free.

You could make 3 versions of your code and decide which to run. The advantage of your original idea is that you don't need to make the same change in 3 places whenever you decide to make a change. Function definitions do not go in void loop, so you don't need 3 copies of that code.

rperez88: Good point, being a selector switch it's a break before make? There will be brief moment when none of the switches are on if I understand you correctly.

They manufacture both. (Which you have, I don't know.)

For selecting a resistor in a LM317, if it went open-circuit (BBM) then the output would hop to max and zap anything connected to it. When two positions short (MBB) then the output would dip, in transition, before settling at the new position.

CrossRoads: Sure, you could use D0,D1,D2 - except D0, D1 are the serial interface. I try to keep them free.

You could make 3 versions of your code and decide which to run. The advantage of your original idea is that you don't need to make the same change in 3 places whenever you decide to make a change. Function definitions do not go in void loop, so you don't need 3 copies of that code.

o ok ya ill need D0 and D1 free because im actually using Tx for midi data transfer. So if i used D2,D3,D4...it would be something like:

selection = (PORTD && B00011100)?
switch (selection){
case 001:
// original void loop
break;
case 010:
// slightly altered void loop
break;
case 100:
// slightly altered in a different way void loop
break;
case default:
//blank

}

as far as testing for a valid condition, if I left the default case blank that should handle mis readings as the switch is transitioning from One state to the other right?

If you don't shift the bits over, the cases will be: B00000100, or 4 decimal, or 0x40 B00001000, or 8 decimal, or 0x10 B00010000, or 16 decimal, or 0x20

All will work case B00000100: case 0x40: case 4:

I don't know what would happen to the rest of your code if there was no valid case and no code executed. You'd have to take that into account.

CrossRoads: If you don't shift the bits over, the cases will be: B00000100, or 4 decimal, or 0x40 B00001000, or 8 decimal, or 0x10 B00010000, or 16 decimal, or 0x20

All will work case B00000100: case 0x40: case 4:

I don't know what would happen to the rest of your code if there was no valid case and no code executed. You'd have to take that into account.

ok that makes sense. I still dont understand why I should shift the bits over though? why couldn't I just use case 4, 8, and 16 ?

You could.

CrossRoads: You could.

Ok then I will. I just wasn't sure if I was missing something else that I wasn't understanding

Ive attempted to implement this with my code and im getting no output what so ever. It complies, so im not quite sure where the issue is. My only guess is that int selection is holding Tx low (which i am using for my midi output)
My rotary switch is connected directly to pins D2, D4, and D8. and also from the switch is GND going to the rest of my circuit.

should I be using resistors in series with my switch going to the pins?

//playNote = 0x90,stopNote = 0x80,velocity = 0x50;
/*801,761,716,666,609,545,475,399,320,238,156,76*/
const int AF[12] = {780,740,700,655,595,520,455,370,280,210,130,50} ;
const int analogPins[6] = {A0, A1, A2, A3, A4, A5};
int analogString[6] = {1023, 1023, 1023, 1023, 1023, 1023}; // [E, A, D, G, B, e] stores values 0 - 1023 bits
int midiNotesOut[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; //Midi notes that will be played
int prevNotesOut[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; //Notes from previous round
int marker[6] = {0, 0, 0, 0, 0, 0};
int selection;

#include <MIDI.h>

void setup(){
MIDI.begin();
int x;
MIDIOutput( 0x80, midiNotesOut[x], 0x50);//silence
}

void loop(){
  selection = PORTD && B00001110;
  switch (selection){
    case 4:
delayMicroseconds(10);
for(int x = 0; x < 6; x++){
int temp = 0;
prevNotesOut[x] = midiNotesOut[x];
for( int ave = 0; ave < 30; ave++){
analogString[x] = analogRead(x); 
temp = temp+analogString[x];
}
analogString[x] = temp/30;

if(analogString[x] < 830){
  
for( int y = 0; y < 12; y++){ //find the fret position
if(analogString[x] > AF[y]){
midiNotesOut[x] = 0x35 + y + (x*5);// equation for midi note strings E,A,D,G
if(x == 4 || x== 5) midiNotesOut[x] -= 1; //equation for midi note strings B,e
y = 12; // Break out of the loop
marker[x] = 1;
}//if statement note equation
}//inner for
}else if(analogString[x] > 850){/*if string value is more than 850 it probably isnt
                                  being pressed*/
  
if ((marker[x] == 1)){
MIDIOutput( 0x80, midiNotesOut[x], 0x00);//this turns all notes off
marker[x] = 0;
}
midiNotesOut[x] = 0x00;

}

if((prevNotesOut[x] != midiNotesOut[x]) && (midiNotesOut[x] != 0x00)){
if(prevNotesOut[x] != 0x00){
MIDIOutput( 0x80, prevNotesOut[x], 0x00);
}
MIDIOutput( 0x90, midiNotesOut[x], 0x50);
}
}//first for loop closing bracket
break;
//void loop closing bracket


case 8:
delayMicroseconds(10);
for(int x = 0; x < 6; x++){
int temp = 0;
prevNotesOut[x] = midiNotesOut[x];
for( int ave = 0; ave < 30; ave++){
analogString[x] = analogRead(x); 
temp = temp+analogString[x];
}
analogString[x] = temp/30;

if(analogString[x] < 830){
  
for( int y = 0; y < 12; y++){ //find the fret position
if(analogString[x] > AF[y]){
midiNotesOut[x] = 0x29 + y + (x*5);// equation for midi note strings E,A,D,G
if(x == 4 || x== 5) midiNotesOut[x] -= 1; //equation for midi note strings B,e
y = 12; // Break out of the loop
marker[x] = 1;
}//if statement note equation
}//inner for
}else if(analogString[x] > 850){/*if string value is more than 850 it probably isnt
                                  being pressed*/
  
if ((marker[x] == 1)){
MIDIOutput( 0x80, midiNotesOut[x], 0x00);//this turns all notes off
marker[x] = 0;
}
midiNotesOut[x] = 0x00;

}

if((prevNotesOut[x] != midiNotesOut[x]) && (midiNotesOut[x] != 0x00)){
if(prevNotesOut[x] != 0x00){
MIDIOutput( 0x80, prevNotesOut[x], 0x00);
}
MIDIOutput( 0x90, midiNotesOut[x], 0x50);
}
}//first for loop closing bracket
//void loop closing bracket

case 16:
delayMicroseconds(10);
for(int x = 0; x < 6; x++){
int temp = 0;
prevNotesOut[x] = midiNotesOut[x];
for( int ave = 0; ave < 30; ave++){
analogString[x] = analogRead(x); 
temp = temp+analogString[x];
}
analogString[x] = temp/30;

if(analogString[x] < 830){
  
for( int y = 0; y < 12; y++){ //find the fret position
if(analogString[x] > AF[y]){
midiNotesOut[x] = 0x41 + y + (x*5);// equation for midi note strings E,A,D,G
if(x == 4 || x== 5) midiNotesOut[x] -= 1; //equation for midi note strings B,e
y = 12; // Break out of the loop
marker[x] = 1;
}//if statement note equation
}//inner for
}else if(analogString[x] > 850){/*if string value is more than 850 it probably isnt
                                  being pressed*/
  
if ((marker[x] == 1)){
MIDIOutput( 0x80, midiNotesOut[x], 0x00);//this turns all notes off
marker[x] = 0;
}
midiNotesOut[x] = 0x00;

}

if((prevNotesOut[x] != midiNotesOut[x]) && (midiNotesOut[x] != 0x00)){
if(prevNotesOut[x] != 0x00){
MIDIOutput( 0x80, prevNotesOut[x], 0x00);
}
MIDIOutput( 0x90, midiNotesOut[x], 0x50);
}
}//first for loop closing bracket
//void loop closing bracket
default:

//empty

break;
  }}
  
void MIDIOutput( int command, int note, int velocity){
  Serial.write(command);
  Serial.write(note);
  Serial.write(velocity);
}