TransWikia.com

using a switch case with a 5-position switch and serial output

Arduino Asked by Au42 on September 25, 2021

I’m trying to get started on developing a menu system for my LCD1602. I have a Parallax 5-position switch (up,down,left,right,center) and I would like to interface the two.

I’ve been trying to get some code working but I’m kind of lost. I don’t have a lot of recent experience with Arduino and could use some advice. I realize that there is a version of the 1602 that comes with a keypad integrated into the circuit but I don’t have that model. I have a plain-jane screen and a separate 5-position switch.

I’m also aware that the easiest way to accomplish what I desire is with a resistor network and mapping the ADC values. However, I don’t want to make an analog switch, I want to make a digital switch.

Is there any way I can take the pins and put them into an array and then translate that into a switch case statement?

I’ve tried several different ideas and nothing seems to be working. Forgive the example code, it’s hacked together.

below is my code

*/

// constants won't change. They're used here to set pin numbers:
char buttonChar1 = 'a';     // the number of the pushbutton pin
const int buttonPin1 = 2;
const int buttonPin2 = 3;
const int buttonPin3 = 4;
const int buttonPin4 = 5;
const int buttonPin5 = 6;
const int ledPin =  13;      // the number of the LED pin

// variables will change:
int buttonState1 = 0; // variable for reading the pushbutton status
int buttonState2 = 0;
int buttonState3 = 0;
int buttonState4 = 0;
int buttonState5 = 0;
int pinsArray[5] = {2, 3, 4, 5, 6};
void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(buttonPin3, INPUT);
  pinMode(buttonPin4, INPUT);
  pinMode(buttonPin5, INPUT);
}

void loop() {
  // read the state of the pushbutton value:
  buttonState1 = digitalRead(buttonPin1) == 2;
  buttonState2 = digitalRead(buttonPin2) == 3;
  buttonState3 = digitalRead(buttonPin3) == 4;
  buttonState4 = digitalRead(buttonPin4) == 5;
  buttonState5 = digitalRead(buttonPin5) == 6;
  // check if the pushbutton is pressed. If it is, the buttonState is HIGH:

  switch (pinsArray[5]) {
    case 2:    // 
      digitalWrite(ledPin, HIGH);
      Serial.println("button1");
      break;
    case 3:     // 
      digitalWrite(ledPin, HIGH);
      Serial.println("dim");
      break;
    case 4:    // 
      Serial.println("medium");
      break;
    case 5:    //
      Serial.println("bright");
      break;
  }
  }

3 Answers

When you want to perform actions in response to button presses, you should take care of reacting to the signal edges rather than levels. In other words, you perform the action only when the signal changes from LOW to HIGH, not every time you see it HIGH.

You should also read about button bounce, and either implement your own debouncing or use an existing library. Below is an example using Bounce2, but there are other options:

#include <Bounce2.h>

const uint8_t pinDim    = 3;
const uint8_t pinMedium = 4;
const uint8_t pinBright = 5;

Bounce buttonDim, buttonMedium, buttonBright;

void setup() {
    buttonDim.attach(pinDim, INPUT);
    buttonMedium.attach(pinMedium, INPUT);
    buttonBright.attach(pinBright, INPUT);
}

void loop() {
    buttonDim.update();
    buttonMedium.update();
    buttonBright.update();

    if (buttonDim.rose()) {
        Serial.println("dim");
    }
    if (buttonMedium.rose()) {
        Serial.println("Medium");
    }
    if (buttonBright.rose()) {
        Serial.println("bright");
    }
}

You could also, as suggested in Michel Keijzers' answer, use arrays for the pins and Bounce objects. While these would help streamline the calls to attach() and update(), they will not help with the meaty part of the code, i.e. reacting to the presses. There, I would prefer the button to have descriptive names.

Answered by Edgar Bonet on September 25, 2021

Michael has already given you some excellent advice on how to clean up your code.

Your switch statement does not make much sense. You're switching based on an out-of-range index into an array of constants.

Once you've read the states of all your buttons as outlined by Michael, your loop needs to decide what to do about the state of each switch.

Is this a joystick style switch, where the user can only engage one direction at a time? Or is it possible to press 2 switches at once?

If it's a diamond arrangement of 5 switches with a switch in the middle, the user could press any combination of switches at the same time.

I'd suggest code like this:

void loop() {
    if buttonStates[0] == HIGH {
       //code to handle button 0 (pin 2) being pressed
    }

    if buttonStates[1] == HIGH {
       //code to handle button 0 (pin 3) being pressed
    }
    //And so on for the rest of your switches.
}

Answered by Duncan C on September 25, 2021

Next time align your code with ctrl-K (after selecting).

And yes, you can heavily optimize your code (for maintainability) using arrays:

Instead of

const int buttonPin1 = 2;
const int buttonPin2 = 3;
const int buttonPin3 = 4;
const int buttonPin4 = 5;
const int buttonPin5 = 6;

use

const int buttonPins[] = { 2, 3, 4, 5, 6 };

In software engineering it's normal to start with index 0 (such as an array index).

For the button states:

int buttonState1 = 0; // variable for reading the pushbutton status
int buttonState2 = 0;
int buttonState3 = 0;
int buttonState4 = 0;
int buttonState5 = 0;

you can use

boolean buttonStates[5];
for (uint8_t buttonIndex = 0; buttonindex < 5; buttonIndex++)
{
    buttonStates[buttonIndex]= false;
}

Instead of setting the pin modes:

pinMode(buttonPin1, INPUT); pinMode(buttonPin2, INPUT); pinMode(buttonPin3, INPUT); pinMode(buttonPin4, INPUT); pinMode(buttonPin5, INPUT);

Use a for loop:

for (uint8_t buttonIndex = 0; buttonindex < 5; buttonIndex++)
{
   pinMode(buttonPins[buttonIndex], INPUT);
}

You can combine the two for loops above with one.

To read the button states:

buttonState1 = digitalRead(buttonPin1) == 2;
buttonState2 = digitalRead(buttonPin2) == 3;
buttonState3 = digitalRead(buttonPin3) == 4;
buttonState4 = digitalRead(buttonPin4) == 5;
buttonState5 = digitalRead(buttonPin5) == 6;

Use

for (uint8_t buttonIndex = 0; buttonindex < 5; buttonIndex++)
{
   buttonStates[buttonIndex] = digitalRead(buttonPins[buttonIndex]) == buttonPinds[buttonIndex]) ? true : false;
}

For the switch, I think you need to keep it as it differs per pin.

And instead of using the value 5 use e.g.:

const uint8_t NR_OF_BUTTONS = 5;

and use the NR_OF_BUTTONS constant everywhere.

Note: I don't have a compiler at hand, so forgive me for any possible compiler errors.

Also, instead of multiple arrays (each of length NR_OF_BUTTONS), you can use an array of a struct which contain the pin number and state, but this is maybe beyond the scope of your programming knowledge. The use of arrays is already a huge improvement.

Answered by Michel Keijzers on September 25, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP