Идеальная программа на С для МК — продолжение

Введение в продолжение

В мы начали разработку программы для МК некоторого устройства. Мы получили первую версию алгоритма работы этого устройства записанного в С-подобном стиле. Также мы провели анализ этого алгоритма и наметили проблемы и/или ошибки которые нужно решить, а также некоторые теоретические вопросы связанные с общим пониманием построения алгоритма, такие как идентификация состояний и сущностей которым эти состояния принадлежат.

Мы пишем первую версию (и все промежуточные версии) программы не для того чтобы решить поставленную заказчиком программы (устройства) задачу! Сначала мы должны убедиться, что задача правильно (корректно) сформулирована и мы ее правильно поняли! Потому первая задача которую мы решаем и, соответственно, должна решать наша программа это демонстрация возможностей и идентификация, измерение параметров, значения которых и будут составлять  окончательные технические требования к устройству и его встроенной программе.

Разработка ПО тем более встроенного ПО всегда включает в себя этот этап верификации и уточнения задания. Будь оно сформулировано по всем правилам как техническое задание или выражено в виде некоторых пожеланий-предположений о требуемой функциональности устройства оно все равно требует проверки РЕАЛИЗУЕМОСТИ (feasibility по английски).

Уточнение понимания работы управляемой системы, ловушка очевидности

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

Система работает вот таким образом <здесь приводится «очевидное» описание>, потому что по другому сделать нельзя!

По крайней мере мой опыт показывает что никогда нельзя опираться на непроверенное представление о работе системы подлежащей управлению. Это значит что мы не лишь должны иметь представление о работе системы, которой мы собираемся управлять. Мы должны придумать, как проверить это свое представление!

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

Я исходил из того что реле прерывателя включается лишь с подрулевого рычага, и поэтому параллельный ключ, который добавляет наше устройство не включит прерывания! Переключение режима работы прерывателя изображено на Рис.1.

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

В конце концов я выяснил у автора задачи что прерыватель включается при появлении напряжения в цепи ламп поворотников (любых). То есть замыкание дополнительного ключа также включает прерыватель! Рис.2

Про состояния или проблема терминологии

В нашем случае можно определить:

  • состояние управляемой системы (назовем его RLC) которое МК получает ввиде 3-х битного слова по линиям inL, inR, inC;
  • состояния устройства которое МК формирует на выходах outR, outL;

Дело в том что вот это значение RLC кодирующее положение подрулевого рычага мы взяли и обозвали «состоянием», а это тянет и уводит нас в какие-то высшие сферы, дальние дали абстрактных мат.теорий о машинах состояний. Я предлагаю забыть слово состояние, и обзывать это значение «параметром» нашего алгоритма, это позволяет сосредоточиться на практических аспектах решения конкретной задачи!

Тем более есть глобальные состояния устройства, которые действительно важно различать:

  • это активное состояние устройства, когда устройство замкнет хотя бы один дублирующий ключ, таким образом обеспечивая вмешательство в работу управляемой системы(активность проявляя), и
  • пассивное состояние – это ожидание активирующего устройство события (событие включения поворотника здесь).

Код с состояниями

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

Я бы main() написал вот так:

uint8_t rlCode;
uint8_t rlCodeSaved;
uint8_t count_pause;

int main(void)
{
   port_ini(); //инициализация портов

StartPoint:
   //начинаем с отключенными ключами устройства:
   PORTB &= ~((1 << RIGHT_OUT) | (1 << LEFT_OUT));
   count_pause = 0;
   do{//ждем нажатия поворотника:
   rlCode = get_code();
   } while (!(rlCode == command_Right || rlCode == command_Left));
   //устройство переключается в активное состояние-замыкает дублирующий ключ,
   //который закодирован в rlCode:
   if (rlCode == command_Right) { PORTB |= (1 << RIGHT_OUT); }
   if (rlCode == command_Left) { PORTB |= (1 << LEFT_OUT); }
//мы продублировали замыкание цепи от подрулевого рычага!
   rlCodeSaved = rlCode;
   while (1)// цикл отсчета продленного кол-ва «морганий поворотника»
   {//—>LOOP
   do{//ждем переключения поворотника или паузу от прерывателя
   rlCode = get_code();//дребезг=command_Error тоже игнорируем:
//мы продублировали замыкание цепи от подрулевого рычага, поэтому
//если рычаг вернется в нейтральное положение условие все равно будет выполняться:
   } while (rlCode == rlCodeSaved || rlCode == command_Error);
   if (rlCode != command_Pause) goto StartPoint;
   count_pause++;//считаем разы продленного «моргания» на каждой паузе!
   if (count_pause == TURN_COUNT)
   {//rlCodeSaved хранит инфу о том какой поворотник мы включили!
   //но мы можем просто выключить оба здесь!
   PORTB &= ~((1 << RIGHT_OUT) | (1 << LEFT_OUT));// отключили дублирование
// NO goto StartPoint; теперь мы должны дождаться когда отключат этот поворотник!
//чтобы повторно не включить удлиннение нажатия поворотника
   }
   do{
   rlCode = get_code();//ждем окончания паузы
   } while (rlCode == command_Pause || rlCode == command_Error);
//возвращаемся в //начало циклА отсчета продленного кол-ва «морганий поворотника»—>LOOP
   }
}

Идеальная программа???

Я наверно всех разочарую, потому что в конце концов вынужден написать банальную вещь:

Идеальной программа станет лишь тогда, когда будет проверена ее стабильная работа в реальном «железе», и ее работа удовлетворит пожелания заказчика разработки устройства, в какой бы форме эти пожелания не выражались!

К счастью я придумал второй критерий идеальности, который кажется на совсем банальный:

Идеальная программа должна легко (то есть достаточно быстро) позволять удовлетворять вновь возникающие пожелания заказчика (в ограниченной области функциональности, конечно), неизбежно возникающие от прикосновения ко вновь обретенным возможностям автоматизации его скучных-нудных операций 🙂 !

Мне кажется мой вариант программы удовлетворяет обоим этим критериям!

Добавить комментарий

Ваш адрес email не будет опубликован.