Включение и выключение с Arduino: Несколько состояний от одной кнопки

Несколько состояний от одной кнопки

Это руководство демонстрирует, как управлять несколькими светодиодами с помощью одной кнопки на Arduino, циклически переключаясь между различными состояниями при каждом нажатии.

Схема подключения

Схема использует три светодиода, подключённых к пинам Arduino:

  • Пин 10: Зелёный светодиод (с резистором)

  • Пин 9: Жёлтый светодиод (с резистором)

  • Пин 8: Красный светодиод (с резистором)

  • Пин 2: Кнопка

Макетная плата Схема подключения

Пояснение кода

Определение пинов

int pin_LEDgreen = 10;
int pin_LEDyellow = 9;
int pin_LEDred = 8;

Переменная состояния

Переменная типа byte отслеживает текущее состояние (0–3):

  • state = 0: все светодиоды выключены

  • state = 1: зелёный светодиод включён

  • state = 2: жёлтый светодиод включён

  • state = 3: красный светодиод включён

Логика увеличения состояния

state++;
if (state > 3) { state = 0; }

Управление светодиодами

Код использует простые операторы if для управления светодиодами. Сначала все светодиоды выключаются, затем включается только нужный на основе текущего состояния.

Базовый скетч

//  Sketch: Multiple states from a single button switch
//  www.martyncurrey.com
//
//  An example of using a single button switch to set multiple states or conditions
//
//  Pins
//  D10 to resister and green LED
//  D9 to resister and yellow LED
//  D8 to resister and red LED
//  D2 to push button switch
//
//  state holds the current status.
//  0 = all off.
//  1 = green LED
//  2 = yellow LED
//  3 = red LED

// Define the pins being used
int pin_LEDgreen = 10;
int pin_LEDyellow = 9;
int pin_LEDred = 8;

int pin_switch = 2;

// variables to hold the new and old switch states
boolean oldSwitchState = LOW;
boolean newSwitchState1 = LOW;
boolean newSwitchState2 = LOW;
boolean newSwitchState3 = LOW;

byte state = 0;

void setup()
{
    Serial.begin(9600);
    Serial.print("Sketch:   ");   Serial.println(__FILE__);
    Serial.print("Uploaded: ");   Serial.println(__DATE__);
    Serial.println(" ");

    pinMode(pin_LEDgreen, OUTPUT);    digitalWrite(pin_LEDgreen,LOW);
    pinMode(pin_LEDyellow, OUTPUT);   digitalWrite(pin_LEDyellow,LOW);
    pinMode(pin_LEDred, OUTPUT);      digitalWrite(pin_LEDred,LOW);

    pinMode(pin_switch, INPUT);
}

void loop()
{
    newSwitchState1 = digitalRead(pin_switch);
    delay(1);
    newSwitchState2 = digitalRead(pin_switch);
    delay(1);
    newSwitchState3 = digitalRead(pin_switch);

    // if all 3 values are the same we can continue
    if (  (newSwitchState1==newSwitchState2) && (newSwitchState1==newSwitchState3) )
    {

        if ( newSwitchState1 != oldSwitchState )
        {

           // has the button switch been closed?
           if ( newSwitchState1 == HIGH )
           {
                // increase the value of state
                state++;
                if (state > 3) { state = 0; }

                // turn all LEDs off
                digitalWrite(pin_LEDgreen, LOW);
                digitalWrite(pin_LEDyellow, LOW);
                digitalWrite(pin_LEDred, LOW);

                // Turn on the next LED
                if (state==1) { digitalWrite(pin_LEDgreen, HIGH);  }
                if (state==2) { digitalWrite(pin_LEDyellow, HIGH);  }
                if (state==3) { digitalWrite(pin_LEDred, HIGH);  }

           }
           oldSwitchState = newSwitchState1;
        }
    }
}

Улучшенная версия с массивами

Для масштабируемости с большим количеством светодиодов предлагается улучшенная версия с использованием массивов.

Определение массивов

char LED_Pins_array[] = { 10, 9, 8};

char LED_Sequence_array[] = { 10, 9, 8, 9};
byte squenceLength = 4;

Улучшенный скетч

//  Sketch: Multiple states from a single button switch, refined
//  www.martyncurrey.com
//
//  An example of using a single button switch to set multiple states or conditions
//  Now using an array to store the LED pins
//
//  Pins
//  D10 to resister and green LED
//  D9 to resister and yellow LED
//  D8 to resister and red LED
//  D2 to push button switch
//
//  state holds the current status.
//  0 = all off.
//  1 = green LED
//  2 = yellow LED
//  3 = red LED

// Define the pins being used for the LEDs
//                    green/yellow/red
char LED_Pins_array[] = { 10, 9, 8};

// Array to hold the LED sequence. green, yellow, red, yellow, green.
// position 0 is not used (considered not good practice but keeps the code easy to understand)
char LED_Sequence_array[] = { 10, 9, 8, 9};
byte squenceLength = 4;

int pin_switch = 2;

// variables to hold the new and old switch states
boolean oldSwitchState = LOW;
boolean newSwitchState1 = LOW;
boolean newSwitchState2 = LOW;
boolean newSwitchState3 = LOW;

byte state = -1;

void setup()
{
    Serial.begin(9600);
    Serial.print("Sketch:   ");   Serial.println(__FILE__);
    Serial.print("Uploaded: ");   Serial.println(__DATE__);
    Serial.println(" ");

    for (byte i=0; i< 3; i++)
    {
         pinMode(LED_Pins_array[i], OUTPUT);    digitalWrite(LED_Pins_array[i],LOW);
    }
    pinMode(pin_switch, INPUT);
}

void loop()
{
    newSwitchState1 = digitalRead(pin_switch);
    delay(1);
    newSwitchState2 = digitalRead(pin_switch);
    delay(1);
    newSwitchState3 = digitalRead(pin_switch);

    // if all 3 values are the same we can continue
    if (  (newSwitchState1==newSwitchState2) && (newSwitchState1==newSwitchState3) )
    {
        if ( newSwitchState1 != oldSwitchState )
        {

           // has the button switch been closed?
           if ( newSwitchState1 == HIGH )
           {

                state++;
                if (state > (squenceLength -1) ) { state = 0; }

                // turn all LEDs off
                for (byte i=0; i< 3; i++)
                {
                     digitalWrite(LED_Pins_array[i],LOW);
                }

                // Turn on the next LED
                digitalWrite(LED_Sequence_array[state],HIGH);
           }
           oldSwitchState = newSwitchState1;
        }
    }
}

Ключевые концепции

Устранение дребезга (Debouncing): Код считывает состояние кнопки три раза с небольшими задержками для устранения ложных срабатываний.

Управление состоянием: Переменная state циклически проходит через предопределённые значения, управляя тем, какой светодиод активен.

Преимущества массивов: Улучшенная версия демонстрирует, как массивы делают код более поддерживаемым и масштабируемым для проектов с большим количеством светодиодов.

Упражнения для самостоятельной работы

  • Храните показания состояния кнопки в массиве вместо отдельных переменных

  • Создайте отдельную функцию для обработки обнаружения нажатия кнопки

  • Расширьте последовательность светодиодов дополнительными цветами


Оригинал статьи: Martyn Currey — martyncurrey.com