Управление одной кнопкой тремя реле

Буду признателен за помощь в реализации следующего алгоритма:
имеется одна кнопка и три реле.
необходимо по короткому нажатию кнопки включать реле P1, следующее короткое нажатие выключает P1 и включает реле P2, длинное нажатие выключает любое из предварительно включенных P1 либо P2 и включает на короткое время P3.
Желательно реализовать все это на ARDUINO mini.
Возможно что-то подобное уже кем-то было реализовано.

Если вы сами вообще ничего изучать/писать не хотите, то вам в раздел Ищу исполнителя.

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

Так что от сообщества нужно? Алгоритм вами описан - берите и пишите его, только уже на C++.
Заодно более “осязаемое” значение приобретет

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

Надо с чего-то начинать. Внесу на рассмотрение:

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

3000р и код у тебя

Вот, вроде, всё ничего, но как-то вот … не концептуально, что ли …

:slight_smile:

Так потому, что это “скелет”, на него еще надо “мясо нарастить”… :slight_smile:

YaGPT так ответил

Спойлер
int buttonPin = 2; // цифровой вывод, к которому подключена кнопка
int relayPinP1 = 3; // цифровой выход, к которому подключен контакт реле P1
int relayPinP2 = 4; // цифровой выход, к которому подключены контакты реле P2
int relayPinP3 = 5; // цифровой вход, к которому подключается контакт катушки реле P3

boolean isButtonPressed = false; // флаг, указывающий, была ли нажата кнопка

void setup() {
  pinMode(buttonPin, INPUT); // устанавливаем пин, к которому подключена кнопка, в режим входа
  pinMode(relayPinP1, OUTPUT); // устанавливаем цифровой выход, к которому подключен P1 в режим выхода
  pinMode(relayPinP2, OUTPUT); // устанавливаем P2 в режим выхода
  digitalWrite(relayPinP3, HIGH); // включаем реле P3 на высокое напряжение
}

void loop() {
  if (digitalRead(buttonPin) == HIGH) { // если кнопка нажата
    isButtonPressed = true; // устанавливаем флаг нажатой кнопки
    digitalWrite(relayPinP1, LOW); // выключаем P1
    delay(100); // задержка 100 мс
    digitalWrite(relayPinP2, HIGH); // включаем P2
    delay(500); // задержка на 500 мс
  } else if (isButtonPressed == true) { // иначе, если кнопка нажата,
    digitalWrite(relayPinP2, LOW); // выключаем P2
    digitalWrite(relayPinP3, LOW); // выключаем реле P3
    isButtonPressed = false; // сбрасываем флаг нажатой кнопки
  }
}

Другой вариант

int buttonPin = 2; // Пин подключения кнопки
int p1Pin = 3; // Пин включения реле P1
int p2Pin = 4; // Пин включения реле P2
int p3Pin = 5; // Пин включения реле P3

boolean isP1On = false; // Флаг включения реле P1
boolean isP2On = false; // Флаг включения реле P2

void setup() {
  pinMode(buttonPin, INPUT_PULLUP); // Подключаем кнопку к пину с подтягивающим резистором
  pinMode(p1Pin, OUTPUT);
  pinMode(p2Pin, OUTPUT);
  pinMode(p3Pin, OUTPUT);
}

void loop() {
  if (digitalRead(buttonPin) == LOW) { // Если кнопка нажата
    if (isP1On) { // Если реле P1 уже включено
      digitalWrite(p1Pin, LOW); // Выключаем P1
      isP1On = false;
    } else {
      digitalWrite(p2Pin, LOW); // Включаем P2
      isP2On = true;
    }
  } else if (digitalRead(buttonPin) == HIGH) { // Если кнопка отпущена
    digitalWrite(p3Pin, HIGH); // Включаем на короткое время P3
    delay(50); // Задержка 50 мс
    digitalWrite(p3Pin, LOW); // Отключаем P3
  }
}

Работает или нет - не знаю !!!

А так?

void loop() {
  // put your main code here, to run repeatedly:

}

void setup() {
  // put your setup code here, to run once:

}
1 лайк

Поддерживаю! Где инициализация Serial, во что рыбу заворачивать будем как программу отлаживать?

1 лайк

Куда ТС то пропал?
Двигаемся дальше:

Спойлер
/*
 * Абзавём входные данные, а именно пины для КНОПКИ и ТРЁХ РЕЛЕ
 */

#define     BUTTON_PIN  12    // Кнопка
#define     RELE1_PIN   2     // Реле 1
#define     RELE2_PIN   3     // Реле 2
#define     RELE3_PIN   4     // Реле 3

void setup() {
  // Крутая вставка от DetSimen для отладки
  Serial.begin(9600);
  stdout = fdevopen([](char ch, FILE* f)->int {return Serial.print(ch); }, NULL);
  // puts("Program started...");

  // Теперь настроим пины
  pinMode(BUTTON_PIN, INPUT_PULLUP);  // На вход и подтянуть к +питания (экономим на резисторах для "подтяжки")
  pinMode(RELE1_PIN, OUTPUT);         // А пины реле на выход
  pinMode(RELE2_PIN, OUTPUT);
  pinMode(RELE3_PIN, OUTPUT);

  // И зададим начальное значение - все реле выключены
  digitalWrite(RELE1_PIN, LOW);
  digitalWrite(RELE2_PIN, LOW);
  digitalWrite(RELE3_PIN, LOW);
}

void loop() {
  // put your main code here, to run repeatedly:

}

Скетч использует 772 байт (2%) памяти устройства. Всего доступно 32768 байт.
Глобальные переменные используют 9 байт (0%) динамической памяти, оставляя 2039 байт для локальных переменных. Максимум: 2048 байт.

Почитать про INPUT_PULLUP

Вставь, правда, в самое начало setup() строки

    Serial.begin(115200);
    stdout = fdevopen([](char ch, FILE* f)->int {return Serial.print(ch); }, NULL);
    puts("Program started...");

отлаживать будет проще, весь стандартный Сишный вывод (printf(), puts(), putchar()) будет идти в Serial искаропки.

P.S. Алехандро, можно это в Вики вставить, полезная штучка. :slight_smile: (наерна)

4 лайка

Нихарашо абзывацца!

2 лайка

окаймить

#ifdef DEBUG

....
#endif

Едем дальше?

/*
 * Абзавём входные данные, а именно пины для КНОПКИ и ТРЁХ РЕЛЕ
 */

#define     BUTTON_PIN        12    // Кнопка
#define     RELE1_PIN         2     // Реле 1
#define     RELE2_PIN         3     // Реле 2
#define     RELE3_PIN         4     // Реле 3
#define     TIME_BOUNCE       70    // 70мс время "фильтрации" дребезга контактов
#define     LONG_PRESS_TIME   2000  // 2 секунды время удержания кнопки

enum BUTTON_RESULT : uint8_t {
  NOT_PRESS, 
  PRESS,
  LONG_PRESS                                                     
};

BUTTON_RESULT current_button_res = NOT_PRESS;

void setup() {
  // Крутая вставка от DetSimen для отладки
  Serial.begin(9600);
  stdout = fdevopen([](char ch, FILE* f)->int {return Serial.print(ch); }, NULL);
  // puts("Program started...");
  
  // Теперь настроим пины
  pinMode(BUTTON_PIN, INPUT_PULLUP);  // На вход и подтянуть к +питания (экономим на резисторах для "подтяжки")
  pinMode(RELE1_PIN, OUTPUT);         // А пины реле на выход
  pinMode(RELE2_PIN, OUTPUT);
  pinMode(RELE3_PIN, OUTPUT);

  // И зададим начальное значение - все реле выключены
  digitalWrite(RELE1_PIN, LOW);
  digitalWrite(RELE2_PIN, LOW);
  digitalWrite(RELE3_PIN, LOW);
}

void loop() {
  // С чего начать основную программу?
  // А начну-ка с чтения состояния кнопки. ТС, как думаешь - это правильное решение?
  uint8_t button_state = digitalRead(BUTTON_PIN); // Ну во, вот тут мы её и "уконтропупили". 
                                                  // Теперь в переменной button_state содержится состояние кнопки
                                                  // LOW - если кнопка нажата, и HIGH - если кнопка не нажата
                                                    
  // Ещё нам понадобятся дополнительные переменные, оставим место тут для них
uint32_t _millis = millis();                      // Запомним текущее значение миллисекунд
  static uint32_t timeHoldBegin;                  // Время начала удержания кнопки
  static uint32_t timeHold;                       // Длительность удержания кнопки
  
  // А дальше нам нужно узнать - нажимал кто на кнопку? А если нажимал - то как долго удерживал?
  if (!button_state) {                            // Если кнопка нажата
    timeHold =  _millis - timeHoldBegin;          // Считаем длительность удержания
  } else {                                        // Еслди кнопку отпустили
    timeHoldBegin = _millis;                      // Сбрасываем
    timeHold = 0;
    current_button_res = NOT_PRESS;
  }

  if (timeHold > TIME_BOUNCE && timeHold < LONG_PRESS_TIME) { // Если время удержание в интервале между временем подавления дребезга и удержанием
    current_button_res = PRESS;                               // То нужно как-то "зарегистрировать нажатие"
  }

  if (timeHold > LONG_PRESS_TIME) {                           // Если время удержание больше времени удержаниея (2 сек)
    current_button_res = LONG_PRESS;                          // То нужно как-то "зарегистрировать долгое удержание"
  }

  // Состояние кнопки узнали.
  // А дальше пошла "жара" (то есть обработка нажатий)

  switch (current_button_res) {
    case PRESS:                                               // Если кликнули один раз
      // Обрабатываем короткие нажатия

      break;
    case LONG_PRESS:                                          // Если долго держали
      // Обрабатываем долгое удержание
    
      break;
    case NOT_PRESS:                                            // Если кнопку не нажимали
      // Ничего не делаем. Это просто для наглядности
      break;
    default:
      break;
  }
}

а не Serial.write(ch); случаем?

print() принимает char, а write() - int

Чегой-то не хватает)))