Ардуино для начинающих. Урок 5. Кнопки, ШИМ, функции

В этом уроке мы узнаем: как подключить кнопку к ардуино, как подавить дребезг контактов, как в прошивке обработать нажатие на кнопку, как послать ШИМ сигнал, как создать свою функцию и как управлять светодиодом.

В этом уроке используются следующие детали:

Большая макетная плата на 1600 точек с 4 шинами питания:Купить
Набор резисторов из 100 штук на все случаи:Купить
Набор светодиодов из 100 штук:Купить
5 штук кнопок в удобной форме:Купить
Соединительные провода 120 штук:Купить

Подключение кнопки к Arduino

Подключение кнопки к Arduino
Подключение кнопки к Arduino

Как видите, ничего сложно в подключении кнопки к ардуино нет. Обратите внимание, что кнопка установлена так, что каждый ее контакт подключен к разным линиям макетной платы. Так же вы можете заметить резистор на 10 кОм который притягивает контакт к земле. Это нужно для того, что бы мы на 8 контакте не ловили наводок. Попробуйте убрать этот резистор из схемы. Светодиод будет загораться при шевелении проводов или кнопки. Теперь давайте рассмотрим скетч:

 // Первый скетч. Светодиод горит при нажатой кнопке
 // переменные с пинами подключенных устройств
int switchPin = 8;
int ledPin = 13;

void setup() {
	pinMode(switchPin, INPUT);
	pinMode(ledPin, OUTPUT);
}

void loop() {
	// включаем всетодиод при нажатой кнопке
	if(digitalRead(switchPin) == HIGH) {
		digitalWrite(ledPin, HIGH);
	} else {
		digitalWrite(ledPin, LOW);
	}
}

В этом уроке, как и прошлом, в самом начале мы объявляем переменные со значениями пинов к которым у нас подключены кнопка и светодиод. Далее в функции setup() мы обозначаем какой пин используется как вход, а какой как выход. В функции loop() мы используем условный оператор if с оператором сравнения и проверяем приходит ли на пин 8 высокий сигнал. Если да то включаем светодиод, если нет то выключаем. Описание функций и операторов вы найдете в справочнике по языку программирования Arduino

Теперь немного усложним наш код. Давайте сделаем так, что бы при нажатии на кнопку светодиод загорался и гас только при следующем нажатии на кнопку. Для этого в схеме мы менять ничего не будем, а скетч теперь будет выглядеть так:

 // второй скетч. меняет состояние при нажатии на кнопку
 // переменные с пинами подключенных устройств
int switchPin = 8;
int ledPin = 13;

// переменные для хранения состояния кнопки и светодиода
boolean lastButton = LOW;
boolean currentButton = LOW;
boolean ledOn = false;

void setup() {
	pinMode(switchPin, INPUT);
	pinMode(ledPin, OUTPUT);
}

// функция для подавления дребезга
boolean debounse(boolean last) {
	boolean current = digitalRead(switchPin);
	if(last != current) {
		delay(5);
		current = digitalRead(switchPin);
	}
	return current;
}

void loop() {
	currentButton = debounse(lastButton);
	if(lastButton == LOW && currentButton == HIGH) {
		ledOn = !ledOn;
	}
	lastButton = currentButton;
	digitalWrite(ledPin, ledOn);
}

В этом скетче мы добавили переменные для хранения состояния светодиода и кнопки. Так же мы создали новую функцию для подавления дребезга контактов debounse(). Код в цикле loop() тоже немного изменился. Теперь в условном операторе мы проверяем нажата ли кнопка и если нажата, то меняем состояние светодиода на противоположное. Потом меняем переменную с последним состоянием на текущее состояние кнопки и включаем или выключаем светодиод.

Понравилось? Давайте еще больше усложним наш проект. Теперь мы будем управлять яркостью светодиода. Для этого нам надо немного изменить схему нашего устройства. Для управления яркостью мы будем использовать ШИМ. Значит нам надо подключить светодиод к выходу, который может выдавать ШИМ. Теперь наша схема будет выглядеть вот так:

Подключение светодиода к Arduino
Подключение светодиода к Arduino

Теперь светодиод подключен к 11 пину ардуино, которой умеет делать ШИМ. И нам пришлось добавить токоограничивающий резистор на 220 Ом перед светодиодом, что бы его не спалить. Это необходимо потому, что светодиоды работают при напряжении 3.3 В, а пин ардуино отдает 5 В. Теперь посмотрим что нужно изменить в скетче:

 // переменные с пинами подключенных устройств
int switchPin = 8;
int ledPin = 11;

// переменные для хранения состояния кнопки и светодиода
boolean lastButton = LOW;
boolean currentButton = LOW;
int ledLevel = 0;

void setup() {
	pinMode(switchPin, INPUT);
	pinMode(ledPin, OUTPUT);
}

// функция для подавления дребезга
boolean debounse(boolean last) {
	boolean current = digitalRead(switchPin);
	if(last != current) {
		delay(5);
		current = digitalRead(switchPin);
	}
	return current;
}

void loop() {
	currentButton = debounse(lastButton);
	if(lastButton == LOW && currentButton == HIGH) {
		ledLevel = ledLevel + 51;
	}
	lastButton = currentButton;

	if(ledLevel > 255) ledLevel = 0;
	analogWrite(ledPin, ledLevel);
}

В этом примере мы изменили значение переменной ledPin на 11. Так же добавили переменную для хранения уровня ШИМ ledLevel. При нажатии на кнопку будем увеличивать эту переменную. Функция debounce() осталась без изменений. В цикле мы теперь используем функцию analogWrite().

Вот и все! Сегодняшний урок на этом мы закончим. Надеюсь вам все было понятно. Если нет, то можете задавать свои вопросы в комментариях ниже.

24 комментариев

  1. Николай

    Здравствуйте)))
    Подскажите пожалуйста новечьку,
    Как можно реализовать такой скечь
    При нажатии на кнопку светодиод плавно загорается если нажать ещё раз на кнопку то светодиод плавно тухнет…?

    • Александр

      // переменные с пинами подключенных устройств
      int switchPin = 8;
      int ledPin = 11;

      // переменные для хранения состояния кнопки и светодиода
      boolean lastButton = LOW;
      boolean currentButton = LOW;
      int ledLevel = 0;

      void setup() {
      pinMode(switchPin, INPUT);
      pinMode(ledPin, OUTPUT);
      }

      // функция для подавления дребезга
      boolean debounse(boolean last) {
      boolean current = digitalRead(switchPin);
      if(last != current) {
      delay(5);
      current = digitalRead(switchPin);
      }
      return current;
      }

      void loop() {
      currentButton = debounse(lastButton);
      //первый цикл, постепенно включает светодиодик
      if(lastButton == LOW && currentButton == HIGH) {
      for(int i=ledLevel;i 255) ledLevel = 0;
      }
      currentButton = debounse(lastButton);

      //второй цикл, постепенно выключает светодиодик
      if(lastButton == LOW && currentButton == HIGH) {
      for(int i=ledLevel;i>0;i=i-1){
      ledLevel = ledLevel — 1;
      delay(100);
      analogWrite(ledPin, ledLevel);}
      //if(ledLevel > 255)
      ledLevel = 0;
      }

      }

  2. Денис

    Очевидно при нажатии на кнопку в цикле менять значение ledLevel

  3. Mr.ALB

    //Как можно реализовать такой скечь
    //При нажатии на кнопку светодиод плавно загорается если нажать ещё раз на кнопку то светодиод плавно тухнет…?

    /*== к примеру, вот так ==*/

    // переменные с пинами подключенных устройств
    int switchPin = 8;
    int ledPin = 11;

    // переменные для хранения состояния кнопки и светодиода
    boolean lastButton = LOW;
    boolean currentButton = LOW;
    int ledLevel = 0;

    // настройка изменения яркости
    int deltaLevel = 5; // Шаг изменения яркости
    int sign = 1; // Знак шага
    int step_delay = 100; // задержка в шаге изменения яркости светодиода

    // настройка сигнализатора окончания изменения яркости
    int max_blink = 3; //число морганий светодиода на pin13 (LED_BUILTIN)
    int blink_delay = 500; //задержка состояния светодиода на pin13 (LED_BUILTIN)

    void setup()
    {
    pinMode(switchPin, INPUT);
    pinMode(ledPin, OUTPUT);
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, LOW);// потушим светодиод на pin13 (LED_BUILTIN)
    }

    // функция для подавления дребезга
    boolean debounse(boolean last)
    {
    boolean current = digitalRead(switchPin);
    if(last != current)
    {
    delay(5);
    current = digitalRead(switchPin);
    }
    return current;
    }

    // При нажатии на кнопку, светодиод медленно увеличивает яркость
    // При повторном нажатии на кнопку, светодиод медленно гаснет
    void loop()
    {
    currentButton = debounse(lastButton);
    if(lastButton == LOW && currentButton == HIGH)
    {
    if(ledLevel == 0) sign = 1;
    if(ledLevel == 255) sign = -1;
    for(int i = 0; i 255) ledLevel = 255;
    if(ledLevel < 0) ledLevel = 0;
    analogWrite(ledPin, ledLevel);
    delay(step_delay);
    }
    /* Сигнализация окончания цикла изменения яркости светодиода */
    for(int i = 0; i < max_blink; i++)
    {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(blink_delay);
    digitalWrite(LED_BUILTIN, LOW);
    delay(blink_delay);
    }
    }
    lastButton = currentButton; // переписываем состояние кнопки
    }

    //P.S. почему-то первый ответ криво пошёл, исказился код… надеюсь этот пройдёт

  4. Света

    МУЖЧИНЫ кто согласится написать скетч за вознаграждение,к примеру на телефон.

    • Tviort

      Здравствуйте. Какой именно скетч вам нужен?

  5. иван

    помогите освоить кнопки для изменения параметра int b = 7883; с запоминанием
    #include

    LiquidCrystal_I2C lcd(0x27, 16, 2);

    #include

    AccelStepper Stepper1(1, 13, 12); //использует пин 12 и 13 для dir и step, 1 — режим «external driver» (A4988)

    int dir = 1;

    int a = 0;

    int relayPin = 11;

    int b = 7883;

    void setup() {

    lcd.init();

    lcd.backlight();

    lcd.setCursor(0, 1);

    lcd.print(b);

    pinMode (relayPin, OUTPUT);

    digitalWrite (relayPin, HIGH);

    }

    void loop() {

    Stepper1.setMaxSpeed(1500.0);
    Stepper1.setAcceleration(1500.0);
    if (Stepper1.distanceToGo() == 0) {
    digitalWrite (relayPin, LOW);
    delay(30);
    Stepper1.move(b);
    delay(500);

    }
    if (Stepper1.distanceToGo() == b)
    {
    digitalWrite (relayPin, HIGH);
    delay(30);
    a = 0;
    }
    Stepper1.run(); //запуск шагового двигателя. Эта строка повторяется вновь и вновь для непрерывного вращения двигателя

    }

  6. иван

    так то тело работает как надо, но чтото я в ступоре что и где написать ему еще ))))))

  7. Игорь

    Привет) Имеем простейший скетч для управления оборотами бк мотора. как добавить сюда кнопку, при нажатии и удержании двиг должен крутиться на выставленых оборотах, при отпускании кнопки двиг останавливается
    #include

    Servo motor;

    void setup() {
    motor.attach(8);
    motor.writeMicroseconds(2300);
    delay(2000);
    motor.writeMicroseconds(800);
    delay(6000);
    }

    void loop() {

    int val = map(analogRead(0), 0, 1023, 800, 2300);
    motor.writeMicroseconds(val);

    }

    • Tviort

      Очень просто! в setup() {} надо добавить строку: pinMode(D5, INPUT); // D5 номер цифрового пина к которому подключена кнопка. Можете подключить к любому цифровому пину но не забудьте поменять значение

      В loop(){} добавляем следующее условие:
      if(digitalRead(D5)) { // ждем высокого сигнала с кнопки
      int val = map(analogRead(0), 0, 1023, 800, 2300);
      motor.writeMicroseconds(val);
      }

      • Игорь

        #include

        Servo motor;

        void setup() {
        pinMode(D5, INPUT);
        motor.attach(8);
        motor.writeMicroseconds(2300);
        delay(2000);
        motor.writeMicroseconds(800);
        delay(6000);
        }

        void loop() {

        if(digitalRead(D5))
        int val = map(analogRead(0), 0, 1023, 800, 2300);
        motor.writeMicroseconds(val);

        }

        ошибка ‘D5’ was not declared in this scope

  8. Дмитрий

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

    • Владимир

      Странно что вам никто не ответил. В цикле изменяйте параметры ШИМ от 0 до 255 и постоянно опрашивайте кнопку на предмет нажатия. Сделайте задержку опроса немного больше, например 10ms. Чтобы не ошибиться с «отжатием». По false заканчивайте опрос и устанавливайте выход в LOW.
      Написать видимо могу, но тратить на это время не хочу. Я всего пару часов учу этот предмет 🙂
      Надеюсь вы уже и без меня догадались как это сделать.

  9. Владимир

    Есть стойкое ощущение, что автор статьи дисциплины схемотехника и принцип работы электронных приборов в ВУЗе прогуливал.
    «Теперь светодиод подключен к 11 пину ардуино, которой умеет делать ШИМ. И нам пришлось добавить токоограничивающий резистор на 220 Ом перед светодиодом, что бы его не спалить. Это необходимо потому, что светодиоды работают при напряжении 3.3 В, а пин ардуино отдает 5 В.»
    1. Без разницы где стоит резистор До или После светодиода.
    2. «токоограничивающий резистор» — совершенно верно!
    3. «Это необходимо потому, что светодиоды работают при напряжении 3.3 В, а пин ардуино отдает 5 В.» А это вы батенька придумали самостоятельно. Сетодиод — прибор управляемый током (в п.2 ошибки нет). На напряжение ему плевать, кроме полярности естественно. Дальше закон Киргоффа для участка цепи. Я включаю светодиоды в розетку 220В. Так что напряжение на выходе Arduino тут вообще не причем. Касаемо резистора то тут он, скорее всего ограничивает ток коллектора выходного транзистора контроллера, т.к. светодиод горит ярко уже при 10ma, новые даже при 5-7ma. А здесь ограничено около 20-23ma. Т.е. для свечения светодиода можно было смело ставить 470 Ом и выше. На это плевать когда вы питаетесь от компа и не «греетесь». Как только будете «жрать» батарейки (или сделаете высоко нагруженную схему), то все будет греться а батарея заканчиваться довольно быстро.
    Сорри. не по теме программирования.
    К программированию претензий нет. Я в этом пока не сильно понимаю. Первый день…

  10. Алеша

    Как сделать на 2 кнопках? Чтобы нажал на первую кнопку загорелся первый светодиод,нажал на вторую кнопку загорелся второй светодиод.

  11. Владимир

    Подскажите пожалуйста а как написать код чтоб 2 кнопки и 2 светодиода работало. а то я не как не могу в толк взять. Как и что здесь сделоть. int switchPin = 2;
    int switch1Pin = 4;
    int ledPin = 12;
    int led1Pin = 13;

    // переменные для хранения состояния кнопки и светодиода
    boolean lastButton = LOW;
    boolean last1Button = LOW;
    boolean currentButton = LOW;
    boolean current1Button = LOW;
    boolean ledOn = false;
    boolean led1On = false;

    void setup() {
    pinMode(switchPin, INPUT);
    pinMode(switch1Pin, INPUT);
    pinMode(ledPin, OUTPUT);
    pinMode(led1Pin, OUTPUT);
    }

    // функция для подавления дребезга

    boolean debounse(boolean last);
    boolean debounse1(boolean last1);
    boolean current = digitalRead(switchPin);
    boolean current1 = digitalRead(switch1Pin);

    if (last != current){
    delay(5);
    current = digitalRead(switchPin);
    {
    return current;
    }
    if (last1 != current1){
    delay(5);
    current1 = digitalRead(switch1Pin);
    }
    {
    return current1;
    }

    void loop(){

    currentButton = debounse(lastButton);
    if(lastButton == LOW && currentButton == HIGH) {
    ledOn = !ledOn;
    }
    lastButton = currentButton;
    digitalWrite(ledPin, ledOn);

    current1Button = debounse1(last1Button);
    if(last1Button == LOW && current1Button == HIGH) {
    led1On = !led1On;
    }
    last1Button = current1Button;
    digitalWrite(led1Pin, led1On);
    }}
    }

  12. sergejsimak1

    Подскажите пожалуйста как можно сделать что бы при нажатии и отпускании кнопки определённый цикл запускался, ну скажем мигание светодиода, а при повторном нажатии цикл останавливался.

  13. Санек

    Почему когда открываешь монитор порта на пине 13 появляется напряжение и на других пинах тоже. Тоесть реле подключенное к другим пинам тоже срабатывает

  14. vadimengineer

    «Это необходимо потому, что светодиоды работают при напряжении 3.3 В, а пин ардуино отдает 5 В.» Светодиод работает от тока 10-20мА. И резистор ограничивает ток по закону ОМА. Исправьте ошибку!

  15. Владимир

    подскажите пожалуйста вот ваш код
    // второй скетч. меняет состояние при нажатии на кнопку
    // переменные с пинами подключенных устройств
    int switchPin = 8;
    int ledPin = 13;

    // переменные для хранения состояния кнопки и светодиода
    boolean lastButton = LOW;
    boolean currentButton = LOW;
    boolean ledOn = false;

    void setup() {
    pinMode(switchPin, INPUT);
    pinMode(ledPin, OUTPUT);
    }

    // функция для подавления дребезга
    boolean debounse(boolean last) {
    boolean current = digitalRead(switchPin);
    if(last != current) {
    delay(5);
    current = digitalRead(switchPin);
    }
    return current;
    }

    void loop() {
    currentButton = debounse(lastButton);
    if(lastButton == LOW && currentButton == HIGH) {
    ledOn = !ledOn;
    }
    lastButton = currentButton;
    digitalWrite(ledPin, ledOn);
    }
    одно нажатие на кнопу светодиод горит второе гаснет . мне нужно тоже самое только управлять кодом если кнопка не нажата выполняется первый код нажал выполняется второй , еде раз нажал выполняется первый код , я не пойму как переменную для хранения состояния светодиода boolean ledOn = false; заменить на переменную хранения состояния кода ? подскажите пожалуйста .

Добавить комментарий для Аноним Отменить ответ

Ардуино