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

На вот эти вопросы ответить сможешь?

Я не люблю “менять коней на переправе” (изменять задачу по середине её решения).

Еще раз предлагаю - напишу за 20 евро в крипте. Биткоин, USDT, Бинанс - что угодно. Или ты принципиально хочешь бесплатно? Вполне понимаю, но тогда - не я.

1 лайк

Подходит.
Далее в лс пожалуйста.
Всем спасибо.

А ТС быстро сдался.
Видимо

не сильно то и интересно…

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

#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 секунды время удержания кнопки
#define     SHORT_TIME        3000

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

BUTTON_RESULT current_button_res = NOT_PRESS;

const uint8_t     RELE_PINS[] = {RELE1_PIN, RELE2_PIN, RELE3_PIN}, r_count = sizeof(RELE_PINS) / sizeof(RELE_PINS[0]);
      uint8_t     cur_rele = 0;

void releOff () {
  for (uint8_t i = 0; i < r_count; i++) {
    digitalWrite(RELE_PINS[i], LOW);
  }
}

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

  for (uint8_t i = 0; i < r_count; i++) {
    pinMode(RELE_PINS[i], OUTPUT);         // А пины реле на выход
  }
    // И выключим их все
  releOff();
}

void loop() {

  uint8_t button_state = digitalRead(BUTTON_PIN); // Ну во, вот тут мы её и "уконтропупили".
  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:                                               // Если кликнули один раз
      releOff();
      if (cur_rele < (r_count - 1)) {
        digitalWrite(RELE_PINS[cur_rele], HIGH);
      }
      cur_rele = (cur_rele++) % r_count;
      break;
    case LONG_PRESS:                                          // Если кномпу долго удерживали
      releOff();
      digitalWrite(RELE_PINS[r_count - 1], HIGH);
      delay(SHORT_TIME);
      digitalWrite(RELE_PINS[r_count - 1], LOW);
      cur_rele = 0;
      break;
    case NOT_PRESS:                                           // Если кнопку не нажимали
      // Ничего не делаем. Это просто для наглядности
      break;
    default:
      break;
  }
}

Скетч использует 1396 байт (4%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 23 байт (1%) динамической памяти, оставляя 2025 байт для локальных переменных. Максимум: 2048 байт.

Ну вот не дал человеку заработать 20 ойро !

Да прям? )
Там у ТС еще пару раз ТЗ поменяется.
Этот код под первоначальное из первого сообщения и “додуманное” мною до логического завершения.

А у меня “по ходу пьесы” вопрос возник.
Если в setup вот такой код:

void releOff () {
  for (uint8_t i = 0; i < r_count; i++) {
    digitalWrite(RELE_PINS[i], LOW);
  }
}

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

  for (uint8_t i = 0; i < r_count; i++) {
    pinMode(RELE_PINS[i], OUTPUT);         // А пины реле на выход
  }
    // И выключим их все
  releOff();
}

То скетч занимает 1396 байт, а если вот такой:

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

  for (uint8_t i = 0; i < r_count; i++) {
    pinMode(RELE_PINS[i], OUTPUT);         // А пины реле на выход
    // И выключим их все
    digitalWrite(RELE_PINS[i], LOW);
  }
}

То на 16 байт меньше - 1380 байт. Почему так?

Блин, вот, не первый же раз замужем! Даже неудобно говорить, чтобы код полностью приводил. Если у меня предположение, но без полного кода - пальцем в небо.

По вашему лишний цикл в код отображается “бесплатно” ?

Как же без него? Он чуть выше.

Отчего же?
Но я всегда думал, что процедурный подход позволяет сокращать код, а не увеличивать его. Функция releOff() используется в нескольких местах.
Что происходит во время вызова функции?

А ленивый компилятор решил, нахер прыгать я ещё буду по адресам, заinlineл и нафиг.

PUSHится то что будет “испорчено”, организуется окно в стеке под локальные переменные (если нужно), …, POPается всё что было запушено. Плюс сами CALL и RET дают до 6 байт …

6 байт, но не 16.
К тому же digitalWrite() тоже функция. По сути я заменил одну функцию другой, но объем увеличился.
Не понимать.

У меня 1.8.19 и другие цифры:
С релеофф 1396
Без релеофф и c digitalWrite внутри цикла 1408

BOOM - спасибо большое.

Я не совсем уверен, но думаю, все дело в размере функции.
Если она довольно компактная, то оптимизатор вполне может её заинлайнить.

Он может и цикл развернуть, благо, он там маленький. Над смотреть код. Не понимаю, почему этого до сих пор не сделано.

Потому, что код разный.

Посмотри листинг.