Таблица состояний, как лучше ее обрабатывать

kost82
Offline
Зарегистрирован: 30.11.2015

Добрый день!

Собираю устройство, у которого есть цифровых 8 входов и небольшой OLED-экран. Есть таблица состояний в которой расписаны возможные состояния этих входов и в зависимости от этих состояний на экранчике надо отображать букву или цифру. Всего возможно 9 состояний (комбинаций).

Можно конечно заморочиться и создать кучу условий if...else... или swich...case, но думается мне, что в этом зоопарке легко будет запутаться и поддерживать все это (если вдруг сменится комбинация в таблице) будет непросто.

Есть еще идея считывать состояния портов и записывать их в двоичное число, а потом сверять его с некоторой "маской". Но возможно с этим будет не меньше заморочек. Например есть состояния в которых значения на некоторых входах безразличны. То есть вне зависимости от того что на них будет - цифра/буква на экране будет одна и та же.

Может есть еще какой-то способ? Хочется все сделать без костылей и велосипедов.

zbot
Offline
Зарегистрирован: 15.03.2020

массив и 8 входов как его индекс?

rkit
Offline
Зарегистрирован: 23.11.2016

В 9 состояний боишься запутаться? Серьезно?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

kost82 пишет:
Можно конечно заморочиться и создать кучу условий if...else... или swich...case, но думается мне, что в этом зоопарке легко будет запутаться и поддерживать все это (если вдруг сменится комбинация в таблице) будет непросто.

Может есть еще какой-то способ? Хочется все сделать без костылей и велосипедов.

Здесь происходит следующее. Вот возьмем к примеру автомат Калашникова. У него есть ствол, магазин,спусковой крючек и приклад. Когда это все вместе он работает/стреляет. А когда чего-то нет, то почему-то с работой у него не очень заладится.

Вот так и у Вас.Какой-то элемент теряете и потом , а че , камраты, где нормальная работа.

Итак, это состояние, функция перехода в это состояние, функция опроса условия и функция вообще работы всего этого устройства

Состояние это некая переменная state в которой записано некое число символизирующее состояние устройства 0-Стоим,1- Идем,2-Бежим ну и так далее.

Функция перехода в это состояние. void stand(byte state) . Удобно собрать все переключение в отдельную функцию и потом в нужных местах программы делать переход устройства в это состояние.

Функция опроса условия.Здесь надо отличать условия от состояния. Состояние это значение переменной. А условие это определенная комбинация на выводах. Хотя у вас 8 входов, по факту вас интересует только несколько комбинаций. Вот и сконцентрируйте их в условия 0,1,3 в функции byte condisinal(void);

Функция вообще работы всего этого устройства. Ну а это функция которою вы воткнете в loop() программы. В setup() разумеется написать stand(state_0);  Оформлена функция работы через switch . Вызов функции опроса условий и потом если состояние такое и условие такое то сделать переход в это состояние. И все. В коде это еще проще.

mixail844
Offline
Зарегистрирован: 30.04.2012

вам нужно описать boolean function которая будет делать преображение f(in0,in1,...in7) -> [state0,state1..state8] .если у вас есть таблицая истинности(состояний) то делаеться чисто технически . затем используя правила булевой алгебры постараться ее описать меншим количеством литералов. 

затем останеться просто каждый раз подставлять ваши значения из in0,in1,...,in7 в вашу функцию и получать состояния.

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

естественно , если меняються значения состояний, меняеться и функция. 

 

или же описать фукцию которая будеть преобразовывать f1(in0,in1,...in7) -> [0,1..8] , а затем эти значения ,как посоветовали выше, использовать как индекс массива ,коорый в свою очередь являеться массивом фукций , где каждая фунциявыводит на экран нужную букву или цифру .

sadman41
Offline
Зарегистрирован: 19.10.2016

Лучше делай свич, а то Квон залечит ))

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Вот квон устроился хорошо, такую траву даже на сенокосе фиг встретишь. А уже сентябрь, почти октябрь. Молоток!!!

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

//------------состояние--
const byte state_0 = 0;
const byte state_1 = 1;
const byte state_2 = 2;
//------------условия--
const byte cond_0 = 0;
const byte cond_1 = 1;
const byte cond_2 = 2;
byte state;
void stand(byte s);
byte conditional(void);
void run();

//--------------------------
void setup() {
  stand(state_0);
}

void loop() {
  run();
}

void stand(byte s) {
  state = s;
  switch (state) {
    case state_0:
      break;
    case state_1:
      break;
    case state_2:
      break;
  }
}
byte conditional(void) {
  if (0) return cond_0;
  else if (1)return cond_1;
  else return cond_2;
}
void run() {
  byte cond = conditional();
  switch (state) {
    case state_0:
      if (cond == cond_1) return stand(state_1);
      if (cond == cond_2) return stand(state_2);
      break;
    case state_1:
      if (cond == cond_2) return stand(state_2);
      if (cond == cond_0) return stand(state_0);
      break;
    case state_2:
      if (cond == cond_1) return stand(state_1);
      if (cond == cond_0) return stand(state_0);
      break;
  }
}

 

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

qwone пишет:


//------------состояние--
const byte state_0 = 0;
const byte state_1 = 1;
const byte state_2 = 2;
//------------условия--
const byte cond_0 = 0;
const byte cond_1 = 1;
const byte cond_2 = 2;
byte state;
void stand(byte s);
byte conditional(void);
void run();

//--------------------------
void setup() {
  stand(state_0);
}

void loop() {
  run();
}

void stand(byte s) {
  state = s;
  switch (state) {
    case state_0:
      break;
    case state_1:
      break;
    case state_2:
      break;
  }
}
byte conditional(void) {
  if (0) return cond_0;
  else if (1)return cond_1;
  else return cond_2;
}
void run() {
  byte cond = conditional();
  switch (state) {
    case state_0:
      if (cond == cond_1) return stand(state_1);
      if (cond == cond_2) return stand(state_2);
      break;
    case state_1:
      if (cond == cond_2) return stand(state_2);
      if (cond == cond_0) return stand(state_0);
      break;
    case state_2:
      if (cond == cond_1) return stand(state_1);
      if (cond == cond_0) return stand(state_0);
      break;
  }
}

 

 

Зачем так громоздко? Все гораздо проще на массиве структур делается. Если ОЗУ начнет нехватать, то можно в PROGMEM запихать. Но для 9 соостояний и коротких сообщений особой необходимости я не вижу

 



typedef struct
{
  byte state;  /*Здесь описываем нужные нам состояния*/
  byte ignore; /*здесь записываем 1-ки в тех битах на которые внмание не обращаем*/
  String msg;
} Record;

Record records[] = {
// состояние, игнор биты, сообщение
  0b11001100,0b00000011, "Msg1",
  0b00011000,0b11000000, "Msg2",
  0b00000011,0b00000000, "Msg3"
  };

String GetMsgByState(byte state)
{
  for (int i = 0; i < sizeof(records) / sizeof(Record); i++)
  {
    if ((~(records[i].ignore) & state) == records[i].state) return records[i].msg;
  } 
  return "Not Found";;
}
void setup() {
  Serial.begin(115200);
  byte st = 0b00011000;;
  Serial.println(GetMsgByState(st));
  st = 0b00011100;
  Serial.println(GetMsgByState(st));
  st = 0b11001101;
  Serial.println(GetMsgByState(st));
  st = 0b11001110;
  Serial.println(GetMsgByState(st));
}


void loop() {


}

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

kost82 пишет:

Есть еще идея считывать состояния портов и записывать их в двоичное число, а потом сверять его с некоторой "маской". Но возможно с этим будет не меньше заморочек. Например есть состояния в которых значения на некоторых входах безразличны. То есть вне зависимости от того что на них будет - цифра/буква на экране будет одна и та же.

Ты вот сейчас, у нас на глазах, ПЛМ придумал

kost82
Offline
Зарегистрирован: 30.11.2015

zbot пишет:

массив и 8 входов как его индекс?

Cпасибо! Идея мне понравилась. Главное реализуется легко и поддерживается/расширяется тоже.

rkit пишет:

В 9 состояний боишься запутаться? Серьезно?

Состояний 9, а вложенных условий if-else может быть слишком дофига в коде. Когда через месяц-другой мне надо будет изменить таблицу состояний - нужно будет долго вникать в код. Ну и да, какое-то условие можно легко пропустить.

qwone, asam  - подъ@б засчитан :-)

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

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

kost82 пишет:

 

qwone, asam  - подъ@б засчитан :-)

Вот делай после этого людям добро. Старался, реализовывал задачу, пол-часа потратил. Все работает как тебе нада. И вместо спасибо, ответ такое. Какого х..?  Да больше никогда никому код за просто так писать не буду. 

Чем тебя не устраиват-то? Или просто способностей разобраться как оно работает не хватило?

kost82
Offline
Зарегистрирован: 30.11.2015

Не обижайтесь, но фраза

asam пишет:

Если ОЗУ начнет нехватать, то можно в PROGMEM запихать.

при обработке 9 состояний выглядит как стеб. Если это не так - дико извиняюсь.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

kost82 пишет:

Не обижайтесь, но фраза

asam пишет:

Если ОЗУ начнет нехватать, то можно в PROGMEM запихать.

при обработке 9 состояний выглядит как стеб. Если это не так - дико извиняюсь.

Что конкретно выглядит как стеб? Ты определяешь таблицу состояний (8 входов это 8 бит в одном байте)(я сделал только 3, для 9 надо добавить еще 6 строчек) и передаешь в GetMsgByState() текущее состояние  и получаешь в ответ сообщение для экрана. Если надо выводить только один символ, а не строку, то замени String на char.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ASAM! А вот если бы не стринги он может быть и не возбудился )))

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

ua6em пишет:

ASAM! А вот если бы не стринги он может быть и не возбудился )))

Да уж. человек 5 лет на форуме, а до сих пор в простейшем коде разобраться не в состоянии.

kost82
Offline
Зарегистрирован: 30.11.2015

Видимо после лекции qwone про автомат Калашникова у меня мозг совсем отключился. Простите великодушно.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

kost82 пишет:

Видимо после лекции qwone про автомат Калашникова у меня мозг совсем отключился. Простите великодушно.

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

 

 

rkit
Offline
Зарегистрирован: 23.11.2016

kost82 пишет:

Состояний 9, а вложенных условий if-else может быть слишком дофига в коде.

Если 9 состояний, то больше 9 if не надо.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

asam пишет:

ua6em пишет:

ASAM! А вот если бы не стринги он может быть и не возбудился )))

Да уж. человек 5 лет на форуме, а до сих пор в простейшем коде разобраться не в состоянии.

как простейший? ты там побитовые операции используешь )))

kost82
Offline
Зарегистрирован: 30.11.2015

asam пишет:

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

Да нет, с кодом все в порядке. Просто мне после лекции про то как автоматы Калашникова бороздят просторы большого театра показалось, что начался обычный для этого форума стеб, поэтому в суть кода я не особо вникал, а уцепился за идею с ключами массивов, которая мне показалась простой и понятной. Еще раз извиняюсь за это.

kost82
Offline
Зарегистрирован: 30.11.2015

Решение подходящее, единственное "но" - я не хотел опрашивать в каждом цикле состояние входов, которые безразличны в данном состоянии. Но с другой стороны - пусть ардуина трудится и опрашивает. Не настолько это ресурсозатратная операция.
Ну и да, каюсь, что в побитовых операциях я до сих пор "плаваю", т.к. очень редко ими пользуюсь. Каждый раз приходится гуглить их глубокий смысл.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

zbot пишет:

массив и 8 входов как его индекс?

8-битовый индекс для простой реализации требует 256-элементного массива. А тут всего 9 рабочих состояний - жирновато, как по мне.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

kost82 пишет:
Когда через месяц-другой мне надо будет изменить таблицу состояний

Автоматы делаются не так. Выбирается структура данных для таблицы состояний таком образом, чтобы программа просто проходила по таблице никак на неё не заморачиваясь (получается одна и та же программа для любой таблицы). Тогда, если Вам через месяц потребуется изменить таблицу - Вы просто её измените никак не притрагиваясь к программе.

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

kost82
Offline
Зарегистрирован: 30.11.2015

Конечно интересно. Жду вечера.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Оп, а я сейчас нашёл. Вот с этого поста. Хотя, лучше читать с начал темы, там теория построения автоматов и вообще много полезного.

SLKH
Offline
Зарегистрирован: 17.08.2015

Тупо и надежно:

один массив (256) символов, которые нужно отображать при соответствующей комбинации входов. можно в progmem.

Например:

b00000000 "0"

b00000001 "1" 

..........

b01010100 "7"

b01010101 "7"

..........

b00110001 "1"

...........

b00111001 "1"