Мучаюсь с millis()

Нет, у меня в однопотоке диспетчер сообщений. Ничего не переключается, сообщения берутся из очереди и обрабатываются по очереди и без приоритетов. Мне хватаеть.

2 лайка

Он про твои таймеры. Их в теории можно использовать, как тикеры. А это почти многозадачность. :wink:

Не могут.
Во-первых, в Ардуино принято компилировать из исходников, не используя предварительно откомпилированный код. Следовательно, внести в него изменения не составит труда.
Во-вторых, никто не запрещает использовать собственные обертки для какого угодно количества функций.

Вообще-то речь шла не о switch/case, а о вызове функции из массива по номеру.

Это указано в сообщении №72.

Так там сову на глобус натягивали ))

Речь шла о замене вызова функций из switch вызовом из массива по номеру. Что само по себе глупость, ибо таких switch в программе может быть не один десяток

Да в принципе, любая OS, как говорит Танненбаум, это таймеры+очередь сообщений.

1 лайк

Спорное утверждение. Например удобно эффекты гирлянд на адресных светодиодах запускать Тупо по номеру. Или обработка команд от модема по ключевому слову.
Типа так:

typedef void (*execResponse)(const unsigned char * inLine);
const struct {
	const unsigned char * keyWord;
	execResponse procResp;
} exec_resp_table[] = {
        {(const unsigned char *)"+CWLAP:(", resp_CWLAP},
        {(const unsigned char *)"WIFI ", resp_WIFI}
};

Ну опять же - зачем сову частный случай натягивать на глобус? ))

Правильно: массив тоже глупость, т.к. их (массивов) может быть не один десяток.

Andriano, ты во что уперся? ТС задал вопрос, как сделать три события подряд с интервалом 5 секунд, выложил свой код, где пытался реализовать это в лоб. Не получалось.

@Дим-мычъ чуть модифицировал его код, оставив саму структуру кода.

Я следом модифицировал еще, убрав три проверки интервалов и заменив их циклом. В качестве действия оставил тот же вывод строк, что и у ТС, только, соответственно, в цикле.

Следом @Дим-мычъ предложил, что строки лучше поместить в массив (ага, массив всплыл именно в этот момент).

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

Заметь - не функции вызывать, хотя осмысленные действия ничуть не отрицают их вызов.

Ну а ниже уже ты вышел с массивом адресов функций.

Возможен ли такой вариант? Конечно возможен. Но ответь себе на один вопрос: ВСЕГДА ЛИ можно будет реализовать такой вариант? И вообще - НАСКОЛЬКО ЧАСТО такой вариант будет вообще применим?

А зачем мне на него отвечать, тем более, что ответ совершенно очевиден: любое действие можно осуществить несколькими разными способами. Выбор конкретного - вопрос отдельный, но, как правило, реализован (иногда с применением явных костылей) может быть любой из них.
На вопрос “ВСЕГДА ЛИ?” ответ “ДА”, на вопрос “ВСЕГДА ЛИ это рационально?” ответ “НЕТ”.
А теперь скажи, неужели из сформулированного выше ты чего-то не знал? Тогда зачем задавать вопросы, ответ на которые очевиден?

Ну ты же тут пытаешься меня носом где-то повозить :sweat_smile:

Ответ “НЕТ”!!! Замени мне вот этот switch массивом функций:

    switch (displayMode)
    {
    case DISPLAY_MODE_SHOW_TIME:
      displayMode = DISPLAY_MODE_SET_HOUR;
      break;
    case DISPLAY_MODE_SET_HOUR:
    case DISPLAY_MODE_SET_MINUTE:
      btnSet.setButtonFlag(BTN_FLAG_EXIT);
      break;
    case DISPLAY_MODE_SHOW_TIMER_1:
    case DISPLAY_MODE_SHOW_TIMER_2:
      returnToDefMode();
      break;
    default:
      break;
    }

Что-то сомневаюсь, что получится, даже несмотря на уверенное “ДА” ))

Я слишком вежливый, чтобы прямо спрашивать: “какого хрена ты до меня докопался?” :sweat_smile:

1 лайк
#define BTN_FLAG_EXIT 123

enum index {DISPLAY_MODE_SHOW_TIME, 
            DISPLAY_MODE_SET_HOUR, 
            DISPLAY_MODE_SET_MINUTE, 
            DISPLAY_MODE_SHOW_TIMER_1, 
            DISPLAY_MODE_SHOW_TIMER_2};

class tBtnSet {
  public:
  void setButtonFlag(int n) {
    Serial.print("   setButtonFlag ");
    Serial.println(n);
    };
} btnSet;

void returnToDefMode() {  Serial.println("   returnToDefMode"); };

int func_0(int n) {
  Serial.println("   func DISPLAY_MODE_SHOW_TIME");
  return DISPLAY_MODE_SET_HOUR;
}

int func1(int n) {
  btnSet.setButtonFlag(BTN_FLAG_EXIT);
  return n;
}

int func2(int n) {
  returnToDefMode();
  return n;
}

int func3(int n) {
  Serial.println("   func default");
  return n;
}

int (*fn[])(int n) = {func_0, func1, func1, func2, func2, func3};

void setup() {
  Serial.begin(115200);
  Serial.println('\n');
  for(int i = 0; i < 6; i++) {
    int j = i<5 ? i : 5;
    Serial.print("ArrFunc in: ");
    Serial.println(j);
    int k = fn[j](j);
    Serial.print("ArrFunc out: ");
    Serial.println(k);
  }
  for(int i = 0; i < 6; i++) {
    int j = i<5 ? i : 5;
    Serial.print("SwitchFunc in: ");
    Serial.println(j);
    SwitchFunc(j);
    Serial.print("SwitchFunc out: ");
    Serial.println(j);
  }
}

void loop() { }

void SwitchFunc(int &displayMode) {
  switch (displayMode)
    {
    case DISPLAY_MODE_SHOW_TIME:
      Serial.println("   case DISPLAY_MODE_SHOW_TIME");
      displayMode = DISPLAY_MODE_SET_HOUR;
      break;
    case DISPLAY_MODE_SET_HOUR:
    case DISPLAY_MODE_SET_MINUTE:
      btnSet.setButtonFlag(BTN_FLAG_EXIT);
      break;
    case DISPLAY_MODE_SHOW_TIMER_1:
    case DISPLAY_MODE_SHOW_TIMER_2:
      returnToDefMode();
      break;
    default:
      Serial.println("   case default");
      break;
    }
}

С моей колокольни это выглядит так, что ты до меня докапываешься.

1 лайк

Я ж тебе всю цепочку обсуждения выложил, в том числе показал место, где ты к ней присоединился. В конце. И я к тебе докопался? )))

По коду - поясни выгоду от такого подхода в данном конкретном случае :wink:

Да, я не сижу постоянно на форуме, поэтому зачастую присоединяюсь к обсуждения именно “в конце”. Это предосудительно?
И вообще, какое отношение имеет последовательность сообщений к тому, кто именно “докопался”?

А как ты сам оцениваешь диагноз “глупость”, употребленный тобою в сообщении №108 по отношению к варианту, предложенному собеседником?

Покажи, где я обещал выгоду.

Я-то конкретный код обсуждал, а не коня в вакууме

Так и запишем - глупость )))

Масло маслянное. Но компилятор, скорее всего, убрал тернарную операцию вовсе.

1 лайк

А что не так?
У этих строчек различное назначение:
цикл проверяет полный набор реализованных вариантов, а тернарный оператор обеспечивает, чтобы при любых других значениях выполнялась ветка default.
Если нужна проверка, последнего утверждения, пределы цикла можно расширить до 7, до 12 или до 32767 - по вкусу.

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

1 лайк

У вас переменная цикла принимает значения от 0 до 5 включительно. А тернарное условие делает вот что: если i < 5, то j = i. Если i == 5, то j = i. Переменная i не будет больше чем 5, так что ваше тернарное условие можно было заменить на j = i. Что компилятор, я уверен, и сделал