Jump to content
NobbyNobbs

Программирование джойстиков CH Products

Recommended Posts

Джентльмены, а нельзя ли попросить вас разобрать часть скрипта с первым способом отдельно (   1. Достигаем нужного положения самолёта, зажимаем кнопку. Игра запомнила это положение. Возвращаем ручку в центр.) Просто с наскоку, не имея опыта программирования СН, разобраться в этом огромном зубодробительном скрипте нереально.

  • Upvote 1

Share this post


Link to post
Share on other sites

Джентльмены, а нельзя ли попросить вас разобрать часть скрипта...

Не хочу отбирать хлеб и славу у Terrora. Он сможет грамотно ответить на все вопросы... 

Однако не удержусь и замечу что основа скрипта, это блок:

 

if( [ J_Stick_X <= 128 ] ) then // Если РУС дан влево, то нужно вычислить коэффициент...                                    

            C_Stick_X = 128 + A_xxx_Trim - ((( 128 - A_Stick_X ) * ( 128 + A_xxx_Trim )) / 128);

     else  //  вправо

          C_Stick_X = 128 + A_xxx_Trim + ((( A_Stick_X - 128 ) * (( 255 - 128 ) - A_xxx_Trim )) / 127);

endif

который пишется для каждой оси. Если  A_xxx_Trim = 0 ,то  C_Stick_X = A_Stick_X, что учитывая назначения в блок %DEFINE означает, что расчетное значение отклонения РУСа равно его реальному отклонению.

Если же мы "записали" для A_xxx_Trim  какое либо значение отличное от 0, то расчетное значение C_Stick_X в среднем положении РУСа (т.е. в отпущенном положении) будет "сдвигается" на эту же  величину.  Выражение же в скобках пересчитывает реальное отклонения РУСа таким образом, чтобы результат расчета всегда "укладывался" в диапазон возможных значений....

...да и кстати забыл ещё одну неточность в скрипте. Пропало объявление имен A_xxx_Trim в секции %DEFINE:

%DEFINE A_Ailerons_Trim    A4
%DEFINE A_Rudder_Trim     A5
%DEFINE A_Elevator_Trim    A6
Edited by =J13=Moroka

Share this post


Link to post
Share on other sites

Джентльмены, а нельзя ли попросить вас разобрать часть скрипта с первым способом отдельно (   1. Достигаем нужного положения самолёта, зажимаем кнопку. Игра запомнила это положение. Возвращаем ручку в центр.) Просто с наскоку, не имея опыта программирования СН, разобраться в этом огромном зубодробительном скрипте нереально.

Привет!   Вот прямо то, что тебе нужно имеется в примерах к Help'у

Устаканили самолет найдя нужное положение РУС. В это положении зажимаем кнопку, не отпуская её возвращаем джой в центр, отпускаем кнопку - значения триммирования запомнены. Джой в нуле - самолет летит прямо.

 

Ты можешь читать по английски?   Могу перевести.

post-4254-0-71368800-1409590042_thumb.gif

Share this post


Link to post
Share on other sites

Я отпишусь в ближайшее, как там работает по-подробнее, просто был со временем швах.

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

Edited by 72AG_terror

Share this post


Link to post
Share on other sites

Я отпишусь в ближайшее, как там работает по-подробнее, просто был со временем швах.

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

В общем то если пределы триммирования небольшие, то алгоритма хватает вполне. А практически всегда так и есть.

 

Хотя, как знать, может кому и мало.. только, вот не въеду ведь триммер поверхность малая, и вряд ли ей на првктике даже полхода ручки можно было скомпенсировать, а уж про крайние значения и речи нет

Share this post


Link to post
Share on other sites

В общем то если пределы триммирования небольшие, ...

Триммирование - да, небольшие величины, а вот "сказать" пилоту:

- Держи вираж/горку/снижение/ и не двигай штурвалом, пока я буду за стрелка отстреливаться...

тут алгоритм Terrora очень хорош... Сейчас при пересадке за стрелка или отдаешься автопилоту, или в лучшем случае по прямой на автогоризонте.

...Я, собственно для этого и утащил к себе ;)

Edited by =J13=Moroka

Share this post


Link to post
Share on other sites

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

 

Значит, объясняю. Для простоты рассмотрим ось элеронов (крен).

 

Суть такова:

  1. Нам нужно затриммировать крен. Для этого нужно переместить центр оси. При движении ручки из крайнего левого до крайнего правого положения выводимые джоем значения меняются от Х = 0 до Х = 255. Когда ручка в центре: Х = 128. Значит нам надо, чтобы когда ручка находилась в центре, значение было 128 + Дтрим, где Дтрим -- это такая дельта, на которую нам надо сдвинуть ручку, она может быть больше нуля, если мы хотим переместить центр вправо, или меньше нуля, если влево.
  2. Чтобы найти Дтрим, мы будем следить за нажатием определённой кнопки. В момент её нажатия мы и определим эту дельту следующим образом: Дтрим = Хтекущее - 128.
  3. При этом надо, чтобы: а) сохранялся весь диапазон оси (0 - 255), б) была возможность корректировать триммирование с хатки, в) можно было сбросить триммирование полностью.

Уже можно попрограммировать. Мы уже знаем, что нам понадобиться в скрипте, зададим это всё:

 

%DEFINE J_Stick_X   JS2.A1  // То есть мы берём первую ось джойстика, который изображён на второй вкладке нашей софтины, и обзываем её J_Stick_X, чтобы не вспоминать, как она там нумеруется.

 

Теперь кнопку:

 

%DEFINE J_Electrotim_Button   JS2.B4  //  То есть кнопка номер 4 (определяется тыканьем в кнопки в софтине) на джойстике на второй вкладке.

 

Ещё зададим кнопку "шифт" для сбрасывания триммирования:

 

%DEFINE SHIFT   JS3.B2

 

И кнопки, а точнее — движения хаткой, для коррекции триммирования:

%DEFINE J_Electrotrim_Bank_Left ( ( JS2.B31 OR JS2.B30 OR JS2.B32 ) AND NOT JS3.B2 )

%DEFINE J_Electrotrim_Bank_Right    ( JS2.B27 OR JS2.B26 OR JS2.B28 ) AND NOT JS3.B2 )

Сложно. Разберём: ( JS2.B31 OR JS2.B30 OR JS2.B32 ) -- очевидно означает "любая из трёх", почему? Потому что хатка может двигаться по диагонали тоже, нам надо отследить эту диагональ. Поэтому и получается: "влево" или "влево-вверх" или "влево-вниз" -- всё это годится. Далее, почему ко всему этому (любая из трёх) добавлено ещё:

( ( любая из трёх ) AND NOT JS3.B2 ) — тут мы указываем на то, что любая из трёх, но пока не нажат шифт (см. чуть выше -- JS3.B2) (шифт нам не особо нужен тут, но если мы вспомним, что ещё потом надо триммировать РН, а чем? А так -- с шифтом РН, без -- элероны).

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

 

Дальше нам для расчёта понадобятся ещё две переменные: собственно величина триммирования (сдвига оси), наша Дтрим.

%DEFINE A_Ailerons_Trim    A1;  // Дтрим

 

И, конечно, надо же задать ещё выводимые оси. Выводимые -- это оси, которые софтина передаёт винде. То есть у нас есть ось физическая, потом, путём пропускания через наш скрипт, мы получаем нужное значение и выводим его в "виртуальную" ось, которую собственно и видит симулятор.

%DEFINE C_Stick_X   CMS.A1   //  Ось номер 1 в списке выводимых осей на вкладке CMS Controls. Её-то и увидит симулятор.

Иными словами произойдёт следующее

J_Stick_Х --> расчёты --> C_Stick_X

 

 

Итак управляющие и прочие вещи заданы. Ещё раз, вот они:

%DEFINE J_Stick_X   JS2.A1    // Ось

%DEFINE J_Electrotim_Button   JS2.B4    // Кнопка

%DEFINE SHIFT   JS3.B2   // Шифт

%DEFINE J_Electrotrim_Bank_Left ( ( JS2.B31 OR JS2.B30 OR JS2.B32 ) AND NOT JS3.B2 )   // Хатка влево

%DEFINE J_Electrotrim_Bank_Right    ( JS2.B27 OR JS2.B26 OR JS2.B28 ) AND NOT JS3.B2 )  // Хатка вправо

%DEFINE A_Ailerons_Trim    A1;  // Дтрим

%DEFINE C_Stick_X   CMS.A1   // Собственно, ось в симуляторе.

 

Теперь перейдём к, собственно, скрипту:

script // означает его начало

 

Для начала начнём отслеживать кнопку:

if ( NOT SHIFT AND J_Electrotim_Button )  //  Что в переводе означает: если НЕ нажат шифт и нажата кнопка триммирования, то надо запомнить нашу дельту

   A_Ailerons_Trim = C_Stick_X - 128;  //  То есть берём значение выводимой оси в этот момент, и находим её сдвиг от нуля.

                                                            //   Допустим значение оси было 148, тогда её сдвиг будет 148 - 128 = 20. То есть ось была "на 20 вправо".

endif

 

 

if( NOT J_Electrotrim_Button ) then

Теперь мы проверяем, не нажата ли в это время кнопка триммирования. Вопрос — зачем? Всё просто: как мы знаем, наше итоговое значение образуется прибавлением Дтрим к физическому значению оси, но, допустим, сначала Дтрим была ноль, потом мы сдвинули ручку и хотим, чтобы это положение стало центром, Дтрим приобретёт какое-то значение, которое, если не блокировать в этот момент оси, сразу же прибавиться к уже и так отклонённой на эту величину ручке, то есть получится, что ручка была сдвинута на одно растояние, а тут это расстояние удвоится, это приведёт к резкому броску по крену в симуляторе. Поэтому мы блокируем изменения выводимого значения до момента отпускания кнопки. То есть для симулятора ручка останется в таком положении, в каком она и была. Это даёт возможность нам вернуть ручку в центр и отпустить кнопку. Иными словами механизм действий лётчика такой: "отклонить ручку, зажать кнопку, поставить ручку в центр, отпустить кнопку". Как вариант, можно ввести временную задержку "включения ручки" (оба метода взяты из DCS Ка-50).

 

Но допустим, кнопка отпущена, что дальше. Вроде бы достаточно просто:

   C_Stick_X = J_Stick_X + A_Ailerons_Trim;  //  То есть просто сдвигаем ручку в нужную сторону и всё.

Но тут происходит неприятная коллизия, которую видно на графике:

post-767-0-58767200-1409687899_thumb.png

Зелёная линия -- это то, что выводит джойстик: от 0% отклонения (полностью влево), до 100% (полностью вправо) мы имеем значения, линейно изменяющиеся от 0 до 255.

Синия линия -- это то, что получится, если мы просто прибавим значение (триммирования) Дтримк оси. Как видно, ось будет начинаться уже не от 0, а от, собственно, значения Дтрим, то есть в этом случае мы украдём у себя почти 1/5 хода элерона влево. Зато справа мы достигнем полного хода элерона уже при, примерно, 75% отклонении ручки. Конечно можно на это забить и сбрасывать триммирование каждый раз перед боем, но это приведёт к а) дерготне, так как сброс происходит резко и полностью, б) а что будет, если забыл? Будешь каждый раз нервничать. Кроме того, действительно, триммирование обычно идёт в зоне около нуля, то есть, более вероятно, что, будет не +50, а, где-то, +5, что практически не скажется на "длине" оси. Так что, можно оставить и так. Но я всё же упёрся рогом. Мне надо знать, что у меня есть полный диапазон. Для этого мне надо сделать так, что бы значения шли по красной линии. Для этого надо расчитывать коэффициенты. Наша формула немного :) преобразуется. Алгоритм такой:

Явно у нас функция состоит из двух половин, то есть для отклонения влево один коэффициент, а вправо -- другой. Поэтому мы будем расчитывать значения отдельно для отклонения влево и для отклонения вправо. Чтобы определить нужное значение оси, мы просто переводим физическое отклонение в процент от длины физической полуоси, а потом умножаем этот процент на длину "виртуальной" полуоси. Действуем следующим образом.

Для отклонения влево (Х =< 128):

  • Х / 128   — процент отклонения (128 кликов -- от крайнего левого положения до центра).
  • 128 + Дтрим — длина "виртуальной" левой полуоси, удлинённой (или укороченной) на величину триммирования
  • Тогда нужное значение = ( 128 + Дтрим) * Х / 128

Вправо (Х > 128). Так как у нас ось идёт от 128 до 255, то тут немного другой алгоритм, зеркальный, так сказать.

  • (Х - 128) / (255 - 128)   — процент отклонения от центра вправо.
  • 255 - 128 - Дтрим    — длина "виртуальной" правой полуоси. Если мы триммируемся на 20 вправо, то правая полуось уменьшается, поэтому - Дтрим
  • ((Х - 128) / (255 - 128)) * (255 - 128 - Дтрим) — величина отклонения от центра, но нам нужно абсолютное значение, поэтому нужно ещё добавить 128+Дтрим.
  • Нужное значение: (Х - 128) * (127 - Дтрим) / 127 + 128 + Дтрим.

Таким образом:

    if( [ J_Stick_X <= 128 ] ) then   // Влево
      C_Stick_X = ( ( 128 + A_Ailerons_Trim ) * J_Stick_X ) / 128;
    else     // Вправо
      C_Stick_X = ( ( ( J_Stick_X - 128 ) * ( 127 - A_Ailerons_Trim ) ) / 127 ) + 128 + A_Ailerons_Trim;
    endif

 

 

Теперь нужно отследить сброс триммеров, тут всё понятно:

  if ( SHIFT AND J_Electrotrim_Button_Pressed ) then
    A_Elevator_Trim = 0;
    A_Ailerons_Trim = 0;
    A_Rudder_Trim = 0;
  endif

 

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

     sequence
        while ( J_Electrotrim_Bank_Left );  //  Пока зажата кнопка триммирования крена влево
          A_Ailerons_Trim = A_Ailerons_Trim - 1; // Отнимаем по 1 каждый проход
          if ([ A_Ailerons_Trim < -127]) then  // Однако если уже максимальный минус, то хватит
            A_Ailerons_Trim = -127;
          endif
          delay( 1 );  // Собственно задержка
      endsequence

 

То же вправо:

 

      sequence
        while ( J_Electrotrim_Bank_Right );
          A_Ailerons_Trim = A_Ailerons_Trim + 1;
          if ( [ A_Ailerons_Trim > 127 ] ) then
            A_Ailerons_Trim = 127;
          endif
          delay( 1 );
      endsequence

 

Вот и вся программа

endscript

 

Что получилось:

%DEFINE J_Stick_X   JS2.A1    // Ось
%DEFINE J_Electrotim_Button   JS2.B4    // Кнопка
%DEFINE SHIFT   JS3.B2   // Шифт
%DEFINE J_Electrotrim_Bank_Left ( ( JS2.B31 OR JS2.B30 OR JS2.B32 ) AND NOT JS3.B2 )   // Хатка влево
%DEFINE J_Electrotrim_Bank_Right    ( JS2.B27 OR JS2.B26 OR JS2.B28 ) AND NOT JS3.B2 )  // Хатка вправо
%DEFINE A_Ailerons_Trim    A1;  // Дтрим
%DEFINE C_Stick_X   CMS.A1   // Собственно, ось в симуляторе.
 
script
  
   if ( NOT SHIFT AND J_Electrotim_Button ) // Нажата кнопка без шифта
      A_Ailerons_Trim = C_Stick_X - 128; // Запоминаем сдвиг
   endif
 
   if( NOT J_Electrotrim_Button ) then  // Кнопка не нажата
      if( [ J_Stick_X <= 128 ] ) then   // РУС отклонён влево

         C_Stick_X = ( ( 128 + A_Ailerons_Trim ) * J_Stick_X ) / 128;

      else     // Вправо

         C_Stick_X = ( ( ( J_Stick_X - 128 ) * ( 127 - A_Ailerons_Trim ) ) / 127 ) + 128 + A_Ailerons_Trim;

      endif
   endif
 
   if ( SHIFT AND J_Electrotrim_Button_Pressed ) then   // Нажата кнопочка c шифтом, сбрасываем триммера

      A_Elevator_Trim = 0;

      A_Ailerons_Trim = 0;

      A_Rudder_Trim = 0;

   endif
 
   sequence  // Отслеживаем кнопки коррекции триммера

      while ( J_Electrotrim_Bank_Left );  //  Пока зажата кнопка триммирования крена влево

         A_Ailerons_Trim = A_Ailerons_Trim - 1; // Отнимаем по 1 каждый проход

         if ([ A_Ailerons_Trim < -127]) then  // Однако если уже максимальный минус, то хватит

            A_Ailerons_Trim = -127;

         endif

         delay( 1 );  // Собственно задержка

   endsequence
 
   sequence

      while ( J_Electrotrim_Bank_Right );

         A_Ailerons_Trim = A_Ailerons_Trim + 1;

         if ( [ A_Ailerons_Trim > 127 ] ) then

            A_Ailerons_Trim = 127;

         endif

         delay( 1 );

  endsequence
 
endscript

Ну, и, наконец, исправленный полный код для всех осей.

 

 

//  ****************
//  "Электротриммирование" действует следующим образом: когда мы отклоняем ручку и нажимаем кнопку триммирования,
//      скрипт запоминает положение ручки и считает это положение новым центром. Дальше все движения ручки происходят
//      от этого нового центра. Что это даёт: игра считает, что ручка постоянно отклонена на какую-то величину.
//      Таким образом мы добиваемся работы триммеров аналогично современным самолётам: триммируется не рулевая
//      поверхность, а тупо сдвигается ручка туда или сюда и удерживается в таком положении, а для лётчика это
//      становится новым "центром" ручки.
//
//      Собственно триммирование осуществляется двумя способами:
//          1. Достигаем нужного положения самолёта, зажимаем кнопку. Игра запомнила это положение. Возвращаем ручку в центр.
//          2. Двигаем хатку, таким образом сдвигаем положение центра в нужную сторону (аналогично триммированию в игре).
//      То есть мы можем как быстро затриммировать нужное положение с кнопки, так и подкорректировать текущее положение с
//      хатки.
//
//      Я использую кнопку под мизинец на Fighterstick и хатку-"пипку" на нём же.
//
//      Кроме того, триммирование по всем осям можно сбросить, для этого жмём кнопку трима, удерживая Шифт
//
// *******************

//  Зададим оси
%DEFINE J_Stick_X           JS2.A1    // Ось джойстика - Х (Fighterstick на второй вкладке, ось X)
%DEFINE J_Stick_Y           JS2.A2    // Ось джойстика - Y  (Y)
%DEFINE J_Pedals            JS1.A3   // Ось колёсика на РУСе    (CH ProPedals на первой вкладке)

//  Кнопка триммирования и ШИФТ
%DEFINE SHIFT               JS3.B2              //  SHIFT -- кнопка-шифт
%DEFINE J_Electrotrim_Button          JS2.B4    //  Кнопка "электротриммирования" (pinky -- кнопка под мизинец на РУС)

//  Хатка на Fighterstick, как кнюппель триммирования
//  Обратите внимание, что "диагональные" положения тоже учитываются, то есть, скажем, "влево-вверх" тоже можно...
%DEFINE J_Electrotrim_Nose_Down ( JS2.B25 OR JS2.B26 OR JS2.B32 ) //  Хатка РУС, она управляет электротриммированием. Нос вниз (хатка вверх)
%DEFINE J_Electrotrim_Nose_Up   ( JS2.B29 OR JS2.B28 OR JS2.B30 ) //  Нос вверх
%DEFINE J_Electrotrim_Bank_Left ( ( JS2.B31 OR JS2.B30 OR JS2.B32 ) AND NOT JS3.B2 )    //  Крен влево  (влево без шифта)
%DEFINE J_Electrotrim_Bank_Right    ( JS2.B27 OR JS2.B26 OR JS2.B28 ) AND NOT JS3.B2 )  //  Крен вправо
%DEFINE J_Electrotrim_Yaw_Left  ( ( JS2.B31 OR JS2.B30 OR JS2.B32 ) AND JS3.B2 )    //  Рысканье влево  (влево с шифтом, предвидя вопрос:
                                                                                        // нельзя использовать одну переменную в объявлении другой)
%DEFINE J_Electrotrim_Yaw_Right ( ( JS2.B27 OR JS2.B26 OR JS2.B28 ) AND JS3.B2)       //  Рысканье вправо

//  Зададим внутренние переменные для вычислений
%DEFINE A_Stick_X       A1  //  Расчитываемое положение РУС по крену,
%DEFINE A_Stick_Y       A2  //  по тангажу.
%DEFINE A_Rudder        A3  //  по РН
%DEFINE A_Ailerons_Trim A4; //  Величина триммирования по элеронам,
%DEFINE A_Elevator_Trim A5; //      по РВ,
%DEFINE A_Rudder_Trim   A6; //      по РН.

//  Наконец зададим выводимые оси
%DEFINE C_Stick_X   CMS.A1  //  Крен
%DEFINE C_Stick_Y   CMS.A2  //  Тангаж
%DEFINE C_Rudder    CMS.A3  //  Руль направления

// Поехали!
script

//* Сначала включим отслеживание нажатия кнопки эл. триммирования  *//
    if ( NOT SHIFT AND J_Electrotrim_Button ); // Нажата наша кнопка (без шифта)
        A_Ailerons_Trim = C_Stick_X - 128;  // Значит это положение и есть новый центр.
        A_Elevator_Trim = C_Stick_Y - 128;  //  Поэтому мы берём дельту-расстояние от центра (128), она может быть и положит. и отрицательной
        A_Rudder_Trim = C_Rudder - 128;     //  И запоминаем эту дельту, на которую нужно теперь сдвигать ось.
    endif

 

    if ( SHIFT AND J_Electrotrim_Button ) then // Сброс триммеров
        A_Elevator_Trim = 0; // Сбрасываем эл. триммирование по всем осям
        A_Ailerons_Trim = 0;
        A_Rudder_Trim = 0;
    endif
 
    //  Начнём с того, что узнаем и запомним физ. положения осей на момент прохода в промежуточные переменные.
    //
    if( NOT J_Electrotrim_Button ) then  //  Если сейчас кнопка эл. триммирования НЕ нажата
                                                //    (при нажатии кнопки управление блокируется (не обсчитывается) до её отпускания,
                                                //    чтобы значение триммирования не складывалось с положением РУС (бросок).
                                                //  Именно поэтому и введены доп. переменные -- чтобы игнорировать движения
                                                //  физ. оси до момента отпускания кнопки. Доп. переменные изменяются только,
                                                //  если кнопка отпущена
        A_Stick_X = J_Stick_X ;   //  Ось крена (элероны)
        A_Stick_Y = J_Stick_Y ;   //  Ось тангажа (РВ)
        A_Rudder  = J_Pedals ;    //  Ось рысканья (РН)
          
    //  Теперь нужно добавить значения триммирования к исходным физ. положениям.
    //  Когда мы "триммируемя", мы смещаем центр той или иной оси на Х кликов. Скажем, на 10 кликов. Получится так:
    //          Пусть РУС в центре: 127 (физ. значение) + 10 (триммирование) = 137 (выводимое значение).
    //          То есть для игры наша ручка будет отклонёна всё время вперёд, хотя на деле она стоит в центре.
    //  Таким образом добиваемся триммирования.
    //  Но! Тут возникает один неприятный момент: ход ручки у нас от 0 до 255, если мы сместим центр, скажем, на +10, со 127 на 137,
    //  то диапазон выводимых значений будет [0-255] + 10 = от 10 до 265. И, так как значения больше max (255) приравниваются к 255, то
    //  получится, что у нас диапазон выводимых в игру значений будет от 10 до 255, то есть мы теряем 10 кликов хода в одну сторону,
    //  а в другу максимум оси будет достигнут до её физического максимума.
    //  Это недопустимо для воздушного боя, поэтому необходимо внести коэффициенты для отклонений в обе стороны, чтобы
    //          max-выводимый = max-физический   и   min-выводимый = 0.
    //
    //  Добавляем значения триммирования к осям и устанавливаем выводимые оси в нужное положение.
        if( [ J_Stick_X <= 128 ] ) then // Если РУС дан влево, то нужно вычислить коэффициент.
                                        //  Очень грубо: перевести в проценты отклонение ручки и умножить на длину вычисляемой оси.
                                        //  Подробно про алгоритм -- смотрим в посте.
            C_Stick_X = ( ( 128 + A_Ailerons_Trim ) * A_Stick_X ) / 128 ;
        else  //  вправо
            C_Stick_X = ( ( ( A_Stick_X - 128 ) * ( 127 - A_Ailerons_Trim ) ) / 127 ) + 128 + A_Ailerons_Trim;
        endif

        if( [ J_Stick_Y <= 128 ] ) then // Тангаж
            C_Stick_Y = ( ( 128 + A_Elevator_Trim ) * A_Stick_Y ) / 128;
        else
            C_Stick_Y = ( ( ( A_Stick_Y - 128 ) * ( 127 - A_Elevator_Trim ) ) / 127 ) + 128 + A_Elevator_Trim;
        endif

        if( [ A_Rudder <= 128 ] ) then  //  ?uneaiua
            C_Rudder = ( ( 128 + A_Rudder_Trim ) * A_Rudder ) / 128;
        else
            C_Rudder = ( ( ( A_Rudder - 128 ) * ( 127 - A_Rudder_Trim ) ) / 127 ) + 128 + A_Rudder_Trim;
        endif
    endif

    // ************************************************** //

    // ************************************************** //
    // ******* Обработка хатки эл. триммирования ******** //
    //
    //  Хатка (пипка) на РУС. Действует очень примерно как кнюппель триммера на РУСе в современных самолётах:
    //      отклоняем, допустим, нашу хатку вверх (типа "ручка от себя"), в реальном самолёте (и на джоях с отдаче) РУС начинает
    //      сам двигаться вперёд, а нашем же случае(у нас нет отдачи) -- центр оси тангажа РУС начинает ползти "от себя".
    //
    //  Применяем sequence, так как нужно использовать определённую задержку. Иначе ось перемещается слишком быстро -- очень неудобно.
    //
      sequence
        while ( J_Electrotrim_Nose_Down );      //  Итак, удерживается кнопка "триммер - нос вниз" (от себя)...
            A_Elevator_Trim = A_Elevator_Trim - 1; // Если триммируется "нос вниз", то отнять 1 от текущего вычисляемого значения оси.
            if ([ A_Elevator_Trim < -127]) then //  Однако если значение уже максимальное, то больше не увеличивать,
                                                //    а то потом обратно выводить (кнопку держать) замучаешься
                                                //      (ведь можно и до -65535 затриммироваться). :)
                A_Elevator_Trim = -127;
            endif
        delay( 1 ); //  Чтобы триммирование происходило не слишком резко, чтобы можно было плавно подстроить,
                    //      даём задержку. Она подобрана экспериментально, к сожалению delay() не воспринимает переменные,
                    //      число (аргумент-величина задержки)приходится писать прямо в команде ("1" или другое).
      endsequence // Одну кнопку отработали

      // Остальные кнопки - аналогично
      // РН триммируется "влево-вправо" с шифтом (без шифта -- элероны)
      sequence
        while ( J_Electrotrim_Nose_Up );
          A_Elevator_Trim = A_Elevator_Trim + 1;
          if ([ A_Elevator_Trim > 127]) then
            A_Elevator_Trim = 127;
          endif
          delay( 1 );
      endsequence
      
      sequence
        while ( J_Electrotrim_Bank_Left );  //  Крен
          A_Ailerons_Trim = A_Ailerons_Trim - 1;
          if ([ A_Ailerons_Trim < -127]) then
            A_Ailerons_Trim = -127;
          endif
          delay( 1 );
      endsequence

      sequence
        while ( J_Electrotrim_Bank_Right );
          A_Ailerons_Trim = A_Ailerons_Trim + 1;
          if ( [ A_Ailerons_Trim > 127 ] ) then
            A_Ailerons_Trim = 127;
          endif
          delay( 1 );
      endsequence
      
      sequence
        while ( J_Electrotrim_Yaw_Left );  //  Рысканье
          A_Rudder_Trim = A_Rudder_Trim - 1;
          if ( [ A_Rudder_Trim < -127 ] ) then
            A_Rudder_Trim = -127;
          endif
          delay( 1 );
      endsequence

      sequence
        while ( J_Electrotrim_Yaw_Right );
          A_Rudder_Trim = A_Rudder_Trim + 1;
          if ( [ A_Rudder_Trim > 127 ] ) then
            A_Rudder_Trim = 127;
          endif
          delay( 1 );
      endsequence
    // ************************************************** //    
endscript   // Усё!

 

 

 

P.S. По поводу зубодробительности — это вы ещё весь профиль не видели. :)

P.S.S. Кстати, вот этот вот сдвиг оси + произвольное изменение её формы -- это ж и есть самая мякотка CH, ни один другой джой так не может. Представьте, у меня на этот сдвиг потом ещё и нелинейность накладывается, и ещё и подруливание. :)

Edited by 72AG_terror
  • Upvote 4

Share this post


Link to post
Share on other sites

...

P.S.S. ...Представьте, у меня на этот сдвиг потом ещё и нелинейность накладывается, и ещё и подруливание. :)

Terror, а про подруливание можно поподробнее? ;)

 

P.S. В строке %DEFINE J_Electrotrim_Bank_Right    (( JS2.B27 OR JS2.B26 OR JS2.B28 ) AND NOT JS3.B2 )  // Хатка вправо" одна передняя скобка всё-таки потерялась  ...,а я предупреждал ;))

Edited by =J13=Moroka

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

 

ссылка на перевод мануала у меня в подписи (перевод не мой, я где-то его скачал), там довольно много простых примеров.

Edited by NobbyNobbs

Share this post


Link to post
Share on other sites

ссылка на перевод мануала у меня в подписи (перевод не мой, я где-то его скачал), там довольно много простых примеров.

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

Опять же какие-то вещи просто ускользают от понимания. Я вот до сих пор не понял в чем смысл вкладки CMS control в CH Manager. http://www.vaaf.net/wiki/images/6/63/CHTrim_CMSAssign.png  Так что это такая вещь, что не все сразу могут взять прочитать мануал и начать правильно действовать.

Share this post


Link to post
Share on other sites

 

 

Я вот до сих пор не понял в чем смысл вкладки CMS control в CH Manager

 

ммм... с моим косноязычием сложно сформулировать, но вкратце - эта вкладка нужна чтобы виртуальные кнопки и оси, созданные в скрипте, сделать видимыми для системы, привязав к уже существующему или вновь созданному Control Manager Device.

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

 Я вот до сих пор не понял в чем смысл вкладки CMS control в CH Manager.

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

...И все таки без чтения мануала тяжело :( Начни с 62 стр. (Введение в CMS, Основы CMS). Уже следующие 4-5 страниц объяснят основные понятия...

Edited by =J13=Moroka

Share this post


Link to post
Share on other sites

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

...И все таки без чтения мануала тяжело :( Начни с 62 стр. (Введение в CMS, Основы CMS). Уже следующие 4-5 страниц объяснят основные понятия...

 

 

 Я вот до сих пор не понял в чем смысл вкладки CMS control в CH Manager. http://www.vaaf.net/wiki/images/6/63/CHTrim_CMSAssign.png  

 

 

Да, да.  Ну смотри - Через скрипты ты не сможешь изменить статус физической оси или кнопки (как то JS1.A1 или JS2.B4) - их ты можешь только читать (это же физические устройства - не так ли?)   А вот CMS устройства виртуальные, с ними как раз через скрипты, тебе и дается возможность сделать что хочешь. А затем через GUI уже закрепить эту CMS ось либо кнопку за каким либо виртуальным дейвайсом, что у тебя уже есть в режиме Mapped и дальше работать с ней уже привычным образом - как с обычной физической осью либо кнопкой.

Edited by [I.B.]Zulu

Share this post


Link to post
Share on other sites

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

Это только потому, что ты как раз и не понял концепции (принципа работы) - а именно CMS и есть суть и соль этой концепции :)

 

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

 

Прочти две короткие главы размеров в одну страницу текста:  Help -> CMS Scripting -> CMS Basics;   и Help -> Scripts -> Basic Scripting;   Они как раз ответят на твои вопросы.

Edited by [I.B.]Zulu

Share this post


Link to post
Share on other sites

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

То есть вот когда мы визардом создаем виртуальное устройство из допустим педалей, троттла и стика это понятно. Из нескольких физических одно виртуальное. А вот со скриптами и виртуальными устройствами что-то как-то нИочИнь.

Share this post


Link to post
Share on other sites

Могу помочь с пошаговым разбором. Какая стоит задача? Лучше придумать что-нибудь простое (например создать виртуальную ось и управлять ею физическими кнопками).

Share this post


Link to post
Share on other sites

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

 

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

Share this post


Link to post
Share on other sites

... это как раз почти тот случай, что описан в мануале... 

(copy-paste из мануала):

Пример # 3 - Автоматическое Триммирование

...

SCRIPT

IF( NOT JS1.B2 ) THEN // Если кнопка 2 не нажата то
CMS.A1 = JS1.A1 + A1; // Прибавить смещение X к X джойстика
CMS.A2 = JS1.A2 + A2; // Прибавить смещение Y к Y джойстика
ENDIF
SEQUENCE
WAIT( JS1.B2 ); // Ждать нажатия Кнопки 2
A1 = JS1.A1 - 128; // Расчитать смещение по Х и сохранить в A1
A2 = JS1.A2 - 128; // Расчитать смещение по Х и сохранить в A2
ENDSEQUENCE
ENDSCRIPT
 
Должны быть сделаны несколько назначений в ГИП. Во-первых, X и Y оси «CombatStick»
должны быть назначены на «None», чтобы не мешали. Во-вторых, CMS.A1 и CMS.A2
значения должны быть назначены X и Y осям на Устройство Диспетчера 1, чтобы
оттриммированные значения были доступны Windows.

 ...только сброса триммеров нет 

Для сброса можно добавить:

SEQUENCE

WAIT( JS1/B3 and JS1.B2 ); // Ждать одновременного нажатия Кнопок B2 и B3. B3  будет "Шифтом"
A1 = 0; // Сбросить смещение по Х в ноль
A2 = 0; // Сбросить смещение по Y в ноль
ENDSEQUENCE

...но у тебя должен быть в составе конфигурации CMS Controls, потому что только он "понимает" язык скрипта...

..давай дальше спрашивай...

Edited by =J13=Moroka

Share this post


Link to post
Share on other sites

Прошу прощения, вечером продолжу, а то сейчас  времени нет.

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

Share this post


Link to post
Share on other sites

Попробую разъяснить, в чём суть.

Значит так, есть два вида осей и кнопок: физические и виртуальные.

Физические -- это те, которые ты видишь на вкладках с картинками. Ты можешь подвигать ось или понажимать кнопки и прога тебе их покажет. Что с физическими осями можно делать:

  1. Можно их прямо в маппере назначить на какую-нибудь ось нашего устройства, типа "пусть это будет ось Z", там же, через ГУИ, можно подкрутить мёртвые зоны и прочие нелинейности. В этом случае, когда ось назначена прямо в маппере, софтина будет транслировать эту ось в игру напрямую. И игра её будет видеть именно так, как ты назначил: как ось Z, с МЗ и нелинейностью, которые ты назначил. Для ещё большей понятности -- назначение осей в маппере: это, так скажем, общепринятая штука, которая есть во всех остальных джоях тоже (настройка МЗ, нелинейности, направления и проч.) единственное, что ещё добавилось -- возможность выбрать, под каким именем эта ось будет фигурировать в винде (Z там, или R, или X). Ещё раз -- назначенная в маппере ось транслируется прямо в игру. То же самое и с кнопками -- ты можешь или прямо назначить, что это будет кнопка джоя № такая-то и назначать на неё что-то прямо в игре, или же можешь, вместо этого, назначить на эту кнопку клавиатурную команду, которую софтина и будет транслировать, когда ты её жмёшь. Вобщем, всё это -- стандартные возможности обычного джоя. Для многого этого более чем достаточно.
  2. Эти оси и кнопки можно считывать в скрипте. Например ты хочешь, чтобы какая-то ось, когда ты её двигаешь в зону 90-100%, вызывала нажатие какой-то кнопки. Для этого ты прочитываешь показания этой оси в скрипте, и, если она в нужной зоне, генерируешь в скрипте нажатие кнопки.

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

 

Вот тут-то мы подходим ко вкладке CMS Controls. На этой вкладке мы видим много кружков, которые означают уже не реальные, а виртуальные кнопки и оси. Выбрав, например, одну из этих осей, ты можешь так же, как и в обычном маппере, назначить ей название и проч. То есть если ты здесь назначишь "ось R", то игра увидит эту ось тоже. Но, в отличие от физической оси, этой осью ты управляешь исключительно из скрипта. То же и с кнопкой -- ты можешь назначить на неё какую-то команду или назвать её какой-то кнопкой, и игра её тоже увидит, но и этой кнопкой ты управляешь тоже только из скрипта. То есть ты можешь в скрипте написать: "нажать кнопку CMS.B1 и держать её 10 секунд", для игры это будет, как будто действительно нажата какая-то физическая кнопка. Допустим ты назначил на неё выпуск закрылков (кнопку F), тогда 10 секунд будет удерживаться кнопка F. Вот теперь следи за руками: допустим у тебя на курке назначено в маппере: "Space", то есть стрельба. Одновременно ты отслеживаешь в скрипте этот самый курок и, когда он нажат, ты в скрипте "нажимаешь" кнопку "Enter", тогда у тебя, при нажатии на курок, будут генерироваться сразу две кнопки: Space и Enter! Теперь, допустим, ты убрал в маппере назначенный на неё Space, тогда при нажатии на курок у тебя всё равно сгенериться Enter, потому что скрипт всё равно эту кнопку видит.

Ось -- абсолютно то же самое: если ты её обозначил в маппере, как ось Z -- она транслируется напрямую в игру. Допустим ты одновременно отследил эту ось в скрипте и приравнял её (только с обратным знаком) виртуальной оси, например CMS.A1, которую ось на вкладке CMS Controls назначил, как ось R. И вот тогда, если ты двигаешь эту ось, игра видит две одновременно движущихся оси: Z и R. Только при этом R движется в противоположенную сторону. Допустим ты теперь поставил в маппере None на назначение оси. Тогда игра увидит только одну ось R, которая будет вести себя точно так же, как и до этого.

  • Upvote 4

Share this post


Link to post
Share on other sites

Прикрепил пошаговую инструкцию и map файл. К сожалению, один в один не получится применить, так как сделано для микростика на Throttle Pro как пример, РУС у меня не CH.

Возможно поможет в понимании процесса.

Demo.zip

Share this post


Link to post
Share on other sites

Фиксированные значения на микростике 3

С маниакальной настойчивостью продолжаю пробовать различные варианты управления осями с помощью микростика на своём ProThottle

Успешно опробовав триммирование от Terrora, я с энтузиазмом програмиста-мичуринца решил "скрестить" свой микростик с фиксацией с алгоритмами того триммирования... а потому что..

... имеющийся способ фиксации значений микростика имеет, 2 проблемы: Первая - большая "мертвая зона", могущая меняться от 0 до почти полного хода мкстика! И вторая: "резкая" регулировка плюс большой её шаг (4 отсчета) во всем диапазоне.

Используя "эффект триммерования" и запоминая величину смещения (у меня в скрипте база - base) по цетральному положению стика (+/- "мертвая зона"- dz)...  управление осью начинается практически сразу, при отклонении микростика. А расчет отклонения с учетом "scalinga" всегда обеспечит регулировку во всем возможном диапазоне... ("Мертвую зону" рекомендуется делать не менее неточности вашего мкстика.)

 

// CMS Script File
// Title: Fix-MJoy 3 адаптивный расчет
%define dz 10 // мертвая зона-зона фиксации "base"
%define base a3 // расчетная база Y
%define htr a4 // нижний порог верхней зоны =128+dz
%define ltr a5 // верхний порог нижней зоны =127-dz
%define js js1.a2 // задаем рабочую ось мкстика
//
script
htr = 128 + dz;
ltr = 127 - dz;
sequence
WAIT( [js > ltr] and [js < htr] ); // если мкстик в центре (внутри мертвой зоны "dz"),
base = cms.a1; // запоминаем "base"-текущее значение расчетной оси
endsequence
if( [ js > htr ] ) then // если мкстик дан вниз > dz
a1 = (((255-base) * (js-htr)) / (127-dz)) + base;// то вычисляем с учетом "scalinga" оси
if ([ a1 > cms.a1 ]) then // запоминаем максимальное отклонение
cms.a1 = a1;
endif
endif
if ([ js < ltr ]) then// если ввверх... снова вычесляем с учетом "scalinga"
a2 = ((base*(js-(127-dz))) / ltr) + base;
if ([ a2 < cms.a1 ]) then // запоминаем минимальное...
cms.a1 = a2;
endif
endif
//
endscript

 

посмотреть работу удобно назначив cms.a1 на ось R  Device1

 

 Фиксированные значения... 4! (нет я не маньяк, просто увлекаюсь... :rolleyes: )

...а что если не использовать scaling? а просто "сдвигать" ось при каждом отклонении мкстика от центрального положения на постоянную величину?... Тогда в скрипте придется контролировать, чтобы результат не вышел из диапазона 0...255. А само управление осью становится похоже на "качание насоса" :) Подбирая в скрипте slope от 1 и более. Количество "качаний" меняется от 1-го до slope...

 

// CMS Script File
// Title: Fix-MJoy 3 Постоянное прирощение
%define dz 12 // мертвая зона-зона фиксации "base"
%define base a6 // расчетная база постоянного прирощения
%define htr a7 // нижний порог верхней зоны =128+dz
%define ltr a8 // верхний порог нижней зоны =127-dz
%define js js1.a2 // рабочая ось мкстика
%define slope 4 // коэфф. крутизны регулирки: чем больше, тем медленнее
//
script
htr = 128 + dz;
ltr = 127 - dz;
//
sequence // если мкстик в центре (внутри мертвой зоны "dz"),
// запоминаем "base"-текущее значение расчетной оси
WAIT( [js > ltr] and [js < htr] );
base = cms.a1;
endsequence
//
if( [ js > htr ] ) then // если мкстик дан вниз
a3 = (2*(js-htr))/slope + base; // увеличиваем на постоянное прирощение
if ([ a3 > cms.a1 ]and[a3 <= 255]) then // запоминаем и контролируем максимум
cms.a1 = a3;
endif
endif
if ([ js < ltr ]) then// если мкстик вверх... вычесляем
a4 = (2*(js-ltr))/slope + base; // уменьшаем на постоянное прирощение
if ([ a4 < cms.a1 ]and[(a4+1) > 0]) then // запоминаем минимальное, допустимое...
cms.a1 = a4;
endif
endif
endscript

 

... пока не придумал куда ЭТО использовать :)

P.S. ...в планах опробовать вариантах, при котором при любой начальной позиции мкстика (а не только после отпускания в центр, как сейчас), его движение будет регулировать ось... 

Edited by =J13=Moroka
  • Upvote 1

Share this post


Link to post
Share on other sites

Братья пацаки :gamer: А вот такой интересный вопрос :scratch_one-s_head: Сделал я скрипт лимитатора оборотов двигателя для своей системы,для фридриха(скрипт из первого поста темы),он работает.Но для густава нужны другие значения оси,те которые я забил в скрипт не подходят ему.Можно ли как нибудь разделить скрипты для mode1 и mode2.или нужно делать разные карты для этих крафтов,чтобы использовать этот скрипт?

Share this post


Link to post
Share on other sites

Братья пацаки :gamer: А вот такой интересный вопрос :scratch_one-s_head: Сделал я скрипт лимитатора оборотов двигателя для своей системы,для фридриха(скрипт из первого поста темы),он работает.Но для густава нужны другие значения оси,те которые я забил в скрипт не подходят ему.Можно ли как нибудь разделить скрипты для mode1 и mode2.или нужно делать разные карты для этих крафтов,чтобы использовать этот скрипт?

 

Не надо разные карты.   

 

Сделай проверку по глобальной переменной CURRENTMODE  т.е. раздели на две ветки по этому условию.

 

IF ([CURRENTMODE EQ 0]) THEN   // MODE 0 Вкладка 1 (Зеленый светодиод если есть)

...bla bla bla  Friedrich

 

 

ENDIF

 

IF ([CURRENTMODE EQ 1] OR [CURRENTMODE EQ 2]) THEN   // MODE 1,2 Вкладка 2,3 (Красный, или желтый светодиод если есть)

...bla bla bla  Gustav

 

 

ENDIF

 

--------------------------------------------------------------------------------------

У тебя есть какое либо CH устройство со светодиодами???

Edited by [I.B.]Zulu
  • Upvote 2

Share this post


Link to post
Share on other sites
У тебя есть какое либо CH устройство со светодиодами???

 

У меня Fighterstick,Pro Throttle,Pro Pedals.Попробую похимичить :joy:

Edited by beretta5

Share this post


Link to post
Share on other sites

У меня Fighterstick,Pro Throttle,Pro Pedals.Попробую похимичить :joy:

Замечательно, например на ТротлПро режимы переключаются нажатием в центр микростика. При этом меняется значение CURRENTMODE. Вот его то и можно отследить

Share this post


Link to post
Share on other sites

Братья пацаки :gamer: А вот такой интересный вопрос :scratch_one-s_head: Сделал я скрипт лимитатора оборотов двигателя для своей системы,для фридриха(скрипт из первого поста темы),он работает.Но для густава нужны другие значения оси,те которые я забил в скрипт не подходят ему.Можно ли как нибудь разделить скрипты для mode1 и mode2.или нужно делать разные карты для этих крафтов,чтобы использовать этот скрипт?

 

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

Share this post


Link to post
Share on other sites

С режимами я разобрался :salute: благодарю за помощь.Но :( имеется другая бяка.Вот,к примеру лимитатор оборотов для fw190.

IF ([CURRENTMODE EQ 2]) THEN  //лимитатор fw190 a3
if ([js1.a3<25] and ([a3==0])) then
cms.a3=180;
else if ([js1.a3<18] and ([a3==1])) then
cms.a3=205;
else if ([js1.a3<12] and ([a3==2])) then
cms.a3=218;
else
cms.a3=255-js1.a3;
endif
endif
endif

sequence
wait((js2.b16)and[a3<3]);
a3=a3+1;
endsequence
sequence
wait((js2.b14)and[a3>0]);
a3=a3-1;
endsequence
endif
Работает он так.Крутим крутилку на джое до конца и виртуальная ось а3 выставляет 180 едениц(не 255 как бы выставила реальная ось,она отключена что бы не мешать)обороты у фоки 2100.Дальше клацаем кнопку 205ед.-2300об/мин,218ед.-2400об/мин. и 255ед.-2700об/мин.Таким же макаром переключаем обороты вниз другой кнопкой до 2100об/мин.А далше ниже 2100 оперируем крутилкой.Так вот :gamer: бяка в следующем,в самом конце хода крутилки почему то есть скачёк до 230 едениц.Когда крутилка становится в своё максимальное положение выходной сигнал падает до положеных 180 едениц.Этот скачёк раздражает.Можно ли его как нибудь убрать?

P.S. С резисторм всё в норме.

Edited by beretta5

Share this post


Link to post
Share on other sites

С режимами я разобрался :salute: благодарю за помощь.Но :( имеется другая бяка.Вот,к примеру лимитатор оборотов для fw190.

IF ([CURRENTMODE EQ 2]) THEN  //лимитатор fw190 a3

if ([js1.a3<25] and ([a3==0])) then

................

Так вот :gamer: бяка в следующем,в самом конце хода крутилки почему то есть скачёк до 230 едениц.Когда крутилка становится в своё максимальное положение выходной сигнал падает до положеных 180 едениц.Этот скачёк раздражает.Можно ли его как нибудь убрать?

P.S. С резисторм всё в норме.

 

Семён Семёныч! 255 - 180 = 75. А не 25. :) Поэтому он и проезжает 180 до 255 - 25 = 230. И только после этого срабатывает первый if и из-за этого происходит скачок. А до этого не один if не срабатывает, поэтому задействуется: cms.a3 = 255 - js1.a3. Пусть js1.a3 = 30, тогда cms.a3 = 225. Зато когда js1.a3 становится меньше 25 -- происходит скачок.

 

Для отладки таких случаев рекомендую временно включать физическую ось в режим DirectX на какое-нибудь другое имя (ось R), тогда в калибровщике ты будешь видеть обе оси вместе и сможешь отлаживать зависимости. Потом, естественно, отключаешь.

 

Кстати, так и предполагалось, что колёсико работает во всех режимах? Я так понял, что идея была такая:

1. До режима 2100 U/min (180) работает колёсико (так, что 0% оси = холостые, а 100% оси = 2100).

2. Когда колёсико в max, то следующий режим -- 2300 U/min достигается с первого нажатия кнопки.

3. 2400 - со второго

4. 2700 - третьего.

Сейчас же колёсико работает всегда независимо от режима, грубо говоря кнопка задаёт ей просто предел: от первого нажатия она работает от 0 до 2300, второго: 0 - 2400 и так далее. Мне кажется это не очень удобно: бьёшься, убрал газ, кнопку забыл отжать в нужный режим, потом дал гашетку и через 5 минут спалился.

Я полагаю, ты колёсико хотел отключить на макс. режимах?

 

Вобщем, предлагаю так модифицировать скрипт:

1.1. Если на макс. режимах надо подстраивать обороты, то колёсико, при выходе из зоны, должно уменьшать переменную a3 на 1. То есть если ты снизил обороты, скажем, ниже 2100 с колёсика -- опять автоматически включился режим a3 = 0;

1.2. Если же подстройка не нужна, то просто не отрабатывать колёсико на макс. режимах.

2. Внедрить "аварийный" режим с шифтом -- сразу на 2700.

3. Для пущей наглядности заменить if ... then на select.

 

Вобщем, вот мои варианты.

Вариант 1.1. Автоматический сброс ограничителя в текущую зону (минимально корректируя твой скрипт)

....
    if ( [ js1.a3 < 75 ] ) then
        a3 = 0;
        cms.a3 = 180;
   else if ( [ js1.a3 < 50 ] and [ js1.a3 >= 32 ] and [ a3 > 0 ] ) then
        if ( [ a3 > 1 ] ) then
           a3 = 1;
        endif
        cms.a3 = 205;
   else if ( [js1.a3 < 32 ] and ([a3 == 2])) then
        cms.a3 = 218;
   else
        cms.a3 = 255 - js1.a3;
   endif
   endif
   endif
...

Вариант 1.2. Отключение колеса в макс. режимах вообще

...
    if ( [ a3 > 0 ] ) then
        else if ( [ a3 == 1 ] ) then
            cms.a3 = 205;
        else if ( [a3 == 2 ] ) then
            cms.a3 = 218;
        endif
        endif
    else
        if ( [ js1.a3 < 75 ] ) then
            cms.a3 = 180;
        else   
            cms.a3 = 255 - js1.a3;
        endif
    endif
...
Edited by 72AG_terror
  • Upvote 1

Share this post


Link to post
Share on other sites

Я полагаю, ты колёсико хотел отключить на макс. режимах?

 

Я хотел убрать скачёк.Спасибо,разобрался,теперь всё плавно без скачков :salute:

Share this post


Link to post
Share on other sites

....Вот,к примеру лимитатор оборотов для fw190.

... а почему бы не использовать  масштабирование (scaling) для расчетного значения газа?

У колёсика будет полный ход и не будет "мертвых зон" ;) ... Скрипт нисколько НЕ усложняется...

// Limitator 190A3

script
  sequence // тут всё как у тебя...
    wait((js1.b7)and[a3<3]); // свою кнопку подставь... у меня просто нет b16
    a3=a3+1;
  endsequence
  sequence
    wait((js1.b9)and[a3>0]); // и здесь свою кнопку ... b14 то же нет
    a3=a3-1;
  endsequence
if ([a3==0]) then // тут почти как у тебя. Но присваиваем значение не оси, а переменной a2
  a2 = 180;
else
  if ([a3==1]) then
    a2 = 205;
  else
    if ([a3==2]) then
      a2 = 218;
    else
      a2 = 255;
    endif
  endif
endif
cms.a3 = (a2*js1.a3)/255+(255-a2); // тут почти как у Terrora . Расчитываем ось газа с масштабированием
endScript
Edited by =J13=Moroka

Share this post


Link to post
Share on other sites

... а почему бы не использовать масштабирование (scaling) для расчетного значения газа?

Ок :gamer: Будет время,попробую этот скрипт ;)

Share this post


Link to post
Share on other sites

...а если хочется совсем без скачков, то можно добавить 1 переменную и 6 строк кода. И тогда газ будет без дерганий... можно пьяным летать, не растрясёт :)

 

// CMS Script File
// Limitator 190A3
script
sequence // тут всё как у тебя...
wait((js1.b7)and[a3<3]); // свою кнопку подставь... у меня просто нет b16
a3=a3+1;
endsequence
sequence
wait((js1.b9)and[a3>0]); // и здесь свою кнопку ... b14 то же нет
a3=a3-1;
endsequence
if ([a3==0]) then // тут почти как у тебя. Но присваиваем значение не оси, а переменной a2
a2 = 180;
else
if ([a3==1]) then
a2 = 205;
else
if ([a3==2]) then
a2 = 218;
else
a2 = 255;
endif
endif
endif
// когда a2 скачет, a1 будет изменяться по шажку
if ([a1 > a2]) then
a1 = a1-1; // по шажку уменьшаем...
endif
if ([a1 < a2]) then
a1 = a1+1; // по шажку увеличиваем...
endif
// и в формулу теперь подставляем "плавное" a1 вместо a2...

cms.a3 = (a1*js1.a3)/255+(255-a1); // тут почти как у Terrora . Расчитываем ось газа с масштабированием
endScript

 

Edited by =J13=Moroka

Share this post


Link to post
Share on other sites

... а почему бы не использовать масштабирование (scaling) для расчетного значения газа? У колёсика будет полный ход и не будет "мертвых зон" ;) ... Скрипт нисколько НЕ усложняется...

 

 

Попробовал этот скрипт :wacko: Вот к примеру он для фридриха

if([a3==0])then

a2=105;

else

if([a3==1])then

a2=150;

else

if([a3==2])then

a2=225;

else

a2=255;

endif

endif

endif

cms.a3=(a2*js2.a3)/255+(255-a2);

sequence

wait((js2.b16)and[a3<3]);

a3=a3+1;

endsequence

sequence

wait((js2.b14)and[a3>0]);

a3=a3-1;

endsequence

 

Дело в следующем :gamer: ось инвертировалась.Крутим крутилку,выдаёт сигнал с 255 до 150.

Дальше кнопкой 105,30 и 0.Вот такая байда получилась.Щас у мну нет времени,меня сутки не будет у компа.Если у тебя есть время попробуй разобраться.

Share this post


Link to post
Share on other sites

...Дело в следующем :gamer: ось инвертировалась.Крутим крутилку,выдаёт сигнал с 255 до 150.

Дальше кнопкой 105,30 и 0.Вот такая байда получилась.Щас у мну нет времени,меня сутки не будет у компа.Если у тебя есть время попробуй разобраться.

... "По умолчанию" большему газу соответствует меньшее значение оси... (т.е. когда колесико крутим "вперёд" значение идет к 0)  У тебя, видимо, чем больше значение оси, тем и газ больше...

Возможно у тебя инвертирована ось cms.a3 или в самой игре, или в GUI стоит галочка реверс.

Тогда тебе достаточно либо изменить формулу на: cms.a3 = a2-(a2*js1.a3)/255... либо в GUI  для cms.a3, или самой игре поставить(или снять) галочку "reverse"... смотри, что проще...

p.s. в скрипте "без скачков" то же

Edited by =J13=Moroka

Share this post


Link to post
Share on other sites

... "По умолчанию" большему газу соответствует меньшее значение оси... (т.е. когда колесико крутим "вперёд" значение идет к 0)  У тебя, видимо, чем больше значение оси, тем и газ больше...

Возможно у тебя инвертирована ось cms.a3 или в самой игре, или в GUI стоит галочка реверс.

Тогда тебе достаточно либо изменить формулу на: cms.a3 = a2-(a2*js1.a3)/255... либо в GUI  для cms.a3, или самой игре поставить(или снять) галочку "reverse"... смотри, что проще...

p.s. в скрипте "без скачков" то же

Потестил скрипт :joy: Нормально работает,мёртвых зон нет,ось в игре инвертировал.Только фильтрацию шума джойстика в игре отключил.Она,как оказалось,мешает установке точного положения РУДа при переключениях кнопками.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...