Електроника и Електротехника | Electronics and Electrical Engineering > Цифрово / дигитално управление | Digital Command Control

Осветление на вагони

<< < (2/9) > >>

ivo:
Благодаря :)

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

IvanC:
Схемата на печатната платка:



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

Иван

IvanC:
Това е програмата на функционалния декодер:


--- Код: ---
#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:

--- Код: ---
                                                  // ------------------------------------------------- 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:

--- Код: ---
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


--- Край на кода ---

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

Иван

Навигация

[0] Списък на темите

[#] Следваща страница

[*] Предходна страница

Премини на пълна версия