Как НЕ повторять фрагмент кода снова и снова?

У меня ОЧЕНЬ длинный код:

Sketch использует 30 468 байт (92 %) места для хранения программ. Максимум 32768 байт.

Я пытался уменьшить его размер, чтобы написать больше кода. Одна из моих основных частей кода, которая повторяется много раз в случаях переключения или в операторах if, связана с устранением дребезга кнопок.

Вот пример моего кода:

  case 12:
    if ((millis() - millistimer) > BounceD) {
      if (receivedValue == RFb) {
        magnetDistance += 5;
        millistimer = millis();
        receivedValue = 0;
      }
    }
    if ((millis() - millistimer) > BounceD) {
      if (receivedValue == RFd) {
        magnetDistance -= 5;
        millistimer = millis();
        receivedValue = 0;
      }
    }
    break;

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

Есть две кнопки, которые в каждом case увеличивают/уменьшают разные значения.

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


ИЗМЕНИТЬ:

Поле receivedValue обновляется с помощью кнопок пульта дистанционного управления при нажатии любой кнопки на пульте дистанционного управления.

, 👍2

Обсуждение

Я не думаю, что это связано с _длинным кодом_. Скорее всего, вы используете конструкции, о которых известно, что они занимают много места, например string. Пожалуйста, предоставьте ПОЛНЫЙ код, чтобы иметь возможность судить об основной причине вашего большого использования пространства., @Kwasmich

Вы слышали о функциях? Это классная конструкция, позволяющая написать блок кода один раз и использовать его несколько раз., @chrisl

@Kwasmich На самом деле у меня есть несколько строк, я не могу их просто удалить! что мне с ними делать?, @ElectronSurf

@chrisl, значит, функция для устранения подпрыгивания? как мне вызвать это для каждой кнопки?, @ElectronSurf

Замените «string» в C++ на строки в стиле C, которые представляют собой массивы символов — «char[]» и используйте соответствующие методы для манипулирования строками., @Kwasmich

@Kwasmich, не могли бы вы предоставить ссылку на статью (учебник) для дальнейшего чтения?, @ElectronSurf

https://majenko.co.uk/blog/evils-arduino-strings, @Juraj

@Juraj Спасибо., @ElectronSurf

http://www.cplusplus.com/doc/tutorial/functions/, @Juraj

Есть даже библиотеки для устранения дребезга, вроде библиотеки Bounce 2., @chrisl

Не могли бы вы опубликовать весь код или хотя бы немного больше? Поскольку код даже не выполняет digitalRead, чтобы прочитать состояние кнопок. Во-вторых, второй оператор if никогда не будет принимать значение true, поэтому его можно полностью удалить., @Gerben

@Gerben все случаи выглядят так же, как я писал, я просто удалил часть lcd.print() и т. д., @ElectronSurf

@Kwasmich я изменил все строки на char, но это уменьшило размер только на 3%, @ElectronSurf

@chrisl Я не могу использовать библиотеку Bounce 2, потому что кнопки являются дистанционными радиочастотными кнопками, я использую библиотеку [RC-Switch](https://github.com/sui77/rc-switch)., @ElectronSurf

Если вы не используете физические кнопки, зачем вам дебаунс? Отскок — это свойство физических кнопок., @chrisl

@chrisl, потому что пульт, который у меня есть, постоянно отправляет получателю значение! и когда значение будет получено, оно сделает математику и изменит receivedValue на ноль, и цикл продолжится..., @ElectronSurf


1 ответ


Лучший ответ:

2

В приведенном выше коротком примере сначала выясните, что является дубликатом (два внешних оператора if, включая их тело), а затем различия:

  • Rfb и Rfd
  • +5 против -5

Чем сделать функцию для дублированного кода, а все отличия превратить в параметр (я не знаю тип Rfd, поэтому беру для него int).

Вы получите:

case 12:
  processButton(&Rfb,  5); // Смещение расстояния магнита на +5
  processButton(&RFd, -5); // Смещение магнитного расстояния на -5
  break;

  ...


void processButton(int* rf, int diff)
{
  if ((millis() - millistimer) > BounceD) {
    if (receivedValue == *rf) {
      magnetDistance += diff;
      millistimer = millis();
      *rf = 0;
    }
  }
}

Обратите внимание, что если magnetDistance и millistimer являются локальными переменными, вы также должны передать их (как указатель для изменения значения), если они являются глобальными, вы можете сохранить код как указано выше.

ОБНОВЛЕНИЕ

Параметр работает следующим образом. Например,

processButton(Rfb,  5);

Вызовет следующую функцию:

void processButton(int rf, int diff)

Где значение rf будет равно Rfb, а diff будет равно 5 (+5).

Таким образом, при выполнении magnetDistance += diff; diff будет равен +5, а magnetDistance будет увеличен на +5. В следующем вызове magnetDistance будет равен -5 и, таким образом, будет вычтен.

ОБНОВЛЕНИЕ 2

Чтобы изменить переменную, вы должны передать ее как указатель, иначе (скопированное) значение параметра будет изменено и не вернет свое значение вызываемой функции. Таким образом, вы должны указать параметр как адрес (оператор &) и использовать -> вместо . чтобы добраться до значения.

,

не могли бы вы прокомментировать этот код? это просто увеличивает значение magnetDistance или тоже уменьшает его? потому что RFb и RFd - это две разные кнопки., @ElectronSurf

Вместо того, чтобы комментировать код (что более или менее тривиально), я добавил объяснение того, как работают параметры, я думаю, это та информация, которую вы упускаете. Он увеличивает или уменьшает значение в зависимости от значения, переданного в функцию (в первый раз +5, во второй раз -5)., @Michel Keijzers

спасибо, а если три раза нажать RFb? он просто сделает +5 и -5 три раза вместо того, чтобы просто сделать +5 три раза., @ElectronSurf

Я не уверен, что вы имеете в виду... мой код должен работать точно так же, как ваш код, но удаляя дублированные части кода (которые превращаются в функцию с параметрами)... Я предлагаю вам добавить несколько Serial.prints, чтобы увидеть, что значения передаются, так что вы можете убедиться в этом сами., @Michel Keijzers

поскольку это удаленная кнопка RC, receivedValue **должно** обновляться значением, которое оно получает при нажатии кнопки на пульте, в вашем коде кажется, что receivedValue не получает никакого значения от пульта и просто делает математическая часть..., @ElectronSurf

полученное значение используется только для сравнения, оно не обновляется в вашем коде., @Michel Keijzers

Хорошо, извините, мой плохой, я обновлю вопрос прямо сейчас., @ElectronSurf

Вы только сбрасываете receivedValue на ноль, поэтому вы можете сделать это и внутри функции., @chrisl

@newbie Я изменил свой ответ, чтобы приспособить его к оператору нулевого присваивания (см. также комментарий Крисла выше)., @Michel Keijzers

@новичок Я буду., @Michel Keijzers