Автор Тема: Осветление на вагони  (Прочетена 14243 пъти)

IvanC

  • Trade Count: (0)
  • Sr. Member
  • ****
  • Публикации: 274
  • Рейтинг: 198
Осветление на вагони
« -: 31 Януари 2022, 04:17:08 »
С добавяне на вътрешно осветление на вагони се занимавам отдавна. От няколко години правя осветление със светодиоди и стабилизирано захранване на 3,3 волта и в повечето случаи с един или два "златни" кондензатора, които да премахнат досадното премигване на осветлението.

Схемата е тази:



но с малка промяна - понеже в момента използвам светодиоди с голяма яркост при 5 mA номинален ток, баластните съпротивления, които използвам са 1 килоом, като понякога го променям в зависимост от цвета на интериора - при светъл интериор използвам баластни съпротивления с по-голямо съпротивление (до 2 килоома), а при тъмен интериор по-малки стойности (750 - 820 ома).

Монтирал съм и декодери на няколко вагона - мотрисни и такива с командна кабина. В тези случаи използвам "заводски" декодер, който да управлява челните светлини и осветлението на салона. Тук няма нищо особено, свързването е на същия принцип както при монтиране на декодер на локомотив с единствената разлика, че няма мотор за опроводяване.

Последното осветление, което направих е на багажен вагон на Брава. Тук има малко предистория. Имам събрана композиция на Рейнголд (II-ра епоха) от стари вагони на Лилипут. Вагоните преработих, като добавих токоснемане на талигите, направих кулисни механизми с NEM глави за тегличите и осветление на салона по "класическата" ми схема, показана горе. В композицията имам и багажен вагон - пак на Лилипут, който от завода вече си имаше кулиса за тегличите с NEM глава. Направих му токоснемане и осветление по горната схема. Та преди месец-два видях, че Липето са пуснали допълнителен багажен вагон за Рейнголда. Преди да го поръчам се разтърсих из нета за повече информация за "цифровата" версия 45415:



Не успях да намеря информация, освен още снимки и това, което Липето показват на техния сайт. Дори и на сайта на Брава не дават този вагон - просто липсва там. Мислейки си, че щом е "цифров с вътрешно осветление", поне ще има токоснемане и платка със светодиоди, като в най-лошия случай ще трябва да монтирам друг декодер.

Поръчах вагона и той пристигна в тенекиената кутия:





Оказа се, че токоснемане от колелата няма! От единия край има теглич с 6-изводен конектор, на платката няма токоизправител, "декодерът" не е декодер а "приемник" (emphanger) на D&H, който получава захранване и цифров сигнал през конектора на теглича, явно пригоден да работи с декодер в един от другите вагони от композицията на Брава. Ако по време на проучването, което се опитах да направя преди поръчката бях намерил тази информация, щях да поръчам 45413, който е без осветление и цифровите изгъзици на Брава/D&H.













Съответно платката и тегличът бяха свалени и се захванах с направата на токоснемане и ново осветление.


Токоснемане - пластини и опроводяване:










Проводниците от талигите прекарах между пода и рамата и през тоалетната:



Оригиналните колооси бяха с две изолирани колела от осите и ги смених с такива, с едно изолирано колело, за да може токоснемането да работи.


Платка за осветлението и декодер
На този вагон реших да сложа декодер по моя идея - "декодерът" е на базата на ATmega328P, като използвах Ардуино Про-мини на 3,3 волта и 8 MHz. Захранването е идентично с това на "аналоговото" осветление със стабилизатор на 3,3 волта и "златен" кондензатор. Програмата в про-минито е моя разработка, като съм изпозлвал готова библиотека за DCC. Има маскимално до 12 изхода с възможност за много ефекти на светлините - мигане по различни начини, плавно палене и гасене на светлините, ефект на палене на луминисцентно осветление, задаване на ШИМ на всеки един изход, задаване на активното ниво (0 или 1), възможност за запазване на последното състояние в EPROM-а поотделно за всяка функция. Всичко това се избира със CV-та, така че е напълно програмируемо от DCC станция.

Осветлението е разделено на 3 кръга, така, както беше на оригиналната платка на вагона:
1. Багажни отделения
2. Купе на началник влака, тоалетна и амвон
3. Преддверията на вратите в двата края на вагона.

Ефекти не съм използвал. Настроих CV-тата така, че F1 да управлява осветлението на багажните отделения, F3 на купето, амвона и тоалетната, F5 преддверията и F0 да пали всички светлини.









И едно клипче - https://youtu.be/ypFDbH0G-8g

Иван
« Последна редакция: 31 Януари 2022, 04:21:39 от IvanC »

ivo

  • КЖМ - България
  • Trade Count: (8)
  • Hero Member
  • *****
  • Публикации: 2006
  • Рейтинг: 558
  • HO - II-III, София
Re: Осветление на вагони
« Отговор #1 -: 31 Януари 2022, 14:54:54 »
Здравей  :)

едно питане относно: "Оригиналните колооси бяха с две изолирани колела от осите и ги смених с такива, с едно изолирано колело, за да може токоснемането да работи."

колелата които си сложил с ос 24мм. и диаметър 11мм. са ???

имам същия вагон и не мога да намеря такива колела ...

IvanC

  • Trade Count: (0)
  • Sr. Member
  • ****
  • Публикации: 274
  • Рейтинг: 198
.
« Отговор #2 -: 31 Януари 2022, 17:46:20 »
Иво,

Колоосите са InterMountain 40049 (12 бр. в комплект), които са с малка ширина на бандажа и нисък реборд (RP-25). Стават и 40048, които са с широки бандажи и нисък реборд. Диаметърът на колелата е идентичен с оригиналните на вагона - 11 мм.

И на двата вида осите са много дълги (25,8 мм) и ги скъсих до (по памет) 23,8 мм като на оригиналните.





За съжаление от около година вече не мога да ги намеря. Последно купих от тях през 2020 година и имам малък запас, който започна да се изчерпва и периодично ги търся, но без успех.

Пробвах 40198 на Roco, от които имам и ги има налични в Липето, но не стават - диаметърът на ребордите на колелата е много голям и не се събират в талигите. Осите им също са по-дълги от необходимото, но това е малкият проблем - 40182 са с необходимата дължина. Големият диаметър на ребордите не позволява да се използват тези колооси. Може би 40264, които са с RP-25 профил ще станат след скъсяване на осите с 0,9 - 1,0 мм.

Иван

Krasi Tankista

  • Trade Count: (1)
  • Hero Member
  • *****
  • Публикации: 910
  • Рейтинг: 593
Re: Осветление на вагони
« Отговор #3 -: 31 Януари 2022, 19:33:12 »
Цитат на: ivo link=topic=5553.msg123110#msg123110 date=1643633694
Здравей  :)

едно питане относно: "Оригиналните колооси бяха с две изолирани колела от осите и ги смених с такива, с едно изолирано колело, за да може токоснемането да работи."

колелата които си сложил с ос 24мм. и диаметър 11мм. са ???

имам същия вагон и не мога да намеря такива колела ...

А тук търсил ли си?
http://blaetterkatalog.weinert-modellbau.de/#page_66

IvanC

  • Trade Count: (0)
  • Sr. Member
  • ****
  • Публикации: 274
  • Рейтинг: 198
.
« Отговор #4 -: 31 Януари 2022, 20:07:39 »
Цитат на: Krasi Tankista link=topic=5553.msg123113#msg123113 date=1643650392
А тук търсил ли си?
http://blaetterkatalog.weinert-modellbau.de/#page_66

Краси, супер си!

Според каталога 11 мм диаметър за Брава (23 мм ос) са 9746 с RP-25 профил и ги има налични на Липето. А Fine-25 еквивалента за Брава са 97460 но са с резервация.

Иван

ivo

  • КЖМ - България
  • Trade Count: (8)
  • Hero Member
  • *****
  • Публикации: 2006
  • Рейтинг: 558
  • HO - II-III, София
Re: Осветление на вагони
« Отговор #5 -: 01 Февруари 2022, 17:04:01 »
Благодаря :)

Накрая намерих в Ebay  :)  https://www.ebay.de/itm/194615066415?hash=item2d4ff63f2f:g:7IgAAOSwwTlUn~wp от Benno002-22

IvanC

  • Trade Count: (0)
  • Sr. Member
  • ****
  • Публикации: 274
  • Рейтинг: 198
Схема на печатната платка
« Отговор #6 -: 03 Февруари 2022, 22:07:20 »
Схемата на печатната платка:



Вместо диода за разряд на "златния" кондензатор C5 използвах съпротивление 0 ома, т.е. мост. Този стабилизатор на напрежение се справя много добре със зарядния ток на коднензаторите.

Иван

IvanC

  • Trade Count: (0)
  • Sr. Member
  • ****
  • Публикации: 274
  • Рейтинг: 198
Програмата на функционалния декодер - част 1
« Отговор #7 -: 05 Февруари 2022, 22:14:16 »
Това е програмата на функционалния декодер:


#include <NmraDcc.h>                              // Библиотека за DCC декодер - необходима за правилната работа на програмата

//#define debug_cvchange                            // Генерира код за дебъгване ако се махнат двете наклонени черти в началото на реда;
//#define debug_ack                                 //   нужно е само на автора на програмата
//#define debug_speed
//#define debug_functions
//#define debug_mapping
//#define debug_effects
#define debug_defaults
#define dump_CVs_enabled                          // uncomment to enable CV change readback and CV dump to serial

#if defined(debug_cvchange) or defined(debug_ack) or defined(debug_speed) or defined(debug_functions) or defined(debug_mapping) or defined(debug_effects) or defined(debug_defaults) or defined(dump_CVs_enabled)
  #define debug_main
#endif

// ---------------- Константи за нормалната работа на програмата - да не се променят!!! ----------------
#define mfrID                   13
#define mfrVer                  11
#define mfrSubver                1

#define defaultAddress           3                // default decoder address
#define defaultLongAddress     128                // default long address

// ---------------------------------- Задаване функциите на изводите: ----------------------------------
#define dccPin                   2                // Вход за DCC сигнала; стойност 2 или 3;
                                                  //   да не се използват други стойности!!!
#define motorPwm                14                // Изход за ШИМ на мотора
#define motorDir                13                // Изход за посока на мотора

//                    FA0f FA0r FA1  FA2  FA3  FA4  FA5  FA6  FA7  FA8
const byte foPin[] = {  3,   5,   6,   9,  10,  11,  12,   8,   7,   4};  // Изводи за управление на функциите.
                                                                          //   Първите 6 извода да не се променят
                                                                          //   и да няма дублиране с dccPin!!!

const int  outs    = sizeof(foPin) / sizeof(foPin[0]);
byte       foPol[outs];                           // "Поляритет" на изводите - виж cvFAPolLo и cvFAPolHi:
                                                  //   0 - активно ниско ниво
                                                  //   1 - активно високо ниво

// -------------- Още константи за нормалната работа на програмата - да не се променят!!! --------------
#define maxFuncs                13
#define pwmTime                 20                // time in µs for PWM counter increment
#define pwmStep                  8                // PWM counter increment step

#define stopped              false
#define moving                true
#define reverse                  0
#define forward                  2
#define off                      0
#define on                     255
#define momentumConst       900000UL

// ------------------------------------- Променливи на програмата: -------------------------------------
struct throttleStruct {byte Value; byte Dir;};

throttleStruct throttle      = {0, forward};
throttleStruct intThrottle   = {0, forward};
byte locoDirFwd              = DCC_DIR_FWD;
byte vMin                    = 1;
byte vMid                    = 85;
byte vMax                    = 255;
byte doMotorFlag             = false;
unsigned long accelCount     = momentumConst;
unsigned long decelCount     = momentumConst;
unsigned long accelCounter   = 0;
unsigned long decelCounter   = 0;
unsigned long truePwmTime    = pwmTime;
int  deltaThrottle           = 0;

byte stateF[maxFuncs];
byte stateFA[outs];
byte oldStateFA[outs];
byte pwmFA[outs];
byte effectFA[outs];
byte outPwm[outs];
unsigned long effectMillis[outs];
int  cEff[outs];
byte doFunctions             = true;
byte throttleReq             = false;
byte cvChanged               = false;

                                                  //                                                CCCC     VV     VV
                                                  //                                              CC    CC    VV    VV    SSS
                                                  //                                             CC           VV   VV    SS
                                                  //                                             CC            VV VV      SSS
                                                  //                                              CC    CC      VVV         SS
                                                  //                                                CCCC         V        SSS

                                                  // -------------------------------------------- ID and reset to defaults CVs -------------------------------------------
#define cvMfr                    8                // manufacturer ID
#define cvVer                    7                // decoder type and code
#define cvSub                   65                // decoder software version
#define cvDef                   11                // reset to defaults: write 11 to reset all CVs to defaults

                                                  // --------------------------------------- address and decoder configuration CVs ---------------------------------------
#define cvShortAddress           1                // decoder short address
#define cvLongAddressHi         17                // decoder long address high byte
#define cvLongAddressLo         18                // decoder long address low byte
#define cvConfig1               29                // decoder configuration I bits

                                                  // ----------------------------------------------- speed and momentum CVs ----------------------------------------------
#define cvStartV                 2                // minimum motor PWM
#define cvMaxV                   5                // maximum motor PWM
#define cvMidV                   6                // motor PWM @63 throttle
#define cvAccel                  3                // acceleration time from min to max motor PWM in 0.9s
#define cvDecel                  4                // deceleration time from max to min motor PWM in 0.9s
#define cvMomReduction         124                // momentum reduction:
                                                  //            255 = no reduction
                                                  //            192 = reduced to 75%
                                                  //            128 = reduced to 50%
                                                  //             64 = reduced to 25%
                                                  //              0 = no momentum
#define cvHalfSpeedKey         155                // speed reduction key:
                                                  //              0 = no key assigned
                                                  //         1 - 28 = active when F1 - F28 (if supported) key on
                                                  //             29 = active when F0 key on
                                                  //      101 - 128 = active when F1 - F28 (if supported) key off
                                                  //            129 = active when F0 key off
#define cvMomentumKey          156                // momentum reduction key - same key assignment as cvHalfSpeedKey


                                                  // ------------------------------------------------- motor control CVs -------------------------------------------------
#define cvMotorFreq              9                // motor control frequency                                  FUTURE IMPLEMENTATION
#define cvMotorPI               56                // motor control P and I                                    FUTURE IMPLEMENTATION
#define cvMotorVref             57                // motor control reference voltage                          FUTURE IMPLEMENTATION
#define cvMotorBEMF             58                // motor control BEMF intensity                             FUTURE IMPLEMENTATION

                                                  // ------------------------------- "NMRA" (F0f-FA6) key-to-output mapping (no shift) CVs -------------------------------
#define cvF0f                   33                // F0f key
#define cvF0r                   34                // F0r key
#define cvF1                    35                // F1 key
#define cvF2                    36                // F2 key
#define cvF3                    37                // F3 key
#define cvF4                    38                // F4 key
#define cvF5                    39                // F5 key
#define cvF6                    40                // F6 key
#define cvF7                    41                // F7 key
#define cvF8                    42                // F8 key
#define cvF9                    43                // F9 key
#define cvF10                   44                // F10 key
#define cvF11                   45                // F11 key
#define cvF12                   46                // F12 key

                                                  // ----------------------------------- extended (FA7-FA14) key-to-output mapping CVs -----------------------------------
#define cvF0fe                 133                // F0f key
#define cvF0re                 134                // F0r key
#define cvF1e                  135                // F1 key
#define cvF2e                  136                // F2 key
#define cvF3e                  137                // F3 key
#define cvF4e                  138                // F4 key
#define cvF5e                  139                // F5 key
#define cvF6e                  140                // F6 key
#define cvF7e                  141                // F7 key
#define cvF8e                  142                // F8 key
#define cvF9e                  143                // F9 key
#define cvF10e                 144                // F10 key
#define cvF11e                 145                // F11 key
#define cvF12e                 146                // F12 key

                                                  // --------------------------------------------- function output effect CVs --------------------------------------------
#define cvF0fEffect            125                // F0f output effect
#define cvF0rEffect            126                // F0r output effect
#define cvFA1Effect            127                // FA1 output effect
#define cvFA2Effect            128                // FA2 output effect
#define cvFA3Effect            129                // FA3 output effect
#define cvFA4Effect            130                // FA4 output effect
#define cvFA5Effect            131                // FA5 output effect
#define cvFA6Effect            132                // FA6 output effect
#define cvFA7Effect            159                // FA7 output effect
#define cvFA8Effect            160                // FA8 output effect
#define cvFA9Effect            161                // FA9 output effect
#define cvFA10Effect           162                // FA10 output effect
#define cvFA11Effect           163                // FA11 output effect
#define cvFA12Effect           164                // FA12 output effect
#define cvFA13Effect           165                // FA13 output effect
#define cvFA14Effect           166                // FA14 output effect

                                                  // -------------------------------------------------- effect selectors -------------------------------------------------
#define outEffDir                3                // output direction mask
#define outEffBidir              0                // xxxxxx00 - active in both directions
#define outEffFwd                1                // xxxxxx01 - active only forward
#define outEffRev                2                // xxxxxx10 - active only in reverse
#define outEffMask             252                // output effect mask
#define outEffNone               0                // 000000xx - no effect (except direction)
#define outEffMars               4                // 000001xx - mars light
#define outEffRandom             8                // 000010xx - random flicker
#define outEffFlash             12                // 000011xx - flashing light
#define outEffStrobe1           16                // 000100xx - single pulse strobe
#define outEffStrobe2           20                // 000101xx - double pulse strobe
#define outEffBeacon            24                // 000110xx - rotary beacon
#define outEffGyra              28                // 000111xx - gyralite
#define outEffDitch1R           32                // 001000xx - ditch light 1, right
#define outEffDitch1L           36                // 001001xx - ditch light 1, left
#define outEffDitch2R           40                // 001010xx - ditch light 2, right
#define outEffDitch2L           44                // 001011xx - ditch light 2, left
#define outEffCoupler           48                // 001100xx - coupler per cv115
#define outEffSoft              52                // 001101xx - soft start per cv63
#define outEffBrake             56                // 001110xx - auto brake light                              FUTURE IMPLEMENTATION
#define outEffStand             60                // 001111xx - output active at standstill only
#define outEff5min              64                // 010000xx - output off after 5 minutes
#define outEff10min             68                // 010001xx - output off after 10 minutes
#define outEffSSmoke            72                // 010010xx - speed dependent steam smoke                   FUTURE IMPLEMENTATION
#define outEffLowVin            76                // 010011xx - relay protection for servos, off at low input voltage   FUTURE IMPLEMENTATION
#define outEffDSmoke            80                // 010100xx - driving dependent diesel smoke                FUTURE IMPLEMENTATION
#define outEffFade              88                // 010110xx - fade-in per cv190, fade-out per cv191
#define outEffFluo              92                // 010111xx - fluorescent lamp effect
#define outEffSparks            96                // 011000xx - sparks with heavy braking                     FUTURE IMPLEMENTATION

                                                  // --------------------------------------------------- available CVs ---------------------------------------------------
#define cv47Available           47                // available                                                FUTURE IMPLEMENTATION
                                                  //    to
#define cv53Available           53                // available                                                FUTURE IMPLEMENTATION


Продължението следва...

Иван

IvanC

  • Trade Count: (0)
  • Sr. Member
  • ****
  • Публикации: 274
  • Рейтинг: 198
Програмата на функционалния декодер - част 2
« Отговор #8 -: 05 Февруари 2022, 22:20:39 »

                                                  // ------------------------------------------------- effect control CVs ------------------------------------------------
#define cvMarsMin               54                // mars and gyralite effect minimum PWM
#define cvRandMin               55                // random flicker effect minimum PWM
#define cvMars                  59                // mars and gyralite effect cycle time in 0.1s
#define cvFlash                 60                // flashing effect:
                                                  //   hundreds and tens - flasher cycle time in 0.2s
                                                  //              0x = 0.2s cycle (5 times per second)
                                                  //              1x = 0.4s cycle (2.5 times per second)
                                                  //              2x = 0.6s cycle (1.7 times per second)
                                                  //              . . . . . . . .
                                                  //             24x = 5.0s cycle
                                                  //   ones digit xx0 = 10% on time
                                                  //              xx1 = 20% on time
                                                  //              . . . . . . . .
                                                  //              xx9 = 100% on time
#define cvStrobe                61                // strobe effect:
                                                  //   hundreds digit - strobe flash duration in 0.035s
                                                  //              0xx = 0.035s
                                                  //              1xx = 0.070s
                                                  //              2xx = 0.105s
                                                  //   tens digit - strobe cycle time in 0.2s
                                                  //              x0x = 0.2s
                                                  //              x1x = 0.4s
                                                  //              . . . . . . . .
                                                  //              x9x = 2.0s
                                                  //   ones digit - pause between double strobes in 0.05s
                                                  //              xx0 = 0.05s
                                                  //              xx1 = 0.10s
                                                  //              . . . . . . . .
                                                  //              xx9 = 0.50s
#define cvBeacon                62                // rotary beacon cycle time in 0.1s
#define cvSoftSt                63                // soft start effect time in 0.1s
#define cvDitch                 64                // ditch lights:
                                                  //   hundreds digit - low PWM pause:
                                                  //              0xx = 10% of cycle time
                                                  //              1xx = 20% of cycle time
                                                  //   tens digit - minimum PWM:
                                                  //              x0x = 0% (completely off)
                                                  //              x1x = 5%
                                                  //              . . . . . . . .
                                                  //              x9x = 42%
                                                  //   ones digit - cycle time:
                                                  //              xx0 = 0.5s
                                                  //              xx1 = 0.6s
                                                  //              . . . . . . . .
                                                  //              xx9 = 1.4s
#define cvCoupler              115                // coupler settings:
                                                  //   hundreds and tens - max PWM time in 0.2s:
                                                  //               0x = 0.0s
                                                  //               1x = 0.2s
                                                  //               2x = 0.4s
                                                  //              . . . . . . . .
                                                  //              24x = 4.8s
                                                  //   ones digit - holding PWM:
                                                  //              xx0 =  0%
                                                  //              xx1 = 10%
                                                  //              . . . . . . . .
                                                  //              xx9 = 90%
#define cvFadeIn               190                // fade-in  effect time in 0.1s
#define cvFadeOut              191                // fade-out effect time in 0.1s

                                                  // --------------------------------------------------- available CVs ---------------------------------------------------
#define cv147Available         147                // available                                                FUTURE IMPLEMENTATION
                                                  //    to
#define cv154Available         154                // available                                                FUTURE IMPLEMENTATION

#define cv192Available         192                // available                                                FUTURE IMPLEMENTATION
                                                  //    to
#define cv199Available         199                // available                                                FUTURE IMPLEMENTATION

                                                  // ---------------------------------------------- function output PWM CVs ----------------------------------------------
#define cvF0fPwm               209                // F0f PWM
#define cvF0rPwm               210                // F0r PWM
#define cvFA1Pwm               211                // FA1 PWM
#define cvFA2Pwm               212                // FA2 PWM
#define cvFA3Pwm               213                // FA3 PWM
#define cvFA4Pwm               214                // FA4 PWM
#define cvFA5Pwm               215                // FA5 PWM
#define cvFA6Pwm               216                // FA6 PWM
#define cvFA7Pwm               217                // FA7 PWM
#define cvFA8Pwm               218                // FA8 PWM
#define cvFA9Pwm               219                // FA9 PWM
#define cvFA10Pwm              220                // FA10 PWM
#define cvFA11Pwm              221                // FA11 PWM
#define cvFA12Pwm              222                // FA12 PWM
#define cvFA13Pwm              223                // FA13 PWM
#define cvFA14Pwm              224                // FA14 PWM

                                                  // -------------------------------------- function output memory and polarity CVs --------------------------------------
#define cvMem                  200                // function state storage; uses 8 bytes for 29 inputs:
                                                  //   +0 to +3 contain function state masks set by user
                                                  //   +4 to +7 store function states saved by firmware on state change
#define cvFAPolLo              225                // F0f - FA6 output polarity: 0 - active low; 1 - active high
#define cvFAPolHi              226                // FA7 - FA14 output polarity as described above

                                                  // --------------------------------------------------- available CVs ---------------------------------------------------
#define cv227Available         227                // available                                                FUTURE IMPLEMENTATION
                                                  //    to
#define cv249Available         249                // available                                                FUTURE IMPLEMENTATION

                                                  // ----------------------------------------------------- other CVs -----------------------------------------------------
#define cvDump                 256                // write any non-zero value to this CV to dump CV values to serial

struct cvPair {int cv; byte value;};

byte          defsCVCnt      = 0;
int           setCVInd       = 0;
byte          setCVVal       = 0;
unsigned long cvChangeMillis = 0;
int           getCVInd       = 0;

int           marsStep       = 1;
unsigned long marsMillis     = 0;
byte          marsMin        = 32;
byte          randMin        = 32;
unsigned long flashOnMillis  = 0;
unsigned long flashOffMillis = 0;
unsigned long strobeOnMillis = 0;
unsigned long strobeOffMillis = 0;
unsigned long strobe2Millis  = 0;
int           beaconStep     = 1;
unsigned long beaconMillis   = 0;
int           ditchCounter   = 0;
int           ditchStep      = 1;
unsigned long ditchMillis    = 0;
unsigned long oldDitchMillis = 0;
byte          ditchMin       = 32;
byte          ditchPause     = 25;
byte          ditchFlag      = 0;
unsigned long couplerMillis  = 0;
word          couplerPwm     = 0;
int           softStStep     = 1;
unsigned long softStMillis   = 0;
int           fadeInStep     = 1;
int           fadeOutStep    = 1;
unsigned long fadeInMillis   = 0;
unsigned long fadeOutMillis  = 0;
unsigned long pwmMicros      = 0;                 // PWM µs storage
byte          pwmCounter     = 0;                 // PWM counter

cvPair factoryDefaults[] = {                      // default CV values table
  {cvShortAddress, defaultAddress},
  {cvLongAddressHi, CALC_MULTIFUNCTION_EXTENDED_ADDRESS_MSB(defaultLongAddress)},
  {cvLongAddressLo, CALC_MULTIFUNCTION_EXTENDED_ADDRESS_LSB(defaultLongAddress)},
  {cvConfig1, 6}, {cvSub, mfrSubver}, {cvDef, 0},
  {cvStartV, 1}, {cvMaxV, 1}, {cvMidV, 1}, {cvAccel, 5}, {cvDecel, 5},
  {cvMotorFreq, 95}, {cvMotorPI, 55}, {cvMotorVref, 0}, {cvMotorBEMF, 255},
  {cvMomReduction, 0}, {cvHalfSpeedKey, 0}, {cvMomentumKey, 0},
  {cvF0f,  1}, {cvF0r,  2}, {cvF1,   4}, {cvF2,   8},
  {cvF3,  16}, {cvF4,  32}, {cvF5,  64}, {cvF6, 128},
  {cvF7,   0}, {cvF8,   0}, {cvF9,   0}, {cvF10,  0},
  {cvF11,  0}, {cvF12,  0},
  {cvF0fe, 0}, {cvF0re, 0}, {cvF1e,  0}, {cvF2e,  0},
  {cvF3e,  0}, {cvF4e,  0}, {cvF5e,  0}, {cvF6e,  0},
  {cvF7e,  1}, {cvF8e,  2}, {cvF9e,  4}, {cvF10e, 8},
  {cvF11e, 0}, {cvF12e, 0},
  {cvF0fEffect,  0}, {cvF0rEffect,  0}, {cvFA1Effect,  0}, {cvFA2Effect,  0},
  {cvFA3Effect,  0}, {cvFA4Effect,  0}, {cvFA5Effect,  0}, {cvFA6Effect,  0},
  {cvFA7Effect,  0}, {cvFA8Effect,  0}, {cvFA9Effect,  0}, {cvFA10Effect, 0},
  {cvFA11Effect, 0}, {cvFA12Effect, 0}, {cvFA13Effect, 0}, {cvFA14Effect, 0},
  {cvMarsMin, 32}, {cvRandMin, 32}, {cvMars,   15}, {cvFlash, 53},
  {cvStrobe,  57}, {cvBeacon,  30}, {cvSoftSt, 15}, {cvDitch, 35},
  {cvCoupler,  0}, {cvFadeIn,   8}, {cvFadeOut, 8},
  {cvF0fPwm,  160}, {cvF0rPwm,  160}, {cvFA1Pwm,  160}, {cvFA2Pwm,  160},
  {cvFA3Pwm,  160}, {cvFA4Pwm,  160}, {cvFA5Pwm,  160}, {cvFA6Pwm,  160},
  {cvFA7Pwm,  160}, {cvFA8Pwm,  160}, {cvFA9Pwm,  160}, {cvFA10Pwm, 160},
  {cvFA11Pwm, 160}, {cvFA12Pwm, 160}, {cvFA13Pwm, 160}, {cvFA14Pwm, 160},
  {cvFAPolLo,   0}, {cvFAPolHi,   0},
  {cvMem + 0, 255}, {cvMem + 1, 255}, {cvMem + 2, 255}, {cvMem + 3, 255},
  {cvMem + 4,   0}, {cvMem + 5,   0}, {cvMem + 6,   0}, {cvMem + 7,   0},
  {cvDump, 0}
};

NmraDcc Dcc;

void setup() {                                    // program setup
  pinMode(motorPwm, OUTPUT);
  pinMode(motorDir, OUTPUT);
  for (int i = 0; i < outs; i++) {                  // initialize all function outputs
    stateFA[i] = 0;                                   // initialize output state
    oldStateFA[i] = 0;
    effectFA[i] = 0;                                  // and effects (no effects)
    effectMillis[i] = 0;
    cEff[i] = 0;
  } // for i
  for (int i = 1; i < maxFuncs; i++) stateF[i] = 0; // initialize all function input states
  stateF[0] = 1;
  #ifdef digitalPinToInterrupt
    Dcc.pin(dccPin, 1);
  #else
    Dcc.pin(0, dccPin, 1);
  #endif
  Dcc.init(mfrID, mfrVer, FLAGS_MY_ADDRESS_ONLY | FLAGS_AUTO_FACTORY_DEFAULT, 0); // initialize DCC library
  if (Dcc.getCV(cvSub)  != mfrSubver) Dcc.setCV(cvSub, mfrSubver); // set sub version CV value
  if (Dcc.getCV(cvDef)  != 0) Dcc.setCV(cvDef,  0); // reset factory defaults CV value
  if (Dcc.getCV(cvDump) != 0) Dcc.setCV(cvDump, 0); // reset dump CV value
  getVvalues();
  getMomentumValues();
  getCouplerValues();
  marsMin = Dcc.getCV(cvMarsMin);                   // load mars light minimum PWM
  randMin = Dcc.getCV(cvRandMin);                   // load random flicker minimum PWM
  getEffectMillis(cvMars,    43);
  getEffectMillis(cvFlash,   43);
  getEffectMillis(cvStrobe,  43);
  getEffectMillis(cvBeacon,  43);
  getEffectMillis(cvDitch,   43);
  getEffectMillis(cvSoftSt,  43);
  getEffectMillis(cvFadeIn, 128);
  getEffectMillis(cvFadeOut, 43);
  getLocoDir();
  #ifdef debug_main                                 // send decoder info if debug mode is enabled
    Serial.begin(115200);                             // set up UART; needed for dumpCVs
    Serial.println();
    Serial.println("--- Function DCC Decoder --- Ivan Cankov ---");
    Serial.print("Mfr ID: ");
    Serial.print(Dcc.getCV(cvMfr));
    Serial.print("; Version: ");
    Serial.print(Dcc.getCV(cvVer));
    Serial.print(".");
    Serial.print(Dcc.getCV(cvSub));
    Serial.print("; Address: ");
    Serial.print(Dcc.getAddr());
    Serial.print("; CV");
    Serial.print(cvConfig1);
    Serial.print(": ");
    Serial.println(Dcc.getCV(cvConfig1));
    Serial.println();
  #endif
  byte c = cvFAPolLo;
  byte p = 1;
  for (int i = 0; i < outs; i++) {
    pwmFA[i] = Dcc.getCV(cvF0fPwm + i);               // load output PWMs
    foPol[i] =  (Dcc.getCV(c) & p) ? 1 : 0;
    digitalWrite(foPin[i], !foPol[i]);                // deactivate function output
    pinMode(foPin[i], OUTPUT);                        // initialize function output
    if ((i & 7) == 7) {
      c++;
      p = 1;
    } else p *= 2;
  } // for i
  c = cvMem;
  p = 1;
  for (int i = 0; i < maxFuncs; i++) {              // read enabled function states from cvMem
    stateF[i] = (Dcc.getCV(c) & Dcc.getCV(c + 4) & p) ? 1 : 0;
    if ((i & 7) == 7) {
      c++;
      p = 1;
    } else p *= 2;
  } // for i
  randomSeed(analogRead(A7));
  if (Dcc.getAddr() > 9983) defsCVCnt = sizeof(factoryDefaults) / sizeof(cvPair); // make defsCVCnt non-zero and equal to number
    // of CVs to be reset to flag the loop()
    // function reset to factory defaults is needed
} // setup

void loop() {                                     // main cycle
  Dcc.process();
  if (doFunctions || throttleReq) {
    for (int i = 0; i < outs; i++) stateFA[i] = 0;    // reset all function output states
    for (int i = 0; i < maxFuncs; i++) doMapping(i);  // apply function mapping to output states
    doOutputs();                                      // check output states and apply effects as needed
    doFunctions = false;
    throttleReq = false;
  } // if doFunctions
  checkEffectInProgress();
  if (doMotorFlag) doMotor();
  if (defsCVCnt && Dcc.isSetCVReady()) {  // check if factory reset of CVs was requested
    defsCVCnt--;                          // decrement from initial size of array
    Dcc.setCV(factoryDefaults[defsCVCnt].cv, factoryDefaults[defsCVCnt].value);
    #ifdef debug_defaults
      Serial.print("Load Factory Defaults: CV");
      Serial.print(factoryDefaults[defsCVCnt].cv);
      Serial.print(": ");
      Serial.println(factoryDefaults[defsCVCnt].value);
    #endif
    if (!defsCVCnt) asm("jmp 0");         // done with factory defaults, restart program; comment if restart is not desired
//    if (!defsCVCnt) requestFunctionCheck(); // uncomment if restart is not desired
  } // if defsCVCnt
  if (setCVInd && Dcc.isSetCVReady() && (millis() - cvChangeMillis > 63)) { // CV needs to reset immediately
    Dcc.setCV(setCVInd, setCVVal);                        // after its value has been set
    if (setCVInd == cvDump) dumpCVs();                    // dump CVs if dump CV changed
    setCVInd = 0;                                         // clear request
  } // if setCVInd
  #ifdef dump_CVs_enabled
    if (getCVInd && !setCVInd) {                          // check for CV readback to serial request
      Serial.print("CV");                                   // CV readback to serial requested
      Serial.print(getCVInd);                               // send CV to serial
      Serial.print(",");
      Serial.println(Dcc.getCV(getCVInd));
      getCVInd = 0;                                         // clear request
    } // if getCVInd
  #endif
} // loop


Продължението следва...

Иван

IvanC

  • Trade Count: (0)
  • Sr. Member
  • ****
  • Публикации: 274
  • Рейтинг: 198
Програмата на функционалния декодер - част 3
« Отговор #9 -: 05 Февруари 2022, 22:24:04 »

void notifyDccCVChange(unsigned int cv, byte value) {  // called when DCC packet changes CV value
  #ifdef debug_cvchange
    Serial.print("notifyDccCVChange: CV");
    Serial.print(cv);
    Serial.print(": ");
    Serial.println(value);
  #endif
  switch (cv) {
    case cvDef:                                       // factory defaults CV has changed
      if (value == cvDef)                               // change to reset to factory defaults
        defsCVCnt = sizeof(factoryDefaults) / sizeof(cvPair); // make defsCVCnt non-zero and equal to number
      // of CVs to be reset to flag the loop()
      // function reset to factory defaults is needed
      break;
    case cvSub:                                       // subversion has been changed
      setCVInd = cvSub;                                 // flag the loop() to restore it
      setCVVal = mfrSubver;
      break;
    case cvStartV:
    case cvMaxV:
    case cvMidV:
      getVvalues();
    case cvAccel:
    case cvDecel:
      getMomentumValues();
      break;
    case cvMarsMin:                                   // mars light minimum PWM value changed
      marsMin = Dcc.getCV(cv);                        // load mars light minimum PWM
      break;
    case cvRandMin:                                   // random flicker minimum PWM value changed
      randMin = Dcc.getCV(cv);                        // load random flicker minimum PWM
      break;
    case cvMars:                                      // mars light value changed
    case cvFlash:                                     // flash value changed
    case cvStrobe:                                    // strobe value changed
    case cvBeacon:                                    // rotary beacon value changed
    case cvDitch:                                     // ditch lights value changed
    case cvSoftSt:                                    // fade-in value changed
    case cvFadeOut:                                   // fade-out value changed
      getEffectMillis(cv, 43);
      break;
    case cvFadeIn:                                    // fade-in value changed
      getEffectMillis(cv, 128);
      break;
    case cvCoupler:
      getCouplerValues();
      break;
    #ifdef dump_CVs_enabled
      case cvDump:                                      // CV dump is requested
        setCVInd = cvDump;                                // flag the loop() to reset the value
        setCVVal = 0;                                     // and dump the CVs to serial
        break;
    #endif
    default:
      cvChanged = cv;
      requestFunctionCheck();
      break;
  } // switch cv
  if ((cv == cvFAPolLo) || (cv == cvFAPolHi)) {     // output polarity value changed
    byte c = cvFAPolLo;
    byte p = 1;
    for (int i = 0; i < outs; i++) {
      foPol[i] =  (Dcc.getCV(c) & p) ? 1 : 0;
      if ((i & 7) == 7) {
        c++;
        p = 1;
      } else p *= 2;
    } // for i
  } // if cv
  if ((cv >= cvF0fPwm) && (cv < cvF0fPwm + outs))
    for (int i = 0; i < outs; i++)
      pwmFA[i] = Dcc.getCV(cvF0fPwm + i);               // load output PWMs
  cvChangeMillis = millis();                        // get current millis for CV change blocking
  getCVInd = cv;                                    // flag the loop() to send a CV readback to serial
} // notifyDccCVChange

void notifyCVAck(void) {                          // called when ACK needs to be sent for a CV read
  #ifdef debug_ack
    Serial.println("notifyCVAck") ;
  #endif
  digitalWrite(motorPwm, on);
  delay(8);
  digitalWrite(motorPwm, off);
} // notifyCVAck

void notifyDccSpeed(unsigned int a, DCC_ADDR_TYPE at, byte s, DCC_DIRECTION d, DCC_SPEED_STEPS ss) {  // called when a DCC speed packet with decoder address is received
  byte ts = (s <= 1) ? stopped : moving;
  byte td = (d == locoDirFwd) ? forward : reverse;
  throttleReq = ((throttle.Dir + (throttle.Value > 0)) != (td + ts));
  doMotorFlag = ((throttle.Value != s) || (throttle.Dir != td));
  if (s) s--;
  else {
    digitalWrite(motorPwm, off);
    intThrottle.Value = s;
    intThrottle.Dir   = td;
    accelCounter = 0;
    decelCounter = 0;
  } // if s
  if (s) {
    byte hs = ss >> 1;
    if (s < hs) s = map(s,  1, hs, vMin, vMid);
    else        s = map(s, hs, ss, vMid, vMax);
  } // if s
  throttle.Value = s;
  throttle.Dir   = td;
  #ifdef debug_speed
    Serial.print("notifyDccSpeed: Address: ");
    Serial.print(a);
    Serial.print((at == DCC_ADDR_SHORT) ? "-S" : "-L");
    Serial.print("; Speed: ");
    Serial.print(s);
    Serial.print((d == DCC_DIR_FWD) ? "-F" : "-R" );
    Serial.print("; Steps: ");
    Serial.print(ss);
    Serial.print("; State: ");
    Serial.print((ts == moving) ? "Moving " : "Stopped ");
    Serial.print((throttle.Dir == forward) ? "forward" : "in reverse");
    Serial.println();
  #endif
} // notifyDccSpeed

void notifyDccFunc(unsigned int a, DCC_ADDR_TYPE aType, FN_GROUP fGroup, byte fState) {  // called when a DCC function packet with decoder address is received
  #ifdef debug_functions
    Serial.print("notifyDccFunc: Address: ");
    Serial.print(a);
    Serial.print((aType == DCC_ADDR_SHORT) ? "-S" : "-L");
    Serial.print("; Function Group: ");
    switch (fGroup) {
      case FN_0_4:   Serial.print(" F0-F4:   "); break;
      case FN_5_8:   Serial.print(" F5-F8:   "); break;
      case FN_9_12:  Serial.print(" F9-F12:  "); break;
      case FN_13_20: Serial.print("F13-F20:  "); break;
      case FN_21_28: Serial.print("F21-F28:  "); break;
    } // switch fGroup
  #endif
  switch (fGroup) {
    case FN_0_4:
      stateF[0] = (fState & FN_BIT_00) ? 1 : 0;
      #ifdef debug_functions
        Serial.print(stateF[0]);
      #endif
      setFuncState(FN_BIT_01, fState, 1, 4);   break;
    case FN_5_8:   setFuncState(FN_BIT_05, fState, 5, 8);   break;
    case FN_9_12:  setFuncState(FN_BIT_09, fState, 9, 12);  break;
    case FN_13_20: setFuncState(FN_BIT_13, fState, 13, 20); break;
    case FN_21_28: setFuncState(FN_BIT_21, fState, 21, 28); break;
  } // switch fGroup
  #ifdef debug_functions
    Serial.println();
  #endif
  doFunctions = 1;
  byte m = 0;
  byte p = 1;
  byte c = cvMem + 4;
  for (int i = 0; i < maxFuncs; i++) {              // store input states to cvMem
    m += (stateF[i]) ? p : 0;
    if ((i == 7) || (i == maxFuncs - 1)) {
      if (Dcc.getCV(c) != m) Dcc.setCV(c, m);
      m = 0;
      p = 1;
      c++;
    } else p *= 2;
  } // for i
} // notifyDccFunc

void getVvalues() {
  byte b = Dcc.getCV(cvStartV);
  vMin = (b < 2) ? 1 : ((b > 252) ? 252 : b);
  b = Dcc.getCV(cvMaxV);
  vMax = (b < 2) ? 255 : ((b < (vMin + 3)) ? (vMin + 3) : b);
  b = Dcc.getCV(cvMidV);
  vMid = (b < 2) ? ((vMax - vMin) / 3 + vMin) : ((b < (vMin + 1)) ? (vMin + 1): ((b > (vMax - 2)) ? (vMax - 2) : b));
  #ifdef debug_speed
    Serial.print(vMin);
    Serial.print(" - ");
    Serial.print(vMid);
    Serial.print(" - ");
    Serial.println(vMax);
  #endif
  doMotorFlag = true;
} // getVvalues

void getMomentumValues(){
  accelCount = momentumConst * Dcc.getCV(cvAccel) / (vMax - vMin);
  decelCount = momentumConst * Dcc.getCV(cvDecel) / (vMax - vMin);
} // getMomentumValues

// ---------------------------------------------------------------------------- doMotor ----------------------------------------------------------------------------

void doMotor() {
  if ((!accelCounter) || (!decelCounter)) {
    byte f = false;
    byte tv = throttle.Value;
    byte mr;
    byte hsk = Dcc.getCV(cvHalfSpeedKey);
    byte k = hsk % 100;
    if (k) {
      if (k == 29) k = 0;
      if (k < maxFuncs) {
        f = stateF[k];
        if (hsk / 100 == 1) f = !f;
        if (f) tv = tv >> 1;
      } // if hsk
    } // if hsk
    f = false;
    hsk = Dcc.getCV(cvMomentumKey);
    k = hsk % 100;
    if (k) {
      if (k == 29) k = 0;
      if (k < maxFuncs) {
        f = stateF[k];
        if (hsk / 100 == 1) f = !f;
        if (f) mr = Dcc.getCV(cvMomReduction);
      } // if hsk
    } // if hsk
    int accel = 0;                                              // constant speed
    if (!intThrottle.Value) {
      intThrottle.Dir = throttle.Dir;
      throttleReq = true;
    } // if !intThrottle.Value
    if (intThrottle.Dir == throttle.Dir) {
      if      (intThrottle.Value < tv) accel =  1;                // accelerating
      else if (intThrottle.Value > tv) accel = -1;                // decelerating
    } else accel = -1;                                            // decelerating
    if (((accel > 0) && (!accelCounter)) || ((accel < 0) && (!decelCounter))) {
      intThrottle.Value += accel;
      throttleReq = true;
      deltaThrottle = (intThrottle.Dir == throttle.Dir) ? tv : -tv;
      deltaThrottle -= intThrottle.Value;
      if (intThrottle.Value != tv) {
        if (accel > 0) {
          accelCounter = expo(accelCount, intThrottle.Value, true) / truePwmTime;
          if (f) accelCounter = (accelCounter * mr) >> 8;
        } // if accel > 0
        else if (accel < 0) {
          decelCounter = expo(decelCount, intThrottle.Value, true) / truePwmTime;
          if (f) decelCounter = (decelCounter * mr) >> 8;
        } // if accel < 0
      } else if (!intThrottle.Value) {
        intThrottle.Dir = throttle.Dir;
        throttleReq = true;
      } // if !intThrottle.Value
    } // if accel
  } // if intThrottle.Dir
  digitalWrite(motorDir, intThrottle.Dir);
  digitalWrite(motorPwm, intThrottle.Value > pwmCounter);
//  analogWrite(motorPwm, intThrottle.Value);
  doMotorFlag = false;
} // doMotor

void getEffectMillis(word cv, byte d) {
  int s;
  unsigned long m;
  byte b = Dcc.getCV(cv);
  switch (cv) {
    case cvFlash:
      m = b / 10 + 1;
      m *= 20;
      b %= 10;
      flashOnMillis  = m * (1 + b);
      flashOffMillis = m * (9 - b);
      return;
    case cvStrobe:
      m = b / 100;
      strobeOnMillis = 35 * (1 + m);
      m = (b / 10) % 10;
      strobeOffMillis = 200 * (1 + m) - strobeOnMillis;
      m = b % 10;
      strobe2Millis = 50 * (1 + m);
      return;
    case cvDitch:
      ditchPause = (b / 100 + 1) * 25;
      ditchMin = ((b / 10) % 10) * 12;
      b %= 10;
      b += 5;
    default:
      b = max(b, 1);
      s = int(d / b);
      s = max(s, 1);
      m = (unsigned long)(s * b / 2.56);
      break;
  } // switch cv
  switch (cv) {
    case cvMars:    marsStep    = s; marsMillis    = m; break;
    case cvBeacon:  beaconStep  = s; beaconMillis  = m; break;
    case cvDitch:   ditchStep   = s; ditchMillis   = m; break;
    case cvSoftSt:  softStStep  = s; softStMillis  = m; break;
    case cvFadeIn:  fadeInStep  = s; fadeInMillis  = m; break;
    case cvFadeOut: fadeOutStep = s; fadeOutMillis = m; break;
  } // switch cv
} // getEffectMillis

void getCouplerValues() {
  unsigned long l = Dcc.getCV(cvCoupler);
  couplerMillis = (l / 10) * 200;
  couplerPwm = (l % 10) * 25;
} // getCouplerValues

unsigned long expo(unsigned long m, byte c, byte t) {
  if (t) {
    if (c < 10)  return (m * 8);
    if (c < 25)  return (m * 4);
  } // if t
  if (c < 51)  return (m * 2);
  if (c < 102) return (m * 1.290);
  if (c < 153) return (m * 0.831);
  if (c < 240) return (m * 0.535);
  return (m * 0.345);
} // expo

void requestFunctionCheck() {
  doFunctions = true;
  throttleReq = true;
  getLocoDir();
} // requestFunctionCheck

byte getFAEffectIndex(byte cv) {                  // returns the function output index based on output effect CV
  for (int i = 0; i < outs; i++) {
    byte j = ((i < 8) ? cvF0fEffect : (cvFA7Effect - 8)) + i; // check all output effects
    if (cv == (((i < 8) ? cvF0fEffect : (cvFA7Effect - 8)) + i)) return (i);
  } // for i
  return (outs);
} // getFAEffectIndex

void dumpCVs() {                                  // dump all CVs to serial
  #ifdef dump_CVs_enabled
    Serial.println("--- CV Dump Start ---");
    Serial.println("CV,Value");
    for (int i = 1; i <= 256; i++) {                  // cycle thru all (256 supported) CVs
      int p = ((i == cvVer) || (i == cvMfr)) ? i : 0;   // CV7 and CV8 are not in defaults array
      if (!p)
        for (int c = 0; c < sizeof(factoryDefaults) / sizeof(cvPair); c++)
          if (i == factoryDefaults[c].cv) p = i;            // get index if CV in defaults array
      if (p) {                                          // check if CV found
        Serial.print("CV");                               // send CV to serial
        Serial.print(p);
        Serial.print(",");
        Serial.println(Dcc.getCV(p));
      } // if p
    } // for i
    Serial.println("---- CV Dump End ----");
  #endif
} // dumpCVs

void getLocoDir() {locoDirFwd = (Dcc.getCV(cvConfig1) & CV29_LOCO_DIR) ^ DCC_DIR_FWD;}  // get direction from CV29.0

void setFuncState (byte g, byte s, byte b, byte e) {
  byte m = g;
  for (int c = b; c <= min(e, maxFuncs - 1); c++) {
    stateF[c] = (s & m) ? 1 : 0;
    m *= 2;
    #ifdef debug_functions
      Serial.print(stateF[c]);
    #endif
  } // for c
} // setFuncState

// --------------------------------------------------------------------------- doMapping ---------------------------------------------------------------------------

void doMapping(int i) {
  byte m = Dcc.getCV((i) ? (cvF0r + i) : ((intThrottle.Dir == forward) ? cvF0f : cvF0r)); // get function mapping CV value
  for (int c = 0; c < outs; c++) {                  // check all mapping
    if ((c < outs) && (m & 1)) {
      if (stateF[i]) stateFA[c] = stateF[i];            // output is controlled by input - store "new" state
        #ifdef debug_mapping
          Serial.print("State of F");
          if (i) Serial.print(i); else Serial.print((intThrottle.Dir == forward) ? "0f" : "0r");
          Serial.print(": ");
          Serial.print(stateF[i]);
          Serial.print("; Mask: ");
          Serial.print(m);
          Serial.print("; State of FA");
          Serial.print(c);
          Serial.print(": ");
          Serial.println(stateFA[c]);
        #endif
    } // if c
    if ((c & 7) == 7) m = Dcc.getCV((i != 0) ? (cvF0re + i) : ((intThrottle.Dir == forward) ? cvF0fe : cvF0re)); else m /= 2;
  } // for c
} // doMapping


Продължението следва...

Иван

IvanC

  • Trade Count: (0)
  • Sr. Member
  • ****
  • Публикации: 274
  • Рейтинг: 198

// --------------------------------------------------------------------------- doOutputs ---------------------------------------------------------------------------

void doOutputs() {                                // apply output effects if any
  unsigned long m;
  for (int i = 0; i < outs; i++) {                  // cycle through all function outputs
    if ((stateFA[i] != oldStateFA[i]) || throttleReq) { // check if output or throttle status has changed
      byte j = ((i < 8) ? cvF0fEffect : (cvFA7Effect - 8)) + i; // check all output effects
      byte d = Dcc.getCV(j);
      effectFA[i] = d & outEffMask;                     // get non-directional effect
      d &= outEffDir;                                   // get directional effect
      byte td = intThrottle.Dir;                        // get direction from throttle state
      if (((d == outEffFwd) && (td == reverse)) ||      // output on forward only, throttle is in reverse or
          ((d == outEffRev) && (td == forward)))        // output on in reverse only, throttle is forward:
        stateFA[i] = 0;                                   // turn off output state
      #ifdef debug_effects
        Serial.print("Output Effects: Index: ");
        Serial.print(i);
        Serial.print("; CV");
        Serial.print(j);
        Serial.print(": ");
        Serial.print(Dcc.getCV(j));
        Serial.print(" - ");
        switch (effectFA[i]) {
          case outEffNone:    Serial.println("None");             break;
          case outEffMars:    Serial.println("Mars");             break;
          case outEffRandom:  Serial.println("Flicker");          break;
          case outEffFlash:   Serial.println("Flasher");          break;
          case outEffStrobe1: Serial.println("Single Strobe");    break;
          case outEffStrobe2: Serial.println("Dual Strobe");      break;
          case outEffBeacon:  Serial.println("Beacon");           break;
          case outEffGyra:    Serial.println("Gyralite");         break;
          case outEffDitch1R: Serial.println("RH Ditch 1");       break;
          case outEffDitch1L: Serial.println("LH Ditch 1");       break;
          case outEffDitch2R: Serial.println("RH Ditch 2");       break;
          case outEffDitch2L: Serial.println("LH Ditch 2");       break;
          case outEffCoupler: Serial.println("Coupler");          break;
          case outEffSoft:    Serial.println("Soft Start");       break;
          case outEffBrake:   Serial.println("Brake Light");      break;
          case outEffStand:   Serial.println("Standing Only");    break;
          case outEff5min:    Serial.println("Off in 5 min");     break;
          case outEff10min:   Serial.println("Off in 10 min");    break;
          case outEffFade:    Serial.println("Fade-in/out");      break;
          case outEffFluo:    Serial.println("Fluorescent");      break;
          case outEffSparks:  Serial.println("Brake Sparks");     break;
          default:            Serial.println("Undefined (None)"); break;
        } // switch effectFA
      #endif
      if (cvChanged) {
        if (i == getFAEffectIndex(cvChanged)) {
          oldStateFA[i] = !stateFA[i];
          cvChanged = 0;
        } // if i
      } // if cvChanged
      switch (effectFA[i]) {
        case outEffFlash:                                 // flashing light effect
          if (stateFA[i] == oldStateFA[i]) break;           // do nothing if output state has not changed
          outPwm[i] = (stateFA[i]) ? on : off;              // apply state to output
          if (!stateFA[i]) {                                // check if output state is off
            effectMillis[i] = 0;                              // no effect on turn off
            break;
          } // if !stateFA
          effectMillis[i] = millis() + flashOnMillis;       // get next time to check output effect
          cEff[i] = 0;                                      // clear output counter
          break;
        case outEffStrobe1:                               // single pulse strobe
        case outEffStrobe2:                               // double pulse strobe
          if (stateFA[i] == oldStateFA[i]) break;           // do nothing if output state has not changed
          outPwm[i] = (stateFA[i]) ? on : off;              // apply state to output
          if (!stateFA[i]) {                                // check if output state is off
            effectMillis[i] = 0;                              // no effect on turn off
            break;
          } // if !stateFA
          effectMillis[i] = millis() + strobeOnMillis;      // get next time to check output effect
          cEff[i] = 0;                                      // clear output counter
          break;
        case outEffStand:                                 // output on standing, off moving
          if (intThrottle.Value) stateFA[i] = 0;            // turn off output state if moving
          outPwm[i] = (stateFA[i]) ? on : off;              // apply state to output
          break;
        case outEff5min:                                  // turn off output after 5 minutes
        case outEff10min:                                 // turn off output after 10 minutes
          if (stateFA[i] == oldStateFA[i]) break;           // do nothing if output state has not changed
          outPwm[i] = (stateFA[i]) ? on : off;              // apply state to output
          if (!stateFA[i]) {                                // check if output state is off
            effectMillis[i] = 0;                              // no effect on turn off
            break;
          } // if !stateFA
          effectMillis[i] = millis();                       // get current time
          effectMillis[i] += (effectFA[i] == outEff5min) ? 300000 : 600000; // add 5 or 10 minutes (300,000µs or 600,000µs)
          break;
        case outEffCoupler:                               // coupler control per cvCoupler
          if (intThrottle.Value) stateFA[i] = 0;            // turn off output state if moving
        case outEffDitch1R:                               // ditch light 1, right
        case outEffDitch1L:                               // ditch light 1, left
        case outEffDitch2R:                               // ditch light 2, right
        case outEffDitch2L:                               // ditch light 2, left
        case outEffMars:                                  // mars light effect
        case outEffRandom:                                // random flicker effect
        case outEffBeacon:                                // rotary beacon effect
        case outEffGyra:                                  // gyralite effect
        case outEffSoft:                                  // soft start per cvSoft [0.1s]
          if (!stateFA[i]) {                                // check if output state is off
            outPwm[i] = off;                                  // turn off output
            effectMillis[i] = 0;                              // no effect on turn off
            cEff[i] = 0;                                      // clear output counter
            break;
          } // if !stateFA
        case outEffFade:                                  // fade-in per cvFadeIn, fade-out per cvFadeOut [0.1s]
          if (stateFA[i] == oldStateFA[i]) break;           // do nothing if output state has not changed
          effectMillis[i] = millis();                       // get current time for input
          break;
        case outEffFluo:                                  // fluorescent light startup
          if (stateFA[i] == oldStateFA[i]) break;           // do nothing if output state has not changed
          outPwm[i] = (stateFA[i]) ? on : off;              // apply state to output
          if (!stateFA[i]) {                                // check if output state is off
            effectMillis[i] = 0;                              // no effect on turn off
            break;
          } // if !stateFA
          effectMillis[i] = millis() + random(50, 300);     // get next time to check output effect
          cEff[i] = random(1, 4) << 1;                      // get random number of flickers
          break;
        default:                                          // no effect
          outPwm[i] = (stateFA[i]) ? on : off;              // apply state to output
          break;
      } // switch effectFA
      oldStateFA[i] = stateFA[i];                       // output status has changed, store status
    } // if stateFA
  } // for i
} // doOutputs

// --------------------------------------------------------------------- checkEffectInProgress ---------------------------------------------------------------------

void checkEffectInProgress() {
  byte f;
  unsigned long m = micros();
  truePwmTime = m - pwmMicros;
  if (truePwmTime > pwmTime) {
    pwmMicros = m;
    pwmCounter += pwmStep;
    doMotorFlag = true;
    if (accelCounter) accelCounter--;
    if (decelCounter) decelCounter--;
  } // if micros
  m = millis();
  ditchFlag = (m - oldDitchMillis > ditchMillis);
  if (ditchFlag) {
    oldDitchMillis = m;
    ditchCounter += ditchStep;
  } // if oldDitchMillis
  for (int i = 0; i < outs; i++) {
    if (effectMillis[i]) {
      byte eff = effectFA[i] & outEffMask;
      switch (eff) {
        case outEffMars:                                  // mars light effect
          f = cEff[i] << 2;
          if (cEff[i] & 64) f = ~f;
          if (millis() - effectMillis[i] < expo(marsMillis, f, false)) break;
          effectMillis[i] = millis();
          cEff[i] += marsStep;
          f = cEff[i] << 2;
          if (cEff[i] & 64) f = ~f;
          if (cEff[i] & 128) f = f / 3;
          outPwm[i] = max(f, marsMin);
          break;
        case outEffRandom:                                // random flicker effect
          if (millis() < effectMillis[i]) break;            // do nothing if time has not elapsed
          cEff[i]++;
          if (!cEff[i]) break;
          cEff[i] = random(randMin, on);
          f = random(0, 120);
          outPwm[i] = (f > 80) ? randMin : cEff[i];
          effectMillis[i] = millis() + f;
          break;
        case outEffFlash:                                 // flashing light effect
          if (millis() < effectMillis[i]) break;            // do nothing if time has not elapsed
          cEff[i]++;
          if (cEff[i] & 1) {
            outPwm[i] = off;
            effectMillis[i] = millis() + flashOffMillis;      // get next time to check output effect
            break;
          } // if cEff
          outPwm[i] = on;
          effectMillis[i] = millis() + flashOnMillis;       // get next time to check output effect
          break;
        case outEffStrobe1:                               // single pulse strobe effect
        case outEffStrobe2:                               // double pulse strobe effect
          if (millis() < effectMillis[i]) break;            // do nothing if time has not elapsed
          cEff[i]++;
          if (cEff[i] & 1) {
            outPwm[i] = off;
            m = (((cEff[i] & 2) == 0) && ((effectFA[i] & outEffMask) == outEffStrobe2)) ? strobe2Millis : strobeOffMillis;
            effectMillis[i] = millis() + m;                   // get next time to check output effect
            break;
          } // if cEff
          outPwm[i] = on;
          effectMillis[i] = millis() + strobeOnMillis;      // get next time to check output effect
          break;
        case outEffBeacon:                                // rotary beacon effect
          f = cEff[i] << 2;
          if (cEff[i] & 64) f = ~f;
          if (millis() - effectMillis[i] < expo(beaconMillis, f, false)) break;
          effectMillis[i] = millis();
          cEff[i] += beaconStep;
          if (cEff[i] & 128) {
            outPwm[i] = off;
            break;
          } // if cEff
          f = cEff[i] << 2;
          if (cEff[i] & 64) f = ~f;
          outPwm[i] = f;
          break;
        case outEffGyra:                                  // gyralite effect
          if (millis() - effectMillis[i] < marsMillis) break;
          effectMillis[i] = millis();
          cEff[i] += marsStep;
          if (cEff[i] & 128) {
            outPwm[i] = marsMin;
            break;
          } // if cEff
          f = cEff[i] << 2;
          if (cEff[i] & 64) f = ~f;
          outPwm[i] = max(f, marsMin);
          break;
        case outEffDitch1R:                               // ditch light 1, right
        case outEffDitch1L:                               // ditch light 1, left
        case outEffDitch2R:                               // ditch light 2, right
        case outEffDitch2L:                               // ditch light 2, left
          if (!ditchFlag) break;
          f = ditchCounter << 1;
          if (eff & 4) f = ~f;
          if (ditchCounter & 128) f = ~f;
          if (f < ditchMin + ditchPause) f = ditchMin;
          outPwm[i] = f;
          break;
        case outEff5min:                                  // turn off output after 5 minutes
        case outEff10min:                                 // turn off output after 10 minutes
          if (millis() < effectMillis[i]) break;            // do nothing if time has not elapsed
          outPwm[i] = off;                                  // time has elapsed, turn off output
          effectMillis[i] = 0;
          break;
        case outEffCoupler:                               // coupler control per cvCoupler
          outPwm[i] = (millis() - effectMillis[i] < couplerMillis) ? on : couplerPwm;
          break;
        case outEffSoft:                                  // soft start per cvSoft [0.1s]
          if (millis() - effectMillis[i] < expo(softStMillis, cEff[i], false)) break;
          effectMillis[i] = millis();
          cEff[i] += softStStep;
          if (cEff[i] > 255) {
            outPwm[i] = on;
            cEff[i] = 255;
            effectMillis[i] = 0;
            break;
          } // if cEff
          outPwm[i] = cEff[i];
          break;
        case outEffFade:                                  // fade-in per cvFadeIn [0.1s]
          f = stateFA[i];                                   // fade-out per cvFadeOut [0.1s]
          m = (f) ? fadeInMillis : expo(fadeOutMillis, cEff[i], false);
          if (millis() - effectMillis[i] < m) break;
          effectMillis[i] = millis();
          cEff[i] += (f) ? fadeInStep : -fadeOutStep;
          if ((cEff[i] < 0) || (cEff[i] > 255)) {
            outPwm[i] = (f) ? on : off;
            cEff[i] = (f) ? 255 : 0;
            effectMillis[i] = 0;
            break;
          } // if cEff
          outPwm[i] = cEff[i];
          break;
        case outEffFluo:                                  // fluorescent ligh start up effect
          m = millis();                                     // get current time
          if (m < effectMillis[i]) break;                   // do nothing if not time yet
          cEff[i]--;                                        // decrement effect counter
          outPwm[i] = (cEff[i] & 1) ? off : on;             // turn on/off output based on even/odd counter
          effectMillis[i] = (cEff[i]) ? (m + ((cEff[i] & 1) ? random(400, 1000) : random(50, 300))) : 0;  // get time for next event
          break;                                            //   or 0 if counter expired
        default:
          effectMillis[i] = 0;
          break;
      } // switch effectFA
    } // if effectMillis
    f = highByte((unsigned int)outPwm[i] * (unsigned int)pwmFA[i]);  // apply max PWM
    if (!foPol[i]) f = ~f;                            // invert output if set as inverted
    if (i <= 5)
      analogWrite(foPin[i], f); else                    // apply hardware PWM to outputs if supported
      digitalWrite(foPin[i], f > pwmCounter);           // apply software PWM to outputs with no hardware PWM
  } // for i
} // checkEffectInProgress


Използва се библиотеката NmraDcc, която е публикувана тук:

https://github.com/mrrwa/NmraDcc

Библиотеката може да се инсталира директно от Ардуино-IDE средата. Ако по някаква причина Ардуино средата не намери библиотеката, може да си свалите файловете от горната препратка. Трябват файловете NmraDcc.cpp и NmraDcc.h, като силно препоръчвам и keywords.txt, за да се маркират ключовите думи от библиотеката със съответните цветове.

Иван

pach

  • Trade Count: (42)
  • Hero Member
  • *****
  • Публикации: 12257
  • Рейтинг: 1308
  • ТТ & Н0; DR & BDZ;ep.I-III(~VI)&selfmade
    • За моделизма
Re: Осветление на вагони
« Отговор #11 -: 05 Февруари 2022, 22:50:51 »
Тази школа, няма как да се развие при младите хобисти!!!
Благодарско Иване  - за споделеното и то до край!!!
 :hi: :clapping: :hi: :clapping: :hi: :clapping: &bgflag

IvanC

  • Trade Count: (0)
  • Sr. Member
  • ****
  • Публикации: 274
  • Рейтинг: 198
Изводи на Про-мини
« Отговор #12 -: 05 Февруари 2022, 22:54:04 »
Изводите на Про-минито са зададени в тези редове:



// ---------------------------------- Задаване функциите на изводите: ----------------------------------
#define dccPin                   2                // Вход за DCC сигнала; стойност 2 или 3;
                                                  //   да не се използват други стойности!!!
#define motorPwm                14                // Изход за ШИМ на мотора
#define motorDir                13                // Изход за посока на мотора

//                    FA0f FA0r FA1  FA2  FA3  FA4  FA5  FA6  FA7  FA8
const byte foPin[] = {  3,   5,   6,   9,  10,  11,  12,   8,   7,   4};  // Изводи за управление на функциите.
                                                                          //   Първите 6 извода да не се променят
                                                                          //   и да няма дублиране с dccPin!!!


Ако не сте много навътре в ATmega328, силно препоръчвам да не променяте така присвоените функции на изводите.

С други думи:

2 - вход за DCC сигнала

3 - изход F0f
5 - изход F0r
6 - изход FA1
9 - изход FA2
10 - изход FA3
11 - изход FA4
12 - изход FA5
8 - изход FA6
7 - изход FA7
4 - изход FA8

Както се вижда броят изходи са 10, а не 12, както бях писал в първото мнение. При силно желание, броят на изходите може да се увеличи на 12 и дори малко повече, но може да доведе до забавяне на работата на програмата с последващи нежелателни ефекти.

"Истинските" (хардуерните) ШИМ изходи са първите 6. Останалите 4 използват софтуерен ШИМ, поради което някои ефекти не работят много добре - получава се видима стъпкова промяна на яркостта на светене на лампата/светодиода, свързан към някой от тези изводи. Заради това, препоръчвам FA5 до FA8 да не използват ефекти с плавна промяна на яркостта.

Всеки изход може да бъде зададен с активно ниско или високо ниво. Това става с помощтта на CV-та, които ще опиша в следващо мнение. Един изход може без проблеми да комутира до 20 mA, но общата комутация за цялото про-мини (сумата от комутирания ток на всички изводи) не трябва да надхвърля 200 mA.

Ако изпозлвате стабилизатор на напрежението за 3.3 V, про-минито трябва да е с кварц за максимум 8 MHz. Ако стабилизаторът е за 5 V, квaрцът може да е за 16 MHz. И в двата случая трябва да изберете правилната честота на кварца от Ардуино средата при програмирането на про-минито. В противен случай времеконстантите няма да отговарят на зададеното, като може времетраенетата на нарастнат или намалят двойно.

Както се вижда по-горе има и изводи за управление на мотор, но тази функцията е много първобитна и съм я направил единствено за да мога да направя задаването на времето за ускорение и спиране, което оказва влияние на някои от ефектите. Електромоторът НЕ МОЖЕ да се свърже директно към изводите на про-минито, а трябват драйвери. Ако се опитате да свържете мотор, като минимум съответните изводи ще се повредят, а е възможно да се повреди и цялото про-мини.

Иван
« Последна редакция: 05 Февруари 2022, 23:00:33 от IvanC »

IvanC

  • Trade Count: (0)
  • Sr. Member
  • ****
  • Публикации: 274
  • Рейтинг: 198
.
« Отговор #13 -: 05 Февруари 2022, 23:00:03 »
Цитат на: pach link=topic=5553.msg123159#msg123159 date=1644094251
Тази школа, няма как да се развие при младите хобисти!!!
Благодарско Иване  - за споделеното и то до край!!!
 :hi: :clapping: :hi: :clapping: :hi: :clapping: &bgflag

Това хоби има много широка техническа и технологическа база. Много от дейностите са коренно различни една от друга. Затова и смятам, че трябва да си помагаме взаимно - всеки да помага в сферата, в която има добри способности. Това е причината да публикувам тази тема - с всичко, което съм направил от началото до края.

Иван

IvanC

  • Trade Count: (0)
  • Sr. Member
  • ****
  • Публикации: 274
  • Рейтинг: 198
Описание на CV-тата на функционалния декодер - част 1
« Отговор #14 -: 06 Февруари 2022, 01:40:06 »
Пропуснах да обясня, че трябваше да разделя програмата на 4 части поради ограничението на форума за максимум 20000 символа в едно мнение. Поради същата причина ще разделя и описанието на CV-тата в няколко мнения.

Виждам, че съм пропуснал и да дам препратка към про-минито, която е:

https://docs.arduino.cc/retired/boards/arduino-pro-mini

Описанието на CV-тата на български ще е на практика превод от английски, защото не съм напълно запознат с българската терминология. Когато започнах да се занимавам с DCC, декодерите, които започнах да използвам бяха с описание на английски и от там съм запознат с английската терминология. То май българска терминология за това няма, но може и да греша в това. Та затова предварително моля да бъда извинен за неточности в българската терминология. Приемам конструктивна критика и поправки в това отношение. И понеже използвам "CV" навсякъде, ще поясня какво означава и защо използвам именно това съкращение.

CV е съкратено от Configuration Variable или на български "конфигурационна променлива". "Конфигурационна", защото задава какво да прави декодера, т.е. определя как е конфигурирана определена част от декодера, а "променлива", защото стойността може да бъде променяна. Стойността може да се променя както от потребителя (нас), така и от програмата на декодера. Някои CV-та могат да се променят само от потребителя, други от потребителя и декодера, трети само от декодера, а някои са само за четене, т.е. те са програмирани от производителя на декодера и не могат да бъдат променяни, освен ако не се смени например програмата в декодера. Като цяло CV-тата казват на програмата на декодера какво точно да прави и как тоано да го прави. В моята програмка, например, CV-тата за ефектите указват кой точно ефект да се използва за всеки изход на декодера, а други CV-та указват параметрите на съответния ефект. Постарал съм се в програмата колкото се може повече от параметрите да се задават с CV-та за колкото се може по-голяма гъвкавост. Това до известна степен усложнява настройките на CV-тата, но няма как - колкото повече възможности, толкова повече се усложнява настройката. Но пък ако не използвате много или въобще ефекти, настройките са минимални. Ще дам и пример накрая с точните настройки, които съм направил за моя багажен вагон.

Написах, че някои от CV-тата са само за четене. И за да няма неяснотии, трябва да поясня, че при този функционален декодер реално четене през централата не може да стане - декодерът в този си вид (като хардуер) няма как да върне сигнал на станцията. Единствената възможност да се прочетат CV-тата е през серийния интерфейс на про-минито, който в програмата така, както съм я публикувал, е разрешен. Това става със запис в едно от CV-тата, което ще опиша по-долу.

Описанието на CV-тата е групирано в зависимост от функционалността им.

CV-та за идентифициране на декодера и зареждане на "заводските" стойности

CV
Заводска
стойност
   Описание
CV8
13
Идентификация на декодера; твърдо зададена с константа в програмата на декодера, т.е. само за четене
CV7
11
Вид на декодера; твърдо зададен с константа в програмата на декодера, т.е. само за четене
CV65
1
Версия на програмата на декодера; твърдо зададена с константа в програмата на декодера, т.е. само за четене
CV11
0
Зареждане на "заводските" стойности в CV-тата при запис на стойност 11 в CV11


CV-та за задаване на адреса и основната конфигурация на декодера

CV
Заводска
стойност
   Описание
CV1
3
Къс адрес на декодера; стойности от 1 до 127; активира се от CV29
CV17
192
Дълъг адрес на декодера, старша част, активира се от CV29
CV18
128
Дълъг адрес на декодера, младша част, активира се от CV29
Дългият адрес се формира по формулата (CV17 - 192) * 256 + CV18
Формулата за изчисляване на CV17 и CV18 при желан дълъг адрес е
CV17 = адрес / 256 + 192
CV18 = остатъкът от разделянето на адреса на 256 = адрес по модул 256 = адрес - 256 * цялата часта от(адрес / 256)
CV29
6
Основна конфигурация на декодера
бит 0 - тегло 1 - посока на движение - 0 = напред; 1 = назад
бит 1 - тегло 2 - брой стъпки на тротъла - 0 = 14 стъпки; 2 = 128 стъпки
бит 2 - тегло 4 - аналогов режим - 0 = аналоговият режим е забранен; 4 = аналоговият режим е разрешен
битове 3 и 4 - тегла 8 и 16 - не се използват
бит 5 - тегло 32 - вид адрес - 0 = къс адрес, зададен от CV1; 32 = дълъг адрес, зададен с (CV17 - 192) * 256 + CV18
битове 6 и 7 - тегла 64 и 128 - не се използват
Стойността на CV29 се образува, като се съберат стойностите на всички битове, например:
бит 0: посока на движение напред = 0
бит 1: 128 стъпки на тротъла = 2
бит 2: разрешен аналогов режим = 4
бит 5: къс адрес според CV1 = 0
-----------------------------------------------------------
0 + 2 + 4 + 0 = 6 - това записваме в CV29 (този пример е за заводската стойност на CV-то)
Ако искаме посока назад (1), 128 стъпки (2), забранен аналогов режим (0) и дълъг адрес (32), в CV29 трябва да запишем 1 + 2 + 0 + 32 = 35

Адресът на декодера е от 1 до 9983 включително. Ако се зададе адрес по-голям от 9983, програмата преценява, че данните в CV-тата са повредени и зарежда заводските стойности.


CV-та за управление на мотора
Както писах по-горе, функциите за управление на мотора са съвсем елементарни и няма хардуер за мотора, но стойностите на тези CV-та имат влияние върху някои от ефектите на изходите.

CV
Заводска
стойност
   Описание
CV2
1
Минимален ШИМ на мотора (при тротъл = 1); стойност от 1 до CV6 - 1
CV5
1
Максимален ШИМ на мотора (при тротъл = 100%); стойност от CV6 + 1 до 255; 1 = 255
CV6
1
ШИМ на мотора при тротъл = 50%; стойност от CV2 + 1 до CV5 - 1; 1 = 1/3 от обхвата, зададен от CV2 и CV5
CV3
5
Време за ускорение от покой до максимална скорост в 0,9 секунди; стойност от 0 до 255; 0 = 0 сек.; 255 = 230 сек.
CV4
5
Време за спиране от максимална скорост до покой в 0,9 секунди; стойност от 0 до 255; 0 = 0 сек.; 255 = 230 сек.
CV124
0
Намаляване на времената, зададени от CV3 и CV4 при активиране на бутона, зададен от CV156:
255
=няма промяна на времената, зададени от CV3 и CV4
192
=времената, зададени от CV3 и CV4 са намалени до 75%
128
=времената са намалени до 50%
64
=времената са намалени до 25%
0
=времената са = 0, т.е. няма плавно потегляне и спиране
Всички стойности от 0 до 255 са валидни
CV155
0
Бутон за активиране на намалена до 50% скорост на движение (маневрен режим или режим "Депо"):
0
=няма присвоен бутон, т.е. функцията не може да бъде активирана
1 - 28
=бутон F1 до F28 активира функцията, когато бутонът е задействан
29
=бутон F0 активира функцията, когато бутонът е задействан
101 - 128
=бутон F1 до F28 активира функцията, когато бутонът НЕ е задействан
129
=бутон F0 активира функцията, когато бутонът НЕ е задействан
Програмата на декодера поддържа бутони от F0 до F12 включително; командите от бутоните от F13 до F28 включително се пренебрегват
CV156
0
Бутон за активиране на намаляването на времената, зададени от CV3 и CV4;
Намаляването на времената е според CV124, описано по-горе;
Задаването на бутона е идентично с описаното за CV155 по-горе

Продължението следва...

Иван
« Последна редакция: 06 Февруари 2022, 01:42:40 от IvanC »