Информация: Уважаемые посетители! В течение нескольких месяцев на форуме существовала проблема с регистрацией новых пользователей, о которой администрации стало известно недавно. Если вы ранее пытались зарегистрироваться на форуме, но не получили на ваш e-mail письмо с ссылкой для подтверждения регистрации, просим вас зарегистрироваться повторно. Приносим извинения за доставленные неудобства. Если вы все еще испытываете проблемы с регистрацией на форуме, обратитесь за помощью на e-mail: mr.angelo@railroadsim.net

Аватара пользователя
Света
 
Сообщения: 236
Зарегистрирован: 18.06.2016, 19:38
Играю в: RailWorks
Роль: Разработчик
Блог: Просмотр блога (2)
Архивы
Поиск в блогах

Функция-драйвер для локомотивного светофора

Постоянная ссылка Света 29.08.2017, 12:28

Представляю вашему вниманию завершенный модуль-функцию (драйвер), предназначенную упростить и автоматизировать управление локомотивным светофором С-2-5М.

Особенности драйвера:
1. Автоматическая обработка команды.
2. Автоматический переход в режим ожидания после выполнения всех команд.
3. Стабильность временных отсчетов.
4. Встроенный стек команд.
5. Смена показаний светофора происходит с фиксированной скоростью, между отключением прежнего показания и зажиганием нового предусмотрено полное отключение огней, имитирующее переходные процессы в блоке АЛСН.
6. Простота использования.

Описание принципа работы:
Алгоритм драйвера состоит из 2 блоков - тактового и командного.

Командный блок предназначен для обработки команд.
При поступлении команды производится сверка текущего режима светофора или, если светофор находится в состоянии переключения - следующего режима; в случае совпадения команда игнорируется. Благодаря этому нет надобности контролировать отправку команд на драйвер - командный блок с этим справится, отсеяв дубликаты.
Также командный блок формирует последовательности команд и загружает их в стек. Благодаря этому можно отправлять любые команды в любой последовательности и с любой скоростью, все они будут помещены в стек и выполняться по заданному времени.
Если поступила команда на новое показание, в стек предварительно будет загружена команда полного гашения. На практике это даст такой эффект работы - гашение предыдущего показания, задержка, включение нового показания.
Если поступила команда тестирования, в стек предварительно будут загружены: команда полного гашения, команда теста, команда полного гашения и текущая выполняемая команда. Эффект работы - гашение текущего показания, задержка, включение всех огней (тест), гашение всех огней, задержка, восстановление предыдущего показания.
При получении команды, командный блок переводит драйвер в активный режим.

Тактовый блок обрабатывает команды, помещенные в стек, с привязкой ко времени .
Как только драйвер переводится в активный режим, проверяется наличие команд в стеке. Если команд нет, драйвер перейдет в режим ожидания. Это означает, что получив тактовый запрос, драйвер проверит свой режим и, если ничего не изменилось, будет выход из функции. Если же команда в стеке обнаружена, драйвер перейдет в активный режим и запустит команду на выполнение. После того, как время, заданное на выполнение команды, истечет, команда будет удалена из стека и цикл повторится. Таким образом, драйвер будет в активном режиме до тех пор, пока последовательно не выполнит все команды, помещенные в стек.

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

Использование:
Светофор АЛСН должен обслуживаться одним контролом, интерфейс которого состоит из вкладок Interior visibility object - по одной вкладке на каждый режим работы:
Изображение
В моем случае это 7 вкладок - З, Ж, КЖ, К, Б, КЖ+Б и "тест".
Как видно по скрину, в каждой вкладке нужно прописать имя нода огонька светофора и значение контрола, при котором этот огонек будет активироваться.

В скрипте нужно создать таблицу, в которой будут указаны команды управления и соответствующие им значения контрола, при которых активируется требуемый нод:
Код: Выделить всё
TabALSN = {
   ["red"]         =   {node = 1},
   ["white"]      =   {node = 2},
   ["yellow-red"]   =   {node = 3},
   ["yellow"]      =   {node = 4},
   ["green"]      =   {node = 5},
   ["YRW"]         =   {node = 6},
   ["test"]      =   {node = 7},
   ["clear"]      =   {node = 0}
   }

Команды, за исключением жестко заданных "clear" и "test", могут быть любые, но, естественно, удобнее применять очевидные имена.
Также надо проинициализировать используемые драйвером переменные:
Код: Выделить всё
   TabComALSN = {}
   StatusALSN = "none"
   ProcessALSN = "waiting"
   
   DisplayAdjustment ("clear") -- гашение светофора

В функции Update (time) делаем тактирование драйвера:
Код: Выделить всё
DisplayAdjustment (time)

Для отсылки команды делаем вызов, указав команду (какую команду указываем, такой нод по таблице TabALSN и включится, например:
Код: Выделить всё
   DisplayAdjustment ("green"), для включения зеленого огня,
   DisplayAdjustment ("red"), для включения красного огня,
   DisplayAdjustment ("clear"), для гашения всех огней.


Код функции:
Код: Выделить всё
-------------------------------------------------------------------------------------
--
-- Обработчик локомотивного светофора
function DisplayAdjustment (data)
   if type (data) == "number" then
      if ProcessALSN == "none" then
         return
      elseif ProcessALSN == "waiting" then
         if TabComALSN[1] then
            StatusALSN = TabComALSN[1]
            ProcessALSN = "transition"
            if StatusALSN == "clear" then
               Call( "SetControlValue", "ALSN", 0, 0)
               Timer ("alsn_clear", 0.7)      -- Время ожидания при переключении огней
            elseif StatusALSN == "test" then
               Call("SetControlValue", "ALSN", 0, 7)
               Timer ("alsn_test_delay", 3)   -- Время свечения всех ламп (тест)
            else
               Timer ("alsn_on", 0.20)
               Call( "SetControlValue", "ALSN", 0, TabALSN[StatusALSN].node )
            end
            table.remove (TabComALSN, 1)
         else
            ProcessALSN = "none"
            return
         end
      elseif ProcessALSN == "transition" then
         if StatusALSN == "clear" then
            if Timer ("alsn_clear") then
               Timer ("alsn_clear", "clear")
               Call( "SetControlValue", "ALSN", 0, 0)
               ProcessALSN = "waiting"
            end
         elseif StatusALSN == "test" then
            if Timer ("alsn_test_delay") then            
               ProcessALSN = "waiting"
               Timer ("alsn_test_delay", "clear")
            end         
         else
            if Timer ("alsn_on") then
               ProcessALSN = "waiting"
               Timer ("alsn_on", "clear")
            end
         end
      end
   else
      local len = 0
      for k, v in pairs (TabComALSN) do
         len = k
      end
      if StatusALSN == data or TabComALSN[len] == data then
         return
      else
         if data ~= "clear" then
            table.insert (TabComALSN, "clear")
         end
         table.insert (TabComALSN, data)
         
         if data == "test" then
            table.insert (TabComALSN, "clear")
            table.insert (TabComALSN, StatusALSN)
         end
         
         if ProcessALSN == "none" then
            ProcessALSN = "waiting"
         end
      end
   end
end
-------------------------------------------------------------------------------------

Извиняться — не значит быть воспитанным. Быть воспитанным — значит не допускать того, за что необходимо извиняться. (с)
0 комментариев 510 просмотров

Кто сейчас на конференции

Зарегистрированные пользователи: Alexa [Bot], Bing [Bot], Google [Bot], Yandex [Bot]