Switch combo with COM input [switch (inByte) / case ]

Wasn't sure how to title this =P

In this project I am trying to accomplish turning on a LED with a switch and being able to send a switch case through the COM port to effect the same LED.

Switch (http://www.arduino.cc/en/tutorial/switch): Works great. It can detect if the "int inPin" is already high or low and do the opposite with a switch press.

I would like to add something like:

void loop() { 
  // read the IO: 
  if (Serial.available() > 0) { 
    int inByte = Serial.read(); 
 
    int speed; // Local variable 
    for (int thisPin = 2; thisPin < 11; thisPin++) {
    pinMode(thisPin, OUTPUT);
 
      switch (inByte) { 
   
//Pins 13 - LED 
 
    case '1': //Press 1 to do something   
      digitalWrite(13, HIGH); // Turns on Lights
      break;

But for the:

switch (inByte) { 

case '1': //Press 1 to do something   
      digitalWrite(13, HIGH); // Turns on Lights
      break;

I would like the same outcome like Switch has (detect if "int inPin" is already high or low and do the opposite:

case '1': //Press 1 to do something   
      digitalWrite(13)

f (reading == HIGH && previous == LOW && millis() - time > debounce) {
    if (state == HIGH)
      state = LOW;
    else
      state = HIGH;

    time = millis();

Not sure how to accomplish this, testing thus far has not worked.
Here is the full code I am using for controlling the "switch (inByte) cases"

void setup() { 
Serial.begin(9600); // Setup Serial library at 9600 bps 
} 
 
void loop() { 
  // read the IO: 
  if (Serial.available() > 0) { 
    int inByte = Serial.read(); 
 
    int speed; // Local variable 
    for (int thisPin = 9; thisPin < 11; thisPin++) {
    pinMode(thisPin, OUTPUT);
 
      switch (inByte) { 
   
//Pins 9 - Lights 
 
    case '1':    
      digitalWrite(9, HIGH); // Turns on Lights
      break;

    case '2':    
      digitalWrite(9, LOW); // Turns off Lights
      break;
 
    default: 
      // turn all the connections off: 
      for (int thisPin = 9; thisPin < 11; thisPin++) { 
        digitalWrite(thisPin, LOW); 
        } 
      } 
    } 
  } 
}

Thank you in advance for the help!
-Enigmacypher7

Sorry, I was giving the arduino "Switch" code as a reference but didn't past it to save room:

It has the int pin already in it.

/* switch
 * 
 * Each time the input pin goes from LOW to HIGH (e.g. because of a push-button
 * press), the output pin is toggled from LOW to HIGH or HIGH to LOW.  There's
 * a minimum delay between toggles to debounce the circuit (i.e. to ignore
 * noise).  
 *
 * David A. Mellis
 * 21 November 2006
 */

int inPin = 2;         // the number of the input pin
int outPin = 13;       // the number of the output pin

int state = HIGH;      // the current state of the output pin
int reading;           // the current reading from the input pin
int previous = LOW;    // the previous reading from the input pin

// the follow variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long time = 0;         // the last time the output pin was toggled
long debounce = 200;   // the debounce time, increase if the output flickers

void setup()
{
  pinMode(inPin, INPUT);
  pinMode(outPin, OUTPUT);
}

void loop()
{
  reading = digitalRead(inPin);

  // if the input just went from LOW and HIGH and we've waited long enough
  // to ignore any noise on the circuit, toggle the output pin and remember
  // the time
  if (reading == HIGH && previous == LOW && millis() - time > debounce) {
    if (state == HIGH)
      state = LOW;
    else
      state = HIGH;

    time = millis();    
  }

  digitalWrite(outPin, state);

  previous = reading;
}

After figuring out how to use my code to detect the pin state, I would like to incorporate it into the "Switch" code above. My code currently will cut a LED off/on by pressing 1 or 2 on the keyboard through a serial program like Putty.

Hope this paints a more accurate picture.

Fair enough. There are two things I need to accomplish my goal.

I am working on the first part right now and just resetup my test.

I need a way for the following code to be able to detect the current state of the selected pin and do the opposite when a keyboard press is sent to the arduino.

This is my default code. If you press "1" the pin (9) will go High and light the LED. If "2" is pressed the LED will turn off as the pin (9) has gone low.

I need to modify this to be able to have the same button on a keyboard pressed to drive the pin High or Low depending on what it is currently set at. Something to the tune of "if pin (9) high, set low and vice versa.)

Desired outcome would be much in the way of how the "Switch code" works with a physical switch.

void setup() { 
Serial.begin(9600); // Setup Serial library at 9600 bps 
} 
 
void loop() { 
  // read the IO: 
  if (Serial.available() > 0) { 
    int inByte = Serial.read(); 
 
    int speed; // Local variable 
    for (int thisPin = 9; thisPin < 11; thisPin++) {
    pinMode(thisPin, OUTPUT);
 
      switch (inByte) { 
   
//Pin 9 - LED 
 
    case '1':    
      digitalWrite(9, HIGH); // Turns on LED
      break;

    case '2':    
      digitalWrite(9, LOW); // Turns off LED
      break;
 
    default: 
      // turn all the connections off: 
      for (int thisPin = 9; thisPin < 11; thisPin++) { 
        digitalWrite(thisPin, LOW); 
        } 
      } 
    } 
  } 
}

Yes, the opposite of the current pin stats; if Low make high. If high, make low.

--

Keyboard presses are as easy as defining them as switch cases:

case '1': will listen for the "1" key
or
case 'k': would listen for the "k" key.

digitalWrite(9, HIGH); would currently make Pin 9 go high and turn the LED on.
digitalWrite(9, LOW); Makes the LED turn off.

Neat and simple huh?

--

The final button could be any button. We can call that "k" if you would like. It would drive pin 9.

switch (inByte) {

// Turn LED on or OFF with key press

case 'k':

digitalWrite(9, Detect current state some how, do opposite. (if high make low / if low make high)

I am not sure if and how much timing would be needed. keyboard presses have never had a timing issue (integer flood issue) before. But might end up needing timing so that the LED does not flash or flicker if the key is held down too long. (Usually repeated HIGH or LOW commands do not have an effect since the LED would already be ON or OFF) Yeah after typing that out and thinking about it, timing might be a good idea.

This will be the next part, it will be necessary but not yet. Lets work through this COM control with the keyboard presses first =)

"All that other jazz in the example you posted is all about responding to the state change on the input pin."

Specifics on timing:

Press "k" light comes on -- if "k" is held the code will wait 15000 ms (15 seconds) until it will send another "k" this would keep a key being held from making the LED flicker. It would however make it turn on and off every 15 seconds, lol. 15 seconds is acceptable.

digitalWrite(9, Detect current state some how, do opposite. (if high make low / if low make high)
digitalWrite(9, !digitalRead(9));

or hold the current pin state in a variable and do

pinState = !pinState;
digitalWrite(9, pinState);

Delta_G,
Calm down. I got the

digitalWrite(13, !digitalRead(13));

That's great and I thank you for that answer...

You kept making me repeat my questions so I elaborated.

After the:

digitalWrite(13, !digitalRead(13));

You asked about timing

That example code you showed, it also has some timing involved. Do you need the timing? How should that work?

I had moved on to timing to keep the LED from flashing... something I hadn't put a lot of thought into but is a really good idea. I just added to to my first what if long English example. I was not ignoring your code.

For the last F-ing time and then you're on your own. What pin?

Dude, the pin the LED is on. We already covered this and I was pretty sure you knew what I was asking due to your example. I apologize for the communication mix up.

UKHeliBob - Much appreciated both of your examples were exactly what I came to the forum to find in the first place.

I am only trying to effect pin 9.

I didn't actually get the code to work.

digitalWrite(13, !digitalRead(13));

The LED turns on with the press of the "1" key (LED connected to arduino Pin 9) but never turns off with the next push of the "1" key.

void setup() { 
Serial.begin(9600); // Setup Serial library at 9600 bps 
} 
 
void loop() { 
  // read the IO: 
  if (Serial.available() > 0) { 
    int inByte = Serial.read(); 
 
 
    int speed; // Local variable 
    for (int thisPin = 2; thisPin < 11; thisPin++) {
    pinMode(thisPin, OUTPUT);
 
      switch (inByte) { 
   
//Pin 9 - LED 
 
    case '1':
      digitalWrite(9, !digitalRead(9));
      break;
        } 
      } 
    } 
  }
    for (int thisPin = 2; thisPin < 11; thisPin++) {
    pinMode(thisPin, OUTPUT);

Why are you setting the mode of the pins in loop()? The mode should be set ONCE, in setup().

Why is the switch statement embedded in the for loop?

The code worked the way it is written.

Well before I changed:

 case '1':    
      digitalWrite(9, HIGH); // Turns on LED
      break;

    case '2':    
      digitalWrite(9, LOW); // Turns off LED
      break;

To the following:

digitalWrite(9, !digitalRead(9));

How should it actually be?

Guys, I only want to be able to turn the LED (Pin 9) on and off with the same button on a keyboard (Key doesn't matter, it has been "1" in the examples). Maybe have a little bit of a wait time to make sure that the LED does not blink on and off if the key is accidentally held down too long. Not sure how this got so blown up.

I'm not sure why you have a for loop in loop(). It isn't necessary. Get rid of it. I think it is what is causing the problem. On one iteration of the loop, you turn the pin on (or off). Then, on the next iteration, you reverse it. That makes no sense. The pin should change state ONLY ONCE, when there is input from the serial port.

Hi!
I've read the posts and I made the code below for inverting LED (Pin 9) state after pressing '1'. It's quite simple but I think it's what you want.

void setup() {
  pinMode(9,OUTPUT);
  digitalWrite(9,LOW);
  Serial.begin(115200);
  Serial.println("Reading now...");
  Serial.println("Press 1 to invert LED (Pin 9) state.");
}

void loop() {
  
  if(Serial.available() > 0){

    byte inByte = Serial.read(); //Read the Serial and return the first byte.
    
    switch(inByte){
      case '1':
        Serial.println("Inverting LED (Pin 9) state");
        digitalWrite(9, !digitalRead(9));
        break;
      default:
        Serial.println("Nothing to do");
        break;
    }
    Serial.read(); //Clear Serial incoming buffer
  }
}

giova014, Thank you.
Your code, which is were my code was heading after puling out the "for loop in loop()" that Paul suggested.

PaulS,

If I pull out the first

 for (int thisPin = 2; thisPin < 11; thisPin++) {
    pinMode(thisPin, OUTPUT);

Then the code does nothing to the LED on Pin 9. Only the boards RX light blinks.

Puling out the 2nd:

    for (int thisPin = 2; thisPin < 11; thisPin++) {
    pinMode(thisPin, OUTPUT);

Doesn't break anything. Actually that was there originally to have the pins go low if any other keyboard key was pressed that was not defined in the code. It is now unnecessary.

I figured I probably pulled out too much of the code from the 1st part.

I have tried killing variations of the whole 2 lines and "for (int thisPin = 2; thisPin < 11; thisPin++) {" along with the "thisPin" in pinMode(thisPin, OUTPUT);

You modified the code. It still doesn't work. You want us to guess what you did?

Sorry, I'll paste a few examples.

Removing the:

    default: 
      // turn all the connections off: 
      for (int thisPin = 9; thisPin < 11; thisPin++) { 
        digitalWrite(thisPin, LOW)

And having just:

void setup() { 
Serial.begin(9600); // Setup Serial library at 9600 bps 
} 
 
void loop() { 
  // read the IO: 
  if (Serial.available() > 0) { 
    int inByte = Serial.read(); 
 
    int speed; // Local variable 
    for (int thisPin = 9; thisPin < 11; thisPin++) {
    pinMode(thisPin, OUTPUT);
 
      switch (inByte) { 
   
//Pins 9 - LED 
 
    case '1':    
      digitalWrite(9, HIGH); // Turns on LED
      break;

    case '2':    
      digitalWrite(9, LOW); // Turns off LED
      break;

        } 
      } 
    } 
  }

Happily works.

However the following does not:

void setup() { 
Serial.begin(9600); // Setup Serial library at 9600 bps 
} 
 
void loop() { 
  // read the IO: 
  if (Serial.available() > 0) { 
    int inByte = Serial.read(); 
 
    int speed; // Local variable 
    pinMode(OUTPUT);
 
      switch (inByte) { 
   
//Pins 9 - LED 
 
    case '1':    
      digitalWrite(9, HIGH); // Turns on LED
      break;

    case '2':    
      digitalWrite(9, LOW); // Turns off LED
      break;

        } 
      } 
    } 
  }

I know something has to be written there or else the commands will not output to the board pins.

I know something has to be written there or else the commands will not output to the board pins.

You need to post ALL of your code. You need to assign the mode of the pins. It is not clear that you are doing that, since setup() is missing in the "code that doesn't work". We could theorize that it doesn't work because you are diddling with the pullup resistor on an input pin.

It does NOT make sense to have the switch statement INSIDE the for loop. There is no reason to turn a specific pin on or off multiple times. ONCE is enough.

Lets just theorize for a second that I really suck at this...

Setup is in the top of the code that I pasted:

void setup() {
Serial.begin(9600); // Setup Serial library at 9600 bps

It does NOT make sense to have the switch statement INSIDE the for loop. There is no reason to turn a specific pin on or off multiple times. ONCE is enough.

Are you saying that

switch (inByte) {

Should be before:

void loop() {

If I move switch (inByte) { before the void loop() { I get the following error:
sketch_apr12a.ino: In function 'void setup()':
sketch_apr12a:3: error: 'inByte' was not declared in this scope

Are you saying that

No. There is a tremendous difference between "the for loop" and "the loop() function".

Well now that it's fixed.

int LED_1 = 9;
#define PIN_ON 0
#define PIN_OFF 1 
   
void setup() { 
Serial.begin(9600); // Setup Serial library at 9600 bps 
pinMode(LED_1, OUTPUT);
digitalWrite(LED_1, PIN_OFF);
} 
 
void loop() { 
  // read the IO: 
  if (Serial.available() > 0) { 
    int inByte = Serial.read(); 
 
      switch (inByte) { 
   
//Pin 9 - LED
 
    case '1':    
      digitalWrite(9, !digitalRead(9)); // Turns on LED
      break;

        } 
      } 
    }

It will now turn on and off with the same key press.

I was having an issue where the LED would come on when the board was reset or plugged into the USB. So upon doing some research and pulling apart examples, I came up with the:

#define PIN_ON 0
#define PIN_OFF 1

And:

digitalWrite(LED_1, PIN_OFF);

To keep the LED off by default. I also now understand the difference between the Setup and Loop functions.

... Off to play around with adding a physical switch in addition to the "keyboard switch".

Nope, testing... It looks like I forgot that delay so that if the key is held down it doesn't make the LED flicker off and on in rapid succession. I am looking at "Debounce" but I am not sure that is really what I am looking for. Is there another way to stop the flickering if the key is held down. Debounce uses a timer, but I would like to able to press as fast as I want, as long as the key has been let go of before the command is resent.

Something in the neighborhood of; do not resend command until key "1" is let go of and repressed..

Does that make sense?

Something in the neighborhood of; do not resend command until key "1" is let go of and repressed

You need to detect when the key becomes pressed, note when it is pressed. Look at the StateChangeDetection example in the IDE to see how it is done.