AlexandrY 2 27 февраля, 2019 Опубликовано 27 февраля, 2019 · Жалоба Пример простого снипета в Stateflow, который принимает состояние кнопки и выдает сообщение когда кнопку нажимают по определенному шаблону. Скажем у вас в дивайсе есть только одна кнопка и надо с нее выдать несколько команд, тогда нажимаем один раз коротко и один раз долго - это будет одна команда, два раза коротко , один раз долго - другая. Снипет ниже это делает Вход здесь - состояние кнопки btn_pressed Выход - очередь сообщений Action А вот схема тестовой установки в Simulink А вот графики с тестовой установки Теперь из этого снипета можно сгенерировать надежный код на C , C++, HDL или для PLC таких как OMRON или SIEMENS Без RTOS и без самопальных кооперативных планировщиков. Но мой взгляд очень удобный метод программирования. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
petrov 6 27 февраля, 2019 Опубликовано 27 февраля, 2019 · Жалоба ИМХО не из всех конструкций в этом Stateflow будут генерироваться правильные автоматы в HDL. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 2 27 февраля, 2019 Опубликовано 27 февраля, 2019 · Жалоба 44 minutes ago, petrov said: ИМХО не из всех конструкций в этом Stateflow будут генерироваться правильные автоматы в HDL. Кто же спорит. Да, нужна сноровка. Было бы это так же просто как ардуино, на этом месте было бы уже вытоптанное поле, а StateFlow выпускался бы в эксклюзивной бесплатной версии под Synergy. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alexunder 4 27 февраля, 2019 Опубликовано 27 февраля, 2019 · Жалоба Интересные примеры. Какая версия Matlab использовалась? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 2 27 февраля, 2019 Опубликовано 27 февраля, 2019 · Жалоба 17 minutes ago, alexunder said: Интересные примеры. Какая версия Matlab использовалась? 2018B Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 27 февраля, 2019 Опубликовано 27 февраля, 2019 · Жалоба 6 часов назад, AlexandrY сказал: Без RTOS и без самопальных кооперативных планировщиков. Идея не нова сама по себе - первое, что попалось на глаза: https://www.natural-sciences.ru/ru/article/view?id=30104 https://scratch.mit.edu/about Хоть второй и, по сути, игрушка, но полноценно раскрывает идею визуального программирования. А теперь по существу. AlexandrY, а реальный выхлоп в виде Си-кода, и результирующего ассемблерного кода на реальной платформе (что у Вас там, Renesas Cortex-M4?) привести можете? А то Вам сначала пикосекундные задержки в Zynq дорогу перешли, то жесткий пресвятой реалтайм жизненно необходим; а тут (вдруг ?) окажется, что кнопку опросить килобайт 10 кода уйдет P.S. Графики желательно было подписать. На третьем графике не понятны действующие лица. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yes 5 27 февраля, 2019 Опубликовано 27 февраля, 2019 · Жалоба это какой-то вырожденный вариант цепей/сетей Петри (Petri net) ? вроде как и обычное описание FSM (state-condition) тоже вырожденный вариант если можно больше одного "шарика" по диаграмме гонять, то невырожденный вроде бы... вообще Petri net штука занятная, но в общем виде не особо для программирования удобная Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 2 27 февраля, 2019 Опубликовано 27 февраля, 2019 · Жалоба 1 hour ago, Arlleex said: а тут (вдруг ?) окажется, что кнопку опросить килобайт 10 кода уйдет Код с этой модели вот такой генерируется: Spoiler /* * File: ButtonService.c * * Code generated for Simulink model 'ButtonService'. * * Model version : 1.7 * Simulink Coder version : 9.0 (R2018b) 24-May-2018 * C/C++ source code generated on : Wed Feb 27 17:13:16 2019 * * Target selection: ert.tlc * Embedded hardware selection: ARM Compatible->ARM Cortex * Code generation objectives: Unspecified * Validation result: Not run */ #include "ButtonService.h" #include "ButtonService_private.h" /* Named constants for Chart: '<Root>/ButtonService' */ #define ButtonServic_IN_NO_ACTIVE_CHILD ((uint8_T)0U) #define ButtonService_IN_PRESSED ((uint8_T)1U) #define ButtonService_IN_RELEASED ((uint8_T)2U) /* Exported block parameters */ int32_T ACT1 = 1; /* Variable: ACT1 * Referenced by: '<Root>/ButtonService' */ int32_T ACT2 = 2; /* Variable: ACT2 * Referenced by: '<Root>/ButtonService' */ int32_T LONG_TIMEOUT = 5; /* Variable: LONG_TIMEOUT * Referenced by: '<Root>/ButtonService' */ int32_T PTTRN_1 = 5; /* Variable: PTTRN_1 * Referenced by: '<Root>/ButtonService' */ int32_T PTTRN_2 = 9; /* Variable: PTTRN_2 * Referenced by: '<Root>/ButtonService' */ /* Block states (default storage) */ DW_ButtonService_T ButtonService_DW; /* External inputs (root inport signals with default storage) */ ExtU_ButtonService_T ButtonService_U; /* External outputs (root outports fed by signals with default storage) */ ExtY_ButtonService_T ButtonService_Y; /* Real-time model */ RT_MODEL_ButtonService_T ButtonService_M_; RT_MODEL_ButtonService_T *const ButtonService_M = &ButtonService_M_; /* Model step function */ void ButtonService_step(void) { boolean_T condIsTrue; int32_T q0; /* Chart: '<Root>/ButtonService' incorporates: * Inport: '<Root>/btn_pressed' * Outport: '<Root>/pttrn' */ ButtonService_DW.chartAbsoluteTimeCounter++; condIsTrue = (ButtonService_DW.is_c3_ButtonService == ButtonService_IN_PRESSED); if ((!condIsTrue) || (!ButtonService_DW.condWasTrueAtLastTimeStep_1)) { ButtonService_DW.durationLastReferenceTick_1 = ButtonService_DW.chartAbsoluteTimeCounter; } ButtonService_DW.condWasTrueAtLastTimeStep_1 = condIsTrue; condIsTrue = (ButtonService_DW.is_c3_ButtonService == ButtonService_IN_RELEASED); if ((!condIsTrue) || (!ButtonService_DW.condWasTrueAtLastTimeStep_1_b)) { ButtonService_DW.durationLastReferenceTick_1_o = ButtonService_DW.chartAbsoluteTimeCounter; } ButtonService_DW.condWasTrueAtLastTimeStep_1_b = condIsTrue; if (ButtonService_DW.is_active_c3_ButtonService == 0U) { ButtonService_DW.chartAbsoluteTimeCounter = 0; ButtonService_DW.is_active_c3_ButtonService = 1U; /* Outport: '<Root>/pttrn' */ ButtonService_Y.pttrn = 1; /* Outport: '<Root>/action' */ ButtonService_Y.action = 0; if (ButtonService_U.btn_pressed) { ButtonService_DW.durationLastReferenceTick_1 = ButtonService_DW.chartAbsoluteTimeCounter; ButtonService_DW.is_c3_ButtonService = ButtonService_IN_PRESSED; ButtonService_DW.condWasTrueAtLastTimeStep_1 = (ButtonService_DW.is_c3_ButtonService == ButtonService_IN_PRESSED); } else { ButtonService_DW.durationLastReferenceTick_1_o = ButtonService_DW.chartAbsoluteTimeCounter; ButtonService_DW.is_c3_ButtonService = ButtonService_IN_RELEASED; ButtonService_DW.condWasTrueAtLastTimeStep_1_b = (ButtonService_DW.is_c3_ButtonService == ButtonService_IN_RELEASED); } } else if (ButtonService_DW.is_c3_ButtonService == ButtonService_IN_PRESSED) { if (!ButtonService_U.btn_pressed) { condIsTrue = (ButtonService_DW.is_c3_ButtonService == ButtonService_IN_PRESSED); if ((!condIsTrue) || (!ButtonService_DW.condWasTrueAtLastTimeStep_1)) { ButtonService_DW.durationLastReferenceTick_1 = ButtonService_DW.chartAbsoluteTimeCounter; } ButtonService_DW.condWasTrueAtLastTimeStep_1 = condIsTrue; if (ButtonService_DW.chartAbsoluteTimeCounter - ButtonService_DW.durationLastReferenceTick_1 >= (LONG_TIMEOUT << 1)) { if (ButtonService_Y.pttrn > 1073741823) { q0 = MAX_int32_T; } else if (ButtonService_Y.pttrn <= -1073741824) { q0 = MIN_int32_T; } else { q0 = ButtonService_Y.pttrn << 1; } if (q0 > 2147483646) { ButtonService_Y.pttrn = MAX_int32_T; } else { ButtonService_Y.pttrn = q0 + 1; } } else if (ButtonService_Y.pttrn > 1073741823) { ButtonService_Y.pttrn = MAX_int32_T; } else if (ButtonService_Y.pttrn <= -1073741824) { ButtonService_Y.pttrn = MIN_int32_T; } else { ButtonService_Y.pttrn <<= 1; } if (ButtonService_Y.pttrn == PTTRN_1) { /* Outport: '<Root>/action' */ ButtonService_Y.action = ACT1; ButtonService_Y.pttrn = 1; } else { if (ButtonService_Y.pttrn == PTTRN_2) { /* Outport: '<Root>/action' */ ButtonService_Y.action = ACT2; ButtonService_Y.pttrn = 1; } } ButtonService_DW.durationLastReferenceTick_1_o = ButtonService_DW.chartAbsoluteTimeCounter; ButtonService_DW.is_c3_ButtonService = ButtonService_IN_RELEASED; ButtonService_DW.condWasTrueAtLastTimeStep_1_b = (ButtonService_DW.is_c3_ButtonService == ButtonService_IN_RELEASED); } } else { condIsTrue = (ButtonService_DW.is_c3_ButtonService == ButtonService_IN_RELEASED); if ((!condIsTrue) || (!ButtonService_DW.condWasTrueAtLastTimeStep_1_b)) { ButtonService_DW.durationLastReferenceTick_1_o = ButtonService_DW.chartAbsoluteTimeCounter; } ButtonService_DW.condWasTrueAtLastTimeStep_1_b = condIsTrue; if (ButtonService_DW.chartAbsoluteTimeCounter - ButtonService_DW.durationLastReferenceTick_1_o > 10) { /* Outport: '<Root>/pttrn' */ ButtonService_Y.pttrn = 1; ButtonService_DW.durationLastReferenceTick_1_o = ButtonService_DW.chartAbsoluteTimeCounter; ButtonService_DW.is_c3_ButtonService = ButtonService_IN_RELEASED; ButtonService_DW.condWasTrueAtLastTimeStep_1_b = (ButtonService_DW.is_c3_ButtonService == ButtonService_IN_RELEASED); } else if (ButtonService_U.btn_pressed) { ButtonService_DW.durationLastReferenceTick_1 = ButtonService_DW.chartAbsoluteTimeCounter; ButtonService_DW.is_c3_ButtonService = ButtonService_IN_PRESSED; ButtonService_DW.condWasTrueAtLastTimeStep_1 = (ButtonService_DW.is_c3_ButtonService == ButtonService_IN_PRESSED); } else { /* Outport: '<Root>/action' */ ButtonService_Y.action = 0; } } /* End of Chart: '<Root>/ButtonService' */ } /* Model initialize function */ void ButtonService_initialize(void) { /* Registration code */ /* initialize error status */ rtmSetErrorStatus(ButtonService_M, (NULL)); /* states (dwork) */ (void) memset((void *)&ButtonService_DW, 0, sizeof(DW_ButtonService_T)); /* external inputs */ ButtonService_U.btn_pressed = false; /* external outputs */ (void) memset((void *)&ButtonService_Y, 0, sizeof(ExtY_ButtonService_T)); /* SystemInitialize for Chart: '<Root>/ButtonService' */ ButtonService_DW.is_active_c3_ButtonService = 0U; ButtonService_DW.is_c3_ButtonService = ButtonServic_IN_NO_ACTIVE_CHILD; ButtonService_DW.chartAbsoluteTimeCounter = 0; } /* Model terminate function */ void ButtonService_terminate(void) { /* (no terminate code required) */ } /* * File trailer for generated code. * * [EOF] */ Тут надо понимать, что код сгенерирован может быть очень по разному. В Matlab есть куча настроек как в генерируемом коде давать имена, как объявлять аргументы, как сепарировать функции, какие типы использовать и т.д. и т.п. Код приведенный здесь сгенерирован по встроенному критерию матлаба лучшей удобочитаемости (как ни странно), а есть еще критерии оптимальности, экономии RAM, экономии Flash и т.д. Даю гарантию вручную вы напишите больше кода, особенно завязните в таймаутах и ожиданиях ивентов (или как в матлабе их называют - темпоральных функциях - after(time), before(time), duration(state) ... ) Скорее всего начнете сразу писать доморощенный шедулер. Обратите внимание на то что модель не зависает ни на такт внутри себя, она на каждом такте возвращает управление внешнему процессу. Нижний график показывает не сигнал, а события отправки в очередь сообщения об обнаружении шаблона нажатия кнопки с номером обнаруженного шаблона. 1 hour ago, yes said: это какой-то вырожденный вариант цепей/сетей Петри (Petri net) ? вроде как и обычное описание FSM (state-condition) тоже вырожденный вариант Мда, шарики навели на ложную ассоциацию с сетями Petri. Но сети Petri тут рядом не лежали. Это именно универсальная нотация программирования. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 27 февраля, 2019 Опубликовано 27 февраля, 2019 · Жалоба 4 минуты назад, AlexandrY сказал: Тут надо понимать, что код сгенерирован может быть очень по разному. ИМХО, приведенный фрагмент кода, несмотря на то, что он сгенерирован по критерию лучшей удобочитаемости, слабо читаем. За лесом переменных сути не особо-то видно. 7 минут назад, AlexandrY сказал: Даю гарантию вручную вы напишите больше кода, особенно завязните в таймаутах и ожиданиях ивентов (или как в матлабе их называют - темпоральных функциях - after(time), before(time), duration(state) ... ) Скорее всего начнете сразу писать доморощенный шедулер. Даю гарантию, что напишу меньше кода, не завязну в таймаутах и ожиданиях. Обойдусь без доморщенного шедулера и код будет куда более читаемым. Но я материально не заинтересован доказывать Вам это 13 минут назад, AlexandrY сказал: Обратите внимание на то что модель не зависает ни на такт внутри себя, она на каждом такте возвращает управление внешнему процессу. Правильно построенная задача в кооперативной/вытесняющей RTOS тоже лишние такты в тепло не превращает. 14 минут назад, AlexandrY сказал: Нижний график показывает не сигнал, а события отправки в очередь сообщения об обнаружении шаблона нажатия кнопки с номером обнаруженного шаблона. Понятно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 2 27 февраля, 2019 Опубликовано 27 февраля, 2019 · Жалоба 15 minutes ago, Arlleex said: Даю гарантию, что напишу меньше кода, не завязну в таймаутах и ожиданиях. Обойдусь без доморщенного шедулера и код будет куда более читаемым. Но я материально не заинтересован доказывать Вам это Я тоже материально не заинтересован, однако легко разработал эту модель и еще имею время с вами ее обсуждать. В этом и есть суть удобства. Код из матлаба читать не надо. Раньше тоже возмущались почему из C-и генерируется такой слабочитаемый ассемблер. Однако привыкли. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 27 февраля, 2019 Опубликовано 27 февраля, 2019 · Жалоба 19 минут назад, AlexandrY сказал: Я тоже материально не заинтересован, однако легко разработал эту модель и еще имею время с вами ее обсуждать. В этом и есть суть удобства. Код из матлаба читать не надо. Раньше тоже возмущались почему из C-и генерируется такой слабочитаемый ассемблер. Однако привыкли. Тогда последние вопросы - допустим, есть эта модель. 1. Как встроить ее в проект, который крутится, например, под RTOS с LwIP и прочим middleware? Как подружить ее с уже написанным и отлаженным софтом (например, после определения команды с кнопки дать семафор планировщику, т.е. банально вызвать OS_SemGive())? 2. Если выхлоп из StateFlow получается модуль из двух файлов .h и .c, то, подключая их к своему проекту на злом уровне оптимизации, каков шанс, что оптимизатор не выкинет половину сгенерированного кода? А если выкинет, то как разобраться, почему он это выкинул, если код из матлаба читать не возможно (и, якобы, не надо)? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
petrov 6 27 февраля, 2019 Опубликовано 27 февраля, 2019 · Жалоба 8 hours ago, AlexandrY said: Кто же спорит. Да, нужна сноровка. Было бы это так же просто как ардуино, на этом месте было бы уже вытоптанное поле, а StateFlow выпускался бы в эксклюзивной бесплатной версии под Synergy. Да в принципе не сложно там всё, наверное как раз дороговизна и мешает заменить древний дрянной HDL. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
twix 0 28 февраля, 2019 Опубликовано 28 февраля, 2019 (изменено) · Жалоба Скажу так, идея фуфло в принципе. Изменено 28 февраля, 2019 пользователем twix Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
petrov 6 28 февраля, 2019 Опубликовано 28 февраля, 2019 · Жалоба twix Визуализация это обработка графической информации. Так вот затраты мозга на работу с графикой по сравнению с текстом ну как у обычного компа, примерно в 100... 1000 раз. Вот бы в текстовый вид перевести разработку схем, печатных плат, антенн и т. д. и т. п. Удачная визуализация всегда сильно продвигает вперёд. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SVNKz 1 28 февраля, 2019 Опубликовано 28 февраля, 2019 · Жалоба Процесс разрабоки программы необходимо разделять на четыре и более, сколько необходимо, этапов. Приоритет ВСЕГДА должен принадлежать заказчику - клиент всегда прав. На первом этапе заказчик должен возможно точнее описать в ТЗ все свои требования, а исполнитель подтвердить или опровергнуть возможность разработки программы в соответствии с ТЗ. Диалог заказчика и исполнителя по алгоритму работы программы должен происходить по наглядно изложенному функциональному алгоритму, в котором ВСЕ требования заказчика изложены понятным и удобным для договаривающихся сторон виде. Это классика методики разработки программ подробно и грамотно изложена в учебниках. Умные и одарённые самоучки-энтузиасты пренебрегают изучением основ программирования и часто даже не знают о существовании такого рода области знаний и литературы. ТС для примера показал алгоритм ввода необходимого клиенту значения посредством ШИМ двух кнопок. Этот метод давно разработан и широко используется. ТС представил избыточный по количеству кнопок и состояний алгоритм - достаточно одной кнопки. https://zenner.nt-rt.ru/ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться