Compare commits
36 Commits
1.4.2
...
ESP32-IRAM
Author | SHA1 | Date | |
---|---|---|---|
|
4b175e9229 | ||
|
71bb657e3a | ||
|
f3a2b87693 | ||
|
e06f6b3bce | ||
|
6a7e206032 | ||
|
6d12e6cd3f | ||
|
b249762550 | ||
|
5cee0d28ed | ||
|
5ba1ee3e8e | ||
|
bb2a659ebe | ||
|
865d919802 | ||
|
ff3e24dff4 | ||
|
6dca23bc27 | ||
|
15da83c411 | ||
|
7a3845cbdf | ||
|
1717a2efb0 | ||
|
32c5597870 | ||
|
2de91bd4fd | ||
|
5a1e0b2997 | ||
|
2b12179152 | ||
|
c2de60b8cb | ||
|
f171dd3894 | ||
|
778de8ce74 | ||
|
ba3264bd87 | ||
|
0fbe2a13d1 | ||
|
369786325f | ||
|
ec801bf463 | ||
|
90470987a8 | ||
|
9294aa29e5 | ||
|
844171f2ac | ||
|
0656f58c5b | ||
|
0d2e8daeaf | ||
|
92dd2e6ac5 | ||
|
07933e42a8 | ||
|
f8f106962f | ||
|
8c782d5f15 |
@@ -1,103 +0,0 @@
|
||||
------------------------------------------------------------------------
|
||||
|
||||
OpenDCC - NmraDcc
|
||||
|
||||
Copyright (c) 2008 Alex Shepherd
|
||||
|
||||
This source file is subject of the GNU general public license 2,
|
||||
that is available at the world-wide-web at
|
||||
http:www.gnu.org/licenses/gpl.txt
|
||||
------------------------------------------------------------------------
|
||||
|
||||
file: Description NmraDcc.txt
|
||||
author:
|
||||
webpage:
|
||||
history:
|
||||
------------------------------------------------------------------------
|
||||
Call the DCC pin function to define which External Interrupt and Pin to use and also to enable the Pull-Up
|
||||
Dcc.pin(0, 2, 1);
|
||||
|
||||
Call the main DCC Init function to enable the DCC Receiver
|
||||
|
||||
Dcc.init( MAN_ID_DIY, 10, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, 0 )
|
||||
|
||||
MAN_ID_DIY = 0x0D (CV8 defined in NmraDcc.h)
|
||||
FLAGS_OUTPUT_ADDRESS_MODE = 0x40 (CV29/541 bit 6 defined in NmraDcc.h)
|
||||
FLAGS_DCC_ACCESSORY_DECODER = 0x80 (CV 29/541 bit 7 defined in NmraDcc.h)
|
||||
------------------------------------------------------------------------
|
||||
You MUST call the NmraDcc.process() method frequently from the Arduino loop()
|
||||
function for correct library operation
|
||||
|
||||
Dcc.process();
|
||||
------------------------------------------------------------------------
|
||||
This function is called whenever a normal DCC Turnout Packet is received
|
||||
|
||||
notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t OutputAddr, uint8_t State)
|
||||
|
||||
Addr = Decoder address
|
||||
BoardAddr = Address of this decoder
|
||||
OutputAddr = Address of Turnout on this decoder
|
||||
State =
|
||||
------------------------------------------------------------------------
|
||||
This function is called whenever a DCC Signal Aspect Packet is received
|
||||
|
||||
notifyDccSigState( uint16_t Addr, uint8_t OutputIndex, uint8_t State)
|
||||
|
||||
Addr = Decoder address
|
||||
OutputIndex = Address of Signal Aspect
|
||||
State =
|
||||
------------------------------------------------------------------------
|
||||
notifyDccFunc( uint16_t Addr, uint8_t FuncNum, uint8_t FuncState)
|
||||
|
||||
Addr = Decoder address
|
||||
FuncNum =
|
||||
FuncState =
|
||||
------------------------------------------------------------------------
|
||||
Perform a decoder total reset
|
||||
|
||||
notifyDccReset(uint8_t hardReset )
|
||||
|
||||
hardReset =
|
||||
------------------------------------------------------------------------
|
||||
The decoder receives a Idle packet and should do nothing
|
||||
|
||||
notifyDccIdle(void)
|
||||
------------------------------------------------------------------------
|
||||
A locomotive packet is received
|
||||
|
||||
notifyDccSpeed( uint16_t Addr, uint8_t Speed, uint8_t ForwardDir, uint8_t MaxSpeed )
|
||||
|
||||
Addr = Address received
|
||||
Speed = Requested speed
|
||||
ForwardDir = True if loco moves forward
|
||||
MaxSpeed =
|
||||
------------------------------------------------------------------------
|
||||
Checks if a CV is present in the table and is writable
|
||||
|
||||
notifyCVValid( uint16_t CV, uint8_t Writable )
|
||||
|
||||
CV = The number of the requested CV
|
||||
Writable = True is CV is writable
|
||||
------------------------------------------------------------------------
|
||||
Read a CV value from the decoder table
|
||||
|
||||
notifyCVRead( uint16_t CV)
|
||||
|
||||
CV = The number of the requested CV
|
||||
------------------------------------------------------------------------
|
||||
Write a CV with Value to the decoder table
|
||||
|
||||
notifyCVWrite( uint16_t CV, uint8_t Value)
|
||||
|
||||
CV = The number of the requested CV
|
||||
Value = Value to be written into the requested CV
|
||||
------------------------------------------------------------------------
|
||||
Check if the CV written to the table has the correct value
|
||||
|
||||
notifyCVChange( uint16_t CV, uint8_t Value)
|
||||
|
||||
CV = The number of the requested CV
|
||||
Value = Value of the changed requested CV
|
||||
------------------------------------------------------------------------
|
||||
notifyCVAck(void)
|
||||
|
648
NmraDcc.cpp
648
NmraDcc.cpp
File diff suppressed because it is too large
Load Diff
500
NmraDcc.h
500
NmraDcc.h
@@ -2,7 +2,7 @@
|
||||
//
|
||||
// Model Railroading with Arduino - NmraDcc.h
|
||||
//
|
||||
// Copyright (c) 2008 - 2105 Alex Shepherd
|
||||
// Copyright (c) 2008 - 2018 Alex Shepherd
|
||||
//
|
||||
// This source file is subject of the GNU general public license 2,
|
||||
// that is available at the world-wide-web at
|
||||
@@ -19,6 +19,8 @@
|
||||
// 2015-11-06 Martin Pischky (martin@pischky.de):
|
||||
// Experimental Version to support 14 speed steps
|
||||
// and new signature of notifyDccSpeed and notifyDccFunc
|
||||
// 2017-11-29 Ken West (kgw4449@gmail.com):
|
||||
// Added method and callback headers.
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
@@ -30,7 +32,7 @@
|
||||
// Uncomment the following Line to Enable Service Mode CV Programming
|
||||
#define NMRA_DCC_PROCESS_SERVICEMODE
|
||||
|
||||
// Uncomment the following line to Enable MutliFunction Decoder Operations
|
||||
// Uncomment the following line to Enable MultiFunction Decoder Operations
|
||||
#define NMRA_DCC_PROCESS_MULTIFUNCTION
|
||||
|
||||
// Uncomment the following line to Enable 14 Speed Step Support
|
||||
@@ -42,11 +44,17 @@
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
|
||||
#include "EEPROM.h"
|
||||
|
||||
#ifndef NMRADCC_IS_IN
|
||||
#define NMRADCC_IS_IN
|
||||
|
||||
#define NMRADCC_VERSION 201 // Version 2.0.1
|
||||
|
||||
#define MAX_DCC_MESSAGE_LEN 6 // including XOR-Byte
|
||||
|
||||
//#define ALLOW_NESTED_IRQ // uncomment to enable nested IRQ's ( only for AVR! )
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t Size ;
|
||||
@@ -90,11 +98,20 @@ typedef struct
|
||||
#define CV_MANUFACTURER_ID 8
|
||||
#define CV_29_CONFIG 29
|
||||
|
||||
#if defined(ESP8266)
|
||||
#include <spi_flash.h>
|
||||
#define MAXCV SPI_FLASH_SEC_SIZE
|
||||
#if defined(ESP32)
|
||||
#include <esp_spi_flash.h>
|
||||
#define MAXCV SPI_FLASH_SEC_SIZE
|
||||
#elif defined(ESP8266)
|
||||
#include <spi_flash.h>
|
||||
#define MAXCV SPI_FLASH_SEC_SIZE
|
||||
#elif defined( __STM32F1__)
|
||||
#define MAXCV (EEPROM_PAGE_SIZE/4 - 1) // number of storage places (CV address could be larger
|
||||
// because STM32 uses virtual adresses)
|
||||
#undef ALLOW_NESTED_IRQ // This is done with NVIC on STM32
|
||||
#define PRIO_DCC_IRQ 9
|
||||
#define PRIO_SYSTIC 8 // MUST be higher priority than DCC Irq
|
||||
#else
|
||||
#define MAXCV E2END // the upper limit of the CV value currently defined to max memory.
|
||||
#define MAXCV E2END // the upper limit of the CV value currently defined to max memory.
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
@@ -192,17 +209,181 @@ class NmraDcc
|
||||
|
||||
// Flag values to be logically ORed together and passed into the init() method
|
||||
#define FLAGS_MY_ADDRESS_ONLY 0x01 // Only process DCC Packets with My Address
|
||||
#define FLAGS_AUTO_FACTORY_DEFAULT 0x02 // Call notifyCVResetFactoryDefault() if CV 7 & 8 == 255
|
||||
#define FLAGS_SETCV_CALLED 0x10 // only used internally !!
|
||||
#define FLAGS_OUTPUT_ADDRESS_MODE 0x40 // CV 29/541 bit 6
|
||||
#define FLAGS_DCC_ACCESSORY_DECODER 0x80 // CV 29/541 bit 7
|
||||
|
||||
// Flag Bits that are cloned from CV29 relating the DCC Accessory Decoder
|
||||
#define FLAGS_CV29_BITS (FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER)
|
||||
|
||||
|
||||
/*+
|
||||
* pin() is called from setup() and sets up the pin used to receive DCC packets.
|
||||
*
|
||||
* Inputs:
|
||||
* ExtIntNum - Interrupt number of the pin. Use digitalPinToInterrupt(ExtIntPinNum).
|
||||
* ExtIntPinNum - Input pin number.
|
||||
* EnablePullup - Set true to enable the pins pullup resistor.
|
||||
*
|
||||
* Returns:
|
||||
* None.
|
||||
*/
|
||||
void pin( uint8_t ExtIntNum, uint8_t ExtIntPinNum, uint8_t EnablePullup);
|
||||
|
||||
/*+
|
||||
* pin() is called from setup() and sets up the pin used to receive DCC packets.
|
||||
* This relies on the internal function: digitalPinToInterrupt() to map the input pin number to the right interrupt
|
||||
*
|
||||
* Inputs:
|
||||
* ExtIntPinNum - Input pin number.
|
||||
* EnablePullup - Set true to enable the pins pullup resistor.
|
||||
*
|
||||
* Returns:
|
||||
* None.
|
||||
*/
|
||||
#ifdef digitalPinToInterrupt
|
||||
void pin( uint8_t ExtIntPinNum, uint8_t EnablePullup);
|
||||
#endif
|
||||
|
||||
/*+
|
||||
* init() is called from setup() after the pin() command is called.
|
||||
* It initializes the NmDcc object and makes it ready to process packets.
|
||||
*
|
||||
* Inputs:
|
||||
* ManufacturerId - Manufacturer ID returned in CV 8.
|
||||
* Commonly MAN_ID_DIY.
|
||||
* VersionId - Version ID returned in CV 7.
|
||||
* Flags - ORed flags beginning with FLAGS_...
|
||||
* FLAGS_MY_ADDRESS_ONLY - Only process packets with My Address.
|
||||
* FLAGS_DCC_ACCESSORY_DECODER - Decoder is an accessory decoder.
|
||||
* FLAGS_OUTPUT_ADDRESS_MODE - This flag applies to accessory decoders only.
|
||||
* Accessory decoders normally have 4 paired outputs
|
||||
* and a single address refers to all 4 outputs.
|
||||
* Setting FLAGS_OUTPUT_ADDRESS_MODE causes each
|
||||
* address to refer to a single output.
|
||||
* OpsModeAddressBaseCV - Ops Mode base address. Set it to 0?
|
||||
*
|
||||
* Returns:
|
||||
* None.
|
||||
*/
|
||||
void init( uint8_t ManufacturerId, uint8_t VersionId, uint8_t Flags, uint8_t OpsModeAddressBaseCV );
|
||||
|
||||
/*+
|
||||
* initAccessoryDecoder() is called from setup() for accessory decoders.
|
||||
* It calls init() with FLAGS_DCC_ACCESSORY_DECODER ORed into Flags.
|
||||
*
|
||||
* Inputs:
|
||||
* ManufacturerId - Manufacturer ID returned in CV 8.
|
||||
* Commonly MAN_ID_DIY.
|
||||
* VersionId - Version ID returned in CV 7.
|
||||
* Flags - ORed flags beginning with FLAGS_...
|
||||
* FLAGS_DCC_ACCESSORY_DECODER will be set for init() call.
|
||||
* OpsModeAddressBaseCV - Ops Mode base address. Set it to 0?
|
||||
*
|
||||
* Returns:
|
||||
* None.
|
||||
*/
|
||||
void initAccessoryDecoder( uint8_t ManufacturerId, uint8_t VersionId, uint8_t Flags, uint8_t OpsModeAddressBaseCV );
|
||||
|
||||
/*+
|
||||
* process() is called from loop() to process DCC packets.
|
||||
* It must be called very frequently to keep up with the packets.
|
||||
*
|
||||
* Inputs:
|
||||
* None.
|
||||
*
|
||||
* Returns:
|
||||
* 1 - Packet succesfully parsed on this call to process().
|
||||
* 0 - Packet not ready or received packet had an error.
|
||||
*/
|
||||
uint8_t process();
|
||||
|
||||
/*+
|
||||
* getCV() returns the selected CV value.
|
||||
*
|
||||
* Inputs:
|
||||
* CV - CV number. It must point to a valid CV.
|
||||
*
|
||||
* Returns:
|
||||
* Value - CV value. Invalid CV numbers will return an undefined result
|
||||
* since nothing will have been set in that EEPROM position.
|
||||
* Calls notifyCVRead() if it is defined.
|
||||
*/
|
||||
uint8_t getCV( uint16_t CV );
|
||||
|
||||
/*+
|
||||
* setCV() sets the value of a CV.
|
||||
*
|
||||
* Inputs:
|
||||
* CV - CV number. It must point to a valid CV.
|
||||
* Value - CV value.
|
||||
*
|
||||
* Returns:
|
||||
* Value - CV value set by this call.
|
||||
* since nothing will have been set in that EEPROM position.
|
||||
* Calls notifyCVWrite() if it is defined.
|
||||
* Calls notifyCVChange() if the value is changed by this call.
|
||||
*/
|
||||
uint8_t setCV( uint16_t CV, uint8_t Value);
|
||||
|
||||
/*+
|
||||
* setAccDecDCCAddrNextReceived() enables/disables the setting of the board address from the next received turnout command
|
||||
*
|
||||
* Inputs:
|
||||
* enable- boolean to enable or disable the mode
|
||||
*
|
||||
* Returns:
|
||||
*/
|
||||
void setAccDecDCCAddrNextReceived(uint8_t enable);
|
||||
|
||||
/*+
|
||||
* isSetCVReady() returns 1 if EEPROM is ready to write.
|
||||
*
|
||||
* Inputs:
|
||||
* CV - CV number. It must point to a valid CV.
|
||||
* Value - CV value.
|
||||
*
|
||||
* Returns:
|
||||
* ready - 1 if ready to write, 0 otherwise. AVR processor will block
|
||||
* for several ms. for each write cycle so you should check this to avoid blocks.
|
||||
* Note: It returns the value returned by notifyIsSetCVReady() if it is defined.
|
||||
* Calls notifyIsSetCVReady() if it is defined.
|
||||
*/
|
||||
uint8_t isSetCVReady( void );
|
||||
|
||||
/*+
|
||||
* getAddr() return the currently active decoder address.
|
||||
* based on decoder type and current address size.
|
||||
*
|
||||
* Inputs:
|
||||
* None.
|
||||
*
|
||||
* Returns:
|
||||
* Adr - The current decoder address based on decoder type(Multifunction, Accessory)
|
||||
* and short or long address selection for Multifunction decoders.
|
||||
*/
|
||||
uint16_t getAddr(void);
|
||||
|
||||
/*+
|
||||
* getX() return debugging data if DCC_DEBUG is defined.
|
||||
* You would really need to be modifying the library to need them.
|
||||
*
|
||||
* Inputs:
|
||||
* None.
|
||||
*
|
||||
* Returns:
|
||||
* getIntCount - Init to 0 and apparently never incremented?
|
||||
* getTickCount - Init to 0 and incremented each time interrupt handler
|
||||
* completes without an error.
|
||||
* getBitCount - Bit count of valid packet, 0 otherwise. Only valid until
|
||||
* start of the next packet.
|
||||
* getState - Current WAIT_... state as defined by DccRxWaitState in NmraDcc.cpp.
|
||||
* getNestedIrqCount - Init to 0 and incremented each time the interrupt handler
|
||||
* is called before the previous interrupt was complete.
|
||||
* This is an error indication and may indicate the system
|
||||
* is not handling packets fast enough or some other error is occurring.
|
||||
*/
|
||||
// #define DCC_DEBUG
|
||||
#ifdef DCC_DEBUG
|
||||
uint8_t getIntCount(void);
|
||||
@@ -222,30 +403,333 @@ class NmraDcc
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*+
|
||||
* notifyDccReset(uint8_t hardReset) Callback for a DCC reset command.
|
||||
*
|
||||
* Inputs:
|
||||
* hardReset - 0 normal reset command.
|
||||
* 1 hard reset command.
|
||||
*
|
||||
* Returns:
|
||||
* None
|
||||
*/
|
||||
extern void notifyDccReset(uint8_t hardReset ) __attribute__ ((weak));
|
||||
|
||||
/*+
|
||||
* notifyDccIdle() Callback for a DCC idle command.
|
||||
*
|
||||
* Inputs:
|
||||
* None
|
||||
*
|
||||
* Returns:
|
||||
* None
|
||||
*/
|
||||
extern void notifyDccIdle(void) __attribute__ ((weak));
|
||||
|
||||
|
||||
/*+
|
||||
* notifyDccSpeed() Callback for a multifunction decoder speed command.
|
||||
* The received speed and direction are unpacked to separate values.
|
||||
*
|
||||
* Inputs:
|
||||
* Addr - Active decoder address.
|
||||
* AddrType - DCC_ADDR_SHORT or DCC_ADDR_LONG.
|
||||
* Speed - Decoder speed. 0 = Emergency stop
|
||||
* 1 = Regular stop
|
||||
* 2 to SpeedSteps = Speed step 1 to max.
|
||||
* Dir - DCC_DIR_REV or DCC_DIR_FWD
|
||||
* SpeedSteps - Highest speed, SPEED_STEP_14 = 15
|
||||
* SPEED_STEP_28 = 29
|
||||
* SPEED_STEP_128 = 127
|
||||
*
|
||||
* Returns:
|
||||
* None
|
||||
*/
|
||||
extern void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_DIRECTION Dir, DCC_SPEED_STEPS SpeedSteps ) __attribute__ ((weak));
|
||||
|
||||
/*+
|
||||
* notifyDccSpeedRaw() Callback for a multifunction decoder speed command.
|
||||
* The value in Raw is the unpacked speed command.
|
||||
*
|
||||
* Inputs:
|
||||
* Addr - Active decoder address.
|
||||
* AddrType - DCC_ADDR_SHORT or DCC_ADDR_LONG.
|
||||
* Raw - Raw decoder speed command.
|
||||
*
|
||||
* Returns:
|
||||
* None
|
||||
*/
|
||||
extern void notifyDccSpeedRaw( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Raw) __attribute__ ((weak));
|
||||
|
||||
/*+
|
||||
* notifyDccFunc() Callback for a multifunction decoder function command.
|
||||
*
|
||||
* Inputs:
|
||||
* Addr - Active decoder address.
|
||||
* AddrType - DCC_ADDR_SHORT or DCC_ADDR_LONG.
|
||||
* FuncGrp - Function group. FN_0 - 14 speed step headlight function.
|
||||
* Mask FN_BIT_00.
|
||||
* FN_0_4 - Functions 0 to 4. Mask FN_BIT_00 - FN_BIT_04
|
||||
* FN_5_8 - Functions 5 to 8. Mask FN_BIT_05 - FN_BIT_08
|
||||
* FN_9_12 - Functions 9 to 12. Mask FN_BIT_09 - FN_BIT_12
|
||||
* FN_13_20 - Functions 13 to 20. Mask FN_BIT_13 - FN_BIT_20
|
||||
* FN_21_28 - Functions 21 to 28. Mask FN_BIT_21 - FN_BIT_28
|
||||
* FuncState - Function state. Bitmask where active functions have a 1 at that bit.
|
||||
* You must & FuncState with the appropriate
|
||||
* FN_BIT_nn value to isolate a given bit.
|
||||
*
|
||||
* Returns:
|
||||
* None
|
||||
*/
|
||||
extern void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) __attribute__ ((weak));
|
||||
|
||||
extern void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t OutputAddr, uint8_t State ) __attribute__ ((weak));
|
||||
/*+
|
||||
* notifyDccAccTurnoutBoard() Board oriented callback for a turnout accessory decoder.
|
||||
* Most useful when CV29_OUTPUT_ADDRESS_MODE is not set.
|
||||
* Decoders of this type have 4 paired turnout outputs per board.
|
||||
* OutputPower is 1 if the power is on, and 0 otherwise.
|
||||
*
|
||||
* Inputs:
|
||||
* BoardAddr - Per board address. Equivalent to CV 1 LSB & CV 9 MSB.
|
||||
* OutputPair - Output pair number. It has a range of 0 to 3.
|
||||
* Equivalent to upper 2 bits of the 3 DDD bits in the accessory packet.
|
||||
* Direction - Turnout direction. It has a value of 0 or 1.
|
||||
* It is equivalent to bit 0 of the 3 DDD bits in the accessory packet.
|
||||
* OutputPower - Output On/Off. Equivalent to packet C bit. It has these values:
|
||||
* 0 - Output pair is off.
|
||||
* 1 - Output pair is on.
|
||||
*
|
||||
* Returns:
|
||||
* None
|
||||
*/
|
||||
|
||||
extern void notifyDccAccTurnoutBoard( uint16_t BoardAddr, uint8_t OutputPair, uint8_t Direction, uint8_t OutputPower ) __attribute__ ((weak));
|
||||
/*+
|
||||
* notifyDccAccTurnoutOutput() Output oriented callback for a turnout accessory decoder.
|
||||
* Most useful when CV29_OUTPUT_ADDRESS_MODE is not set.
|
||||
* Decoders of this type have 4 paired turnout outputs per board.
|
||||
* OutputPower is 1 if the power is on, and 0 otherwise.
|
||||
*
|
||||
* Inputs:
|
||||
* Addr - Per output address. There will be 4 Addr addresses
|
||||
* per board for a standard accessory decoder with 4 output pairs.
|
||||
* Direction - Turnout direction. It has a value of 0 or 1.
|
||||
* Equivalent to bit 0 of the 3 DDD bits in the accessory packet.
|
||||
* OutputPower - Output On/Off. Equivalent to packet C bit. It has these values:
|
||||
* 0 - Output is off.
|
||||
* 1 - Output is on.
|
||||
*
|
||||
* Returns:
|
||||
* None
|
||||
*/
|
||||
extern void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t OutputPower ) __attribute__ ((weak));
|
||||
|
||||
extern void notifyDccSigState( uint16_t Addr, uint8_t OutputIndex, uint8_t State) __attribute__ ((weak));
|
||||
/*+
|
||||
* notifyDccAccBoardAddrSet() Board oriented callback for a turnout accessory decoder.
|
||||
* This notification is when a new Board Address is set to the
|
||||
* address of the next DCC Turnout Packet that is received
|
||||
*
|
||||
* This is enabled via the setAccDecDCCAddrNextReceived() method above
|
||||
*
|
||||
* Inputs:
|
||||
* BoardAddr - Per board address. Equivalent to CV 1 LSB & CV 9 MSB.
|
||||
* per board for a standard accessory decoder with 4 output pairs.
|
||||
*
|
||||
* Returns:
|
||||
* None
|
||||
*/
|
||||
extern void notifyDccAccBoardAddrSet( uint16_t BoardAddr) __attribute__ ((weak));
|
||||
|
||||
/*+
|
||||
* notifyDccAccOutputAddrSet() Output oriented callback for a turnout accessory decoder.
|
||||
* This notification is when a new Output Address is set to the
|
||||
* address of the next DCC Turnout Packet that is received
|
||||
*
|
||||
* This is enabled via the setAccDecDCCAddrNextReceived() method above
|
||||
*
|
||||
* Inputs:
|
||||
* Addr - Per output address. There will be 4 Addr addresses
|
||||
* per board for a standard accessory decoder with 4 output pairs.
|
||||
*
|
||||
* Returns:
|
||||
* None
|
||||
*/
|
||||
extern void notifyDccAccOutputAddrSet( uint16_t Addr) __attribute__ ((weak));
|
||||
|
||||
/*+
|
||||
* notifyDccSigOutputState() Callback for a signal aspect accessory decoder.
|
||||
* Defined in S-9.2.1 as the Extended Accessory Decoder Control Packet.
|
||||
*
|
||||
* Inputs:
|
||||
* Addr - Decoder address.
|
||||
* State - 6 bit command equivalent to S-9.2.1 00XXXXXX.
|
||||
*
|
||||
* Returns:
|
||||
* None
|
||||
*/
|
||||
extern void notifyDccSigOutputState( uint16_t Addr, uint8_t State) __attribute__ ((weak));
|
||||
|
||||
/*+
|
||||
* notifyDccMsg() Raw DCC packet callback.
|
||||
* Called with raw DCC packet bytes.
|
||||
*
|
||||
* Inputs:
|
||||
* Msg - Pointer to DCC_MSG structure. The values are:
|
||||
* Msg->Size - Number of Data bytes in the packet.
|
||||
* Msg->PreambleBits - Number of preamble bits in the packet.
|
||||
* Msg->Data[] - Array of data bytes in the packet.
|
||||
*
|
||||
* Returns:
|
||||
* None
|
||||
*/
|
||||
extern void notifyDccMsg( DCC_MSG * Msg ) __attribute__ ((weak));
|
||||
|
||||
/*+
|
||||
* notifyCVValid() Callback to determine if a given CV is valid.
|
||||
* This is called when the library needs to determine
|
||||
* if a CV is valid. Note: If defined, this callback
|
||||
* MUST determine if a CV is valid and return the
|
||||
* appropriate value. If this callback is not defined,
|
||||
* the library will determine validity.
|
||||
*
|
||||
* Inputs:
|
||||
* CV - CV number.
|
||||
* Writable - 1 for CV writes. 0 for CV reads.
|
||||
*
|
||||
* Returns:
|
||||
* 1 - CV is valid.
|
||||
* 0 - CV is not valid.
|
||||
*/
|
||||
extern uint8_t notifyCVValid( uint16_t CV, uint8_t Writable ) __attribute__ ((weak));
|
||||
|
||||
/*+
|
||||
* notifyCVRead() Callback to read a CV.
|
||||
* This is called when the library needs to read
|
||||
* a CV. Note: If defined, this callback
|
||||
* MUST return the value of the CV.
|
||||
* If this callback is not defined,
|
||||
* the library will read the CV from EEPROM.
|
||||
*
|
||||
* Inputs:
|
||||
* CV - CV number.
|
||||
*
|
||||
* Returns:
|
||||
* Value - Value of the CV.
|
||||
*/
|
||||
extern uint8_t notifyCVRead( uint16_t CV) __attribute__ ((weak));
|
||||
|
||||
/*+
|
||||
* notifyCVWrite() Callback to write a value to a CV.
|
||||
* This is called when the library needs to write
|
||||
* a CV. Note: If defined, this callback
|
||||
* MUST write the Value to the CV and return the value of the CV.
|
||||
* If this callback is not defined,
|
||||
* the library will read the CV from EEPROM.
|
||||
*
|
||||
* Inputs:
|
||||
* CV - CV number.
|
||||
* Value - Value of the CV.
|
||||
*
|
||||
* Returns:
|
||||
* Value - Value of the CV.
|
||||
*/
|
||||
extern uint8_t notifyCVWrite( uint16_t CV, uint8_t Value) __attribute__ ((weak));
|
||||
|
||||
/*+
|
||||
* notifyIsSetCVReady() Callback to to determine if CVs can be written.
|
||||
* This is called when the library needs to determine
|
||||
* is ready to write without blocking or failing.
|
||||
* Note: If defined, this callback
|
||||
* MUST determine if a CV write would block or fail
|
||||
* return the appropriate value.
|
||||
* If this callback is not defined,
|
||||
* the library determines if a write to the EEPROM
|
||||
* would block.
|
||||
*
|
||||
* Inputs:
|
||||
* None
|
||||
*
|
||||
* Returns:
|
||||
* 1 - CV is ready to be written.
|
||||
* 0 - CV is not ready to be written.
|
||||
*/
|
||||
extern uint8_t notifyIsSetCVReady(void) __attribute__ ((weak));
|
||||
|
||||
/*+
|
||||
* notifyCVChange() Called when a CV value is changed.
|
||||
* This is called whenever a CV's value is changed.
|
||||
* notifyDccCVChange() Called only when a CV value is changed by a Dcc packet or a internal lib function.
|
||||
* it is NOT called if the CV is changed by means of the setCV() method.
|
||||
* Note: It is not called if notifyCVWrite() is defined
|
||||
* or if the value in the EEPROM is the same as the value
|
||||
* in the write command.
|
||||
*
|
||||
* Inputs:
|
||||
* CV - CV number.
|
||||
* Value - Value of the CV.
|
||||
*
|
||||
* Returns:
|
||||
* None
|
||||
*/
|
||||
extern void notifyCVChange( uint16_t CV, uint8_t Value) __attribute__ ((weak));
|
||||
extern void notifyDccCVChange( uint16_t CV, uint8_t Value) __attribute__ ((weak));
|
||||
|
||||
/*+
|
||||
* notifyCVResetFactoryDefault() Called when CVs must be reset.
|
||||
* This is called when CVs must be reset
|
||||
* to their factory defaults. This callback
|
||||
* should write the factory default value of
|
||||
* relevent CVs using the setCV() method.
|
||||
* setCV() must not block whens this is called.
|
||||
* Test with isSetCVReady() prior to calling setCV()
|
||||
*
|
||||
* Inputs:
|
||||
* None
|
||||
* *
|
||||
* Returns:
|
||||
* None
|
||||
*/
|
||||
extern void notifyCVResetFactoryDefault(void) __attribute__ ((weak));
|
||||
|
||||
/*+
|
||||
* notifyCVAck() Called when a CV write must be acknowledged.
|
||||
* This callback must increase the current drawn by this
|
||||
* decoder by at least 60mA for 6ms +/- 1ms.
|
||||
*
|
||||
* Inputs:
|
||||
* None
|
||||
* *
|
||||
* Returns:
|
||||
* None
|
||||
*/
|
||||
extern void notifyCVAck(void) __attribute__ ((weak));
|
||||
/*+
|
||||
* notifyAdvancedCVAck() Called when a CV write must be acknowledged.
|
||||
* This callback must increase the current drawn by this
|
||||
* decoder by at least 60mA for 6ms +/- 1ms.
|
||||
*
|
||||
* Inputs:
|
||||
* None
|
||||
* *
|
||||
* Returns:
|
||||
* None
|
||||
*/
|
||||
extern void notifyAdvancedCVAck(void) __attribute__ ((weak));
|
||||
/*+
|
||||
* notifyServiceMode(bool) Called when state of 'inServiceMode' changes
|
||||
*
|
||||
* Inputs:
|
||||
* bool state of inServiceMode
|
||||
* *
|
||||
* Returns:
|
||||
* None
|
||||
*/
|
||||
extern void notifyServiceMode(bool) __attribute__ ((weak));
|
||||
|
||||
// Deprecated, only for backward compatibility with version 1.4.2.
|
||||
// Don't use in new designs. These functions may be dropped in future versions
|
||||
extern void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t OutputAddr, uint8_t State ) __attribute__ ((weak));
|
||||
extern void notifyDccSigState( uint16_t Addr, uint8_t OutputIndex, uint8_t State) __attribute__ ((weak));
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
|
10
README.md
10
README.md
@@ -1,2 +1,12 @@
|
||||
# NmraDcc
|
||||
NMRA Digital Command Control (DCC) Library
|
||||
|
||||
This library allows you to interface to a NMRA DCC track signal and receive DCC commands.
|
||||
|
||||
The library currently supports the AVR ATTiny84/85 & ATMega88/168/328/32u4 and Teensy 3.x using the INT0/1 Hardware Interrupt and micros() ONLY and no longer uses Timer0 Compare Match B, which makes it much more portable to other platforms.
|
||||
|
||||
**Warning** as of version 1.4.4 support has been removed for the following two call-back functions, which will cause your sketch to silently stop working:
|
||||
|
||||
extern void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t OutputAddr, uint8_t State )
|
||||
extern void notifyDccSigState( uint16_t Addr, uint8_t OutputIndex, uint8_t State)
|
||||
|
||||
|
@@ -0,0 +1,259 @@
|
||||
// DCC Stepper Motor Controller ( A4988 ) Example for Model Railroad Turntable Control
|
||||
//
|
||||
// See: https://www.dccinterface.com/how-to/assemblyguide/
|
||||
//
|
||||
// Author: Alex Shepherd 2017-12-04
|
||||
//
|
||||
// This example requires two Arduino Libraries:
|
||||
//
|
||||
// 1) The AccelStepper library from: http://www.airspayce.com/mikem/arduino/AccelStepper/index.html
|
||||
//
|
||||
// 2) The NmraDcc Library from: http://mrrwa.org/download/
|
||||
//
|
||||
// Both libraries can be found and installed via the Arduino IDE Library Manager
|
||||
//
|
||||
// Also checkout the artical I wrote in this project here:
|
||||
// http://mrrwa.org/2017/12/23/dcc-controlled-turntable-stepper-motor-driver/
|
||||
//
|
||||
|
||||
#include <AccelStepper.h>
|
||||
#include <NmraDcc.h>
|
||||
|
||||
// The lines below define the pins used to connect to the A4988 driver module
|
||||
#define A4988_STEP_PIN 4
|
||||
#define A4988_DIRECTION_PIN 5
|
||||
// Uncomment the next line to enable Powering-Off the Stepper when its not running to reduce heating the motor and driver
|
||||
#define A4988_ENABLE_PIN 6
|
||||
|
||||
// The lines below define the stepping speed and acceleration, which you may need to tune for your application
|
||||
#define STEPPER_MAX_SPEED 800 // Sets the maximum permitted speed
|
||||
#define STEPPER_ACCELARATION 1000 // Sets the acceleration/deceleration rate
|
||||
#define STEPPER_SPEED 300 // Sets the desired constant speed for use with runSpeed()
|
||||
|
||||
// The line below defines the number of "Full Steps" your stepper motor does for a full rotation
|
||||
#define MOTOR_FULL_STEPS_PER_REVOLUTION 200
|
||||
|
||||
// The line below defines any reduction gearbox multiplier. No gearbox = 1
|
||||
#define REDUCTION_GEARBOX_RATIO 1
|
||||
|
||||
#define STEPS_PER_REVOLUTION (MOTOR_FULL_STEPS_PER_REVOLUTION * REDUCTION_GEARBOX_RATIO)
|
||||
|
||||
// The A4988 Driver Board has 3 pins that set the Stepping Mode which are connected to 3 jumpers on the board.
|
||||
// Uncomment the line below to match the Boards jumper setting MS1, MS2, MS3
|
||||
// --------------------------------------------------------------------------------------------
|
||||
//#define FULL_TURN_STEPS (STEPS_PER_REVOLUTION) // full steps - MS1=OFF, MS2=OFF, MS3=OFF
|
||||
//#define FULL_TURN_STEPS (STEPS_PER_REVOLUTION * 2) // 1/2 steps - MS1=ON, MS2=OFF, MS3=OFF
|
||||
#define FULL_TURN_STEPS (STEPS_PER_REVOLUTION * 4) // 1/4 steps - MS1=OFF, MS2=ON, MS3=OFF
|
||||
//#define FULL_TURN_STEPS (STEPS_PER_REVOLUTION * 8) // 1/8 steps - MS1=ON, MS2=ON, MS3=OFF
|
||||
//#define FULL_TURN_STEPS (STEPS_PER_REVOLUTION * 16) // 1/16 steps - MS1=ON, MS2=ON, MS3=ON
|
||||
|
||||
#ifndef FULL_TURN_STEPS
|
||||
#error You need to select one of the FULL_TURN_STEPS to match the A4988 Driver Board jumper settings
|
||||
#endif
|
||||
|
||||
// This constant is useful to know the number of steps to rotate the turntable 180 degrees for the back entrance position
|
||||
#define HALF_TURN_STEPS (FULL_TURN_STEPS / 2)
|
||||
|
||||
// Home Position Sensor Input
|
||||
#define HOME_SENSOR_PIN 3
|
||||
#define HOME_SENSOR_ACTIVE_STATE HIGH
|
||||
|
||||
// This structure holds the values for a turntable position wiht the DCC Address, Front Position in Steps from Home Sensor
|
||||
typedef struct
|
||||
{
|
||||
int dccAddress;
|
||||
int positionFront;
|
||||
int positionBack;
|
||||
}
|
||||
TurnoutPosition;
|
||||
|
||||
// The constant HOME_POSITION_DCC_ADDRESS is the base DCC Accessory Decoder Address for the Home Position
|
||||
// with each subsequent position numbered sequentially from there
|
||||
#define POSITION_01_DCC_ADDRESS 200
|
||||
|
||||
// I decided to divide the turntable up into 10 Positions using #defines and mathc so it all scales with changes
|
||||
// to the MS1,MS2,MS3 stepping jumpers above and to make the math tidy, but you assign positions how ever you like
|
||||
#define POSITION_01 (HALF_TURN_STEPS / 10)
|
||||
|
||||
// This array contains the Turnout Positions which can have lines added/removed to suit your turntable
|
||||
TurnoutPosition turnoutPositions[] = {
|
||||
{POSITION_01_DCC_ADDRESS + 0, POSITION_01 * 1, POSITION_01 * 1 + HALF_TURN_STEPS },
|
||||
{POSITION_01_DCC_ADDRESS + 1, POSITION_01 * 2, POSITION_01 * 2 + HALF_TURN_STEPS },
|
||||
{POSITION_01_DCC_ADDRESS + 2, POSITION_01 * 3, POSITION_01 * 3 + HALF_TURN_STEPS },
|
||||
{POSITION_01_DCC_ADDRESS + 3, POSITION_01 * 4, POSITION_01 * 4 + HALF_TURN_STEPS },
|
||||
{POSITION_01_DCC_ADDRESS + 4, POSITION_01 * 5, POSITION_01 * 5 + HALF_TURN_STEPS },
|
||||
{POSITION_01_DCC_ADDRESS + 5, POSITION_01 * 6, POSITION_01 * 6 + HALF_TURN_STEPS },
|
||||
{POSITION_01_DCC_ADDRESS + 6, POSITION_01 * 7, POSITION_01 * 7 + HALF_TURN_STEPS },
|
||||
{POSITION_01_DCC_ADDRESS + 7, POSITION_01 * 8, POSITION_01 * 8 + HALF_TURN_STEPS },
|
||||
{POSITION_01_DCC_ADDRESS + 8, POSITION_01 * 9, POSITION_01 * 9 + HALF_TURN_STEPS },
|
||||
{POSITION_01_DCC_ADDRESS + 9, POSITION_01 *10, POSITION_01 *10 + HALF_TURN_STEPS },
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// You shouldn't need to edit anything below this line unless you're needing to make big changes... ;)
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
#define MAX_TURNOUT_POSITIONS (sizeof(turnoutPositions) / sizeof(TurnoutPosition))
|
||||
|
||||
// Setup the AccelStepper object for the A4988 Stepper Motor Driver
|
||||
AccelStepper stepper1(AccelStepper::DRIVER, A4988_STEP_PIN, A4988_DIRECTION_PIN);
|
||||
|
||||
// Dcc Accessory Decoder object
|
||||
NmraDcc Dcc ;
|
||||
|
||||
// Variables to store the last DCC Turnout message Address and Direction
|
||||
uint16_t lastAddr = 0xFFFF ;
|
||||
uint8_t lastDirection = 0xFF;
|
||||
|
||||
// This function is called whenever a normal DCC Turnout Packet is received
|
||||
void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t OutputPower )
|
||||
{
|
||||
Serial.print("notifyDccAccTurnoutOutput: ") ;
|
||||
Serial.print(Addr,DEC) ;
|
||||
Serial.print(',');
|
||||
Serial.print(Direction,DEC) ;
|
||||
Serial.print(',');
|
||||
Serial.println(OutputPower, HEX) ;
|
||||
|
||||
for (int i = 0; i < MAX_TURNOUT_POSITIONS ; i++)
|
||||
{
|
||||
if ((Addr == turnoutPositions[i].dccAddress) && ((Addr != lastAddr) || (Direction != lastDirection)) && OutputPower)
|
||||
{
|
||||
lastAddr = Addr ;
|
||||
lastDirection = Direction ;
|
||||
|
||||
Serial.print(F("Moving to "));
|
||||
Serial.print(Direction ? F("Front") : F("Back"));
|
||||
Serial.print(F(" Position: "));
|
||||
Serial.print(i, DEC);
|
||||
Serial.print(F(" @ Step: "));
|
||||
|
||||
#ifdef A4988_ENABLE_PIN
|
||||
stepper1.enableOutputs();
|
||||
#endif
|
||||
if (Direction)
|
||||
{
|
||||
Serial.println(turnoutPositions[i].positionFront, DEC);
|
||||
stepper1.moveTo(turnoutPositions[i].positionFront);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(turnoutPositions[i].positionBack, DEC);
|
||||
stepper1.moveTo(turnoutPositions[i].positionBack);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef A4988_ENABLE_PIN
|
||||
bool lastIsRunningState ;
|
||||
#endif
|
||||
|
||||
void setupStepperDriver()
|
||||
{
|
||||
#ifdef A4988_ENABLE_PIN
|
||||
stepper1.setPinsInverted(false, false, true); // Its important that these commands are in this order
|
||||
stepper1.setEnablePin(A4988_ENABLE_PIN); // otherwise the Outputs are NOT enabled initially
|
||||
#endif
|
||||
|
||||
stepper1.setMaxSpeed(STEPPER_MAX_SPEED); // Sets the maximum permitted speed
|
||||
stepper1.setAcceleration(STEPPER_ACCELARATION); // Sets the acceleration/deceleration rate
|
||||
stepper1.setSpeed(STEPPER_SPEED); // Sets the desired constant speed for use with runSpeed()
|
||||
|
||||
#ifdef A4988_ENABLE_PIN
|
||||
lastIsRunningState = stepper1.isRunning();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool moveToHomePosition()
|
||||
{
|
||||
Serial.println(F("Finding Home Sensor...."));
|
||||
|
||||
pinMode(HOME_SENSOR_PIN, INPUT_PULLUP);
|
||||
|
||||
stepper1.move(FULL_TURN_STEPS * 2);
|
||||
while(digitalRead(HOME_SENSOR_PIN) != HOME_SENSOR_ACTIVE_STATE)
|
||||
stepper1.run();
|
||||
|
||||
if(digitalRead(HOME_SENSOR_PIN) == HOME_SENSOR_ACTIVE_STATE)
|
||||
{
|
||||
Serial.println(F("Found Home Position - Setting Current Position to 0"));
|
||||
stepper1.setCurrentPosition(0);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
Serial.println(F("Home Position NOT FOUND - Check Sensor Hardware"));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void setupDCCDecoder()
|
||||
{
|
||||
Serial.println(F("Setting up DCC Decorder..."));
|
||||
|
||||
// Setup which External Interrupt, the Pin it's associated with that we're using and enable the Pull-Up
|
||||
Dcc.pin(0, 2, 1);
|
||||
|
||||
// Call the main DCC Init function to enable the DCC Receiver
|
||||
Dcc.init( MAN_ID_DIY, 10, CV29_ACCESSORY_DECODER | CV29_OUTPUT_ADDRESS_MODE, 0 );
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while(!Serial); // Wait for the USB Device to Enumerate
|
||||
|
||||
Serial.println(F("\nExample Stepper Motor Driver for DCC Turntable Control"));
|
||||
|
||||
Serial.print(F("Full Rotation Steps: "));
|
||||
Serial.println(FULL_TURN_STEPS);
|
||||
|
||||
for(uint8_t i = 0; i < MAX_TURNOUT_POSITIONS; i++)
|
||||
{
|
||||
Serial.print("DCC Addr: ");
|
||||
Serial.print(turnoutPositions[i].dccAddress);
|
||||
|
||||
Serial.print(" Front: ");
|
||||
Serial.print(turnoutPositions[i].positionFront);
|
||||
|
||||
Serial.print(" Back: ");
|
||||
Serial.println(turnoutPositions[i].positionBack);
|
||||
}
|
||||
|
||||
setupStepperDriver();
|
||||
|
||||
if(moveToHomePosition());
|
||||
{
|
||||
setupDCCDecoder();
|
||||
|
||||
#ifdef A4988_ENABLE_PIN
|
||||
stepper1.enableOutputs();
|
||||
#endif
|
||||
|
||||
// Fake a DCC Packet to cause the Turntable to move to Position 1
|
||||
notifyDccAccTurnoutOutput(POSITION_01_DCC_ADDRESS, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// You MUST call the NmraDcc.process() method frequently from the Arduino loop() function for correct library operation
|
||||
Dcc.process();
|
||||
|
||||
// Process the Stepper Library
|
||||
stepper1.run();
|
||||
|
||||
#ifdef A4988_ENABLE_PIN
|
||||
if(stepper1.isRunning() != lastIsRunningState)
|
||||
{
|
||||
lastIsRunningState = stepper1.isRunning();
|
||||
if(!lastIsRunningState)
|
||||
{
|
||||
stepper1.disableOutputs();
|
||||
Serial.println(F("Disable Stepper Outputs"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
@@ -56,20 +56,7 @@ void notifyDccMsg( DCC_MSG * Msg)
|
||||
}
|
||||
#endif
|
||||
|
||||
// This function is called whenever a normal DCC Turnout Packet is received
|
||||
void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t OutputAddr, uint8_t State)
|
||||
{
|
||||
Serial.print("notifyDccAccState: ") ;
|
||||
Serial.print(Addr,DEC) ;
|
||||
Serial.print(',');
|
||||
Serial.print(BoardAddr,DEC) ;
|
||||
Serial.print(',');
|
||||
Serial.print(OutputAddr,DEC) ;
|
||||
Serial.print(',');
|
||||
Serial.println(State, HEX) ;
|
||||
}
|
||||
|
||||
// This function is called whenever a normal DCC Turnout Packet is received
|
||||
// This function is called whenever a normal DCC Turnout Packet is received and we're in Board Addressing Mode
|
||||
void notifyDccAccTurnoutBoard( uint16_t BoardAddr, uint8_t OutputPair, uint8_t Direction, uint8_t OutputPower )
|
||||
{
|
||||
Serial.print("notifyDccAccTurnoutBoard: ") ;
|
||||
@@ -82,7 +69,7 @@ void notifyDccAccTurnoutBoard( uint16_t BoardAddr, uint8_t OutputPair, uint8_t D
|
||||
Serial.println(OutputPower, HEX) ;
|
||||
}
|
||||
|
||||
// This function is called whenever a normal DCC Turnout Packet is received
|
||||
// This function is called whenever a normal DCC Turnout Packet is received and we're in Output Addressing Mode
|
||||
void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t OutputPower )
|
||||
{
|
||||
Serial.print("notifyDccAccTurnoutOutput: ") ;
|
||||
@@ -94,13 +81,11 @@ void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t Output
|
||||
}
|
||||
|
||||
// This function is called whenever a DCC Signal Aspect Packet is received
|
||||
void notifyDccSigState( uint16_t Addr, uint8_t OutputIndex, uint8_t State)
|
||||
void notifyDccSigOutputState( uint16_t Addr, uint8_t State)
|
||||
{
|
||||
Serial.print("notifyDccSigState: ") ;
|
||||
Serial.print("notifyDccSigOutputState: ") ;
|
||||
Serial.print(Addr,DEC) ;
|
||||
Serial.print(',');
|
||||
Serial.print(OutputIndex,DEC) ;
|
||||
Serial.print(',');
|
||||
Serial.println(State, HEX) ;
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,314 @@
|
||||
// NMRA Dcc Multifunction Motor Decoder Demo
|
||||
//
|
||||
// Author: Alex Shepherd 2019-03-30
|
||||
//
|
||||
// This example requires these Arduino Libraries:
|
||||
//
|
||||
// 1) The NmraDcc Library from: http://mrrwa.org/download/
|
||||
//
|
||||
// These libraries can be found and installed via the Arduino IDE Library Manager
|
||||
//
|
||||
// This is a simple demo of how to drive and motor speed and direction using PWM and a motor H-Bridge
|
||||
// It uses vStart and vHigh CV values to customise the PWM values to the motor response
|
||||
// It also uses the Headling Function to drive 2 LEDs for Directional Headlights
|
||||
// Apart from that there's nothing fancy like Lighting Effects or a function matrix or Speed Tables - its just the basics...
|
||||
//
|
||||
|
||||
#include <NmraDcc.h>
|
||||
// Uncomment any of the lines below to enable debug messages for different parts of the code
|
||||
//#define DEBUG_FUNCTIONS
|
||||
//#define DEBUG_SPEED
|
||||
//#define DEBUG_PWM
|
||||
//#define DEBUG_DCC_ACK
|
||||
//#define DEBUG_DCC_MSG
|
||||
|
||||
#if defined(DEBUG_FUNCTIONS) or defined(DEBUG_SPEED) or defined(DEBUG_PWM) or defined(DEBUG_DCC_ACK) or defined(DEBUG_DCC_MSG)
|
||||
#define DEBUG_PRINT
|
||||
#endif
|
||||
|
||||
// This is the default DCC Address
|
||||
#define DEFAULT_DECODER_ADDRESS 3
|
||||
|
||||
// This section defines the Arduino UNO Pins to use
|
||||
#ifdef __AVR_ATmega328P__
|
||||
|
||||
#define DCC_PIN 2
|
||||
|
||||
#define LED_PIN_FWD 5
|
||||
#define LED_PIN_REV 6
|
||||
#define MOTOR_DIR_PIN 12
|
||||
#define MOTOR_PWM_PIN 3
|
||||
|
||||
// This section defines the Arduino ATTiny85 Pins to use
|
||||
#elif ARDUINO_AVR_ATTINYX5
|
||||
|
||||
#define DCC_PIN 2
|
||||
|
||||
#define LED_PIN_FWD 0
|
||||
#define LED_PIN_REV 1
|
||||
#define MOTOR_DIR_PIN 3
|
||||
#define MOTOR_PWM_PIN 4
|
||||
|
||||
#else
|
||||
#error "Unsupported CPU, you need to add another configuration section for your CPU"
|
||||
#endif
|
||||
|
||||
// Some global state variables
|
||||
uint8_t newLedState = 0;
|
||||
uint8_t lastLedState = 0;
|
||||
|
||||
uint8_t newDirection = 0;
|
||||
uint8_t lastDirection = 0;
|
||||
|
||||
uint8_t newSpeed = 0;
|
||||
uint8_t lastSpeed = 0;
|
||||
uint8_t numSpeedSteps = SPEED_STEP_128;
|
||||
|
||||
uint8_t vStart;
|
||||
uint8_t vHigh;
|
||||
|
||||
// Structure for CV Values Table
|
||||
struct CVPair
|
||||
{
|
||||
uint16_t CV;
|
||||
uint8_t Value;
|
||||
};
|
||||
|
||||
// CV Addresses we will be using
|
||||
#define CV_VSTART 2
|
||||
#define CV_VHIGH 5
|
||||
|
||||
// Default CV Values Table
|
||||
CVPair FactoryDefaultCVs [] =
|
||||
{
|
||||
// The CV Below defines the Short DCC Address
|
||||
{CV_MULTIFUNCTION_PRIMARY_ADDRESS, DEFAULT_DECODER_ADDRESS},
|
||||
|
||||
// Three Step Speed Table
|
||||
{CV_VSTART, 120},
|
||||
{CV_VHIGH, 255},
|
||||
|
||||
// These two CVs define the Long DCC Address
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, DEFAULT_DECODER_ADDRESS},
|
||||
|
||||
// ONLY uncomment 1 CV_29_CONFIG line below as approprate
|
||||
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
|
||||
{CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
|
||||
};
|
||||
|
||||
NmraDcc Dcc ;
|
||||
|
||||
uint8_t FactoryDefaultCVIndex = 0;
|
||||
|
||||
// This call-back function is called when a CV Value changes so we can update CVs we're using
|
||||
void notifyCVChange( uint16_t CV, uint8_t Value)
|
||||
{
|
||||
switch(CV)
|
||||
{
|
||||
case CV_VSTART:
|
||||
vStart = Value;
|
||||
break;
|
||||
|
||||
case CV_VHIGH:
|
||||
vHigh = Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void notifyCVResetFactoryDefault()
|
||||
{
|
||||
// Make FactoryDefaultCVIndex non-zero and equal to num CV's to be reset
|
||||
// to flag to the loop() function that a reset to Factory Defaults needs to be done
|
||||
FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
|
||||
};
|
||||
|
||||
// This call-back function is called whenever we receive a DCC Speed packet for our address
|
||||
void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_DIRECTION Dir, DCC_SPEED_STEPS SpeedSteps )
|
||||
{
|
||||
#ifdef DEBUG_SPEED
|
||||
Serial.print("notifyDccSpeed: Addr: ");
|
||||
Serial.print(Addr,DEC);
|
||||
Serial.print( (AddrType == DCC_ADDR_SHORT) ? "-S" : "-L" );
|
||||
Serial.print(" Speed: ");
|
||||
Serial.print(Speed,DEC);
|
||||
Serial.print(" Steps: ");
|
||||
Serial.print(SpeedSteps,DEC);
|
||||
Serial.print(" Dir: ");
|
||||
Serial.println( (Dir == DCC_DIR_FWD) ? "Forward" : "Reverse" );
|
||||
#endif
|
||||
|
||||
newDirection = Dir;
|
||||
newSpeed = Speed;
|
||||
numSpeedSteps = SpeedSteps;
|
||||
};
|
||||
|
||||
// This call-back function is called whenever we receive a DCC Function packet for our address
|
||||
void notifyDccFunc(uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState)
|
||||
{
|
||||
#ifdef DEBUG_FUNCTIONS
|
||||
Serial.print("notifyDccFunc: Addr: ");
|
||||
Serial.print(Addr,DEC);
|
||||
Serial.print( (AddrType == DCC_ADDR_SHORT) ? 'S' : 'L' );
|
||||
Serial.print(" Function Group: ");
|
||||
Serial.print(FuncGrp,DEC);
|
||||
#endif
|
||||
|
||||
if(FuncGrp == FN_0_4)
|
||||
{
|
||||
newLedState = (FuncState & FN_BIT_00) ? 1 : 0;
|
||||
#ifdef DEBUG_FUNCTIONS
|
||||
Serial.print(" FN 0: ");
|
||||
Serial.print(newLedState);
|
||||
#endif
|
||||
}
|
||||
#ifdef DEBUG_FUNCTIONS
|
||||
Serial.println();
|
||||
#endif
|
||||
}
|
||||
|
||||
// This call-back function is called whenever we receive a DCC Packet
|
||||
#ifdef DEBUG_DCC_MSG
|
||||
void notifyDccMsg( DCC_MSG * Msg)
|
||||
{
|
||||
Serial.print("notifyDccMsg: ") ;
|
||||
for(uint8_t i = 0; i < Msg->Size; i++)
|
||||
{
|
||||
Serial.print(Msg->Data[i], HEX);
|
||||
Serial.write(' ');
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
#endif
|
||||
|
||||
// This call-back function is called by the NmraDcc library when a DCC ACK needs to be sent
|
||||
// Calling this function should cause an increased 60ma current drain on the power supply for 6ms to ACK a CV Read
|
||||
// So we will just turn the motor on for 8ms and then turn it off again.
|
||||
|
||||
void notifyCVAck(void)
|
||||
{
|
||||
#ifdef DEBUG_DCC_ACK
|
||||
Serial.println("notifyCVAck") ;
|
||||
#endif
|
||||
|
||||
digitalWrite(MOTOR_DIR_PIN, HIGH);
|
||||
digitalWrite(MOTOR_PWM_PIN, HIGH);
|
||||
|
||||
delay( 8 );
|
||||
|
||||
digitalWrite(MOTOR_DIR_PIN, LOW);
|
||||
digitalWrite(MOTOR_PWM_PIN, LOW);
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
#ifdef DEBUG_PRINT
|
||||
Serial.begin(115200);
|
||||
Serial.println("NMRA Dcc Multifunction Motor Decoder Demo");
|
||||
#endif
|
||||
|
||||
// Setup the Pins for the Fwd/Rev LED for Function 0 Headlight
|
||||
pinMode(LED_PIN_FWD, OUTPUT);
|
||||
pinMode(LED_PIN_REV, OUTPUT);
|
||||
|
||||
// Setup the Pins for the Motor H-Bridge Driver
|
||||
pinMode(MOTOR_DIR_PIN, OUTPUT);
|
||||
pinMode(MOTOR_PWM_PIN, OUTPUT);
|
||||
|
||||
|
||||
// Setup which External Interrupt, the Pin it's associated with that we're using and enable the Pull-Up
|
||||
Dcc.pin(DCC_PIN, 0);
|
||||
|
||||
Dcc.init( MAN_ID_DIY, 10, FLAGS_MY_ADDRESS_ONLY | FLAGS_AUTO_FACTORY_DEFAULT, 0 );
|
||||
|
||||
// Uncomment to force CV Reset to Factory Defaults
|
||||
// notifyCVResetFactoryDefault();
|
||||
|
||||
// Read the current CV values for vStart and vHigh
|
||||
vStart = Dcc.getCV(CV_VSTART);
|
||||
vHigh = Dcc.getCV(CV_VHIGH);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// You MUST call the NmraDcc.process() method frequently from the Arduino loop() function for correct library operation
|
||||
Dcc.process();
|
||||
|
||||
// Handle Speed changes
|
||||
if(lastSpeed != newSpeed)
|
||||
{
|
||||
lastSpeed = newSpeed;
|
||||
|
||||
// Stop if speed = 0 or 1
|
||||
|
||||
if(newSpeed <= 1)
|
||||
digitalWrite(MOTOR_PWM_PIN, LOW);
|
||||
|
||||
// Calculate PWM value in the range 1..255
|
||||
else
|
||||
{
|
||||
uint8_t vScaleFactor;
|
||||
|
||||
if((vHigh > 1) && (vHigh > vStart))
|
||||
vScaleFactor = vHigh - vStart;
|
||||
else
|
||||
vScaleFactor = 255 - vStart;
|
||||
|
||||
uint8_t modSpeed = newSpeed - 1;
|
||||
uint8_t modSteps = numSpeedSteps - 1;
|
||||
|
||||
uint8_t newPwm = (uint8_t) vStart + modSpeed * vScaleFactor / modSteps;
|
||||
|
||||
#ifdef DEBUG_PWM
|
||||
Serial.print("New Speed: vStart: ");
|
||||
Serial.print(vStart);
|
||||
Serial.print(" vHigh: ");
|
||||
Serial.print(vHigh);
|
||||
Serial.print(" modSpeed: ");
|
||||
Serial.print(modSpeed);
|
||||
Serial.print(" vScaleFactor: ");
|
||||
Serial.print(vScaleFactor);
|
||||
Serial.print(" modSteps: ");
|
||||
Serial.print(modSteps);
|
||||
Serial.print(" newPwm: ");
|
||||
Serial.println(newPwm);
|
||||
#endif
|
||||
|
||||
analogWrite(MOTOR_PWM_PIN, newPwm);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Direction and Headlight changes
|
||||
if((lastDirection != newDirection) || (lastLedState != newLedState))
|
||||
{
|
||||
lastDirection = newDirection;
|
||||
lastLedState = newLedState;
|
||||
|
||||
digitalWrite(MOTOR_DIR_PIN, newDirection);
|
||||
|
||||
if(newLedState)
|
||||
{
|
||||
#ifdef DEBUG_FUNCTIONS
|
||||
Serial.println("LED On");
|
||||
#endif
|
||||
digitalWrite(LED_PIN_FWD, newDirection ? LOW : HIGH);
|
||||
digitalWrite(LED_PIN_REV, newDirection ? HIGH : LOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG_FUNCTIONS
|
||||
Serial.println("LED Off");
|
||||
#endif
|
||||
digitalWrite(LED_PIN_FWD, LOW);
|
||||
digitalWrite(LED_PIN_REV, LOW);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle resetting CVs back to Factory Defaults
|
||||
if( FactoryDefaultCVIndex && Dcc.isSetCVReady())
|
||||
{
|
||||
FactoryDefaultCVIndex--; // Decrement first as initially it is the size of the array
|
||||
Dcc.setCV( FactoryDefaultCVs[FactoryDefaultCVIndex].CV, FactoryDefaultCVs[FactoryDefaultCVIndex].Value);
|
||||
}
|
||||
}
|
438
examples/NmraValidation/Accessory_Test/Accessory_Test.ino
Executable file
438
examples/NmraValidation/Accessory_Test/Accessory_Test.ino
Executable file
@@ -0,0 +1,438 @@
|
||||
/***********************************************************************************************
|
||||
*
|
||||
* This sketch test the NmraDcc library as an accessory decoder.
|
||||
* Author: Kenneth West
|
||||
* kgw4449@gmail.com
|
||||
*
|
||||
* This sketch has added the printf() function to the Print class.
|
||||
* You can find instructions for doing this here:
|
||||
* http://playground.arduino.cc/Main/Printf
|
||||
*
|
||||
* It is based on NmraDcc library NmraDccAccessoryDecoder_1 example.
|
||||
* You can find the library here:
|
||||
* https://github.com/mrrwa/NmraDcc
|
||||
*
|
||||
* This Example shows how to use the library with the Iowa Scaled Engineering ARD-DCCSHIELD
|
||||
* You can find out more about this DCC Interface here:
|
||||
* http://www.iascaled.com/store/ARD-DCCSHIELD
|
||||
*
|
||||
* For more information refer to the file: README.md here:
|
||||
* https://github.com/IowaScaledEngineering/ard-dccshield
|
||||
*
|
||||
* This demo assumes the following Jumper settings on the ARD-DCCSHIELD
|
||||
*
|
||||
* JP1 - I2C Pull-Up Resistors - Don't Care
|
||||
* JP2 - (Pins 1-2) I2C /IORST JP2 - Don't-Care
|
||||
* JP2 - (Pins 3-4) - DCC Signal to Arduino Pin - OFF
|
||||
* JP3 - I2C /INT and /OE - Don't-Care
|
||||
* JP4 - DCC Signal to Arduino Pin - D2 ON
|
||||
* JP5 - Arduino Powered from DCC - User Choice
|
||||
* JP6 - Boards without VIO - User Choice
|
||||
* JP7 - Enable Programming ACK - 1-2 ON 3-4 ON
|
||||
*
|
||||
* The connections are as follows:
|
||||
*
|
||||
* Pin Name Mode Description
|
||||
* ----------------------------------------------------------------------------------
|
||||
* D2 DCC_PIN INPUT_PULLUP DCC input signal.
|
||||
* A1 ACK_PIN OUTPUT CV acknowledge control.
|
||||
* A0 ACC_A_PIN OUTPUT Accessory output A.
|
||||
* D13 ACC_B_PIN OUTPUT Accessory output B.
|
||||
* D4 SCOPE_PIN OUTPUT SCOPE trigger pin.
|
||||
*
|
||||
***********************************************************************************************
|
||||
*/
|
||||
|
||||
#include <NmraDcc.h>
|
||||
|
||||
// Uncomment this line to print out minimal status information.
|
||||
#define DCC_STATUS
|
||||
|
||||
// Uncomment this line to issue scope trigger at beginning of motor callback.
|
||||
#define DO_SCOPE
|
||||
|
||||
// Uncomment this line to handle Basic Accessory decoders.
|
||||
#define ACCESSORY_DCC
|
||||
|
||||
// Uncomment this line to handle Signal decoders.
|
||||
#define SIGNAL_DCC
|
||||
|
||||
const byte VER_MAJOR = 2; // Major version in CV 7
|
||||
const byte VER_MINOR = 1; // Minor version in CV 112
|
||||
const byte DCC_PIN = 2; // DCC input pin.
|
||||
const int ACK_PIN = A1; // CV acknowledge pin.
|
||||
const byte SCOPE_PIN = 4; // Scope trigger pin.
|
||||
const byte ACC_A_PIN = A0; // Motor out A pin.
|
||||
const byte ACC_B_PIN = 13; // Motor out B pin.
|
||||
const byte CV_VERSION = 7; // Decoder version.
|
||||
const byte CV_MANUF = 8; // Manufacturer ID.
|
||||
const byte CV_MANUF_01 = 112; // Manufacturer Unique 01.
|
||||
const byte MANUF_ID = MAN_ID_DIY; // Manufacturer ID in CV 8.
|
||||
const unsigned long DELAY_TIME = 50; // Delay time in ms.
|
||||
|
||||
// The following constant is the 9 bit accessory address. It is followed by the 6 LSB bits that
|
||||
// go into CV1 and the 6 MBB bits that go into CV9.
|
||||
// Note: Set FORCE_CVS true to force CVs to update if just the address is changed.
|
||||
const bool FORCE_CVS = false; // Set true to force CV write.
|
||||
const uint16_t ACC_ADDR = 1; // 11 bit address:
|
||||
// 0 - broadcast, 1 to 2044 - specific.
|
||||
const uint16_t BD_ADDR = ((ACC_ADDR - 1) >> 2) + 1;
|
||||
// 9 bit board address:
|
||||
// 0 - broadcast, 1 to 511 - specific.
|
||||
const byte BD_LSB = BD_ADDR & 0x3f; // Board address LSB.
|
||||
const byte BD_MSB = BD_ADDR >> 6; // Board address MSB.
|
||||
|
||||
// CV29_DEFAULT is the factory hardware default for CV29.
|
||||
const byte CV29_DEFAULT = CV29_OUTPUT_ADDRESS_MODE |
|
||||
CV29_ACCESSORY_DECODER;
|
||||
|
||||
enum ACC_DIR {
|
||||
REV = 0, // Direction is reverse.
|
||||
NORM = 1, // Direction is normal.
|
||||
};
|
||||
|
||||
enum ShowTypes {
|
||||
S_IDLE = 0x01, // Show Idle packets.
|
||||
S_RESET = 0x02, // Show Reset packets.
|
||||
S_DCC = 0x04, // Show DCC information.
|
||||
S_ACK = 0x08, // Basic acknowledge off.
|
||||
S_ALL = 0x80, // Show raw packet data.
|
||||
};
|
||||
|
||||
ACC_DIR AccDir = REV; // Accessory direction.
|
||||
byte ShowData = 0x00; // Packet information to show.
|
||||
unsigned long EndTime = 0; // End time in ms.
|
||||
|
||||
NmraDcc Dcc ;
|
||||
|
||||
struct CVPair
|
||||
{
|
||||
uint16_t CV;
|
||||
uint8_t Value;
|
||||
};
|
||||
|
||||
CVPair FactoryDefaultCVs [] =
|
||||
{
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_LSB, BD_LSB}, // Accessory address LSB.
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_MSB, BD_MSB}, // Accessory address MSB.
|
||||
|
||||
// Reload these just in case they are writeen by accident.
|
||||
{CV_VERSION, VER_MAJOR}, // Decoder version.
|
||||
{CV_MANUF, MANUF_ID }, // Manufacturer ID.
|
||||
|
||||
{CV_29_CONFIG, CV29_DEFAULT}, // Configuration CV.
|
||||
{CV_MANUF_01, VER_MINOR}, // Minor decoder version.
|
||||
};
|
||||
|
||||
uint8_t FactoryDefaultCVIndex = 0;
|
||||
|
||||
void notifyCVResetFactoryDefault()
|
||||
{
|
||||
// Make FactoryDefaultCVIndex non-zero and equal to num CV's to be reset
|
||||
// to flag to the loop() function that a reset to Factory Defaults needs to be done
|
||||
Serial.println(F("notifyCVResetFactoryDefault called."));
|
||||
FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
|
||||
};
|
||||
|
||||
// This function is called whenever a normal DCC Turnout Packet is received
|
||||
#define NOTITY_DCC_ACC_TURNOUT_BOARD
|
||||
#ifdef NOTITY_DCC_ACC_TURNOUT_BOARD
|
||||
void notifyDccAccTurnoutBoard( uint16_t BoardAddr, uint8_t OutputPair, uint8_t Direction, uint8_t OutputPower )
|
||||
{
|
||||
if (ShowData & S_DCC) {
|
||||
Serial.print("notifyDccAccTurnoutBoard: ") ;
|
||||
Serial.print(BoardAddr,DEC) ;
|
||||
Serial.print(',');
|
||||
Serial.print(OutputPair,DEC) ;
|
||||
Serial.print(',');
|
||||
Serial.print(Direction,DEC) ;
|
||||
Serial.print(',');
|
||||
Serial.println(OutputPower, HEX) ;
|
||||
}
|
||||
}
|
||||
#endif // NOTITY_DCC_ACC_TURNOUT_BOARD
|
||||
|
||||
// This function is called whenever a normal DCC Turnout Packet is received
|
||||
// if NOTIFY_DCC_ACC_TURNOUT and ACCESSORY_DCC are defined.
|
||||
#define NOTITY_DCC_ACC_TURNOUT_OUTPUT
|
||||
#if defined(NOTITY_DCC_ACC_TURNOUT_OUTPUT) && defined(ACCESSORY_DCC)
|
||||
void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t OutputPower )
|
||||
{
|
||||
#ifdef DO_SCOPE
|
||||
digitalWrite(SCOPE_PIN, HIGH);
|
||||
digitalWrite(SCOPE_PIN, LOW);
|
||||
#endif // DO_SCOPE
|
||||
|
||||
if (ShowData & S_DCC) {
|
||||
Serial.print("notifyDccAccTurnoutOutput: ") ;
|
||||
Serial.print(Addr,DEC) ;
|
||||
Serial.print(',');
|
||||
Serial.print(Direction,DEC) ;
|
||||
Serial.print(',');
|
||||
Serial.println(OutputPower, HEX) ;
|
||||
}
|
||||
|
||||
// Set the output to the given direction for just the ACC_ADDR output
|
||||
// since this callback is called for all 4 output addresses.
|
||||
if (Addr == ACC_ADDR) {
|
||||
setAcc(Direction ? REV : NORM);
|
||||
}
|
||||
}
|
||||
#endif // NOTITY_DCC_ACC_TURNOUT_OUTPUT
|
||||
|
||||
// This function is called whenever a DCC Signal Aspect Packet is received
|
||||
// if NOTIFY_DCC_SIG_STATE and SIGNAL_DCC are defined.
|
||||
#define NOTITY_DCC_SIG_STATE
|
||||
#if defined(NOTITY_DCC_SIG_STATE) && defined(SIGNAL_DCC)
|
||||
void notifyDccSigOutputState( uint16_t Addr, uint8_t State)
|
||||
{
|
||||
#ifdef DO_SCOPE
|
||||
digitalWrite(SCOPE_PIN, HIGH);
|
||||
digitalWrite(SCOPE_PIN, LOW);
|
||||
#endif // DO_SCOPE
|
||||
|
||||
if (ShowData & S_DCC) {
|
||||
Serial.print("notifyDccSigOutputState: ") ;
|
||||
Serial.print(Addr,DEC) ;
|
||||
Serial.print(',');
|
||||
Serial.println(State, DEC) ;
|
||||
}
|
||||
|
||||
// Set the output to the given direction for 1st ACC_ADDR output.
|
||||
if (Addr == ACC_ADDR) {
|
||||
setAcc(State == 0 ? REV : NORM);
|
||||
}
|
||||
}
|
||||
#endif // NOTITY_DCC_SIG_STATE
|
||||
|
||||
// This function is called whenever a DCC Reset packet is received.
|
||||
// Uncomment to print Reset Packets
|
||||
#define NOTIFY_DCC_RESET
|
||||
#ifdef NOTIFY_DCC_RESET
|
||||
void notifyDccReset(uint8_t hardReset )
|
||||
{
|
||||
if (ShowData & S_RESET) { // Show Reset packets if S_RESET is set.
|
||||
Serial.printf(F("notifyDccReset: %6s.\n"), hardReset ? "HARD" : "NORMAL");
|
||||
}
|
||||
}
|
||||
#endif // NOTIFY_DCC_RESET
|
||||
|
||||
// This function is called whenever a DCC Idle packet is received.
|
||||
// Uncomment to print Idle Packets
|
||||
#define NOTIFY_DCC_IDLE
|
||||
#ifdef NOTIFY_DCC_IDLE
|
||||
void notifyDccIdle()
|
||||
{
|
||||
if (ShowData & S_IDLE) { // Show Idle packets if S_IDLE is set.
|
||||
Serial.println("notifyDccIdle: Idle received") ;
|
||||
}
|
||||
}
|
||||
#endif // NOTIFY_DCC_IDLE
|
||||
|
||||
// Uncomment the #define below to print changed CV values.
|
||||
#define NOTIFY_CV_CHANGE
|
||||
#ifdef NOTIFY_CV_CHANGE
|
||||
void notifyCVChange( uint16_t CV, uint8_t Value) {
|
||||
Serial.printf(F("notifyCVChange: CV %4u value changed to %3u 0x%02X.\n"), CV, Value, Value);
|
||||
}
|
||||
#endif // NOTIFY_CV_CHANGE
|
||||
|
||||
// This function is called when any DCC packet is received.
|
||||
// Uncomment to print all DCC Packets
|
||||
#define NOTIFY_DCC_MSG
|
||||
#ifdef NOTIFY_DCC_MSG
|
||||
void notifyDccMsg( DCC_MSG * Msg)
|
||||
{
|
||||
if (ShowData & S_ALL) { // Show all packets if S_ALL is set.
|
||||
Serial.print("notifyDccMsg: ") ;
|
||||
for(uint8_t i = 0; i < Msg->Size; i++)
|
||||
{
|
||||
Serial.print(Msg->Data[i], HEX);
|
||||
Serial.write(' ');
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
#endif // NOTIFY_DCC_MSG
|
||||
|
||||
// This function is called by the NmraDcc library when a DCC ACK needs to be sent.
|
||||
// Calling this function should cause an increased 60ma current drain on
|
||||
// the power supply for 6ms to ACK a CV Read
|
||||
void notifyCVAck(void)
|
||||
{
|
||||
#ifdef DO_SCOPE
|
||||
digitalWrite(SCOPE_PIN, HIGH);
|
||||
digitalWrite(SCOPE_PIN, LOW);
|
||||
#endif // DO_SCOPE
|
||||
|
||||
if ((ShowData & S_ACK) == 0x00) { // Send CV acknowledge current pulse. [
|
||||
Serial.println("notifyCVAck: Current pulse sent") ;
|
||||
|
||||
digitalWrite( ACK_PIN, HIGH );
|
||||
delay( 6 );
|
||||
digitalWrite( ACK_PIN, LOW );
|
||||
}
|
||||
else { // Suppress CV acknowledge current pulse.
|
||||
Serial.println("notifyCVAck: Current pulse NOT sent") ;
|
||||
}
|
||||
}
|
||||
|
||||
void setAcc(ACC_DIR dir) {
|
||||
bool on; // Output on/off.
|
||||
on = dir == NORM ? true : false;
|
||||
#ifdef DCC_STATUS
|
||||
if (AccDir != dir) {
|
||||
Serial.printf(F("Accessory changed to %4s.\n"), on ? "NORM" : "REV");
|
||||
}
|
||||
#endif // DCC_STATUS
|
||||
AccDir = dir;
|
||||
digitalWrite(ACC_A_PIN, on);
|
||||
digitalWrite(ACC_B_PIN, !on);
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.printf(F("Starting Accessory_Test Version %d.%d, Build date %s %s\n"),
|
||||
VER_MAJOR,
|
||||
VER_MINOR,
|
||||
__DATE__,
|
||||
__TIME__);
|
||||
Serial.printf(F("Default ACC_ADDR %4u "), ACC_ADDR);
|
||||
Serial.printf(F("BD_ADDR %4u 0x%04X, BD_LSB %3u 0x%02X, BD_MSB %3u 0x%02X.\n"),
|
||||
BD_ADDR,
|
||||
BD_ADDR,
|
||||
BD_LSB,
|
||||
BD_LSB,
|
||||
BD_MSB,
|
||||
BD_MSB);
|
||||
Serial.println(F("Cmds: a - All, d - DCC, i - Idle, r - Reset, c - CV Ack off,"));
|
||||
Serial.println(F(" <Other> - Everything off."));
|
||||
|
||||
// Set AccOn REV to force setAcc() to set the output.
|
||||
AccDir = REV;
|
||||
|
||||
// Configure motor and fuction output pin pairs.
|
||||
pinMode( ACC_A_PIN, OUTPUT);
|
||||
pinMode( ACC_B_PIN, OUTPUT);
|
||||
setAcc(NORM);
|
||||
|
||||
// Configure the DCC CV Programing ACK pin for an output
|
||||
pinMode( ACK_PIN, OUTPUT );
|
||||
digitalWrite( ACK_PIN, LOW);
|
||||
|
||||
// Configure Scope trigger output.
|
||||
#ifdef DO_SCOPE
|
||||
pinMode( SCOPE_PIN, OUTPUT);
|
||||
digitalWrite(SCOPE_PIN, LOW);
|
||||
#endif // DO_SCOPE
|
||||
|
||||
// Setup which External Interrupt, the Pin it's associated with that we're using and enable the Pull-Up
|
||||
Dcc.pin(digitalPinToInterrupt(DCC_PIN), DCC_PIN, 1);
|
||||
|
||||
// Reset the CVs to factory default if the decode type,manuf. ID or major version
|
||||
// do not match. Do this before init() since it sets these CVs.
|
||||
if ( (FORCE_CVS) ||
|
||||
(Dcc.getCV(CV_29_CONFIG) != CV29_DEFAULT) ||
|
||||
(Dcc.getCV(CV_MANUFACTURER_ID) != MANUF_ID) ||
|
||||
(Dcc.getCV(CV_VERSION_ID) != VER_MAJOR) ||
|
||||
(Dcc.getCV(CV_MANUF_01) != VER_MINOR))
|
||||
{
|
||||
notifyCVResetFactoryDefault();
|
||||
}
|
||||
|
||||
// Call the main DCC Init function to enable the DCC Receiver
|
||||
Dcc.init( MANUF_ID, VER_MAJOR, // FLAGS_MY_ADDRESS_ONLY |
|
||||
CV29_DEFAULT, 0 );
|
||||
|
||||
// Make sure CV_MANUF_01 CV matches VER_MINOR.
|
||||
Dcc.setCV(CV_MANUF_01, VER_MINOR);
|
||||
|
||||
Serial.println(F("Init Done"));
|
||||
|
||||
// Flush serial prior to entering loop().
|
||||
Serial.flush();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// You MUST call the NmraDcc.process() method frequently from the Arduino loop() function for correct library operation
|
||||
Dcc.process();
|
||||
|
||||
if (Serial.available()) {
|
||||
// Get the new byte and process it.
|
||||
switch ((char)Serial.read()) {
|
||||
case 'a':
|
||||
if (ShowData & S_ALL) {
|
||||
ShowData &= ~S_ALL;
|
||||
}
|
||||
else {
|
||||
ShowData |= S_ALL;
|
||||
}
|
||||
Serial.println(ShowData & S_ALL ? "All ON" : "All OFF");
|
||||
break;
|
||||
case 'd':
|
||||
if (ShowData & S_DCC) {
|
||||
ShowData &= ~S_DCC;
|
||||
}
|
||||
else {
|
||||
ShowData |= S_DCC;
|
||||
}
|
||||
Serial.println(ShowData & S_DCC ? "DCC ON" : "DCC OFF");
|
||||
break;
|
||||
case 'i':
|
||||
if (ShowData & S_IDLE) {
|
||||
ShowData &= ~S_IDLE;
|
||||
}
|
||||
else {
|
||||
ShowData |= S_IDLE;
|
||||
}
|
||||
Serial.println(ShowData & S_IDLE ? "Idle ON" : "Idle OFF");
|
||||
break;
|
||||
case 'r':
|
||||
if (ShowData & S_RESET) {
|
||||
ShowData &= ~S_RESET;
|
||||
}
|
||||
else {
|
||||
ShowData |= S_RESET;
|
||||
}
|
||||
Serial.println(ShowData & S_RESET ? "Reset ON" : "Reset OFF");
|
||||
break;
|
||||
case 'c':
|
||||
if (ShowData & S_ACK) {
|
||||
ShowData &= ~S_ACK;
|
||||
}
|
||||
else {
|
||||
ShowData |= S_ACK;
|
||||
}
|
||||
Serial.println(ShowData & S_ACK ? "Ack OFF" : "Ack ON");
|
||||
break;
|
||||
case '\n':
|
||||
case '\r':
|
||||
break;
|
||||
default:
|
||||
if (ShowData != 0x00) {
|
||||
EndTime = millis() + DELAY_TIME;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((EndTime != 0) && (millis() > EndTime)) {
|
||||
Serial.printf(F("Clearing ShowData 0x%02X\n"), ShowData);
|
||||
ShowData = 0x00;
|
||||
EndTime = 0;
|
||||
}
|
||||
|
||||
if( FactoryDefaultCVIndex && Dcc.isSetCVReady())
|
||||
{
|
||||
FactoryDefaultCVIndex--; // Decrement first as initially it is the size of the array
|
||||
Serial.printf(F("CV %4u reset to factory default %3u 0x%02X.\n"),
|
||||
FactoryDefaultCVs[FactoryDefaultCVIndex].CV,
|
||||
FactoryDefaultCVs[FactoryDefaultCVIndex].Value,
|
||||
FactoryDefaultCVs[FactoryDefaultCVIndex].Value);
|
||||
Dcc.setCV( FactoryDefaultCVs[FactoryDefaultCVIndex].CV,
|
||||
FactoryDefaultCVs[FactoryDefaultCVIndex].Value);
|
||||
}
|
||||
}
|
||||
|
1388
examples/NmraValidation/Loco Cap 2.1/arlc_3n.log
Executable file
1388
examples/NmraValidation/Loco Cap 2.1/arlc_3n.log
Executable file
File diff suppressed because it is too large
Load Diff
1383
examples/NmraValidation/Loco Cap 2.1/arlc_3n.sum
Executable file
1383
examples/NmraValidation/Loco Cap 2.1/arlc_3n.sum
Executable file
File diff suppressed because it is too large
Load Diff
1388
examples/NmraValidation/Loco Cap 2.1/arlc_3r.log
Executable file
1388
examples/NmraValidation/Loco Cap 2.1/arlc_3r.log
Executable file
File diff suppressed because it is too large
Load Diff
1383
examples/NmraValidation/Loco Cap 2.1/arlc_3r.sum
Executable file
1383
examples/NmraValidation/Loco Cap 2.1/arlc_3r.sum
Executable file
File diff suppressed because it is too large
Load Diff
1388
examples/NmraValidation/Loco Cap 2.1/arlc_5n.log
Executable file
1388
examples/NmraValidation/Loco Cap 2.1/arlc_5n.log
Executable file
File diff suppressed because it is too large
Load Diff
1383
examples/NmraValidation/Loco Cap 2.1/arlc_5n.sum
Executable file
1383
examples/NmraValidation/Loco Cap 2.1/arlc_5n.sum
Executable file
File diff suppressed because it is too large
Load Diff
1388
examples/NmraValidation/Loco Cap 2.1/arlc_5r.log
Executable file
1388
examples/NmraValidation/Loco Cap 2.1/arlc_5r.log
Executable file
File diff suppressed because it is too large
Load Diff
1383
examples/NmraValidation/Loco Cap 2.1/arlc_5r.sum
Executable file
1383
examples/NmraValidation/Loco Cap 2.1/arlc_5r.sum
Executable file
File diff suppressed because it is too large
Load Diff
1388
examples/NmraValidation/Loco Cap 2.1/arlc_6n.log
Executable file
1388
examples/NmraValidation/Loco Cap 2.1/arlc_6n.log
Executable file
File diff suppressed because it is too large
Load Diff
1383
examples/NmraValidation/Loco Cap 2.1/arlc_6n.sum
Executable file
1383
examples/NmraValidation/Loco Cap 2.1/arlc_6n.sum
Executable file
File diff suppressed because it is too large
Load Diff
1388
examples/NmraValidation/Loco Cap 2.1/arlc_6r.log
Executable file
1388
examples/NmraValidation/Loco Cap 2.1/arlc_6r.log
Executable file
File diff suppressed because it is too large
Load Diff
1383
examples/NmraValidation/Loco Cap 2.1/arlc_6r.sum
Executable file
1383
examples/NmraValidation/Loco Cap 2.1/arlc_6r.sum
Executable file
File diff suppressed because it is too large
Load Diff
486
examples/NmraValidation/Loco_Test/Loco_Test.ino
Executable file
486
examples/NmraValidation/Loco_Test/Loco_Test.ino
Executable file
@@ -0,0 +1,486 @@
|
||||
/***********************************************************************************************
|
||||
*
|
||||
* This sketch tests the NmraDcc library as a multifunction decoder.
|
||||
* Author: Kenneth West
|
||||
* kgw4449@gmail.com
|
||||
*
|
||||
* This sketch has added the printf() function to the Print class.
|
||||
* You can find instructions for doing this here:
|
||||
* http://playground.arduino.cc/Main/Printf
|
||||
*
|
||||
* This sketch is based on NmraDcc library NmraDccMultiFunctionDecoder_1 example.
|
||||
* You can find the library here:
|
||||
* https://github.com/mrrwa/NmraDcc
|
||||
*
|
||||
* This Example shows how to use the library with the Iowa Scaled Engineering ARD-DCCSHIELD
|
||||
* You can find out more about this DCC Interface here:
|
||||
* http://www.iascaled.com/store/ARD-DCCSHIELD
|
||||
*
|
||||
* For more information refer to the file: README.md here:
|
||||
* https://github.com/IowaScaledEngineering/ard-dccshield
|
||||
*
|
||||
* This demo assumes the following Jumper settings on the ARD-DCCSHIELD
|
||||
*
|
||||
* JP1 - I2C Pull-Up Resistors - Don't Care
|
||||
* JP2 - (Pins 1-2) I2C /IORST JP2 - Don't-Care
|
||||
* JP2 - (Pins 3-4) - DCC Signal to Arduino Pin - OFF
|
||||
* JP3 - I2C /INT and /OE - Don't-Care
|
||||
* JP4 - DCC Signal to Arduino Pin - D2 ON
|
||||
* JP5 - Arduino Powered from DCC - User Choice
|
||||
* JP6 - Boards without VIO - User Choice
|
||||
* JP7 - Enable Programming ACK - 1-2 ON 3-4 ON
|
||||
*
|
||||
* The connections are as follows:
|
||||
*
|
||||
* Pin Name Mode Description
|
||||
* ----------------------------------------------------------------------------------
|
||||
* D2 DCC_PIN INPUT_PULLUP DCC input signal.
|
||||
* A1 ACK_PIN OUTPUT CV acknowledge control.
|
||||
* A0 MOTOR_A_PIN OUTPUT Motor output A.
|
||||
* D13 MOTOR_B_PIN OUTPUT Motor output B.
|
||||
* D12 FUNC_A_PIN OUTPUT Function output A.
|
||||
* D11 FUNC_B_PIN OUTPUT Function output B.
|
||||
* D4 SCOPE_PIN OUTPUT SCOPE trigger.
|
||||
*
|
||||
**********************************************************************************************/
|
||||
// Column locations.
|
||||
//3456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456
|
||||
// 1 2 3 4 5 6 7 8 9 9
|
||||
//const unsigned long FAKE_LONG = 10000UL; // Fake variable for column positions.
|
||||
|
||||
#include <NmraDcc.h>
|
||||
|
||||
// Uncomment this line to print out minimal status information.
|
||||
#define DCC_STATUS
|
||||
|
||||
// Uncomment this line to issue scope trigger at beginning of motor callback.
|
||||
#define DO_SCOPE
|
||||
|
||||
const byte VER_MAJOR = 2; // Major version in CV 7
|
||||
const byte VER_MINOR = 1; // Minor version in CV 112
|
||||
const byte DCC_PIN = 2; // DCC input pin.
|
||||
const int ACK_PIN = A1; // CV acknowledge pin.
|
||||
const byte MOTOR_A_PIN = A0; // Motor out A pin.
|
||||
const byte MOTOR_B_PIN = 13; // Motor out B pin.
|
||||
const byte FUNC_A_PIN = 12; // Function A pin.
|
||||
const byte FUNC_B_PIN = 11; // Function B pin.
|
||||
const byte SCOPE_PIN = 4; // Scope trigger pin.
|
||||
const byte CV_VERSION = 7; // Decoder version.
|
||||
const byte CV_MANUF = 8; // Manufacturer ID.
|
||||
const byte CV_MANUF_01 = 112; // Manufacturer Unique 01.
|
||||
const byte MANUF_ID = MAN_ID_DIY; // Manufacturer ID in CV 8.
|
||||
const byte DECODER_ADDR = 3; // Decoder address.
|
||||
const byte SP_ESTOP = 0; // Emergency stop speed.
|
||||
const byte SP_STOP = 1; // Stop speed value.
|
||||
const unsigned long DELAY_TIME = 50; // Delay time in ms.
|
||||
|
||||
// Note: Set FORCE_CV_WRITE true to force CVs to update if just the address is changed.
|
||||
const bool FORCE_CV_WRITE = false; // Set true to force CV write.
|
||||
|
||||
enum ShowTypes {
|
||||
S_IDLE = 0x01, // Show Idle packets.
|
||||
S_RESET = 0x02, // Show Reset packets.
|
||||
S_DCC = 0x04, // Show DCC information.
|
||||
S_ACK = 0x08, // Basic acknowledge off.
|
||||
S_ALL = 0x80, // Show raw packet data.
|
||||
};
|
||||
|
||||
bool MotorFwd = false; // Motor direction.
|
||||
bool FuncOn = true; // Function on/off.
|
||||
byte ShowData = 0x00; // Packet information to show.
|
||||
unsigned long EndTime = 0; // End time in ms.
|
||||
|
||||
struct CVPair
|
||||
{
|
||||
uint16_t CV;
|
||||
uint8_t Value;
|
||||
};
|
||||
|
||||
CVPair FactoryDefaultCVs [] =
|
||||
{
|
||||
// The CV Below defines the Short DCC Address
|
||||
{CV_MULTIFUNCTION_PRIMARY_ADDRESS, DECODER_ADDR}, // Short address.
|
||||
|
||||
// Reload these just in case they are writeen by accident.
|
||||
{CV_VERSION, VER_MAJOR}, // Decoder version.
|
||||
{CV_MANUF, MANUF_ID }, // Manufacturer ID.
|
||||
|
||||
// These two CVs define the Long DCC Address
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0}, // Extended address MSB.
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, DECODER_ADDR}, // Extended address LSB.
|
||||
|
||||
{CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
|
||||
{CV_MANUF_01, VER_MINOR}, // Minor decoder version.
|
||||
};
|
||||
|
||||
NmraDcc Dcc ;
|
||||
|
||||
uint8_t FactoryDefaultCVIndex = 0;
|
||||
|
||||
void notifyCVResetFactoryDefault()
|
||||
{
|
||||
// Make FactoryDefaultCVIndex non-zero and equal to num CV's to be reset
|
||||
// to flag to the loop() function that a reset to Factory Defaults needs to be done
|
||||
Serial.println(F("notifyCVResetFactoryDefault called."));
|
||||
FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
|
||||
};
|
||||
|
||||
// Uncomment the #define below to print all Speed Packets
|
||||
#define NOTIFY_DCC_SPEED
|
||||
#ifdef NOTIFY_DCC_SPEED
|
||||
void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_DIRECTION Dir, DCC_SPEED_STEPS SpeedSteps )
|
||||
{
|
||||
#ifdef DO_SCOPE
|
||||
digitalWrite(SCOPE_PIN, HIGH);
|
||||
digitalWrite(SCOPE_PIN, LOW);
|
||||
#endif // DO_SCOPE
|
||||
|
||||
if (ShowData & S_DCC) {
|
||||
Serial.print("notifyDccSpeed: Addr: ");
|
||||
Serial.print(Addr,DEC);
|
||||
Serial.print( (AddrType == DCC_ADDR_SHORT) ? "-S" : "-L" );
|
||||
Serial.print(" Speed: ");
|
||||
Serial.print(Speed,DEC);
|
||||
Serial.print(" Steps: ");
|
||||
Serial.print(SpeedSteps,DEC);
|
||||
Serial.print(" Dir: ");
|
||||
Serial.println( (Dir == DCC_DIR_FWD) ? "Forward" : "Reverse" );
|
||||
}
|
||||
|
||||
if ((Speed > SP_STOP) && (Dir == DCC_DIR_REV)) {
|
||||
setMotor(false);
|
||||
}
|
||||
else {
|
||||
setMotor(true);
|
||||
}
|
||||
};
|
||||
#endif // NOTIFY_DCC_SPEED
|
||||
|
||||
// Uncomment the #define below to print all Function Packets
|
||||
#define NOTIFY_DCC_FUNC
|
||||
#ifdef NOTIFY_DCC_FUNC
|
||||
void notifyDccFunc(uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState)
|
||||
{
|
||||
if (ShowData & S_DCC) {
|
||||
Serial.print("notifyDccFunc: Addr: ");
|
||||
Serial.print(Addr,DEC);
|
||||
Serial.print( (AddrType == DCC_ADDR_SHORT) ? 'S' : 'L' );
|
||||
Serial.print(" Function Group: ");
|
||||
Serial.print(FuncGrp,DEC);
|
||||
}
|
||||
|
||||
switch( FuncGrp ) {
|
||||
#ifdef NMRA_DCC_ENABLE_14_SPEED_STEP_MODE
|
||||
case FN_0:
|
||||
if (ShowData & S_DCC) {
|
||||
Serial.print(" FN0: ");
|
||||
Serial.println((FuncState & FN_BIT_00) ? "1 " : "0 ");
|
||||
}
|
||||
break;
|
||||
#endif // NMRA_DCC_ENABLE_14_SPEED_STEP_MODE
|
||||
|
||||
case FN_0_4:
|
||||
if (ShowData & S_DCC) {
|
||||
Serial.print(" FN 0: ");
|
||||
Serial.print((FuncState & FN_BIT_00) ? "1 ": "0 ");
|
||||
Serial.print(" FN 1-4: ");
|
||||
Serial.print((FuncState & FN_BIT_01) ? "1 ": "0 ");
|
||||
Serial.print((FuncState & FN_BIT_02) ? "1 ": "0 ");
|
||||
Serial.print((FuncState & FN_BIT_03) ? "1 ": "0 ");
|
||||
Serial.println((FuncState & FN_BIT_04) ? "1 ": "0 ");
|
||||
}
|
||||
|
||||
if (FuncState & FN_BIT_00) {
|
||||
setFunc(true);
|
||||
}
|
||||
else {
|
||||
setFunc(false);
|
||||
}
|
||||
break;
|
||||
|
||||
case FN_5_8:
|
||||
if (ShowData & S_DCC) {
|
||||
Serial.print(" FN 5-8: ");
|
||||
Serial.print((FuncState & FN_BIT_05) ? "1 ": "0 ");
|
||||
Serial.print((FuncState & FN_BIT_06) ? "1 ": "0 ");
|
||||
Serial.print((FuncState & FN_BIT_07) ? "1 ": "0 ");
|
||||
Serial.println((FuncState & FN_BIT_08) ? "1 ": "0 ");
|
||||
}
|
||||
break;
|
||||
|
||||
case FN_9_12:
|
||||
if (ShowData & S_DCC) {
|
||||
Serial.print(" FN 9-12: ");
|
||||
Serial.print((FuncState & FN_BIT_09) ? "1 ": "0 ");
|
||||
Serial.print((FuncState & FN_BIT_10) ? "1 ": "0 ");
|
||||
Serial.print((FuncState & FN_BIT_11) ? "1 ": "0 ");
|
||||
Serial.println((FuncState & FN_BIT_12) ? "1 ": "0 ");
|
||||
}
|
||||
break;
|
||||
|
||||
case FN_13_20:
|
||||
if (ShowData & S_DCC) {
|
||||
Serial.print(" FN 13-20: ");
|
||||
Serial.print((FuncState & FN_BIT_13) ? "1 ": "0 ");
|
||||
Serial.print((FuncState & FN_BIT_14) ? "1 ": "0 ");
|
||||
Serial.print((FuncState & FN_BIT_15) ? "1 ": "0 ");
|
||||
Serial.print((FuncState & FN_BIT_16) ? "1 ": "0 ");
|
||||
Serial.print((FuncState & FN_BIT_17) ? "1 ": "0 ");
|
||||
Serial.print((FuncState & FN_BIT_18) ? "1 ": "0 ");
|
||||
Serial.print((FuncState & FN_BIT_19) ? "1 ": "0 ");
|
||||
Serial.println((FuncState & FN_BIT_20) ? "1 ": "0 ");
|
||||
}
|
||||
break;
|
||||
|
||||
case FN_21_28:
|
||||
if (ShowData & S_DCC) {
|
||||
Serial.print(" FN 21-28: ");
|
||||
Serial.print((FuncState & FN_BIT_21) ? "1 ": "0 ");
|
||||
Serial.print((FuncState & FN_BIT_22) ? "1 ": "0 ");
|
||||
Serial.print((FuncState & FN_BIT_23) ? "1 ": "0 ");
|
||||
Serial.print((FuncState & FN_BIT_24) ? "1 ": "0 ");
|
||||
Serial.print((FuncState & FN_BIT_25) ? "1 ": "0 ");
|
||||
Serial.print((FuncState & FN_BIT_26) ? "1 ": "0 ");
|
||||
Serial.print((FuncState & FN_BIT_27) ? "1 ": "0 ");
|
||||
Serial.println((FuncState & FN_BIT_28) ? "1 ": "0 ");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif // NOTIFY_DCC_FUNC
|
||||
|
||||
// Uncomment the #define below to print all Reset Packets.
|
||||
#define NOTIFY_DCC_RESET
|
||||
#ifdef NOTIFY_DCC_RESET
|
||||
void notifyDccReset(uint8_t hardReset) {
|
||||
setMotor(true);
|
||||
setFunc(false);
|
||||
if (ShowData & S_RESET) {
|
||||
Serial.printf(F("notifyDccReset: %6s.\n"), hardReset ? "HARD" : "NORMAL");
|
||||
}
|
||||
}
|
||||
#endif // NOTIFY_DCC_RESET
|
||||
|
||||
// This function is called whenever a DCC Idle packet is received.
|
||||
// Uncomment to print Idle Packets
|
||||
#define NOTIFY_DCC_IDLE
|
||||
#ifdef NOTIFY_DCC_IDLE
|
||||
void notifyDccIdle()
|
||||
{
|
||||
if (ShowData & S_IDLE) { // Show Idle packets if S_IDLE is set.
|
||||
Serial.println("notifyDccIdle: Idle received") ;
|
||||
}
|
||||
}
|
||||
#endif // NOTIFY_DCC_IDLE
|
||||
|
||||
// Uncomment the #define below to print changed CV values.
|
||||
#define NOTIFY_CV_CHANGE
|
||||
#ifdef NOTIFY_CV_CHANGE
|
||||
void notifyCVChange( uint16_t CV, uint8_t Value) {
|
||||
Serial.printf(F("notifyCVChange: CV %4u value changed to %3u 0x%02X.\n"), CV, Value, Value);
|
||||
}
|
||||
#endif // NOTIFY_CV_CHANGE
|
||||
|
||||
// This function is called when any DCC packet is received.
|
||||
// Uncomment to print all DCC Packets
|
||||
#define NOTIFY_DCC_MSG
|
||||
#ifdef NOTIFY_DCC_MSG
|
||||
void notifyDccMsg( DCC_MSG * Msg)
|
||||
{
|
||||
if (ShowData & S_ALL) { // Show all packets if S_ALL is set.
|
||||
Serial.print("notifyDccMsg: ") ;
|
||||
for(uint8_t i = 0; i < Msg->Size; i++)
|
||||
{
|
||||
Serial.print(Msg->Data[i], HEX);
|
||||
Serial.write(' ');
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
#endif // NOTIFY_DCC_MSG
|
||||
|
||||
// This function is called by the NmraDcc library when a DCC ACK needs to be sent.
|
||||
// Calling this function should cause an increased 60ma current drain on
|
||||
// the power supply for 6ms to ACK a CV Read
|
||||
void notifyCVAck(void)
|
||||
{
|
||||
#ifdef DO_SCOPE
|
||||
digitalWrite(SCOPE_PIN, HIGH);
|
||||
digitalWrite(SCOPE_PIN, LOW);
|
||||
#endif // DO_SCOPE
|
||||
|
||||
if ((ShowData & S_ACK) == 0x00) { // Send CV acknowledge current pulse. [
|
||||
Serial.println("notifyCVAck: Current pulse sent") ;
|
||||
|
||||
digitalWrite( ACK_PIN, HIGH );
|
||||
delay( 6 );
|
||||
digitalWrite( ACK_PIN, LOW );
|
||||
}
|
||||
else { // Suppress CV acknowledge current pulse.
|
||||
Serial.println("notifyCVAck: Current pulse NOT sent") ;
|
||||
}
|
||||
}
|
||||
|
||||
void setMotor(bool fwd) {
|
||||
#ifdef DCC_STATUS
|
||||
if (MotorFwd != fwd) {
|
||||
Serial.printf(F("Motor changed to %3s.\n"), fwd ? "FWD" : "REV");
|
||||
}
|
||||
#endif // DCC_STATUS
|
||||
MotorFwd = fwd;
|
||||
digitalWrite(MOTOR_A_PIN, fwd);
|
||||
digitalWrite(MOTOR_B_PIN, !fwd);
|
||||
}
|
||||
|
||||
void setFunc(bool on) {
|
||||
#ifdef DCC_STATUS
|
||||
if (FuncOn != on) {
|
||||
Serial.printf(F("Function changed to %3s.\n"), on ? "ON" : "OFF");
|
||||
}
|
||||
#endif // DCC_STATUS
|
||||
FuncOn = on;
|
||||
digitalWrite(FUNC_A_PIN, !on);
|
||||
digitalWrite(FUNC_B_PIN, on);
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.print(F("NMRA Dcc Loco_Test "));
|
||||
Serial.printf(F(" Version %d.%d, Build date %s %s\n"), VER_MAJOR,
|
||||
VER_MINOR,
|
||||
__DATE__,
|
||||
__TIME__);
|
||||
Serial.println(F("Cmds: a - All, d - DCC, i - Idle, r - Reset, c - CV Ack off,"));
|
||||
Serial.println(F(" <Other> - Everything off."));
|
||||
|
||||
// Set MotorFwd false and FuncOn true to force the set the output.
|
||||
MotorFwd = false;
|
||||
FuncOn = true;
|
||||
|
||||
// Configure motor and fuction output pin pairs.
|
||||
pinMode( MOTOR_A_PIN, OUTPUT);
|
||||
pinMode( MOTOR_B_PIN, OUTPUT);
|
||||
setMotor(true);
|
||||
pinMode( FUNC_A_PIN, OUTPUT);
|
||||
pinMode( FUNC_B_PIN, OUTPUT);
|
||||
setFunc(false);
|
||||
|
||||
// Configure Scope trigger output.
|
||||
#ifdef DO_SCOPE
|
||||
pinMode( SCOPE_PIN, OUTPUT);
|
||||
digitalWrite(SCOPE_PIN, LOW);
|
||||
#endif // DO_SCOPE
|
||||
|
||||
// Configure the DCC CV Programing ACK and set it LOW to keep the ACK current off.
|
||||
pinMode( ACK_PIN, OUTPUT );
|
||||
digitalWrite(ACK_PIN, LOW );
|
||||
|
||||
// Setup which External Interrupt, the Pin it's associated with that we're using
|
||||
// and enable the Pull-Up.
|
||||
Dcc.pin(digitalPinToInterrupt(DCC_PIN), DCC_PIN, 1);
|
||||
|
||||
// Reset the CVs to factory default if the manuf. ID or major version do not match.
|
||||
// Do this before init() since it sets these CVs.
|
||||
if ( ( FORCE_CV_WRITE) ||
|
||||
((Dcc.getCV(CV_29_CONFIG) & CV29_ACCESSORY_DECODER) != 0) ||
|
||||
( Dcc.getCV(CV_MANUFACTURER_ID) != MANUF_ID) ||
|
||||
( Dcc.getCV(CV_VERSION_ID) != VER_MAJOR) ||
|
||||
( Dcc.getCV(CV_MANUF_01) != VER_MINOR))
|
||||
{
|
||||
notifyCVResetFactoryDefault();
|
||||
}
|
||||
|
||||
Dcc.init( MANUF_ID, VER_MAJOR, FLAGS_MY_ADDRESS_ONLY, 0 );
|
||||
|
||||
// Make sure CV_MANUF_01 CV matches VER_MINOR.
|
||||
Dcc.setCV(CV_MANUF_01, VER_MINOR);
|
||||
|
||||
Serial.println(F("Init Done"));
|
||||
|
||||
// Flush serial prior to entering loop().
|
||||
Serial.flush();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// You MUST call the NmraDcc.process() method frequently from the Arduino loop() function for correct library operation
|
||||
Dcc.process();
|
||||
|
||||
if (Serial.available()) {
|
||||
// Get the new byte and process it.
|
||||
switch ((char)Serial.read()) {
|
||||
case 'a':
|
||||
if (ShowData & S_ALL) {
|
||||
ShowData &= ~S_ALL;
|
||||
}
|
||||
else {
|
||||
ShowData |= S_ALL;
|
||||
}
|
||||
Serial.println(ShowData & S_ALL ? "All ON" : "All OFF");
|
||||
break;
|
||||
case 'd':
|
||||
if (ShowData & S_DCC) {
|
||||
ShowData &= ~S_DCC;
|
||||
}
|
||||
else {
|
||||
ShowData |= S_DCC;
|
||||
}
|
||||
Serial.println(ShowData & S_DCC ? "DCC ON" : "DCC OFF");
|
||||
break;
|
||||
case 'i':
|
||||
if (ShowData & S_IDLE) {
|
||||
ShowData &= ~S_IDLE;
|
||||
}
|
||||
else {
|
||||
ShowData |= S_IDLE;
|
||||
}
|
||||
Serial.println(ShowData & S_IDLE ? "Idle ON" : "Idle OFF");
|
||||
break;
|
||||
case 'r':
|
||||
if (ShowData & S_RESET) {
|
||||
ShowData &= ~S_RESET;
|
||||
}
|
||||
else {
|
||||
ShowData |= S_RESET;
|
||||
}
|
||||
Serial.println(ShowData & S_RESET ? "Reset ON" : "Reset OFF");
|
||||
break;
|
||||
case 'c':
|
||||
if (ShowData & S_ACK) {
|
||||
ShowData &= ~S_ACK;
|
||||
}
|
||||
else {
|
||||
ShowData |= S_ACK;
|
||||
}
|
||||
Serial.println(ShowData & S_ACK ? "Ack OFF" : "Ack ON");
|
||||
break;
|
||||
case '\n':
|
||||
case '\r':
|
||||
break;
|
||||
default:
|
||||
if (ShowData != 0x00) {
|
||||
EndTime = millis() + DELAY_TIME;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((EndTime != 0) && (millis() > EndTime)) {
|
||||
Serial.printf(F("Clearing ShowData 0x%02x\n"), ShowData);
|
||||
ShowData = 0x00;
|
||||
EndTime = 0;
|
||||
}
|
||||
|
||||
if( FactoryDefaultCVIndex && Dcc.isSetCVReady())
|
||||
{
|
||||
FactoryDefaultCVIndex--; // Decrement first as initially it is the size of the array
|
||||
Serial.printf(F("CV %4u reset to factory default %3u 0x%02X.\n"),
|
||||
FactoryDefaultCVs[FactoryDefaultCVIndex].CV,
|
||||
FactoryDefaultCVs[FactoryDefaultCVIndex].Value,
|
||||
FactoryDefaultCVs[FactoryDefaultCVIndex].Value);
|
||||
Dcc.setCV( FactoryDefaultCVs[FactoryDefaultCVIndex].CV,
|
||||
FactoryDefaultCVs[FactoryDefaultCVIndex].Value);
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
85
examples/SMA/AccDec_10Servos_7LED_6Ftn/AccDec_10Servos_7LED_6Ftn.ino
Executable file → Normal file
85
examples/SMA/AccDec_10Servos_7LED_6Ftn/AccDec_10Servos_7LED_6Ftn.ino
Executable file → Normal file
@@ -1,5 +1,10 @@
|
||||
// Production 17 Function DCC Decoder
|
||||
// Version 5.4 Geoff Bunza 2014,2015,2016
|
||||
// Production 17 Switch Acessory DCC Decoder AccDec_10Servos_7LED_6Ftn.ino
|
||||
// Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
|
||||
// Now works with both short and long DCC Addesses for CV Control Default 24 (LSB CV 121 ; MSB CV 122)
|
||||
// ACCESSORY DECODER DEFAULT ADDRESS IS 40 (MAX 40-56 SWITCHES)
|
||||
// ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255
|
||||
// BE CAREFUL! DIFFERENT DCC BASE STATIONS ALLOW DIFFERING MAX ADDRESSES
|
||||
|
||||
// NO LONGER REQUIRES modified software servo Lib
|
||||
// Software restructuring mods added from Alex Shepherd and Franz-Peter
|
||||
// With sincere thanks
|
||||
@@ -19,7 +24,7 @@
|
||||
SoftwareServo servo[17];
|
||||
#define servo_start_delay 50
|
||||
#define servo_init_delay 7
|
||||
#define servo_slowdown 3 //servo loop counter limit
|
||||
#define servo_slowdown 12 //servo loop counter limit
|
||||
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
|
||||
|
||||
int tim_delay = 500;
|
||||
@@ -49,6 +54,7 @@ int t; // temp
|
||||
#define SET_CV_Address 24 // THIS ADDRESS IS FOR SETTING CV'S Like a Loco
|
||||
#define Accessory_Address 40 // THIS ADDRESS IS THE START OF THE SWITCHES RANGE
|
||||
// WHICH WILL EXTEND FOR 16 MORE SWITCH ADDRESSES
|
||||
// THIS CAN START ABOVE ADDRESS 256
|
||||
uint8_t CV_DECODER_MASTER_RESET = 120; // THIS IS THE CV ADDRESS OF THE FULL RESET
|
||||
#define CV_To_Store_SET_CV_Address 121
|
||||
#define CV_Accessory_Address CV_ACCESSORY_DECODER_ADDRESS_LSB
|
||||
@@ -61,7 +67,7 @@ struct QUEUE
|
||||
int stop_value;
|
||||
int start_value;
|
||||
};
|
||||
QUEUE *ftn_queue = new QUEUE[16];
|
||||
QUEUE *ftn_queue = new QUEUE[17];
|
||||
|
||||
struct CVPair
|
||||
{
|
||||
@@ -70,15 +76,25 @@ struct CVPair
|
||||
};
|
||||
CVPair FactoryDefaultCVs [] =
|
||||
{
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_LSB, Accessory_Address},
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_MSB, 0},
|
||||
// These two CVs define the Long Accessory Address
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_LSB, Accessory_Address&0xFF},
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_MSB, (Accessory_Address>>8)&0x07},
|
||||
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
|
||||
|
||||
// Speed Steps don't matter for this decoder
|
||||
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
|
||||
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
|
||||
{CV_29_CONFIG,CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_F0_LOCATION}, // Accesory Decoder Short Address
|
||||
// {CV_29_CONFIG, CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Accesory Decoder Long Address
|
||||
|
||||
{CV_DECODER_MASTER_RESET, 0},
|
||||
{CV_To_Store_SET_CV_Address, SET_CV_Address},
|
||||
{CV_To_Store_SET_CV_Address+1, 0},
|
||||
{CV_To_Store_SET_CV_Address, SET_CV_Address&0xFF }, // LSB Set CV Address
|
||||
{CV_To_Store_SET_CV_Address+1,(SET_CV_Address>>8)&0x3F }, //MSB Set CV Address
|
||||
{30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{32, 28}, //F0 Start Position F0=0
|
||||
{33, 140}, //F0 End Position F0=1
|
||||
{34, 28}, //F0 Current Position
|
||||
@@ -112,21 +128,21 @@ CVPair FactoryDefaultCVs [] =
|
||||
{62, 28}, // Start Position Fx=0
|
||||
{63, 140}, // End Position Fx=1
|
||||
{64, 28}, // Current Position
|
||||
{65, 2}, //F7 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{65, 1}, //F7 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{66, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{67, 28}, // Start Position Fx=0
|
||||
{68,140}, // End Position Fx=1
|
||||
{69, 28}, // Current Position
|
||||
{70, 2}, //F8 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{67, 1}, // Start Position Fx=0
|
||||
{68,35}, // End Position Fx=1
|
||||
{69, 1}, // Current Position
|
||||
{70, 1}, //F8 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{71, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{72, 28}, // Start Position Fx=0
|
||||
{73, 140}, // End Position Fx=1
|
||||
{74, 28}, // Current Position
|
||||
{75, 2}, //F9 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{72, 1}, // Start Position Fx=0
|
||||
{73, 100}, // End Position Fx=1
|
||||
{74, 1}, // Current Position
|
||||
{75, 0}, //F9 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{76, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{77, 28}, // Start Position Fx=0
|
||||
{78, 140}, // End Position Fx=1
|
||||
{79, 28}, // Current Position
|
||||
{77, 1}, // Start Position Fx=0
|
||||
{78, 10}, // End Position Fx=1
|
||||
{79, 1}, // Current Position
|
||||
{80, 0}, //F10 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{81, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{82, 1}, // Start Position Fx=0
|
||||
@@ -135,22 +151,22 @@ CVPair FactoryDefaultCVs [] =
|
||||
{85, 1}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{86, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{87, 1}, // Start Position Fx=0
|
||||
{88, 5}, // End Position Fx=1
|
||||
{88, 50}, // End Position Fx=1
|
||||
{89, 1}, // Current Position
|
||||
{90, 1}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{91, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{92, 1}, // Start Position Fx=0
|
||||
{93, 20}, // End Position Fx=1
|
||||
{93, 100}, // End Position Fx=1
|
||||
{94, 1}, // Current Position
|
||||
{95, 3}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{96, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{97, 1}, // Start Position Fx=0
|
||||
{98, 35}, // End Position Fx=1
|
||||
{98, 200}, // End Position Fx=1
|
||||
{99, 2}, // Current Position
|
||||
{100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{101, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{102, 1}, // Start Position Fx=0
|
||||
{103, 4}, // End Position Fx=1
|
||||
{103, 200}, // End Position Fx=1
|
||||
{104, 1}, // Current Position
|
||||
{105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{106, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
@@ -203,7 +219,7 @@ void setup() //******************************************************
|
||||
// Setup which External Interrupt, the Pin it's associated with that we're using
|
||||
Dcc.pin(0, 2, 0);
|
||||
// Call the main DCC Init function to enable the DCC Receiver
|
||||
Dcc.init( MAN_ID_DIY, 100, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address);
|
||||
Dcc.init( MAN_ID_DIY, 601, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address);
|
||||
delay(800);
|
||||
|
||||
#if defined(DECODER_LOADED)
|
||||
@@ -299,7 +315,7 @@ void loop() //****************************************************************
|
||||
// from the Arduino loop() function for correct library operation
|
||||
Dcc.process();
|
||||
SoftwareServo::refresh();
|
||||
delay(4);
|
||||
delay(3);
|
||||
for (int i=0; i < numfpins; i++) {
|
||||
if (ftn_queue[i].inuse==1) {
|
||||
|
||||
@@ -370,22 +386,17 @@ void loop() //****************************************************************
|
||||
}
|
||||
}
|
||||
|
||||
extern void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t OutputAddr, uint8_t State) {
|
||||
uint16_t Current_Decoder_Addr;
|
||||
uint8_t Bit_State;
|
||||
Current_Decoder_Addr = Dcc.getAddr();
|
||||
Bit_State = OutputAddr & 0x01;
|
||||
extern void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t OutputPower ) {
|
||||
uint16_t Current_Decoder_Addr = Dcc.getAddr();
|
||||
|
||||
if ( Addr >= Current_Decoder_Addr && Addr < Current_Decoder_Addr+17) { //Controls Accessory_Address+16
|
||||
#ifdef DEBUG
|
||||
Serial.print("Addr = ");
|
||||
Serial.println(Addr);
|
||||
Serial.print("BoardAddr = ");
|
||||
Serial.println(BoardAddr);
|
||||
Serial.print("Bit_State = ");
|
||||
Serial.println(Bit_State);
|
||||
Serial.print("Direction = ");
|
||||
Serial.println(Direction);
|
||||
#endif
|
||||
exec_function(Addr-Current_Decoder_Addr, Bit_State );
|
||||
exec_function(Addr-Current_Decoder_Addr, Direction );
|
||||
}
|
||||
}
|
||||
void exec_function (int function, int FuncState) {
|
||||
|
69
examples/SMA/AccDec_13Servos_4LED_6Ftn/AccDec_13Servos_4LED_6Ftn.ino
Executable file → Normal file
69
examples/SMA/AccDec_13Servos_4LED_6Ftn/AccDec_13Servos_4LED_6Ftn.ino
Executable file → Normal file
@@ -1,5 +1,11 @@
|
||||
// Production 17 Function DCC Decoder
|
||||
// Version 5.1 Geoff Bunza 2014,2015,2016
|
||||
// Production 17 Switch Acessory DCC Decoder AccDec_13Servos_4LED_6Ftn.ino
|
||||
// Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
|
||||
// Now works with both short and long DCC Addesses for CV Control Default 24 (LSB CV 121 ; MSB CV 122)
|
||||
// ACCESSORY DECODER DEFAULT ADDRESS IS 40 (MAX 40-56 SWITCHES)
|
||||
// ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255
|
||||
// BE CAREFUL! DIFFERENT DCC BASE STATIONS ALLOW DIFFERING MAX ADDRESSES
|
||||
|
||||
// NO LONGER REQUIRES modified software servo Lib
|
||||
// Software restructuring mods added from Alex Shepherd and Franz-Peter
|
||||
// With sincere thanks
|
||||
@@ -12,14 +18,13 @@
|
||||
// ******** INFO TO THE SERIAL MONITOR
|
||||
//#define DEBUG
|
||||
|
||||
|
||||
#include <NmraDcc.h>
|
||||
#include <SoftwareServo.h>
|
||||
|
||||
SoftwareServo servo[17];
|
||||
#define servo_start_delay 50
|
||||
#define servo_init_delay 7
|
||||
#define servo_slowdown 3 //servo loop counter limit
|
||||
#define servo_slowdown 12 //servo loop counter limit
|
||||
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
|
||||
|
||||
int tim_delay = 500;
|
||||
@@ -49,6 +54,7 @@ int t; // temp
|
||||
#define SET_CV_Address 24 // THIS ADDRESS IS FOR SETTING CV'S Like a Loco
|
||||
#define Accessory_Address 40 // THIS ADDRESS IS THE START OF THE SWITCHES RANGE
|
||||
// WHICH WILL EXTEND FOR 16 MORE SWITCH ADDRESSES
|
||||
// THIS CAN START ABOVE ADDRESS 256
|
||||
uint8_t CV_DECODER_MASTER_RESET = 120; // THIS IS THE CV ADDRESS OF THE FULL RESET
|
||||
#define CV_To_Store_SET_CV_Address 121
|
||||
#define CV_Accessory_Address CV_ACCESSORY_DECODER_ADDRESS_LSB
|
||||
@@ -61,7 +67,7 @@ struct QUEUE
|
||||
int stop_value;
|
||||
int start_value;
|
||||
};
|
||||
QUEUE *ftn_queue = new QUEUE[16];
|
||||
QUEUE *ftn_queue = new QUEUE[17];
|
||||
|
||||
struct CVPair
|
||||
{
|
||||
@@ -70,13 +76,24 @@ struct CVPair
|
||||
};
|
||||
CVPair FactoryDefaultCVs [] =
|
||||
{
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_LSB, Accessory_Address},
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_MSB, 0},
|
||||
// These two CVs define the Long Accessory Address
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_LSB, Accessory_Address&0xFF},
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_MSB, (Accessory_Address>>8)&0x07},
|
||||
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
|
||||
|
||||
// Speed Steps don't matter for this decoder
|
||||
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
|
||||
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
|
||||
{CV_29_CONFIG,CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_F0_LOCATION}, // Accesory Decoder Short Address
|
||||
// {CV_29_CONFIG, CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Accesory Decoder Long Address
|
||||
|
||||
{CV_DECODER_MASTER_RESET, 0},
|
||||
{CV_To_Store_SET_CV_Address, SET_CV_Address},
|
||||
{CV_To_Store_SET_CV_Address+1, 0},
|
||||
{CV_To_Store_SET_CV_Address, SET_CV_Address&0xFF }, // LSB Set CV Address
|
||||
{CV_To_Store_SET_CV_Address+1,(SET_CV_Address>>8)&0x3F }, //MSB Set CV Address
|
||||
{30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{32, 28}, //F0 Start Position F0=0
|
||||
@@ -142,22 +159,22 @@ CVPair FactoryDefaultCVs [] =
|
||||
{92, 28}, // Start Position Fx=0
|
||||
{93, 140}, // End Position Fx=1
|
||||
{94, 28}, // Current Position
|
||||
{95, 1}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=PWM
|
||||
{95, 3}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{96, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{97, 1}, // Start Position Fx=0
|
||||
{98, 20}, // End Position Fx=1
|
||||
{99, 1}, // Current Position
|
||||
{100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=PWM
|
||||
{98, 200}, // End Position Fx=1
|
||||
{99, 2}, // Current Position
|
||||
{100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{101, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{102, 1}, // Start Position Fx=0
|
||||
{103, 4}, // End Position Fx=1
|
||||
{103, 200}, // End Position Fx=1
|
||||
{104, 1}, // Current Position
|
||||
{105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=PWM
|
||||
{105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{106, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{107, 1}, // Start Position Fx=0
|
||||
{108, 60}, // End Position Fx=1
|
||||
{109, 20}, // Current Position
|
||||
{110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=PWM
|
||||
{109, 1}, // Current Position
|
||||
{110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{111, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{112, 1}, // Start Position Fx=0
|
||||
{113, 4}, // End Position Fx=1
|
||||
@@ -203,7 +220,7 @@ void setup() //******************************************************
|
||||
// Setup which External Interrupt, the Pin it's associated with that we're using
|
||||
Dcc.pin(0, 2, 0);
|
||||
// Call the main DCC Init function to enable the DCC Receiver
|
||||
Dcc.init( MAN_ID_DIY, 100, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address);
|
||||
Dcc.init( MAN_ID_DIY, 601, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address);
|
||||
delay(800);
|
||||
|
||||
#if defined(DECODER_LOADED)
|
||||
@@ -299,7 +316,7 @@ void loop() //****************************************************************
|
||||
// from the Arduino loop() function for correct library operation
|
||||
Dcc.process();
|
||||
SoftwareServo::refresh();
|
||||
delay(4);
|
||||
delay(3);
|
||||
for (int i=0; i < numfpins; i++) {
|
||||
if (ftn_queue[i].inuse==1) {
|
||||
|
||||
@@ -370,24 +387,20 @@ void loop() //****************************************************************
|
||||
}
|
||||
}
|
||||
|
||||
extern void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t OutputAddr, uint8_t State) {
|
||||
uint16_t Current_Decoder_Addr;
|
||||
uint8_t Bit_State;
|
||||
Current_Decoder_Addr = Dcc.getAddr();
|
||||
Bit_State = OutputAddr & 0x01;
|
||||
extern void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t OutputPower ) {
|
||||
uint16_t Current_Decoder_Addr = Dcc.getAddr();
|
||||
|
||||
if ( Addr >= Current_Decoder_Addr && Addr < Current_Decoder_Addr+17) { //Controls Accessory_Address+16
|
||||
#ifdef DEBUG
|
||||
Serial.print("Addr = ");
|
||||
Serial.println(Addr);
|
||||
Serial.print("BoardAddr = ");
|
||||
Serial.println(BoardAddr);
|
||||
Serial.print("Bit_State = ");
|
||||
Serial.println(Bit_State);
|
||||
Serial.print("Direction = ");
|
||||
Serial.println(Direction);
|
||||
#endif
|
||||
exec_function(Addr-Current_Decoder_Addr, Bit_State );
|
||||
exec_function(Addr-Current_Decoder_Addr, Direction );
|
||||
}
|
||||
}
|
||||
|
||||
void exec_function (int function, int FuncState) {
|
||||
byte pin;
|
||||
int servo_temp;
|
||||
|
70
examples/SMA/AccDec_15Servos_2LED_6Ftn/AccDec_15Servos_2LED_6Ftn.ino
Executable file → Normal file
70
examples/SMA/AccDec_15Servos_2LED_6Ftn/AccDec_15Servos_2LED_6Ftn.ino
Executable file → Normal file
@@ -1,5 +1,10 @@
|
||||
// Production 17 Function DCC Decoder
|
||||
// Version 5.4 Geoff Bunza 2014,2015,2016
|
||||
// Production 17 Switch Acessory DCC Decoder AccDec_15Servos_2LED_6Ftn.ino
|
||||
// Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
|
||||
// Now works with both short and long DCC Addesses for CV Control Default 24 (LSB CV 121 ; MSB CV 122)
|
||||
// ACCESSORY DECODER DEFAULT ADDRESS IS 40 (MAX 40-56 SWITCHES)
|
||||
// ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255
|
||||
// BE CAREFUL! DIFFERENT DCC BASE STATIONS ALLOW DIFFERING MAX ADDRESSES
|
||||
|
||||
// NO LONGER REQUIRES modified software servo Lib
|
||||
// Software restructuring mods added from Alex Shepherd and Franz-Peter
|
||||
// With sincere thanks
|
||||
@@ -12,14 +17,13 @@
|
||||
// ******** INFO TO THE SERIAL MONITOR
|
||||
//#define DEBUG
|
||||
|
||||
|
||||
#include <NmraDcc.h>
|
||||
#include <SoftwareServo.h>
|
||||
|
||||
SoftwareServo servo[17];
|
||||
#define servo_start_delay 50
|
||||
#define servo_init_delay 7
|
||||
#define servo_slowdown 3 //servo loop counter limit
|
||||
#define servo_slowdown 12 //servo loop counter limit
|
||||
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
|
||||
|
||||
int tim_delay = 500;
|
||||
@@ -49,6 +53,7 @@ int t; // temp
|
||||
#define SET_CV_Address 24 // THIS ADDRESS IS FOR SETTING CV'S Like a Loco
|
||||
#define Accessory_Address 40 // THIS ADDRESS IS THE START OF THE SWITCHES RANGE
|
||||
// WHICH WILL EXTEND FOR 16 MORE SWITCH ADDRESSES
|
||||
// THIS CAN START ABOVE ADDRESS 256
|
||||
uint8_t CV_DECODER_MASTER_RESET = 120; // THIS IS THE CV ADDRESS OF THE FULL RESET
|
||||
#define CV_To_Store_SET_CV_Address 121
|
||||
#define CV_Accessory_Address CV_ACCESSORY_DECODER_ADDRESS_LSB
|
||||
@@ -61,7 +66,7 @@ struct QUEUE
|
||||
int stop_value;
|
||||
int start_value;
|
||||
};
|
||||
QUEUE *ftn_queue = new QUEUE[16];
|
||||
QUEUE *ftn_queue = new QUEUE[17];
|
||||
|
||||
struct CVPair
|
||||
{
|
||||
@@ -70,13 +75,24 @@ struct CVPair
|
||||
};
|
||||
CVPair FactoryDefaultCVs [] =
|
||||
{
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_LSB, Accessory_Address},
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_MSB, 0},
|
||||
// These two CVs define the Long Accessory Address
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_LSB, Accessory_Address&0xFF},
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_MSB, (Accessory_Address>>8)&0x07},
|
||||
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
|
||||
|
||||
// Speed Steps don't matter for this decoder
|
||||
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
|
||||
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
|
||||
{CV_29_CONFIG,CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_F0_LOCATION}, // Accesory Decoder Short Address
|
||||
// {CV_29_CONFIG, CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Accesory Decoder Long Address
|
||||
|
||||
{CV_DECODER_MASTER_RESET, 0},
|
||||
{CV_To_Store_SET_CV_Address, SET_CV_Address},
|
||||
{CV_To_Store_SET_CV_Address+1, 0},
|
||||
{CV_To_Store_SET_CV_Address, SET_CV_Address&0xFF }, // LSB Set CV Address
|
||||
{CV_To_Store_SET_CV_Address+1,(SET_CV_Address>>8)&0x3F }, //MSB Set CV Address
|
||||
{30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{32, 28}, //F0 Start Position F0=0
|
||||
@@ -203,7 +219,7 @@ void setup() //******************************************************
|
||||
// Setup which External Interrupt, the Pin it's associated with that we're using
|
||||
Dcc.pin(0, 2, 0);
|
||||
// Call the main DCC Init function to enable the DCC Receiver
|
||||
Dcc.init( MAN_ID_DIY, 100, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address);
|
||||
Dcc.init( MAN_ID_DIY, 601, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address);
|
||||
delay(800);
|
||||
|
||||
#if defined(DECODER_LOADED)
|
||||
@@ -277,7 +293,13 @@ void setup() //******************************************************
|
||||
}
|
||||
break;
|
||||
case 5: // Fade On
|
||||
|
||||
{
|
||||
ftn_queue[i].inuse = 0;
|
||||
ftn_queue[i].start_value = 0;
|
||||
ftn_queue[i].increment = int (char (Dcc.getCV( 31+(i*5))));
|
||||
digitalWrite(fpins[i], 0);
|
||||
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5))) *10.;
|
||||
}
|
||||
break;
|
||||
case 6: // NEXT FEATURE to pin
|
||||
break;
|
||||
@@ -293,7 +315,7 @@ void loop() //****************************************************************
|
||||
// from the Arduino loop() function for correct library operation
|
||||
Dcc.process();
|
||||
SoftwareServo::refresh();
|
||||
delay(4);
|
||||
delay(3);
|
||||
for (int i=0; i < numfpins; i++) {
|
||||
if (ftn_queue[i].inuse==1) {
|
||||
|
||||
@@ -353,13 +375,7 @@ void loop() //****************************************************************
|
||||
}
|
||||
break;
|
||||
case 5: // Fade On
|
||||
{
|
||||
ftn_queue[i].inuse = 0;
|
||||
ftn_queue[i].start_value = 0;
|
||||
ftn_queue[i].increment = int (char (Dcc.getCV( 31+(i*5))));
|
||||
digitalWrite(fpins[i], 0);
|
||||
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5))) *10.;
|
||||
}
|
||||
|
||||
break;
|
||||
case 6: // NEXT FEATURE to pin
|
||||
break;
|
||||
@@ -370,24 +386,20 @@ void loop() //****************************************************************
|
||||
}
|
||||
}
|
||||
|
||||
extern void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t OutputAddr, uint8_t State) {
|
||||
uint16_t Current_Decoder_Addr;
|
||||
uint8_t Bit_State;
|
||||
Current_Decoder_Addr = Dcc.getAddr();
|
||||
Bit_State = OutputAddr & 0x01;
|
||||
extern void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t OutputPower ) {
|
||||
uint16_t Current_Decoder_Addr = Dcc.getAddr();
|
||||
|
||||
if ( Addr >= Current_Decoder_Addr && Addr < Current_Decoder_Addr+17) { //Controls Accessory_Address+16
|
||||
#ifdef DEBUG
|
||||
Serial.print("Addr = ");
|
||||
Serial.println(Addr);
|
||||
Serial.print("BoardAddr = ");
|
||||
Serial.println(BoardAddr);
|
||||
Serial.print("Bit_State = ");
|
||||
Serial.println(Bit_State);
|
||||
Serial.print("Direction = ");
|
||||
Serial.println(Direction);
|
||||
#endif
|
||||
exec_function(Addr-Current_Decoder_Addr, Bit_State );
|
||||
exec_function(Addr-Current_Decoder_Addr, Direction );
|
||||
}
|
||||
}
|
||||
|
||||
void exec_function (int function, int FuncState) {
|
||||
byte pin;
|
||||
int servo_temp;
|
||||
|
47
examples/SMA/AccDec_17LED_1Ftn/AccDec_17LED_1Ftn.ino
Executable file → Normal file
47
examples/SMA/AccDec_17LED_1Ftn/AccDec_17LED_1Ftn.ino
Executable file → Normal file
@@ -1,5 +1,9 @@
|
||||
// Production 17 Function DCC Decoder
|
||||
// Version 5.4 Geoff Bunza 2014,2015,2016
|
||||
// Production 17 Switch Acessory DCC Decoder AccDec_17LED_1Ftn.ino
|
||||
// Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
|
||||
// Now works with both short and long DCC Addesses for CV Control Default 24 (LSB CV 121 ; MSB CV 122)
|
||||
// ACCESSORY DECODER DEFAULT ADDRESS IS 40 (MAX 40-56 SWITCHES)
|
||||
// ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255
|
||||
// BE CAREFUL! DIFFERENT DCC BASE STATIONS ALLOW DIFFERING MAX ADDRESSES
|
||||
|
||||
// ******** UNLESS YOU WANT ALL CV'S RESET UPON EVERY POWER UP
|
||||
// ******** AFTER THE INITIAL DECODER LOAD REMOVE THE "//" IN THE FOOLOWING LINE!!
|
||||
@@ -9,7 +13,7 @@
|
||||
|
||||
int tim_delay = 500;
|
||||
#define numleds 17
|
||||
byte ledpins [] = {0,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
|
||||
byte ledpins [] = {3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
|
||||
|
||||
const int FunctionPin0 = 3;
|
||||
const int FunctionPin1 = 4;
|
||||
@@ -31,9 +35,14 @@ const int FunctionPin16 = 19; //A5
|
||||
NmraDcc Dcc ;
|
||||
DCC_MSG Packet ;
|
||||
|
||||
#define This_Decoder_Address 40 //ACCESSORY DECODER ADDRESS
|
||||
//Start of SWITCHES RANGE
|
||||
uint8_t CV_DECODER_MASTER_RESET = 120;
|
||||
#define SET_CV_Address 24 // THIS ADDRESS IS FOR SETTING CV'S Like a Loco
|
||||
#define Accessory_Address 40 // THIS ADDRESS IS THE START OF THE SWITCHES RANGE
|
||||
// WHICH WILL EXTEND FOR 16 MORE SWITCH ADDRESSES
|
||||
// THIS CAN START ABOVE ADDRESS 256
|
||||
uint8_t CV_DECODER_MASTER_RESET = 120; // THIS IS THE CV ADDRESS OF THE FULL RESET
|
||||
#define CV_To_Store_SET_CV_Address 121
|
||||
#define CV_Accessory_Address CV_ACCESSORY_DECODER_ADDRESS_LSB
|
||||
|
||||
struct CVPair
|
||||
{
|
||||
uint16_t CV;
|
||||
@@ -41,11 +50,24 @@ struct CVPair
|
||||
};
|
||||
CVPair FactoryDefaultCVs [] =
|
||||
{
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_LSB, This_Decoder_Address},
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_MSB, 0},
|
||||
// These two CVs define the Long Accessory Address
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_LSB, Accessory_Address&0xFF},
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_MSB, (Accessory_Address>>8)&0x07},
|
||||
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
|
||||
|
||||
// Speed Steps don't matter for this decoder
|
||||
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
|
||||
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
|
||||
{CV_29_CONFIG,CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_F0_LOCATION}, // Accesory Decoder Short Address
|
||||
// {CV_29_CONFIG, CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Accesory Decoder Long Address
|
||||
|
||||
{CV_DECODER_MASTER_RESET, 0},
|
||||
{CV_To_Store_SET_CV_Address, SET_CV_Address&0xFF }, // LSB Set CV Address
|
||||
{CV_To_Store_SET_CV_Address+1,(SET_CV_Address>>8)&0x3F }, //MSB Set CV Address
|
||||
};
|
||||
|
||||
uint8_t FactoryDefaultCVIndex = 0;
|
||||
@@ -86,16 +108,15 @@ void setup()
|
||||
// Setup which External Interrupt, the Pin it's associated with that we're using and enable the Pull-Up
|
||||
Dcc.pin(0, 2, 0);
|
||||
// Call the main DCC Init function to enable the DCC Receiver
|
||||
Dcc.init( MAN_ID_DIY, 100, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, 0 );
|
||||
Dcc.init( MAN_ID_DIY, 601, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address);
|
||||
}
|
||||
void loop()
|
||||
{
|
||||
// You MUST call the NmraDcc.process() method frequently from the Arduino loop() function for correct library operation
|
||||
Dcc.process();
|
||||
}
|
||||
extern void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t OutputAddr, uint8_t State) {
|
||||
uint8_t Bit_State = OutputAddr & 0x01;
|
||||
if ( Addr >= This_Decoder_Address && Addr < This_Decoder_Address+17) //Controls This_Decoder_Address+16
|
||||
digitalWrite( ledpins[Addr-This_Decoder_Address], Bit_State );
|
||||
extern void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t OutputPower ) {
|
||||
if ( Addr >= Accessory_Address && Addr < Accessory_Address+17) //Controls This_Decoder_Address+16
|
||||
digitalWrite( ledpins[Addr-Accessory_Address], Direction );
|
||||
}
|
||||
|
||||
|
79
examples/SMA/AccDec_17LED_6Ftn/AccDec_17LED_6Ftn.ino
Executable file → Normal file
79
examples/SMA/AccDec_17LED_6Ftn/AccDec_17LED_6Ftn.ino
Executable file → Normal file
@@ -1,5 +1,10 @@
|
||||
// Production 17 Function DCC Decoder
|
||||
// Version 5.4 Geoff Bunza 2014,2015,2016
|
||||
// Production 17 Switch Acessory DCC Decoder AccDec_17LED_6Ftn.ino
|
||||
// Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
|
||||
// Now works with both short and long DCC Addesses for CV Control Default 24 (LSB CV 121 ; MSB CV 122)
|
||||
// ACCESSORY DECODER DEFAULT ADDRESS IS 40 (MAX 40-56 SWITCHES)
|
||||
// ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255
|
||||
// BE CAREFUL! DIFFERENT DCC BASE STATIONS ALLOW DIFFERING MAX ADDRESSES
|
||||
|
||||
// NO LONGER REQUIRES modified software servo Lib
|
||||
// Software restructuring mods added from Alex Shepherd and Franz-Peter
|
||||
// With sincere thanks
|
||||
@@ -12,14 +17,13 @@
|
||||
// ******** INFO TO THE SERIAL MONITOR
|
||||
//#define DEBUG
|
||||
|
||||
|
||||
#include <NmraDcc.h>
|
||||
#include <SoftwareServo.h>
|
||||
|
||||
SoftwareServo servo[17];
|
||||
#define servo_start_delay 50
|
||||
#define servo_init_delay 7
|
||||
#define servo_slowdown 3 //servo loop counter limit
|
||||
#define servo_slowdown 12 //servo loop counter limit
|
||||
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
|
||||
|
||||
int tim_delay = 500;
|
||||
@@ -49,6 +53,7 @@ int t; // temp
|
||||
#define SET_CV_Address 24 // THIS ADDRESS IS FOR SETTING CV'S Like a Loco
|
||||
#define Accessory_Address 40 // THIS ADDRESS IS THE START OF THE SWITCHES RANGE
|
||||
// WHICH WILL EXTEND FOR 16 MORE SWITCH ADDRESSES
|
||||
// THIS CAN START ABOVE ADDRESS 256
|
||||
uint8_t CV_DECODER_MASTER_RESET = 120; // THIS IS THE CV ADDRESS OF THE FULL RESET
|
||||
#define CV_To_Store_SET_CV_Address 121
|
||||
#define CV_Accessory_Address CV_ACCESSORY_DECODER_ADDRESS_LSB
|
||||
@@ -61,7 +66,7 @@ struct QUEUE
|
||||
int stop_value;
|
||||
int start_value;
|
||||
};
|
||||
QUEUE *ftn_queue = new QUEUE[16];
|
||||
QUEUE *ftn_queue = new QUEUE[17];
|
||||
|
||||
struct CVPair
|
||||
{
|
||||
@@ -70,13 +75,24 @@ struct CVPair
|
||||
};
|
||||
CVPair FactoryDefaultCVs [] =
|
||||
{
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_LSB, Accessory_Address},
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_MSB, 0},
|
||||
// These two CVs define the Long Accessory Address
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_LSB, Accessory_Address&0xFF},
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_MSB, (Accessory_Address>>8)&0x07},
|
||||
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
|
||||
|
||||
// Speed Steps don't matter for this decoder
|
||||
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
|
||||
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
|
||||
{CV_29_CONFIG,CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_F0_LOCATION}, // Accesory Decoder Short Address
|
||||
// {CV_29_CONFIG, CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Accesory Decoder Long Address
|
||||
|
||||
{CV_DECODER_MASTER_RESET, 0},
|
||||
{CV_To_Store_SET_CV_Address, SET_CV_Address},
|
||||
{CV_To_Store_SET_CV_Address+1, 0},
|
||||
{CV_To_Store_SET_CV_Address, SET_CV_Address&0xFF }, // LSB Set CV Address
|
||||
{CV_To_Store_SET_CV_Address+1,(SET_CV_Address>>8)&0x3F }, //MSB Set CV Address
|
||||
{30, 0}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{32, 28}, //F0 Start Position F0=0
|
||||
@@ -127,36 +143,36 @@ CVPair FactoryDefaultCVs [] =
|
||||
{77, 1}, // Start Position Fx=0
|
||||
{78, 10}, // End Position Fx=1
|
||||
{79, 1}, // Current Position
|
||||
{80, 5}, //F10 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{80, 0}, //F10 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{81, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{82, 1}, // Start Position Fx=0
|
||||
{83, 5}, // End Position Fx=1
|
||||
{84, 1}, // Current Position
|
||||
{85, 4}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{86, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{85, 1}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{86, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{87, 1}, // Start Position Fx=0
|
||||
{88, 5}, // End Position Fx=1
|
||||
{88, 50}, // End Position Fx=1
|
||||
{89, 1}, // Current Position
|
||||
{90, 0}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{90, 1}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{91, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{92, 1}, // Start Position Fx=0
|
||||
{93, 20}, // End Position Fx=1
|
||||
{93, 100}, // End Position Fx=1
|
||||
{94, 1}, // Current Position
|
||||
{95, 0}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{95, 3}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{96, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{97, 1}, // Start Position Fx=0
|
||||
{98, 35}, // End Position Fx=1
|
||||
{98, 200}, // End Position Fx=1
|
||||
{99, 2}, // Current Position
|
||||
{100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{101, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{102, 1}, // Start Position Fx=0
|
||||
{103, 4}, // End Position Fx=1
|
||||
{103, 200}, // End Position Fx=1
|
||||
{104, 1}, // Current Position
|
||||
{105, 0}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{106, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{107, 1}, // Start Position Fx=0
|
||||
{108, 60}, // End Position Fx=1
|
||||
{109, 20}, // Current Position
|
||||
{109, 1}, // Current Position
|
||||
{110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{111, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{112, 1}, // Start Position Fx=0
|
||||
@@ -177,6 +193,9 @@ void notifyCVResetFactoryDefault()
|
||||
FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
|
||||
};
|
||||
|
||||
// NOTE: NO PROGRAMMING ACK IS SET UP TO MAXIMAIZE
|
||||
// OUTPUT PINS FOR FUNCTIONS
|
||||
|
||||
void setup() //******************************************************
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@@ -203,7 +222,7 @@ void setup() //******************************************************
|
||||
// Setup which External Interrupt, the Pin it's associated with that we're using
|
||||
Dcc.pin(0, 2, 0);
|
||||
// Call the main DCC Init function to enable the DCC Receiver
|
||||
Dcc.init( MAN_ID_DIY, 100, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address);
|
||||
Dcc.init( MAN_ID_DIY, 601, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address);
|
||||
delay(800);
|
||||
|
||||
#if defined(DECODER_LOADED)
|
||||
@@ -299,7 +318,7 @@ void loop() //****************************************************************
|
||||
// from the Arduino loop() function for correct library operation
|
||||
Dcc.process();
|
||||
SoftwareServo::refresh();
|
||||
delay(4);
|
||||
delay(3);
|
||||
for (int i=0; i < numfpins; i++) {
|
||||
if (ftn_queue[i].inuse==1) {
|
||||
|
||||
@@ -370,24 +389,20 @@ void loop() //****************************************************************
|
||||
}
|
||||
}
|
||||
|
||||
extern void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t OutputAddr, uint8_t State) {
|
||||
uint16_t Current_Decoder_Addr;
|
||||
uint8_t Bit_State;
|
||||
Current_Decoder_Addr = Dcc.getAddr();
|
||||
Bit_State = OutputAddr & 0x01;
|
||||
extern void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t OutputPower ) {
|
||||
uint16_t Current_Decoder_Addr = Dcc.getAddr();
|
||||
|
||||
if ( Addr >= Current_Decoder_Addr && Addr < Current_Decoder_Addr+17) { //Controls Accessory_Address+16
|
||||
#ifdef DEBUG
|
||||
Serial.print("Addr = ");
|
||||
Serial.println(Addr);
|
||||
Serial.print("BoardAddr = ");
|
||||
Serial.println(BoardAddr);
|
||||
Serial.print("Bit_State = ");
|
||||
Serial.println(Bit_State);
|
||||
Serial.print("Direction = ");
|
||||
Serial.println(Direction);
|
||||
#endif
|
||||
exec_function(Addr-Current_Decoder_Addr, Bit_State );
|
||||
exec_function(Addr-Current_Decoder_Addr, Direction );
|
||||
}
|
||||
}
|
||||
|
||||
void exec_function (int function, int FuncState) {
|
||||
byte pin;
|
||||
int servo_temp;
|
||||
|
58
examples/SMA/AccDec_7ServoBackandForth6Ftn/AccDec_7ServoBackandForth6Ftn.ino
Executable file → Normal file
58
examples/SMA/AccDec_7ServoBackandForth6Ftn/AccDec_7ServoBackandForth6Ftn.ino
Executable file → Normal file
@@ -1,13 +1,19 @@
|
||||
// Production 17 Function DCC Decoder
|
||||
// Version 5.4 Geoff Bunza 2014,2015,2016
|
||||
// Production 17 Switch Acessory DCC Decoder AccDec_7ServoBackandForth6Ftn.ino
|
||||
// Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
|
||||
// Now works with both short and long DCC Addesses for CV Control Default 24 (LSB CV 121 ; MSB CV 122)
|
||||
// ACCESSORY DECODER DEFAULT ADDRESS IS 40 (MAX 40-56 SWITCHES)
|
||||
// ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255
|
||||
// BE CAREFUL! DIFFERENT DCC BASE STATIONS ALLOW DIFFERING MAX ADDRESSES
|
||||
|
||||
// NO LONGER REQUIRES modified software servo Lib
|
||||
// Software restructuring mods added from Alex Shepherd and Franz-Peter
|
||||
// With sincere thanks
|
||||
|
||||
// This Decoder Version has been modified so that each Switch Closure Transition from Thrown to Closed
|
||||
// Swings the Servo Quickly from Start to Stop and Back to Start
|
||||
// This is ONLY done in the transition from Thrown to Closed Servo Speed can be slowed by changing the
|
||||
// RATE CV towards 1
|
||||
//
|
||||
|
||||
// ******** UNLESS YOU WANT ALL CV'S RESET UPON EVERY POWER UP
|
||||
// ******** AFTER THE INITIAL DECODER LOAD REMOVE THE "//" IN THE FOOLOWING LINE!!
|
||||
//#define DECODER_LOADED
|
||||
@@ -22,7 +28,7 @@
|
||||
SoftwareServo servo[17];
|
||||
#define servo_start_delay 50
|
||||
#define servo_init_delay 7
|
||||
#define servo_slowdown 3 //servo loop counter limit
|
||||
#define servo_slowdown 12 //servo loop counter limit
|
||||
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
|
||||
|
||||
int tim_delay = 500;
|
||||
@@ -64,7 +70,7 @@ struct QUEUE
|
||||
int stop_value;
|
||||
int start_value;
|
||||
};
|
||||
QUEUE *ftn_queue = new QUEUE[16];
|
||||
QUEUE *ftn_queue = new QUEUE[17];
|
||||
|
||||
struct CVPair
|
||||
{
|
||||
@@ -73,13 +79,24 @@ struct CVPair
|
||||
};
|
||||
CVPair FactoryDefaultCVs [] =
|
||||
{
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_LSB, Accessory_Address},
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_MSB, 0},
|
||||
// These two CVs define the Long Accessory Address
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_LSB, Accessory_Address&0xFF},
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_MSB, (Accessory_Address>>8)&0x07},
|
||||
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
|
||||
|
||||
// Speed Steps don't matter for this decoder
|
||||
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
|
||||
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
|
||||
{CV_29_CONFIG,CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_F0_LOCATION}, // Accesory Decoder Short Address
|
||||
// {CV_29_CONFIG, CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Accesory Decoder Long Address
|
||||
|
||||
{CV_DECODER_MASTER_RESET, 0},
|
||||
{CV_To_Store_SET_CV_Address, SET_CV_Address},
|
||||
{CV_To_Store_SET_CV_Address+1, 0},
|
||||
{CV_To_Store_SET_CV_Address, SET_CV_Address&0xFF }, // LSB Set CV Address
|
||||
{CV_To_Store_SET_CV_Address+1,(SET_CV_Address>>8)&0x3F }, //MSB Set CV Address
|
||||
{30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{32, 28}, //F0 Start Position
|
||||
@@ -180,6 +197,9 @@ void notifyCVResetFactoryDefault()
|
||||
FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
|
||||
};
|
||||
|
||||
// NOTE: NO PROGRAMMING ACK IS SET UP TO MAXIMAIZE
|
||||
// OUTPUT PINS FOR FUNCTIONS
|
||||
|
||||
void setup() //******************************************************
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@@ -206,7 +226,7 @@ void setup() //******************************************************
|
||||
// Setup which External Interrupt, the Pin it's associated with that we're using
|
||||
Dcc.pin(0, 2, 0);
|
||||
// Call the main DCC Init function to enable the DCC Receiver
|
||||
Dcc.init( MAN_ID_DIY, 100, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address);
|
||||
Dcc.init( MAN_ID_DIY, 601, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address);
|
||||
delay(800);
|
||||
|
||||
#if defined(DECODER_LOADED)
|
||||
@@ -302,7 +322,7 @@ void loop() //****************************************************************
|
||||
// from the Arduino loop() function for correct library operation
|
||||
Dcc.process();
|
||||
SoftwareServo::refresh();
|
||||
delay(4);
|
||||
delay(3);
|
||||
for (int i=0; i < numfpins; i++) {
|
||||
if (ftn_queue[i].inuse==1) {
|
||||
|
||||
@@ -352,24 +372,20 @@ void loop() //****************************************************************
|
||||
}
|
||||
}
|
||||
|
||||
extern void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t OutputAddr, uint8_t State) {
|
||||
uint16_t Current_Decoder_Addr;
|
||||
uint8_t Bit_State;
|
||||
Current_Decoder_Addr = Dcc.getAddr();
|
||||
Bit_State = OutputAddr & 0x01;
|
||||
extern void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t OutputPower ) {
|
||||
uint16_t Current_Decoder_Addr = Dcc.getAddr();
|
||||
|
||||
if ( Addr >= Current_Decoder_Addr && Addr < Current_Decoder_Addr+17) { //Controls Accessory_Address+16
|
||||
#ifdef DEBUG
|
||||
Serial.print("Addr = ");
|
||||
Serial.println(Addr);
|
||||
Serial.print("BoardAddr = ");
|
||||
Serial.println(BoardAddr);
|
||||
Serial.print("Bit_State = ");
|
||||
Serial.println(Bit_State);
|
||||
Serial.print("Direction = ");
|
||||
Serial.println(Direction);
|
||||
#endif
|
||||
exec_function(Addr-Current_Decoder_Addr, Bit_State );
|
||||
exec_function(Addr-Current_Decoder_Addr, Direction );
|
||||
}
|
||||
}
|
||||
|
||||
void exec_function (int function, int FuncState) {
|
||||
byte pin;
|
||||
int servo_temp;
|
||||
|
98
examples/SMA/AccDec_7Servos_10LED_6Ftn/AccDec_7Servos_10LED_6Ftn.ino
Executable file → Normal file
98
examples/SMA/AccDec_7Servos_10LED_6Ftn/AccDec_7Servos_10LED_6Ftn.ino
Executable file → Normal file
@@ -1,5 +1,10 @@
|
||||
// Production 17 Function DCC Decoder
|
||||
// Version 5.4 Geoff Bunza 2014,2015,2016
|
||||
// Production 17 Switch Acessory DCC Decoder AccDec_7Servos_10LED_6Ftn.ino
|
||||
// Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
|
||||
// Now works with both short and long DCC Addesses for CV Control Default 24 (LSB CV 121 ; MSB CV 122)
|
||||
// ACCESSORY DECODER DEFAULT ADDRESS IS 40 (MAX 40-56 SWITCHES)
|
||||
// ACCESSRY DECODER ADDRESS CAN NOW BE SET ABOVE 255
|
||||
// BE CAREFUL! DIFFERENT DCC BASE STATIONS ALLOW DIFFERING MAX ADDRESSES
|
||||
|
||||
// NO LONGER REQUIRES modified software servo Lib
|
||||
// Software restructuring mods added from Alex Shepherd and Franz-Peter
|
||||
// With sincere thanks
|
||||
@@ -12,14 +17,13 @@
|
||||
// ******** INFO TO THE SERIAL MONITOR
|
||||
//#define DEBUG
|
||||
|
||||
|
||||
#include <NmraDcc.h>
|
||||
#include <SoftwareServo.h>
|
||||
|
||||
SoftwareServo servo[17];
|
||||
#define servo_start_delay 50
|
||||
#define servo_init_delay 7
|
||||
#define servo_slowdown 3 //servo loop counter limit
|
||||
#define servo_slowdown 12 //servo loop counter limit
|
||||
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
|
||||
|
||||
int tim_delay = 500;
|
||||
@@ -49,6 +53,7 @@ int t; // temp
|
||||
#define SET_CV_Address 24 // THIS ADDRESS IS FOR SETTING CV'S Like a Loco
|
||||
#define Accessory_Address 40 // THIS ADDRESS IS THE START OF THE SWITCHES RANGE
|
||||
// WHICH WILL EXTEND FOR 16 MORE SWITCH ADDRESSES
|
||||
// THIS CAN START ABOVE ADDRESS 256
|
||||
uint8_t CV_DECODER_MASTER_RESET = 120; // THIS IS THE CV ADDRESS OF THE FULL RESET
|
||||
#define CV_To_Store_SET_CV_Address 121
|
||||
#define CV_Accessory_Address CV_ACCESSORY_DECODER_ADDRESS_LSB
|
||||
@@ -61,7 +66,7 @@ struct QUEUE
|
||||
int stop_value;
|
||||
int start_value;
|
||||
};
|
||||
QUEUE *ftn_queue = new QUEUE[16];
|
||||
QUEUE *ftn_queue = new QUEUE[17];
|
||||
|
||||
struct CVPair
|
||||
{
|
||||
@@ -70,13 +75,24 @@ struct CVPair
|
||||
};
|
||||
CVPair FactoryDefaultCVs [] =
|
||||
{
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_LSB, Accessory_Address},
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_MSB, 0},
|
||||
// These two CVs define the Long Accessory Address
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_LSB, Accessory_Address&0xFF},
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_MSB, (Accessory_Address>>8)&0x07},
|
||||
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
|
||||
|
||||
// Speed Steps don't matter for this decoder
|
||||
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
|
||||
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
|
||||
{CV_29_CONFIG,CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_F0_LOCATION}, // Accesory Decoder Short Address
|
||||
// {CV_29_CONFIG, CV29_ACCESSORY_DECODER|CV29_OUTPUT_ADDRESS_MODE|CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Accesory Decoder Long Address
|
||||
|
||||
{CV_DECODER_MASTER_RESET, 0},
|
||||
{CV_To_Store_SET_CV_Address, SET_CV_Address},
|
||||
{CV_To_Store_SET_CV_Address+1, 0},
|
||||
{CV_To_Store_SET_CV_Address, SET_CV_Address&0xFF }, // LSB Set CV Address
|
||||
{CV_To_Store_SET_CV_Address+1,(SET_CV_Address>>8)&0x3F }, //MSB Set CV Address
|
||||
{30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{32, 28}, //F0 Start Position F0=0
|
||||
@@ -129,41 +145,41 @@ CVPair FactoryDefaultCVs [] =
|
||||
{79, 28}, // Current Position
|
||||
{80, 0}, //F10 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{81, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{82, 28}, // Start Position Fx=0
|
||||
{83, 140}, // End Position Fx=1
|
||||
{84, 28}, // Current Position
|
||||
{85, 0}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{82, 1}, // Start Position Fx=0
|
||||
{83, 5}, // End Position Fx=1
|
||||
{84, 1}, // Current Position
|
||||
{85, 1}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{86, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{87, 28}, // Start Position Fx=0
|
||||
{88, 140}, // End Position Fx=1
|
||||
{89, 28}, // Current Position
|
||||
{90, 0}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{87, 1}, // Start Position Fx=0
|
||||
{88, 50}, // End Position Fx=1
|
||||
{89, 1}, // Current Position
|
||||
{90, 1}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{91, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{92, 28}, // Start Position Fx=0
|
||||
{93, 140}, // End Position Fx=1
|
||||
{94, 28}, // Current Position
|
||||
{95, 1}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=PWM
|
||||
{92, 1}, // Start Position Fx=0
|
||||
{93, 100}, // End Position Fx=1
|
||||
{94, 1}, // Current Position
|
||||
{95, 3}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{96, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{97, 1}, // Start Position Fx=0
|
||||
{98, 20}, // End Position Fx=1
|
||||
{99, 1}, // Current Position
|
||||
{100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=PWM
|
||||
{98, 200}, // End Position Fx=1
|
||||
{99, 2}, // Current Position
|
||||
{100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{101, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{102, 1}, // Start Position Fx=0
|
||||
{103, 4}, // End Position Fx=1
|
||||
{103, 200}, // End Position Fx=1
|
||||
{104, 1}, // Current Position
|
||||
{105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=PWM
|
||||
{105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{106, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{107, 1}, // Start Position Fx=0
|
||||
{108, 60}, // End Position Fx=1
|
||||
{109, 20}, // Current Position
|
||||
{110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=PWM
|
||||
{109, 1}, // Current Position
|
||||
{110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{111, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{112, 1}, // Start Position Fx=0
|
||||
{113, 4}, // End Position Fx=1
|
||||
{114, 1}, // Current Position
|
||||
//FUTURE USE
|
||||
{115, 0}, //F17 Config 0=On/Off,1=Blink,2=Servo,3=PWM
|
||||
{115, 0}, //F17 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{116, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{117, 28}, // Start Position Fx=0
|
||||
{118, 50}, // End Position Fx=1
|
||||
@@ -177,6 +193,9 @@ void notifyCVResetFactoryDefault()
|
||||
FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
|
||||
};
|
||||
|
||||
// NOTE: NO PROGRAMMING ACK IS SET UP TO MAXIMAIZE
|
||||
// OUTPUT PINS FOR FUNCTIONS
|
||||
|
||||
void setup() //******************************************************
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@@ -203,7 +222,7 @@ void setup() //******************************************************
|
||||
// Setup which External Interrupt, the Pin it's associated with that we're using
|
||||
Dcc.pin(0, 2, 0);
|
||||
// Call the main DCC Init function to enable the DCC Receiver
|
||||
Dcc.init( MAN_ID_DIY, 100, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address);
|
||||
Dcc.init( MAN_ID_DIY, 601, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER, CV_To_Store_SET_CV_Address);
|
||||
delay(800);
|
||||
|
||||
#if defined(DECODER_LOADED)
|
||||
@@ -299,7 +318,7 @@ void loop() //****************************************************************
|
||||
// from the Arduino loop() function for correct library operation
|
||||
Dcc.process();
|
||||
SoftwareServo::refresh();
|
||||
delay(4);
|
||||
delay(3);
|
||||
for (int i=0; i < numfpins; i++) {
|
||||
if (ftn_queue[i].inuse==1) {
|
||||
|
||||
@@ -370,24 +389,21 @@ void loop() //****************************************************************
|
||||
}
|
||||
}
|
||||
|
||||
extern void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t OutputAddr, uint8_t State) {
|
||||
uint16_t Current_Decoder_Addr;
|
||||
uint8_t Bit_State;
|
||||
Current_Decoder_Addr = Dcc.getAddr();
|
||||
Bit_State = OutputAddr & 0x01;
|
||||
// This function is called whenever a normal DCC Turnout Packet is received and we're in Output Addressing Mode
|
||||
extern void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t OutputPower ) {
|
||||
uint16_t Current_Decoder_Addr = Dcc.getAddr();
|
||||
|
||||
if ( Addr >= Current_Decoder_Addr && Addr < Current_Decoder_Addr+17) { //Controls Accessory_Address+16
|
||||
#ifdef DEBUG
|
||||
Serial.print("Addr = ");
|
||||
Serial.println(Addr);
|
||||
Serial.print("BoardAddr = ");
|
||||
Serial.println(BoardAddr);
|
||||
Serial.print("Bit_State = ");
|
||||
Serial.println(Bit_State);
|
||||
Serial.print("Direction = ");
|
||||
Serial.println(Direction);
|
||||
#endif
|
||||
exec_function(Addr-Current_Decoder_Addr, Bit_State );
|
||||
exec_function(Addr-Current_Decoder_Addr, Direction );
|
||||
}
|
||||
}
|
||||
|
||||
void exec_function (int function, int FuncState) {
|
||||
byte pin;
|
||||
int servo_temp;
|
||||
|
51
examples/SMA/Dec_10Serv_7LED_6Ftn/Dec_10Serv_7LED_6Ftn.ino
Executable file → Normal file
51
examples/SMA/Dec_10Serv_7LED_6Ftn/Dec_10Serv_7LED_6Ftn.ino
Executable file → Normal file
@@ -1,5 +1,6 @@
|
||||
// Production 17 Function DCC Decoder
|
||||
// Version 5.4 Geoff Bunza 2014,2015,2016
|
||||
// Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
|
||||
// Now works with both short and long DCC Addesses
|
||||
// NO LONGER REQUIRES modified software servo Lib
|
||||
// Software restructuring mods added from Alex Shepherd and Franz-Peter
|
||||
// With sincere thanks
|
||||
@@ -19,7 +20,7 @@
|
||||
SoftwareServo servo[17];
|
||||
#define servo_start_delay 50
|
||||
#define servo_init_delay 7
|
||||
#define servo_slowdown 3 //servo loop counter limit
|
||||
#define servo_slowdown 12 //servo loop counter limit
|
||||
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
|
||||
|
||||
int tim_delay = 500;
|
||||
@@ -49,7 +50,6 @@ NmraDcc Dcc ;
|
||||
DCC_MSG Packet ;
|
||||
uint8_t CV_DECODER_MASTER_RESET = 120;
|
||||
int t; // temp
|
||||
#define This_Decoder_Address 24
|
||||
struct QUEUE
|
||||
{
|
||||
int inuse;
|
||||
@@ -58,19 +58,29 @@ struct QUEUE
|
||||
int stop_value;
|
||||
int start_value;
|
||||
};
|
||||
QUEUE *ftn_queue = new QUEUE[16];
|
||||
QUEUE *ftn_queue = new QUEUE[17];
|
||||
|
||||
struct CVPair
|
||||
{
|
||||
uint16_t CV;
|
||||
uint8_t Value;
|
||||
};
|
||||
|
||||
#define This_Decoder_Address 24
|
||||
|
||||
CVPair FactoryDefaultCVs [] =
|
||||
{
|
||||
{CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address},
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
|
||||
{CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address&0x7F },
|
||||
|
||||
// These two CVs define the Long DCC Address
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, ((This_Decoder_Address>>8)&0x7F)+192 },
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF },
|
||||
|
||||
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
|
||||
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
|
||||
{CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
|
||||
|
||||
{CV_DECODER_MASTER_RESET, 0},
|
||||
{30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
@@ -130,22 +140,22 @@ CVPair FactoryDefaultCVs [] =
|
||||
{85, 1}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{86, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{87, 1}, // Start Position Fx=0
|
||||
{88, 5}, // End Position Fx=1
|
||||
{88, 50}, // End Position Fx=1
|
||||
{89, 1}, // Current Position
|
||||
{90, 1}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{91, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{92, 1}, // Start Position Fx=0
|
||||
{93, 20}, // End Position Fx=1
|
||||
{93, 100}, // End Position Fx=1
|
||||
{94, 1}, // Current Position
|
||||
{95, 3}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{96, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{97, 1}, // Start Position Fx=0
|
||||
{98, 35}, // End Position Fx=1
|
||||
{98, 200}, // End Position Fx=1
|
||||
{99, 2}, // Current Position
|
||||
{100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{101, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{102, 1}, // Start Position Fx=0
|
||||
{103, 4}, // End Position Fx=1
|
||||
{103, 200}, // End Position Fx=1
|
||||
{104, 1}, // Current Position
|
||||
{105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{106, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
@@ -173,6 +183,8 @@ void notifyCVResetFactoryDefault()
|
||||
FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
|
||||
};
|
||||
|
||||
// NOTE: NO PROGRAMMING ACK IS SET UP TO MAXIMAIZE
|
||||
// OUTPUT PINS FOR FUNCTIONS
|
||||
void setup() //******************************************************
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@@ -199,7 +211,7 @@ void setup() //******************************************************
|
||||
// Setup which External Interrupt, the Pin it's associated with that we're using
|
||||
Dcc.pin(0, 2, 0);
|
||||
// Call the main DCC Init function to enable the DCC Receiver
|
||||
Dcc.init( MAN_ID_DIY, 100, FLAGS_MY_ADDRESS_ONLY, 0 );
|
||||
Dcc.init( MAN_ID_DIY, 601, FLAGS_MY_ADDRESS_ONLY, 0 );
|
||||
delay(800);
|
||||
|
||||
#if defined(DECODER_LOADED)
|
||||
@@ -295,7 +307,7 @@ void loop() //****************************************************************
|
||||
// from the Arduino loop() function for correct library operation
|
||||
Dcc.process();
|
||||
SoftwareServo::refresh();
|
||||
delay(4);
|
||||
delay(3);
|
||||
for (int i=0; i < numfpins; i++) {
|
||||
if (ftn_queue[i].inuse==1) {
|
||||
|
||||
@@ -367,6 +379,17 @@ void loop() //****************************************************************
|
||||
}
|
||||
|
||||
void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) {
|
||||
#ifdef DEBUG
|
||||
Serial.print(" addr: ");
|
||||
Serial.print(Addr, DEC) ;
|
||||
Serial.print(" at: ");
|
||||
Serial.print(AddrType, DEC) ;
|
||||
Serial.print(" fg : ");
|
||||
Serial.print(FuncGrp, DEC) ;
|
||||
Serial.print(" fs: ");
|
||||
Serial.println(FuncState, DEC) ;
|
||||
#endif
|
||||
|
||||
switch(FuncGrp)
|
||||
{
|
||||
case FN_0_4: //Function Group 1 F0 F4 F3 F2 F1
|
||||
|
40
examples/SMA/Dec_13Serv_4LED_6Ftn/Dec_13Serv_4LED_6Ftn.ino
Executable file → Normal file
40
examples/SMA/Dec_13Serv_4LED_6Ftn/Dec_13Serv_4LED_6Ftn.ino
Executable file → Normal file
@@ -1,5 +1,5 @@
|
||||
// Production 17 Function DCC Decoder
|
||||
// Version 5.4 Geoff Bunza 2014,2015,2016
|
||||
// Production 17 Function DCC Decoder Dec_13Serv_4LED_6Ftn.ino
|
||||
// Version 6.01 Geoff Bunza 2014,2015,2016
|
||||
// NO LONGER REQUIRES modified software servo Lib
|
||||
// Software restructuring mods added from Alex Shepherd and Franz-Peter
|
||||
// With sincere thanks
|
||||
@@ -12,14 +12,13 @@
|
||||
// ******** INFO TO THE SERIAL MONITOR
|
||||
//#define DEBUG
|
||||
|
||||
|
||||
#include <NmraDcc.h>
|
||||
#include <SoftwareServo.h>
|
||||
|
||||
SoftwareServo servo[17];
|
||||
#define servo_start_delay 50
|
||||
#define servo_init_delay 7
|
||||
#define servo_slowdown 3 //servo loop counter limit
|
||||
#define servo_slowdown 12 //servo loop counter limit
|
||||
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
|
||||
|
||||
int tim_delay = 500;
|
||||
@@ -49,7 +48,6 @@ NmraDcc Dcc ;
|
||||
DCC_MSG Packet ;
|
||||
uint8_t CV_DECODER_MASTER_RESET = 120;
|
||||
int t; // temp
|
||||
#define This_Decoder_Address 24
|
||||
struct QUEUE
|
||||
{
|
||||
int inuse;
|
||||
@@ -65,12 +63,22 @@ struct CVPair
|
||||
uint16_t CV;
|
||||
uint8_t Value;
|
||||
};
|
||||
|
||||
#define This_Decoder_Address 24
|
||||
|
||||
CVPair FactoryDefaultCVs [] =
|
||||
{
|
||||
{CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address},
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
|
||||
{CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address&0x7F },
|
||||
|
||||
// These two CVs define the Long DCC Address
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, ((This_Decoder_Address>>8)&0x7F)+192 },
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF },
|
||||
|
||||
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
|
||||
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
|
||||
{CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
|
||||
|
||||
{CV_DECODER_MASTER_RESET, 0},
|
||||
{30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
@@ -137,21 +145,21 @@ CVPair FactoryDefaultCVs [] =
|
||||
{92, 28}, // Start Position Fx=0
|
||||
{93, 140}, // End Position Fx=1
|
||||
{94, 28}, // Current Position
|
||||
{95, 1}, //F13 CConfig 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{95, 3}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{96, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{97, 1}, // Start Position Fx=0
|
||||
{98, 20}, // End Position Fx=1
|
||||
{99, 1}, // Current Position
|
||||
{98, 200}, // End Position Fx=1
|
||||
{99, 2}, // Current Position
|
||||
{100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{101, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{102, 1}, // Start Position Fx=0
|
||||
{103, 4}, // End Position Fx=1
|
||||
{103, 200}, // End Position Fx=1
|
||||
{104, 1}, // Current Position
|
||||
{105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{106, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{107, 1}, // Start Position Fx=0
|
||||
{108, 60}, // End Position Fx=1
|
||||
{109, 20}, // Current Position
|
||||
{109, 1}, // Current Position
|
||||
{110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{111, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{112, 1}, // Start Position Fx=0
|
||||
@@ -199,7 +207,7 @@ void setup() //******************************************************
|
||||
// Setup which External Interrupt, the Pin it's associated with that we're using
|
||||
Dcc.pin(0, 2, 0);
|
||||
// Call the main DCC Init function to enable the DCC Receiver
|
||||
Dcc.init( MAN_ID_DIY, 100, FLAGS_MY_ADDRESS_ONLY, 0 );
|
||||
Dcc.init( MAN_ID_DIY, 601, FLAGS_MY_ADDRESS_ONLY, 0 );
|
||||
delay(800);
|
||||
|
||||
#if defined(DECODER_LOADED)
|
||||
@@ -295,7 +303,7 @@ void loop() //****************************************************************
|
||||
// from the Arduino loop() function for correct library operation
|
||||
Dcc.process();
|
||||
SoftwareServo::refresh();
|
||||
delay(4);
|
||||
delay(3);
|
||||
for (int i=0; i < numfpins; i++) {
|
||||
if (ftn_queue[i].inuse==1) {
|
||||
|
||||
|
36
examples/SMA/Dec_15Serv_2LED_6Ftn/Dec_15Serv_2LED_6Ftn.ino
Executable file → Normal file
36
examples/SMA/Dec_15Serv_2LED_6Ftn/Dec_15Serv_2LED_6Ftn.ino
Executable file → Normal file
@@ -1,5 +1,5 @@
|
||||
// Production 17 Function DCC Decoder
|
||||
// Version 5.4 Geoff Bunza 2014,2015,2016
|
||||
// Production 17 Function DCC Decoder Dec_15Serv_2LED_6Ftn.ino
|
||||
// Version 6.01 Geoff Bunza 2014,2015,2016
|
||||
// NO LONGER REQUIRES modified software servo Lib
|
||||
// Software restructuring mods added from Alex Shepherd and Franz-Peter
|
||||
// With sincere thanks
|
||||
@@ -12,14 +12,13 @@
|
||||
// ******** INFO TO THE SERIAL MONITOR
|
||||
//#define DEBUG
|
||||
|
||||
|
||||
#include <NmraDcc.h>
|
||||
#include <SoftwareServo.h>
|
||||
|
||||
SoftwareServo servo[17];
|
||||
#define servo_start_delay 50
|
||||
#define servo_init_delay 7
|
||||
#define servo_slowdown 3 //servo loop counter limit
|
||||
#define servo_slowdown 12 //servo loop counter limit
|
||||
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
|
||||
|
||||
int tim_delay = 500;
|
||||
@@ -49,7 +48,6 @@ NmraDcc Dcc ;
|
||||
DCC_MSG Packet ;
|
||||
uint8_t CV_DECODER_MASTER_RESET = 120;
|
||||
int t; // temp
|
||||
#define This_Decoder_Address 24
|
||||
struct QUEUE
|
||||
{
|
||||
int inuse;
|
||||
@@ -65,12 +63,22 @@ struct CVPair
|
||||
uint16_t CV;
|
||||
uint8_t Value;
|
||||
};
|
||||
|
||||
#define This_Decoder_Address 24
|
||||
|
||||
CVPair FactoryDefaultCVs [] =
|
||||
{
|
||||
{CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address},
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
|
||||
{CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address&0x7F },
|
||||
|
||||
// These two CVs define the Long DCC Address
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, ((This_Decoder_Address>>8)&0x7F)+192 },
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF },
|
||||
|
||||
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
|
||||
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
|
||||
{CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
|
||||
|
||||
{CV_DECODER_MASTER_RESET, 0},
|
||||
{30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
@@ -147,15 +155,15 @@ CVPair FactoryDefaultCVs [] =
|
||||
{102, 28}, // Start Position Fx=0
|
||||
{103, 140}, // End Position Fx=1
|
||||
{104, 28}, // Current Position
|
||||
{105, 1}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{106, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{107, 1}, // Start Position Fx=0
|
||||
{108, 10}, // End Position Fx=1
|
||||
{108, 60}, // End Position Fx=1
|
||||
{109, 1}, // Current Position
|
||||
{110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{111, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{112, 1}, // Start Position Fx=0
|
||||
{113, 10}, // End Position Fx=1
|
||||
{113, 4}, // End Position Fx=1
|
||||
{114, 1}, // Current Position
|
||||
//FUTURE USE
|
||||
{115, 0}, //F17 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
@@ -199,7 +207,7 @@ void setup() //******************************************************
|
||||
// Setup which External Interrupt, the Pin it's associated with that we're using
|
||||
Dcc.pin(0, 2, 0);
|
||||
// Call the main DCC Init function to enable the DCC Receiver
|
||||
Dcc.init( MAN_ID_DIY, 100, FLAGS_MY_ADDRESS_ONLY, 0 );
|
||||
Dcc.init( MAN_ID_DIY, 601, FLAGS_MY_ADDRESS_ONLY, 0 );
|
||||
delay(800);
|
||||
|
||||
#if defined(DECODER_LOADED)
|
||||
@@ -295,7 +303,7 @@ void loop() //****************************************************************
|
||||
// from the Arduino loop() function for correct library operation
|
||||
Dcc.process();
|
||||
SoftwareServo::refresh();
|
||||
delay(4);
|
||||
delay(3);
|
||||
for (int i=0; i < numfpins; i++) {
|
||||
if (ftn_queue[i].inuse==1) {
|
||||
|
||||
|
31
examples/SMA/Dec_17LED_1Ftn/Dec_17LED_1Ftn.ino
Executable file → Normal file
31
examples/SMA/Dec_17LED_1Ftn/Dec_17LED_1Ftn.ino
Executable file → Normal file
@@ -1,5 +1,6 @@
|
||||
// Production 17 Function DCC Decoder
|
||||
// Version 5.4 Geoff Bunza 2014,2015,2016
|
||||
// Production 17 Function DCC Decoder Dec_17LED_1Ftn.ino
|
||||
// Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
|
||||
// Now works with both short and long DCC Addesses
|
||||
|
||||
// ******** UNLESS YOU WANT ALL CV'S RESET UPON EVERY POWER UP
|
||||
// ******** AFTER THE INITIAL DECODER LOAD REMOVE THE "//" IN THE FOOLOWING LINE!!
|
||||
@@ -9,7 +10,7 @@
|
||||
|
||||
int tim_delay = 500;
|
||||
#define numleds 17
|
||||
byte ledpins [] = {0,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
|
||||
byte ledpins [] = {3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
|
||||
|
||||
const int FunctionPin0 = 3;
|
||||
const int FunctionPin1 = 4;
|
||||
@@ -26,7 +27,6 @@ const int FunctionPin9 = 12;
|
||||
const int FunctionPin10 = 13;
|
||||
const int FunctionPin11 = 14; //A0
|
||||
const int FunctionPin12 = 15; //A1
|
||||
|
||||
const int FunctionPin13 = 16; //A2
|
||||
const int FunctionPin14 = 17; //A3
|
||||
const int FunctionPin15 = 18; //A4
|
||||
@@ -34,7 +34,6 @@ const int FunctionPin16 = 19; //A5
|
||||
NmraDcc Dcc ;
|
||||
DCC_MSG Packet ;
|
||||
uint8_t CV_DECODER_MASTER_RESET = 120;
|
||||
#define This_Decoder_Address 24
|
||||
|
||||
struct CVPair
|
||||
{
|
||||
@@ -42,15 +41,25 @@ struct CVPair
|
||||
uint8_t Value;
|
||||
};
|
||||
CVPair FactoryDefaultCVs [] =
|
||||
|
||||
#define This_Decoder_Address 24
|
||||
|
||||
{
|
||||
{CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address},
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
|
||||
{CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address&0x7F },
|
||||
|
||||
// These two CVs define the Long DCC Address
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, ((This_Decoder_Address>>8)&0x7F)+192 },
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF },
|
||||
|
||||
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
|
||||
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
|
||||
{CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
|
||||
|
||||
{CV_DECODER_MASTER_RESET, 0},
|
||||
};
|
||||
|
||||
uint8_t FactoryDefaultCVIndex = 4;
|
||||
uint8_t FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
|
||||
void notifyCVResetFactoryDefault()
|
||||
{
|
||||
// Make FactoryDefaultCVIndex non-zero and equal to num CV's to be reset
|
||||
@@ -78,7 +87,7 @@ void setup()
|
||||
// Setup which External Interrupt, the Pin it's associated with that we're using and enable the Pull-Up
|
||||
Dcc.pin(0, 2, 0);
|
||||
// Call the main DCC Init function to enable the DCC Receiver
|
||||
Dcc.init( MAN_ID_DIY, 100, FLAGS_MY_ADDRESS_ONLY, 0 );
|
||||
Dcc.init( MAN_ID_DIY, 601, FLAGS_MY_ADDRESS_ONLY, 0 );
|
||||
delay(800);
|
||||
#if defined(DECODER_LOADED)
|
||||
if ( Dcc.getCV(CV_DECODER_MASTER_RESET)== CV_DECODER_MASTER_RESET )
|
||||
|
59
examples/SMA/Dec_17LED_6Ftn/Dec_17LED_6Ftn.ino
Executable file → Normal file
59
examples/SMA/Dec_17LED_6Ftn/Dec_17LED_6Ftn.ino
Executable file → Normal file
@@ -1,5 +1,6 @@
|
||||
// Production 17 Function DCC Decoder
|
||||
// Version 5.4 Geoff Bunza 2014,2015,2016
|
||||
// Production 17 Function DCC Decoder Dec_17LED_6Ftn.ino
|
||||
// Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
|
||||
// Now works with both short and long DCC Addesses
|
||||
// NO LONGER REQUIRES modified software servo Lib
|
||||
// Software restructuring mods added from Alex Shepherd and Franz-Peter
|
||||
// With sincere thanks
|
||||
@@ -10,15 +11,14 @@
|
||||
|
||||
// ******** EMOVE THE "//" IN THE FOOLOWING LINE TO SEND DEBUGGING
|
||||
// ******** INFO TO THE SERIAL MONITOR
|
||||
//#define DEBUG
|
||||
|
||||
#define DEBUG
|
||||
#include <NmraDcc.h>
|
||||
#include <SoftwareServo.h>
|
||||
|
||||
SoftwareServo servo[17];
|
||||
#define servo_start_delay 50
|
||||
#define servo_init_delay 7
|
||||
#define servo_slowdown 3 //servo loop counter limit
|
||||
#define servo_slowdown 12 //servo loop counter limit
|
||||
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
|
||||
|
||||
int tim_delay = 500;
|
||||
@@ -48,7 +48,7 @@ NmraDcc Dcc ;
|
||||
DCC_MSG Packet ;
|
||||
uint8_t CV_DECODER_MASTER_RESET = 120;
|
||||
int t; // temp
|
||||
#define This_Decoder_Address 24
|
||||
|
||||
struct QUEUE
|
||||
{
|
||||
int inuse;
|
||||
@@ -64,12 +64,21 @@ struct CVPair
|
||||
uint16_t CV;
|
||||
uint8_t Value;
|
||||
};
|
||||
|
||||
#define This_Decoder_Address 24
|
||||
|
||||
CVPair FactoryDefaultCVs [] =
|
||||
{
|
||||
{CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address},
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
|
||||
|
||||
// These two CVs define the Long DCC Address
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, ((This_Decoder_Address>>8)&0x7F)+192 },
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF },
|
||||
|
||||
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
|
||||
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
|
||||
{CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
|
||||
{CV_DECODER_MASTER_RESET, 0},
|
||||
{30, 5}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
@@ -129,32 +138,32 @@ CVPair FactoryDefaultCVs [] =
|
||||
{85, 1}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{86, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{87, 1}, // Start Position Fx=0
|
||||
{88, 5}, // End Position Fx=1
|
||||
{88, 50}, // End Position Fx=1
|
||||
{89, 1}, // Current Position
|
||||
{90, 1}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{91, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{92, 1}, // Start Position Fx=0
|
||||
{93, 10}, // End Position Fx=1
|
||||
{93, 100}, // End Position Fx=1
|
||||
{94, 1}, // Current Position
|
||||
{95, 3}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{96, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{97, 1}, // Start Position Fx=0
|
||||
{98, 6}, // End Position Fx=1
|
||||
{99, 1}, // Current Position
|
||||
{98, 200}, // End Position Fx=1
|
||||
{99, 2}, // Current Position
|
||||
{100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{101, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{102, 1}, // Start Position Fx=0
|
||||
{103, 6}, // End Position Fx=1
|
||||
{103, 200}, // End Position Fx=1
|
||||
{104, 1}, // Current Position
|
||||
{105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{106, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{107, 1}, // Start Position Fx=0
|
||||
{108, 10}, // End Position Fx=1
|
||||
{108, 60}, // End Position Fx=1
|
||||
{109, 1}, // Current Position
|
||||
{110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{111, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{112, 1}, // Start Position Fx=0
|
||||
{113, 10}, // End Position Fx=1
|
||||
{113, 4}, // End Position Fx=1
|
||||
{114, 1}, // Current Position
|
||||
//FUTURE USE
|
||||
{115, 0}, //F17 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
@@ -164,7 +173,7 @@ CVPair FactoryDefaultCVs [] =
|
||||
{119, 28}, // Current Position
|
||||
};
|
||||
|
||||
uint8_t FactoryDefaultCVIndex = 95;
|
||||
uint8_t FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
|
||||
void notifyCVResetFactoryDefault()
|
||||
{
|
||||
// Make FactoryDefaultCVIndex non-zero and equal to num CV's to be reset
|
||||
@@ -172,14 +181,17 @@ void notifyCVResetFactoryDefault()
|
||||
FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
|
||||
};
|
||||
|
||||
// NOTE: NO PROGRAMMING ACK IS SET UP TO MAXIMAIZE
|
||||
// OUTPUT PINS FOR FUNCTIONS
|
||||
|
||||
void setup() //******************************************************
|
||||
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Serial.begin(115200);
|
||||
#endif
|
||||
int i;
|
||||
uint8_t cv_value;
|
||||
Serial.begin(115200);
|
||||
// initialize the digital pins as outputs
|
||||
for (int i=0; i < numfpins; i++) {
|
||||
pinMode(fpins[i], OUTPUT);
|
||||
@@ -199,7 +211,7 @@ void setup() //******************************************************
|
||||
// Setup which External Interrupt, the Pin it's associated with that we're using
|
||||
Dcc.pin(0, 2, 0);
|
||||
// Call the main DCC Init function to enable the DCC Receiver
|
||||
Dcc.init( MAN_ID_DIY, 100, FLAGS_MY_ADDRESS_ONLY, 0 );
|
||||
Dcc.init( MAN_ID_DIY, 601, FLAGS_MY_ADDRESS_ONLY, 0 );
|
||||
delay(800);
|
||||
|
||||
#if defined(DECODER_LOADED)
|
||||
@@ -213,6 +225,7 @@ void setup() //******************************************************
|
||||
delay (1000);
|
||||
digitalWrite(fpins[14], 0);
|
||||
}
|
||||
|
||||
for ( i=0; i < numfpins; i++) {
|
||||
cv_value = Dcc.getCV( 30+(i*5)) ;
|
||||
#ifdef DEBUG
|
||||
@@ -295,7 +308,7 @@ void loop() //****************************************************************
|
||||
// from the Arduino loop() function for correct library operation
|
||||
Dcc.process();
|
||||
SoftwareServo::refresh();
|
||||
delay(4);
|
||||
delay(3);
|
||||
for (int i=0; i < numfpins; i++) {
|
||||
if (ftn_queue[i].inuse==1) {
|
||||
|
||||
@@ -367,6 +380,12 @@ void loop() //****************************************************************
|
||||
}
|
||||
|
||||
void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) {
|
||||
#ifdef DEBUG
|
||||
Serial.print("Addr= ");
|
||||
Serial.println(Addr, DEC) ;
|
||||
Serial.print("FuncState= ");
|
||||
Serial.println(FuncState, DEC) ;
|
||||
#endif
|
||||
switch(FuncGrp)
|
||||
{
|
||||
case FN_0_4: //Function Group 1 F0 F4 F3 F2 F1
|
||||
|
@@ -1,9 +1,23 @@
|
||||
// Production 17 Function DCC Decoder
|
||||
// Version 5.4 Geoff Bunza 2014,2015,2016
|
||||
// Production 2 Motor 13 Function DCC Decoder Dec_2MotDrive_12LED_1Srv_6Ftn.ino
|
||||
// Version 6.01a Geoff Bunza 2014,2015,2016,2017,2018
|
||||
// Now works with both short and long DCC Addesses
|
||||
// Better motor control added
|
||||
// NO LONGER REQUIRES modified software servo Lib
|
||||
// Software restructuring mods added from Alex Shepherd and Franz-Peter
|
||||
// With sincere thanks
|
||||
|
||||
/*
|
||||
* Motor selection is via motor select Function 13 (Motor1) and Function 14 (Motor2)
|
||||
* Motor speed for each can only be changed if the corresponding Function is on
|
||||
* (F13 and/or F14). Motor speed is maintained if the corresponding Motor select function
|
||||
* is off. Thus, each motor can be controlled independently and run at different speeds.
|
||||
* F0-F12 control LEDs on Pro Mini Digital Pins 5,6,7,8,11,12,13,14,15,16,17,18,19
|
||||
* Simple speed control is made via throttle speed setting for two motors. Motor selection
|
||||
* is via motor select Function 13 (Motor1) and Function 14 (Motor2). Motor speed for each
|
||||
* can only be changed if the corresponding Function is on (F13 and/or F14). Motor speed is
|
||||
* maintained if the corresponding motor select function is off. Thus, each motor can be
|
||||
* controlled independently and run at different speeds. The other functions are configurable
|
||||
* but are preset for LED on/off control.
|
||||
*/
|
||||
// ******** UNLESS YOU WANT ALL CV'S RESET UPON EVERY POWER UP
|
||||
// ******** AFTER THE INITIAL DECODER LOAD REMOVE THE "//" IN THE FOOLOWING LINE!!
|
||||
//#define DECODER_LOADED
|
||||
@@ -18,15 +32,13 @@
|
||||
SoftwareServo servo[13];
|
||||
#define servo_start_delay 50
|
||||
#define servo_init_delay 7
|
||||
#define servo_slowdown 3 //servo loop counter limit
|
||||
#define servo_slowdown 12 //servo loop counter limit
|
||||
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
|
||||
|
||||
uint8_t Motor1Speed = 0;
|
||||
int Motor1Speed = 0;
|
||||
uint8_t Motor1ForwardDir = 1;
|
||||
uint8_t Motor1MaxSpeed = 127;
|
||||
uint8_t Motor2Speed = 0;
|
||||
int Motor2Speed = 0;
|
||||
uint8_t Motor2ForwardDir = 1;
|
||||
uint8_t Motor2MaxSpeed = 127;
|
||||
int kickstarton = 1400; //kick start cycle on time
|
||||
int kickstarttime = 5; //kick start duration on time
|
||||
int fwdon = 0;
|
||||
@@ -35,6 +47,7 @@ int bwdon = 0;
|
||||
int bwdtime = 1;
|
||||
int bwdshift = 0;
|
||||
int cyclewidth = 2047;
|
||||
int loopdelay =14;
|
||||
int m2h = 3; //R H Bridge //Motor1
|
||||
int m2l = 4; //B H Bridge //Motor1
|
||||
int m0h = 9; //R H Bridge //Motor2
|
||||
@@ -42,7 +55,7 @@ int m0l = 10; //B H Bridge //Motor2
|
||||
|
||||
int speedup = 112; //Right track time differntial
|
||||
int deltime = 1500;
|
||||
int tim_delay = 100;
|
||||
int tim_delay = 30;
|
||||
int numfpins = 17;
|
||||
int num_active_fpins = 13;
|
||||
byte fpins [] = {3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
|
||||
@@ -69,7 +82,6 @@ NmraDcc Dcc ;
|
||||
DCC_MSG Packet ;
|
||||
uint8_t CV_DECODER_MASTER_RESET = 120;
|
||||
int t; // temp
|
||||
#define This_Decoder_Address 24
|
||||
struct QUEUE
|
||||
{
|
||||
int inuse;
|
||||
@@ -78,20 +90,29 @@ struct QUEUE
|
||||
int stop_value;
|
||||
int start_value;
|
||||
};
|
||||
QUEUE *ftn_queue = new QUEUE[16];
|
||||
QUEUE *ftn_queue = new QUEUE[17];
|
||||
|
||||
extern uint8_t Decoder_Address = This_Decoder_Address;
|
||||
struct CVPair
|
||||
{
|
||||
uint16_t CV;
|
||||
uint8_t Value;
|
||||
};
|
||||
|
||||
#define This_Decoder_Address 24
|
||||
|
||||
CVPair FactoryDefaultCVs [] =
|
||||
{
|
||||
{CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address},
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
|
||||
{CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address&0x7F },
|
||||
|
||||
// These two CVs define the Long DCC Address
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, ((This_Decoder_Address>>8)&0x7F)+192 },
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF },
|
||||
|
||||
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
|
||||
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
|
||||
{CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
|
||||
|
||||
{CV_DECODER_MASTER_RESET, 0},
|
||||
{30, 0}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
@@ -186,7 +207,7 @@ CVPair FactoryDefaultCVs [] =
|
||||
{119, 28}, // Current Position
|
||||
};
|
||||
|
||||
uint8_t FactoryDefaultCVIndex = 95;
|
||||
uint8_t FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
|
||||
void notifyCVResetFactoryDefault()
|
||||
{
|
||||
// Make FactoryDefaultCVIndex non-zero and equal to num CV's to be reset
|
||||
@@ -194,6 +215,9 @@ void notifyCVResetFactoryDefault()
|
||||
FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
|
||||
};
|
||||
|
||||
// NOTE: NO PROGRAMMING ACK IS SET UP TO MAXIMAIZE
|
||||
// OUTPUT PINS FOR FUNCTIONS
|
||||
|
||||
void setup() //******************************************************
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@@ -206,21 +230,19 @@ void setup() //******************************************************
|
||||
pinMode(fpins[i], OUTPUT);
|
||||
digitalWrite(fpins[i], 0);
|
||||
}
|
||||
for (int i=0; i < numfpins; i++) {
|
||||
for (int i=8; i < numfpins; i++) {
|
||||
digitalWrite(fpins[i], 1);
|
||||
delay (tim_delay/10);
|
||||
delay (tim_delay);
|
||||
}
|
||||
delay( tim_delay);
|
||||
for (int i=0; i < numfpins; i++) {
|
||||
for (int i=8; i < numfpins; i++) {
|
||||
digitalWrite(fpins[i], 0);
|
||||
delay (tim_delay/10);
|
||||
delay (tim_delay);
|
||||
}
|
||||
delay( tim_delay);
|
||||
|
||||
// Setup which External Interrupt, the Pin it's associated with that we're using
|
||||
Dcc.pin(0, 2, 0);
|
||||
// Call the main DCC Init function to enable the DCC Receiver
|
||||
Dcc.init( MAN_ID_DIY, 100, FLAGS_MY_ADDRESS_ONLY, 0 );
|
||||
Dcc.init( MAN_ID_DIY, 601, FLAGS_MY_ADDRESS_ONLY, 0 );
|
||||
delay(800);
|
||||
|
||||
#if defined(DECODER_LOADED)
|
||||
@@ -309,7 +331,6 @@ void setup() //******************************************************
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loop() //**********************************************************************
|
||||
{
|
||||
//MUST call the NmraDcc.process() method frequently
|
||||
@@ -317,13 +338,27 @@ void loop() //****************************************************************
|
||||
Dcc.process();
|
||||
SoftwareServo::refresh();
|
||||
delay(2);
|
||||
#ifdef DEBUG
|
||||
Serial.print("Motor1Speed= ");
|
||||
Serial.println(Motor1Speed, DEC) ;
|
||||
Serial.print("Motor2Speed= ");
|
||||
Serial.println(Motor2Speed, DEC) ;
|
||||
#endif
|
||||
if (Motor1Speed != 0) {
|
||||
if (Motor1ForwardDir == 0) gofwd1 (fwdtime, int((Motor1Speed&0x7f)*21));
|
||||
else gobwd1 (bwdtime, int((Motor1Speed&0x7f)*21));
|
||||
if (Motor1ForwardDir == 0) gofwd1 (fwdtime, Motor1Speed<<4);
|
||||
else gobwd1 (bwdtime, Motor1Speed<<4);
|
||||
}
|
||||
else {
|
||||
digitalWrite(m2h, LOW); //Motor1 OFF
|
||||
digitalWrite(m2l, LOW); //Motor1 OFF
|
||||
}
|
||||
if (Motor2Speed != 0) {
|
||||
if (Motor2ForwardDir == 0) gofwd2 (fwdtime, int((Motor2Speed&0x7f)*21));
|
||||
else gobwd2 (bwdtime, int((Motor2Speed&0x7f)*21));
|
||||
if (Motor2ForwardDir == 0) gofwd2 (fwdtime, Motor2Speed<<4);
|
||||
else gobwd2 (bwdtime, Motor2Speed<<4);
|
||||
}
|
||||
else {
|
||||
digitalWrite(m0h, LOW); //Motor1 OFF
|
||||
digitalWrite(m0l, LOW); //Motor1 OFF
|
||||
}
|
||||
//
|
||||
for (int i=0; i < num_active_fpins; i++) {
|
||||
@@ -397,65 +432,76 @@ void loop() //****************************************************************
|
||||
}
|
||||
void gofwd1(int fcnt,int fcycle) {
|
||||
int icnt;
|
||||
int totcycle;
|
||||
int delta_tp,delta_tm;
|
||||
delta_tp = fcycle+loopdelay<<2;
|
||||
delta_tm = cyclewidth-fcycle-loopdelay;
|
||||
icnt = 0;
|
||||
while (icnt < fcnt)
|
||||
{
|
||||
digitalWrite(m2h, HIGH); //Motor1
|
||||
delayMicroseconds(fcycle);
|
||||
delayMicroseconds(delta_tp);
|
||||
digitalWrite(m2h, LOW); //Motor1
|
||||
delayMicroseconds(cyclewidth - fcycle);
|
||||
delayMicroseconds(delta_tm);
|
||||
icnt++;
|
||||
}
|
||||
}
|
||||
void gobwd1(int bcnt,int bcycle) {
|
||||
int icnt;
|
||||
int delta_tp,delta_tm;
|
||||
delta_tp = bcycle+loopdelay<<2;
|
||||
delta_tm = cyclewidth-bcycle-loopdelay;
|
||||
icnt=0;
|
||||
while (icnt < bcnt)
|
||||
{
|
||||
digitalWrite(m2l, HIGH); //Motor1
|
||||
delayMicroseconds(bcycle);
|
||||
delayMicroseconds(delta_tp);
|
||||
digitalWrite(m2l, LOW); //Motor1
|
||||
delayMicroseconds(cyclewidth - bcycle);
|
||||
delayMicroseconds(delta_tm);
|
||||
icnt++;
|
||||
}
|
||||
}
|
||||
void gofwd2(int fcnt,int fcycle) {
|
||||
int icnt;
|
||||
int totcycle;
|
||||
int delta_tp,delta_tm;
|
||||
delta_tp = fcycle+loopdelay<<2;
|
||||
delta_tm = cyclewidth-fcycle-loopdelay;
|
||||
icnt = 0;
|
||||
while (icnt < fcnt)
|
||||
{
|
||||
digitalWrite(m0h, HIGH); //Motor2
|
||||
delayMicroseconds(fcycle);
|
||||
delayMicroseconds(delta_tp);
|
||||
digitalWrite(m0h, LOW); //Motor2
|
||||
delayMicroseconds(cyclewidth - fcycle);
|
||||
delayMicroseconds(delta_tm);
|
||||
icnt++;
|
||||
}
|
||||
}
|
||||
void gobwd2(int bcnt,int bcycle) {
|
||||
int icnt;
|
||||
int delta_tp,delta_tm;
|
||||
delta_tp = bcycle+loopdelay<<2;
|
||||
delta_tm = cyclewidth-bcycle-loopdelay;
|
||||
icnt=0;
|
||||
while (icnt < bcnt)
|
||||
{
|
||||
digitalWrite(m0l, HIGH); //Motor2
|
||||
delayMicroseconds(bcycle);
|
||||
delayMicroseconds(delta_tp);
|
||||
digitalWrite(m0l, LOW); //Motor2
|
||||
delayMicroseconds(cyclewidth - bcycle);
|
||||
delayMicroseconds(delta_tm);
|
||||
icnt++;
|
||||
}
|
||||
}
|
||||
void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_DIRECTION ForwardDir, DCC_SPEED_STEPS SpeedSteps ) {
|
||||
if (Function13_value==1) {
|
||||
Motor1Speed = Speed;
|
||||
Motor1Speed = (Speed & 0x7f );
|
||||
if (Motor1Speed == 1) Motor1Speed=0;
|
||||
Motor1ForwardDir = ForwardDir;
|
||||
}
|
||||
if (Function14_value==1) {
|
||||
Motor2Speed = Speed;
|
||||
Motor2Speed = (Speed & 0x7f );
|
||||
if (Motor2Speed == 1) Motor2Speed=0;
|
||||
Motor2ForwardDir = ForwardDir;
|
||||
}
|
||||
}
|
||||
|
||||
void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) {
|
||||
switch(FuncGrp)
|
||||
{
|
726
examples/SMA/Dec_2Mot_3LED_TrigAud/Dec_2Mot_3LED_TrigAud.ino
Normal file
726
examples/SMA/Dec_2Mot_3LED_TrigAud/Dec_2Mot_3LED_TrigAud.ino
Normal file
@@ -0,0 +1,726 @@
|
||||
// Production 2 Motor w/Triggered Audio Multi Function DCC Decoder Dec_2Mot_3LED_TrigAudio.ino
|
||||
// Version 6.01a Geoff Bunza 2014,2015,2016,2017,2018
|
||||
// Now works with both short and long DCC Addesses
|
||||
// Improved motor control added
|
||||
// This decoder will control 2 motors and play audio clips by function:
|
||||
// F0=LED on pin 8, F1-F4 Controls playing specific audio tracks in the 3rd CV (start) at the volume in the 2nd CV (rate)
|
||||
// F5 Controls playing audio track in CV57 at the volume in CV56 ONLY when F5 is ON and Pin17/A3 is held low,
|
||||
// and plays continuously until F5 turns off or Pin17 trigger goes HIGH or open
|
||||
// F6 plays one track selected randomly off the memory card
|
||||
// F13 and F14 select each separate motor which will respond to speed and direction controls
|
||||
// F7-F8 control LEDs by default PINS 18 and 19
|
||||
|
||||
// NO LONGER REQUIRES modified software servo Lib
|
||||
// Software restructuring mods added from Alex Shepherd and Franz-Peter
|
||||
// With sincere thanks
|
||||
|
||||
// * MAX 9 Configurations per pin function:
|
||||
// * 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio,7=Random Audio,8=Triggered Audio
|
||||
/*
|
||||
* Motor selection is via motor select Function 13 (Motor1) and Function 14 (Motor2)
|
||||
* Motor speed for each can only be changed if the corresponding Function is on
|
||||
* (F13 and/or F14). Motor speed is maintained if the corresponding Motor select function
|
||||
* is off. Thus, each motor can be controlled independently and run at different speeds.
|
||||
* F0 LED Pin 13
|
||||
* F1-F6 6 Functions Configures As Audio Play
|
||||
* F7-F8 2 Functions Configures As LEDs by default PINS 18 and 19
|
||||
* F13 Motor1 Control Enable
|
||||
* F14 Motor2 Control Enable
|
||||
* Pro Mini Transmit-7 (TX) connected to DFPlayer Receive (RX)Pin 2 via 470 Ohm Resistor
|
||||
* Pro Mini Receive (RX) connected to DFPlayer Transmit (TX) Pin 3
|
||||
* Remember to connect +5V and GND to the DFPlayer too: DFPLAYER PINS 1 & 7,10 respectively
|
||||
* This is a “mobile/function” decoder that adds audio play to dual motor control and
|
||||
* LED functions. Audio tracks or clips are stored on a micro SD card for playing,
|
||||
* in a folder labeled mp3, with tracks named 0001.mp3, 0002.mp3, etc. F0 is configured
|
||||
* as an on/off LED function, F1-F5 play audio tracks 1-5 respectively.
|
||||
* F6 plays a random selection in random order from tracks 1-6.
|
||||
* F7-F9 control LEDs on Pro Mini Digital Pins 11-13.
|
||||
* Simple speed control is made via throttle speed setting for two motors. Motor selection
|
||||
* is via motor select Function 13 (Motor1) and Function 14 (Motor2). Motor speed for each
|
||||
* can only be changed if the corresponding Function is on (F13 and/or F14). Motor speed is
|
||||
* maintained if the corresponding motor select function is off. Thus, each motor can be
|
||||
* controlled independently and run at different speeds. The other functions are configurable
|
||||
* but are preset for LED on/off control.
|
||||
*/
|
||||
// ******** UNLESS YOU WANT ALL CV'S RESET UPON EVERY POWER UP
|
||||
// ******** AFTER THE INITIAL DECODER LOAD REMOVE THE "//" IN THE FOOLOWING LINE!!
|
||||
//#define DECODER_LOADED
|
||||
|
||||
// ******** EMOVE THE "//" IN THE FOOLOWING LINE TO SEND DEBUGGING
|
||||
// ******** INFO TO THE SERIAL MONITOR
|
||||
//#define DEBUG
|
||||
|
||||
#include <NmraDcc.h>
|
||||
#include <SoftwareServo.h>
|
||||
#include <SoftwareSerial.h>
|
||||
#include <DFPlayer_Mini_Mp3.h>
|
||||
SoftwareSerial mySerial(6,7); // PRO MINI RX, PRO MINI TX serial to DFPlayer
|
||||
|
||||
int busy_pin = 5; // DFPlayer Busy status pin
|
||||
#define num_clips 6 //number of sound tracks/clips on the Micro SD Memory Card
|
||||
int del_tim = 4000;
|
||||
int tctr, tctr2, i;
|
||||
byte audio_on = 0; // Audio ON sets this to 1; otherwise 0
|
||||
|
||||
SoftwareServo servo[10];
|
||||
#define servo_start_delay 50
|
||||
#define servo_init_delay 7
|
||||
#define servo_slowdown 4 //servo loop counter limit
|
||||
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
|
||||
|
||||
int Motor1Speed = 0;
|
||||
uint8_t Motor1ForwardDir = 1;
|
||||
int Motor2Speed = 0;
|
||||
uint8_t Motor2ForwardDir = 1;
|
||||
int kickstarton = 1400; //kick start cycle on time
|
||||
int kickstarttime = 5; //kick start duration on time
|
||||
int fwdon = 0;
|
||||
int fwdtime = 1;
|
||||
int bwdon = 0;
|
||||
int bwdtime = 1;
|
||||
int bwdshift = 0;
|
||||
int cyclewidth = 2047;
|
||||
int loopdelay =14;
|
||||
int m2h = 3; //R H Bridge //Motor1
|
||||
int m2l = 4; //B H Bridge //Motor1
|
||||
int m0h = 9; //R H Bridge //Motor2
|
||||
int m0l = 10; //B H Bridge //Motor2
|
||||
|
||||
int speedup = 112; //Right track time differntial
|
||||
int deltime = 1500;
|
||||
int tim_delay = 30;
|
||||
int numfpins = 13;
|
||||
int num_active_fpins = 9;
|
||||
byte fpins [] = {3,4,8,9,10,11,12,13,14,15,16,18};
|
||||
const int FunctionPin0 = 13;
|
||||
const int FunctionPin1 = 20; // Place holders ONLY
|
||||
const int FunctionPin2 = 20; // Place holders ONLY
|
||||
const int FunctionPin3 = 20; // Place holders ONLY
|
||||
const int FunctionPin4 = 20; //A0 Place holders ONLY
|
||||
|
||||
const int FunctionPin5 = 20; //A1 Place holders ONLY
|
||||
const int FunctionPin6 = 20; //A2 Place holders ONLY
|
||||
const int FunctionPin7 = 18; //A5 Place holders ONLY
|
||||
const int FunctionPin8 = 19; //A4 Place holders ONLY
|
||||
|
||||
const int AudioTriggerPin = 17; //A3 NOW USED AS Audio Trigger Pin INPUT_PULLUP
|
||||
|
||||
const int FunctionPin9 = 20; // Place holders ONLY
|
||||
const int FunctionPin10 = 20; // Place holders ONLY
|
||||
const int FunctionPin11 = 20; // Place holders ONLY
|
||||
const int FunctionPin12 = 20; // Place holders ONLY
|
||||
const int FunctionPin13 = 20; // Place holders ONLY
|
||||
const int FunctionPin14 = 20; // Place holders ONLY
|
||||
const int FunctionPin15 = 20; // Place holders ONLY
|
||||
const int FunctionPin16 = 20; // Place holders ONLY
|
||||
|
||||
int Function13_value = 0;
|
||||
int Function14_value = 0;
|
||||
|
||||
NmraDcc Dcc ;
|
||||
DCC_MSG Packet ;
|
||||
uint8_t CV_DECODER_MASTER_RESET = 120;
|
||||
int t; // temp
|
||||
struct QUEUE
|
||||
{
|
||||
int inuse;
|
||||
int current_position;
|
||||
int increment;
|
||||
int stop_value;
|
||||
int start_value;
|
||||
};
|
||||
QUEUE *ftn_queue = new QUEUE[17];
|
||||
|
||||
struct CVPair
|
||||
{
|
||||
uint16_t CV;
|
||||
uint8_t Value;
|
||||
};
|
||||
|
||||
#define This_Decoder_Address 24
|
||||
|
||||
CVPair FactoryDefaultCVs [] =
|
||||
{
|
||||
{CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address&0x7F },
|
||||
|
||||
// These two CVs define the Long DCC Address
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, ((This_Decoder_Address>>8)&0x7F)+192 },
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF },
|
||||
|
||||
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
|
||||
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
|
||||
{CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
|
||||
|
||||
{CV_DECODER_MASTER_RESET, 0},
|
||||
{30, 0}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio,7=Random Audio,8=Triggered Audio
|
||||
{31, 10}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30)
|
||||
{32, 0}, //F0 Start Position F0=0,Audio=Audio Track/Clip#
|
||||
{33, 8}, //F0 End Position F0=1
|
||||
{34, 1}, //F0 Current Position
|
||||
{35, 6}, //F1 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio,7=Random Audio,8=Triggered Audio
|
||||
{36, 22}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30)
|
||||
{37, 1}, // Start Position Fx=0,Audio=Audio Track/Clip#
|
||||
{38, 8}, // End Position Fx=1
|
||||
{39, 1}, // Current Position
|
||||
{40, 6}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio,7=Random Audio,8=Triggered Audio
|
||||
{41, 22}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30)
|
||||
{42, 2}, // Start Position Fx=0,Audio=Audio Track/Clip#
|
||||
{43, 140}, // End Position Fx=1
|
||||
{44, 0}, // Current Position
|
||||
{45, 6}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio,7=Random Audio,8=Triggered Audio
|
||||
{46, 22}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30)
|
||||
{47, 3}, // Start Position Fx=0,Audio=Audio Track/Clip#
|
||||
{48, 140}, // End Position Fx=1
|
||||
{49, 0}, // Current Position
|
||||
{50, 6}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio,7=Random Audio,8=Triggered Audio
|
||||
{51, 22}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30)
|
||||
{52, 4}, // Start Position Fx=0,Audio=Audio Track/Clip#
|
||||
{53, 140}, // End Position Fx=1
|
||||
{54, 0}, // Current Position
|
||||
{55, 8}, //F5 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio,7=Random Audio,8=Triggered Audio
|
||||
{56, 22}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30)
|
||||
{57, 6}, // Start Position Fx=0,Audio=Audio Track/Clip#
|
||||
{58, 140}, // End Position Fx=1
|
||||
{59, 0}, // Current Position
|
||||
{60, 7}, //F6 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio,7=Random Audio,8=Triggered Audio
|
||||
{61, 22}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30)
|
||||
{62, 6}, // Start Position Fx=0,Audio=Audio Track/Clip#
|
||||
{63, 140}, // End Position Fx=1
|
||||
{64, 28}, // Current Position
|
||||
{65, 0}, //F7 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio,7=Random Audio,8=Triggered Audio
|
||||
{66, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30)
|
||||
{67, 28}, // Start Position Fx=0,Audio=Audio Track/Clip#
|
||||
{68,140}, // End Position Fx=1
|
||||
{69, 28}, // Current Position
|
||||
{70, 0}, //F8 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio,7=Random Audio,8=Triggered Audio
|
||||
{71, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30)
|
||||
{72, 28}, // Start Position Fx=0,Audio=Audio Track/Clip#
|
||||
{73, 140}, // End Position Fx=1
|
||||
{74, 28}, // Current Position
|
||||
{75, 0}, //F9 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio,7=Random Audio,8=Triggered Audio
|
||||
{76, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30)
|
||||
{77, 28}, // Start Position Fx=0,Audio=Audio Track/Clip#
|
||||
{78, 140}, // End Position Fx=1
|
||||
{79, 28}, // Current Position
|
||||
};
|
||||
|
||||
uint8_t FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
|
||||
void notifyCVResetFactoryDefault()
|
||||
{
|
||||
// Make FactoryDefaultCVIndex non-zero and equal to num CV's to be reset
|
||||
// to flag to the loop() function that a reset to Factory Defaults needs to be done
|
||||
FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
|
||||
};
|
||||
|
||||
// NOTE: NO PROGRAMMING ACK IS SET UP TO MAXIMAIZE
|
||||
// OUTPUT PINS FOR FUNCTIONS
|
||||
|
||||
void setup() //******************************************************
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Serial.begin(115200);
|
||||
#endif
|
||||
pinMode (busy_pin, INPUT); // MUST NOT Pull Up == 3.3V device output pin
|
||||
pinMode (AudioTriggerPin, INPUT_PULLUP);
|
||||
|
||||
mySerial.begin (9600);
|
||||
mp3_set_serial (mySerial); //set softwareSerial for DFPlayer-mini mp3 module
|
||||
mp3_reset ();
|
||||
delay(100);
|
||||
mp3_set_volume (18);
|
||||
delay(50);
|
||||
audio_on = 0;
|
||||
uint8_t cv_value;
|
||||
// initialize the digital pins as outputs
|
||||
for (int i=0; i < numfpins; i++) {
|
||||
pinMode(fpins[i], OUTPUT);
|
||||
digitalWrite(fpins[i], 0);
|
||||
}
|
||||
// Setup which External Interrupt, the Pin it's associated with that we're using
|
||||
Dcc.pin(0, 2, 0);
|
||||
// Call the main DCC Init function to enable the DCC Receiver
|
||||
Dcc.init( MAN_ID_DIY, 601, FLAGS_MY_ADDRESS_ONLY, 0 );
|
||||
delay(800);
|
||||
|
||||
#if defined(DECODER_LOADED)
|
||||
if ( Dcc.getCV(CV_DECODER_MASTER_RESET)== CV_DECODER_MASTER_RESET )
|
||||
#endif
|
||||
|
||||
{
|
||||
for (int j=0; j < FactoryDefaultCVIndex; j++ )
|
||||
Dcc.setCV( FactoryDefaultCVs[j].CV, FactoryDefaultCVs[j].Value);
|
||||
digitalWrite(fpins[14], 1);
|
||||
delay (1000);
|
||||
digitalWrite(fpins[14], 0);
|
||||
}
|
||||
for ( i=0; i < num_active_fpins; i++) {
|
||||
cv_value = Dcc.getCV( 30+(i*5)) ;
|
||||
#ifdef DEBUG
|
||||
Serial.print(" cv_value: ");
|
||||
Serial.println(cv_value, DEC) ;
|
||||
#endif
|
||||
switch ( cv_value ) {
|
||||
case 0: // LED on/off
|
||||
ftn_queue[i].inuse = 0;
|
||||
break;
|
||||
case 1: // LED Blink
|
||||
{
|
||||
ftn_queue[i].inuse = 0;
|
||||
ftn_queue[i].current_position = 0;
|
||||
ftn_queue[i].start_value = 0;
|
||||
ftn_queue[i].increment = int (char (Dcc.getCV( 31+(i*5))));
|
||||
digitalWrite(fpins[i], 0);
|
||||
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5))) ;
|
||||
}
|
||||
break;
|
||||
case 2: //servo
|
||||
{
|
||||
ftn_queue[i].current_position =int (Dcc.getCV( 34+(i*5)));
|
||||
ftn_queue[i].stop_value = int (Dcc.getCV( 33+(i*5)));
|
||||
ftn_queue[i].start_value = int (Dcc.getCV( 32+(i*5)));
|
||||
ftn_queue[i].increment = -int (char (Dcc.getCV( 31+(i*5))));
|
||||
// attaches servo on pin to the servo object
|
||||
servo[i].attach(fpins[i]);
|
||||
|
||||
#ifdef DEBUG
|
||||
Serial.print("InitServo ID= ");
|
||||
Serial.println(i, DEC) ;
|
||||
#endif
|
||||
servo[i].write(ftn_queue[i].start_value);
|
||||
for (t=0; t<servo_start_delay; t++)
|
||||
{SoftwareServo::refresh();delay(servo_init_delay);}
|
||||
ftn_queue[i].inuse = 0;
|
||||
servo[i].detach();
|
||||
}
|
||||
break;
|
||||
case 3: // DOUBLE ALTERNATING LED Blink
|
||||
{
|
||||
ftn_queue[i].inuse = 0;
|
||||
ftn_queue[i].current_position = 0;
|
||||
ftn_queue[i].start_value = 0;
|
||||
ftn_queue[i].increment = Dcc.getCV( 31+(i*5));
|
||||
digitalWrite(fpins[i], 0);
|
||||
digitalWrite(fpins[i+1], 0);
|
||||
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5)));
|
||||
}
|
||||
break;
|
||||
case 4: // Simple Pulsed Output based on saved Rate =10*Rate in Milliseconds
|
||||
{
|
||||
ftn_queue[i].inuse = 0;
|
||||
ftn_queue[i].current_position = 0;
|
||||
ftn_queue[i].increment = 10 * int (char (Dcc.getCV( 31+(i*5))));
|
||||
digitalWrite(fpins[i], 0);
|
||||
}
|
||||
break;
|
||||
case 5: // Fade On
|
||||
{
|
||||
ftn_queue[i].inuse = 0;
|
||||
ftn_queue[i].start_value = 0;
|
||||
ftn_queue[i].increment = int (char (Dcc.getCV( 31+(i*5))));
|
||||
digitalWrite(fpins[i], 0);
|
||||
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5))) *10.;
|
||||
}
|
||||
break;
|
||||
case 6: // Audio Track Play
|
||||
ftn_queue[i].inuse = 0;
|
||||
ftn_queue[i].increment = int (char (Dcc.getCV( 31+(i*5))));
|
||||
ftn_queue[i].start_value = int (Dcc.getCV( 32+(i*5)));
|
||||
break;
|
||||
case 7: // Audio Random Track Play
|
||||
ftn_queue[i].inuse = 0;
|
||||
ftn_queue[i].increment = int (char (Dcc.getCV( 31+(i*5))));
|
||||
ftn_queue[i].start_value = int (Dcc.getCV( 32+(i*5)));
|
||||
break;
|
||||
case 8: // Triggered Audio Track Play
|
||||
ftn_queue[i].inuse = 0;
|
||||
ftn_queue[i].increment = int (char (Dcc.getCV( 31+(i*5))));
|
||||
ftn_queue[i].start_value = int (Dcc.getCV( 32+(i*5)));
|
||||
break;
|
||||
case 9: // NEXT FEATURE to pin
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loop() //**********************************************************************
|
||||
{
|
||||
//MUST call the NmraDcc.process() method frequently
|
||||
// from the Arduino loop() function for correct library operation
|
||||
Dcc.process();
|
||||
SoftwareServo::refresh();
|
||||
delay(2);
|
||||
#ifdef DEBUG
|
||||
Serial.print("Motor1Speed= ");
|
||||
Serial.println(Motor1Speed, DEC) ;
|
||||
Serial.print("Motor2Speed= ");
|
||||
Serial.println(Motor2Speed, DEC) ;
|
||||
#endif
|
||||
if (Motor1Speed != 0) {
|
||||
if (Motor1ForwardDir == 0) gofwd1 (fwdtime, Motor1Speed<<4);
|
||||
else gobwd1 (bwdtime, Motor1Speed<<4);
|
||||
}
|
||||
else {
|
||||
digitalWrite(m2h, LOW); //Motor1 OFF
|
||||
digitalWrite(m2l, LOW); //Motor1 OFF
|
||||
}
|
||||
if (Motor2Speed != 0) {
|
||||
if (Motor2ForwardDir == 0) gofwd2 (fwdtime, Motor2Speed<<4);
|
||||
else gobwd2 (bwdtime, Motor2Speed<<4);
|
||||
}
|
||||
else {
|
||||
digitalWrite(m0h, LOW); //Motor1 OFF
|
||||
digitalWrite(m0l, LOW); //Motor1 OFF
|
||||
}
|
||||
//
|
||||
for (int i=0; i < num_active_fpins; i++) {
|
||||
if (ftn_queue[i].inuse==1) {
|
||||
|
||||
switch (Dcc.getCV( 30+(i*5))) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment;
|
||||
if (ftn_queue[i].current_position > ftn_queue[i].stop_value) {
|
||||
ftn_queue[i].start_value = ~ftn_queue[i].start_value;
|
||||
digitalWrite(fpins[i], ftn_queue[i].start_value);
|
||||
ftn_queue[i].current_position = 0;
|
||||
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5)));
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
if (servo_slow_counter++ > servo_slowdown)
|
||||
{
|
||||
ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment;
|
||||
if (ftn_queue[i].increment > 0) {
|
||||
if (ftn_queue[i].current_position > ftn_queue[i].stop_value) {
|
||||
ftn_queue[i].current_position = ftn_queue[i].stop_value;
|
||||
ftn_queue[i].inuse = 0;
|
||||
servo[i].detach();
|
||||
}
|
||||
}
|
||||
if (ftn_queue[i].increment < 0) {
|
||||
if (ftn_queue[i].current_position < ftn_queue[i].start_value) {
|
||||
ftn_queue[i].current_position = ftn_queue[i].start_value;
|
||||
ftn_queue[i].inuse = 0;
|
||||
servo[i].detach();
|
||||
}
|
||||
}
|
||||
servo[i].write(ftn_queue[i].current_position);
|
||||
servo_slow_counter = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment;
|
||||
if (ftn_queue[i].current_position > ftn_queue[i].stop_value) {
|
||||
ftn_queue[i].start_value = ~ftn_queue[i].start_value;
|
||||
digitalWrite(fpins[i], ftn_queue[i].start_value);
|
||||
digitalWrite(fpins[i]+1, ~ftn_queue[i].start_value);
|
||||
ftn_queue[i].current_position = 0;
|
||||
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5)));
|
||||
}
|
||||
i++;
|
||||
break;
|
||||
case 4: // Simple Pulsed Output based on saved Rate =10*Rate in Milliseconds
|
||||
{
|
||||
ftn_queue[i].inuse = 0;
|
||||
ftn_queue[i].current_position = 0;
|
||||
ftn_queue[i].increment = 10 * int (char (Dcc.getCV( 31+(i*5))));
|
||||
digitalWrite(fpins[i], 0);
|
||||
}
|
||||
break;
|
||||
case 5: // Fade On
|
||||
|
||||
break;
|
||||
case 6: // Audio Track Play
|
||||
if (digitalRead(busy_pin)== HIGH) {
|
||||
ftn_queue[i].inuse = 0;
|
||||
}
|
||||
break;
|
||||
case 7: // Audio Random Track/Clip Play
|
||||
if (digitalRead(busy_pin)== HIGH) {
|
||||
ftn_queue[i].inuse = 0;
|
||||
/* Insert the following code if you want continuous random play as long as F6 is selected
|
||||
if (ftn_queue[i].inuse ==1) { // Audio Off continue playing clips
|
||||
mp3_play (random(1,num_clips)); // play random clip
|
||||
delay(5);
|
||||
}
|
||||
*/
|
||||
}
|
||||
break;
|
||||
case 8: // Triggered Audio Track Play
|
||||
if (ftn_queue[i].inuse ==1) { // Function is set ON
|
||||
if ((digitalRead(AudioTriggerPin)== LOW)&&(digitalRead(busy_pin)== HIGH)) { // Trigger ON Audio Off
|
||||
mp3_set_volume (ftn_queue[i].increment);
|
||||
delay(8);
|
||||
mp3_play (ftn_queue[i].start_value); // play clip function
|
||||
delay(5);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 9: // NEXT FEATURE for the Future
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void gofwd1(int fcnt,int fcycle) {
|
||||
int icnt;
|
||||
int delta_tp,delta_tm;
|
||||
delta_tp = fcycle+loopdelay<<2;
|
||||
delta_tm = cyclewidth-fcycle-loopdelay;
|
||||
icnt = 0;
|
||||
while (icnt < fcnt)
|
||||
{
|
||||
digitalWrite(m2h, HIGH); //Motor1
|
||||
delayMicroseconds(delta_tp);
|
||||
digitalWrite(m2h, LOW); //Motor1
|
||||
delayMicroseconds(delta_tm);
|
||||
icnt++;
|
||||
}
|
||||
}
|
||||
void gobwd1(int bcnt,int bcycle) {
|
||||
int icnt;
|
||||
int delta_tp,delta_tm;
|
||||
delta_tp = bcycle+loopdelay<<2;
|
||||
delta_tm = cyclewidth-bcycle-loopdelay;
|
||||
icnt=0;
|
||||
while (icnt < bcnt)
|
||||
{
|
||||
digitalWrite(m2l, HIGH); //Motor1
|
||||
delayMicroseconds(delta_tp);
|
||||
digitalWrite(m2l, LOW); //Motor1
|
||||
delayMicroseconds(delta_tm);
|
||||
icnt++;
|
||||
}
|
||||
}
|
||||
void gofwd2(int fcnt,int fcycle) {
|
||||
int icnt;
|
||||
int delta_tp,delta_tm;
|
||||
delta_tp = fcycle+loopdelay<<2;
|
||||
delta_tm = cyclewidth-fcycle-loopdelay;
|
||||
icnt = 0;
|
||||
while (icnt < fcnt)
|
||||
{
|
||||
digitalWrite(m0h, HIGH); //Motor2
|
||||
delayMicroseconds(delta_tp);
|
||||
digitalWrite(m0h, LOW); //Motor2
|
||||
delayMicroseconds(delta_tm);
|
||||
icnt++;
|
||||
}
|
||||
}
|
||||
void gobwd2(int bcnt,int bcycle) {
|
||||
int icnt;
|
||||
int delta_tp,delta_tm;
|
||||
delta_tp = bcycle+loopdelay<<2;
|
||||
delta_tm = cyclewidth-bcycle-loopdelay;
|
||||
icnt=0;
|
||||
while (icnt < bcnt)
|
||||
{
|
||||
digitalWrite(m0l, HIGH); //Motor2
|
||||
delayMicroseconds(delta_tp);
|
||||
digitalWrite(m0l, LOW); //Motor2
|
||||
delayMicroseconds(delta_tm);
|
||||
icnt++;
|
||||
}
|
||||
}
|
||||
void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_DIRECTION ForwardDir, DCC_SPEED_STEPS SpeedSteps ) {
|
||||
if (Function13_value==1) {
|
||||
Motor1Speed = (Speed & 0x7f );
|
||||
if (Motor1Speed == 1) Motor1Speed=0;
|
||||
Motor1ForwardDir = ForwardDir;
|
||||
}
|
||||
if (Function14_value==1) {
|
||||
Motor2Speed = (Speed & 0x7f );
|
||||
if (Motor2Speed == 1) Motor2Speed=0;
|
||||
Motor2ForwardDir = ForwardDir;
|
||||
}
|
||||
}
|
||||
|
||||
void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) {
|
||||
#ifdef DEBUG
|
||||
Serial.print("Addr= ");
|
||||
Serial.println(Addr, DEC) ;
|
||||
Serial.print("FuncState= ");
|
||||
Serial.println(FuncState, DEC) ;
|
||||
#endif
|
||||
switch(FuncGrp)
|
||||
{
|
||||
case FN_0_4: //Function Group 1 F0 F4 F3 F2 F1
|
||||
exec_function( 0, FunctionPin0, (FuncState & FN_BIT_00)>>4 );
|
||||
exec_function( 1, FunctionPin1, (FuncState & FN_BIT_01));
|
||||
exec_function( 2, FunctionPin2, (FuncState & FN_BIT_02)>>1);
|
||||
exec_function( 3, FunctionPin3, (FuncState & FN_BIT_03)>>2 );
|
||||
exec_function( 4, FunctionPin4, (FuncState & FN_BIT_04)>>3 );
|
||||
break;
|
||||
|
||||
case FN_5_8: //Function Group 1 S FFFF == 1 F8 F7 F6 F5 & == 0 F12 F11 F10 F9 F8
|
||||
exec_function( 5, FunctionPin5, (FuncState & FN_BIT_05));
|
||||
exec_function( 6, FunctionPin6, (FuncState & FN_BIT_06)>>1 );
|
||||
exec_function( 7, FunctionPin7, (FuncState & FN_BIT_07)>>2 );
|
||||
exec_function( 8, FunctionPin8, (FuncState & FN_BIT_08)>>3 );
|
||||
break;
|
||||
|
||||
case FN_9_12:
|
||||
exec_function( 9, FunctionPin9, (FuncState & FN_BIT_09));
|
||||
// exec_function( 10, FunctionPin10, (FuncState & FN_BIT_10)>>1 );
|
||||
// exec_function( 11, FunctionPin11, (FuncState & FN_BIT_11)>>2 );
|
||||
// exec_function( 12, FunctionPin12, (FuncState & FN_BIT_12)>>3 );
|
||||
break;
|
||||
|
||||
case FN_13_20: //Function Group 2 FuncState == F20-F13 Function Control
|
||||
Function13_value = (FuncState & FN_BIT_13);
|
||||
Function14_value = (FuncState & FN_BIT_14)>>1;
|
||||
// exec_function( 15, FunctionPin15, (FuncState & FN_BIT_15)>>2 );
|
||||
// exec_function( 16, FunctionPin16, (FuncState & FN_BIT_16)>>3 );
|
||||
break;
|
||||
|
||||
case FN_21_28:
|
||||
break;
|
||||
}
|
||||
}
|
||||
void exec_function (int function, int pin, int FuncState) {
|
||||
switch ( Dcc.getCV( 30+(function*5)) ) { // Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
case 0: // On - Off LED
|
||||
digitalWrite (pin, FuncState);
|
||||
ftn_queue[function].inuse = 0;
|
||||
break;
|
||||
case 1: // Blinking LED
|
||||
if ((ftn_queue[function].inuse==0) && (FuncState==1)) {
|
||||
ftn_queue[function].inuse = 1;
|
||||
ftn_queue[function].start_value = 0;
|
||||
digitalWrite(pin, 0);
|
||||
ftn_queue[function].stop_value = int(Dcc.getCV( 33+(function*5)));
|
||||
} else {
|
||||
if ((ftn_queue[function].inuse==1) && (FuncState==0)) {
|
||||
ftn_queue[function].inuse = 0;
|
||||
digitalWrite(pin, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2: // Servo
|
||||
if (ftn_queue[function].inuse == 0) {
|
||||
ftn_queue[function].inuse = 1;
|
||||
servo[function].attach(pin);
|
||||
}
|
||||
if (FuncState==1) ftn_queue[function].increment = char ( Dcc.getCV( 31+(function*5)));
|
||||
else ftn_queue[function].increment = - char(Dcc.getCV( 31+(function*5)));
|
||||
if (FuncState==1) ftn_queue[function].stop_value = Dcc.getCV( 33+(function*5));
|
||||
else ftn_queue[function].stop_value = Dcc.getCV( 32+(function*5));
|
||||
break;
|
||||
case 3: // Blinking LED PAIR
|
||||
if ((ftn_queue[function].inuse==0) && (FuncState==1)) {
|
||||
ftn_queue[function].inuse = 1;
|
||||
ftn_queue[function].start_value = 0;
|
||||
digitalWrite(fpins[function], 0);
|
||||
digitalWrite(fpins[function+1], 1);
|
||||
ftn_queue[function].stop_value = int(Dcc.getCV( 33+(function*5)));
|
||||
} else {
|
||||
if (FuncState==0) {
|
||||
ftn_queue[function].inuse = 0;
|
||||
digitalWrite(fpins[function], 0);
|
||||
digitalWrite(fpins[function+1], 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4: // Pulse Output based on Rate*10 Milliseconds
|
||||
if ((ftn_queue[function].inuse==0) && (FuncState==1)) { //First Turn On Detected
|
||||
digitalWrite(fpins[function], 1);
|
||||
delay (10*ftn_queue[function].increment);
|
||||
digitalWrite(fpins[function], 0);
|
||||
ftn_queue[function].inuse = 1; //inuse set to 1 says we already pulsed
|
||||
} else
|
||||
if (FuncState==0) ftn_queue[function].inuse = 0;
|
||||
break;
|
||||
case 5: // Fade On
|
||||
#define fadedelay 24
|
||||
if ((ftn_queue[function].inuse==0) && (FuncState==1)) {
|
||||
ftn_queue[function].inuse = 1;
|
||||
for (t=0; t<ftn_queue[function].stop_value; t+=ftn_queue[function].increment) {
|
||||
digitalWrite( fpins[function], 1);
|
||||
delay(fadedelay*(t/(1.*ftn_queue[function].stop_value)));
|
||||
digitalWrite( fpins[function], 0);
|
||||
delay(fadedelay-(fadedelay*(t/(1.*ftn_queue[function].stop_value))));
|
||||
}
|
||||
digitalWrite( fpins[function], 1 );
|
||||
} else {
|
||||
if ((ftn_queue[function].inuse==1) && (FuncState==0)) {
|
||||
ftn_queue[function].inuse = 0;
|
||||
digitalWrite(fpins[function], 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 6: // Audio Play
|
||||
#ifdef DEBUG
|
||||
Serial.print("function= ");
|
||||
Serial.println(function, DEC) ;
|
||||
Serial.print("FuncState= ");
|
||||
Serial.println(FuncState, DEC) ;
|
||||
#endif
|
||||
if ((digitalRead(busy_pin)==HIGH)&&(FuncState!=0)) { // Audio Off = Not Playing
|
||||
ftn_queue[function].inuse = 1;
|
||||
mp3_set_volume (ftn_queue[function].increment);
|
||||
delay(8);
|
||||
mp3_play (ftn_queue[function].start_value); // play clip function
|
||||
delay(5);
|
||||
}
|
||||
if ((digitalRead(busy_pin)==LOW)&&(FuncState==0)) { // Audio On = Playing
|
||||
ftn_queue[function].inuse = 0; // Fuunction turned off so get ready to stop
|
||||
}
|
||||
break;
|
||||
case 7: // Random Audio Function
|
||||
#ifdef DEBUG
|
||||
Serial.print("function= ");
|
||||
Serial.println(function, DEC) ;
|
||||
Serial.print("FuncState= ");
|
||||
Serial.println(FuncState, DEC) ;
|
||||
#endif
|
||||
if ((digitalRead(busy_pin)==HIGH)&&(FuncState!=0)) { // Audio Off = Not Playing
|
||||
ftn_queue[function].inuse = 1;
|
||||
mp3_set_volume (ftn_queue[function].increment);
|
||||
delay(8);
|
||||
mp3_play (random(1,num_clips+1)); // play random clip
|
||||
delay(5);
|
||||
}
|
||||
if ((digitalRead(busy_pin)==LOW)&&(FuncState==0)) { // Audio On = Playing
|
||||
ftn_queue[function].inuse = 0; // Fuunction turned off so get ready to stop
|
||||
}
|
||||
break;
|
||||
case 8: // Triggered Audio Function
|
||||
ftn_queue[function].inuse = FuncState;
|
||||
break;
|
||||
case 9: // NEXT FEATURE for the Future
|
||||
break;
|
||||
default:
|
||||
ftn_queue[function].inuse = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
mp3_play (); //start play
|
||||
mp3_play (5); //play "mp3/0005.mp3"
|
||||
mp3_next (); //play next
|
||||
mp3_prev (); //play previous
|
||||
mp3_set_volume (uint16_t volume); //0~30
|
||||
mp3_set_EQ (); //0~5
|
||||
mp3_pause ();
|
||||
mp3_stop ();
|
||||
void mp3_get_state (); //send get state command
|
||||
void mp3_get_volume ();
|
||||
void mp3_get_u_sum ();
|
||||
void mp3_get_tf_sum ();
|
||||
void mp3_get_flash_sum ();
|
||||
void mp3_get_tf_current ();
|
||||
void mp3_get_u_current ();
|
||||
void mp3_get_flash_current ();
|
||||
void mp3_single_loop (boolean state); //set single loop
|
||||
void mp3_DAC (boolean state);
|
||||
void mp3_random_play ();
|
||||
*/
|
705
examples/SMA/Dec_2Mot_4LED_Aud_8Ftn/Dec_2Mot_4LED_Aud_8Ftn.ino
Normal file
705
examples/SMA/Dec_2Mot_4LED_Aud_8Ftn/Dec_2Mot_4LED_Aud_8Ftn.ino
Normal file
@@ -0,0 +1,705 @@
|
||||
// Production 2 Motor w/Audio 13 Function DCC Decoder Dec_2Mot_10LED_Audio_8Ftn.ino
|
||||
// Version 6.01a Geoff Bunza 2014,2015,2016,2017,2018
|
||||
// Now works with both short and long DCC Addesses
|
||||
// Improved motor control added
|
||||
// This decoder will control 2 motors and play audio clips by function:
|
||||
// F0=LED on pin 13, F1-F4 Controls playing specific audio tracks in the 3rd CV (start) at the volume in the 2nd CV (rate)
|
||||
// F5 Controls playing audio track in CV57 at the volume in CV56 ONLY when F5 is ON and Pin17/A3 is held low,
|
||||
// and plays continuously until F5 turns off or Pin17 trigger goes HIGH or open
|
||||
// F6 plays one track selected randomly off the memory card
|
||||
// F13 and F14 select each separate motor which will respond to speed and direction controls
|
||||
// F7-F8 control LEDs by default PINS 18 and 19
|
||||
|
||||
// NO LONGER REQUIRES modified software servo Lib
|
||||
// Software restructuring mods added from Alex Shepherd and Franz-Peter
|
||||
// With sincere thanks
|
||||
/*
|
||||
* Motor selection is via motor select Function 13 (Motor1) and Function 14 (Motor2)
|
||||
* Motor speed for each can only be changed if the corresponding Function is on
|
||||
* (F13 and/or F14). Motor speed is maintained if the corresponding Motor select function
|
||||
* is off. Thus, each motor can be controlled independently and run at different speeds.
|
||||
* F0 LED Pin 13
|
||||
* F1-F6 6 Functions Configures As Audio Play
|
||||
* F7-F9 3 Functions Configures As LEDs
|
||||
* F13 Motor1 Control Enable
|
||||
* F14 Motor2 Control Enable
|
||||
* Pro Mini Transmit-7 (TX) connected to DFPlayer Receive (RX)Pin 2 via 470 Ohm Resistor
|
||||
* Pro Mini Receive (RX) connected to DFPlayer Transmit (TX) Pin 3
|
||||
* Remember to connect +5V and GND to the DFPlayer too: DFPLAYER PINS 1 & 7,10 respectively
|
||||
* This is a “mobile/function” decoder that adds audio play to dual motor control and
|
||||
* LED functions. Audio tracks or clips are stored on a micro SD card for playing,
|
||||
* in a folder labeled mp3, with tracks named 0001.mp3, 0002.mp3, etc. F0 is configured
|
||||
* as an on/off LED function, F1-F5 play audio tracks 1-5 respectively.
|
||||
* F6 plays a random selection in random order from tracks 1-6.
|
||||
* F7-F9 control LEDs on Pro Mini Digital Pins 11-13.
|
||||
* Simple speed control is made via throttle speed setting for two motors. Motor selection
|
||||
* is via motor select Function 13 (Motor1) and Function 14 (Motor2). Motor speed for each
|
||||
* can only be changed if the corresponding Function is on (F13 and/or F14). Motor speed is
|
||||
* maintained if the corresponding motor select function is off. Thus, each motor can be
|
||||
* controlled independently and run at different speeds. The other functions are configurable
|
||||
* but are preset for LED on/off control.
|
||||
*/
|
||||
// ******** UNLESS YOU WANT ALL CV'S RESET UPON EVERY POWER UP
|
||||
// ******** AFTER THE INITIAL DECODER LOAD REMOVE THE "//" IN THE FOOLOWING LINE!!
|
||||
//#define DECODER_LOADED
|
||||
|
||||
// ******** EMOVE THE "//" IN THE FOOLOWING LINE TO SEND DEBUGGING
|
||||
// ******** INFO TO THE SERIAL MONITOR
|
||||
//#define DEBUG
|
||||
|
||||
#include <NmraDcc.h>
|
||||
#include <SoftwareServo.h>
|
||||
#include <SoftwareSerial.h>
|
||||
#include <DFPlayer_Mini_Mp3.h>
|
||||
SoftwareSerial mySerial(6,7); // PRO MINI RX, PRO MINI TX serial to DFPlayer
|
||||
|
||||
int busy_pin = 5; // DFPlayer Busy status pin
|
||||
#define num_clips 6 //number of sound tracks/clips on the Micro SD Memory Card
|
||||
int del_tim = 4000;
|
||||
int tctr, tctr2, i;
|
||||
byte audio_on = 0; // Audio ON sets this to 1; otherwise 0
|
||||
|
||||
SoftwareServo servo[10];
|
||||
#define servo_start_delay 50
|
||||
#define servo_init_delay 7
|
||||
#define servo_slowdown 4 //servo loop counter limit
|
||||
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
|
||||
|
||||
int Motor1Speed = 0;
|
||||
uint8_t Motor1ForwardDir = 1;
|
||||
int Motor2Speed = 0;
|
||||
uint8_t Motor2ForwardDir = 1;
|
||||
int kickstarton = 1400; //kick start cycle on time
|
||||
int kickstarttime = 5; //kick start duration on time
|
||||
int fwdon = 0;
|
||||
int fwdtime = 1;
|
||||
int bwdon = 0;
|
||||
int bwdtime = 1;
|
||||
int bwdshift = 0;
|
||||
int cyclewidth = 2047;
|
||||
int loopdelay =14;
|
||||
int m2h = 3; //R H Bridge //Motor1
|
||||
int m2l = 4; //B H Bridge //Motor1
|
||||
int m0h = 9; //R H Bridge //Motor2
|
||||
int m0l = 10; //B H Bridge //Motor2
|
||||
|
||||
int speedup = 112; //Right track time differntial
|
||||
int deltime = 1500;
|
||||
int tim_delay = 30;
|
||||
int numfpins = 14;
|
||||
int num_active_fpins = 10;
|
||||
byte fpins [] = {3,4,8,9,10,11,12,13,14,15,16,17,18,19};
|
||||
const int FunctionPin0 = 13;
|
||||
const int FunctionPin1 = 20; // Place holders ONLY
|
||||
const int FunctionPin2 = 20; // Place holders ONLY
|
||||
const int FunctionPin3 = 20; // Place holders ONLY
|
||||
const int FunctionPin4 = 20; //A0 Place holders ONLY
|
||||
|
||||
const int FunctionPin5 = 20; //A1 Place holders ONLY
|
||||
const int FunctionPin6 = 20; //A2 Place holders ONLY
|
||||
const int FunctionPin7 = 18; //A5 Place holders ONLY
|
||||
const int FunctionPin8 = 19; //A4 Place holders ONLY
|
||||
|
||||
const int AudioTriggerPin = 17; //A3 NOW USED AS Audio Trigger Pin INPUT_PULLUP
|
||||
|
||||
const int FunctionPin9 = 20; // Place holders ONLY
|
||||
const int FunctionPin10 = 20; // Place holders ONLY
|
||||
const int FunctionPin11 = 20; // Place holders ONLY
|
||||
const int FunctionPin12 = 20; // Place holders ONLY
|
||||
const int FunctionPin13 = 20; // Place holders ONLY
|
||||
const int FunctionPin14 = 20; // Place holders ONLY
|
||||
const int FunctionPin15 = 20; // Place holders ONLY
|
||||
const int FunctionPin16 = 20; // Place holders ONLY
|
||||
|
||||
int Function13_value = 0;
|
||||
int Function14_value = 0;
|
||||
|
||||
NmraDcc Dcc ;
|
||||
DCC_MSG Packet ;
|
||||
uint8_t CV_DECODER_MASTER_RESET = 120;
|
||||
int t; // temp
|
||||
|
||||
struct QUEUE
|
||||
{
|
||||
int inuse;
|
||||
int current_position;
|
||||
int increment;
|
||||
int stop_value;
|
||||
int start_value;
|
||||
};
|
||||
QUEUE *ftn_queue = new QUEUE[17];
|
||||
|
||||
struct CVPair
|
||||
{
|
||||
uint16_t CV;
|
||||
uint8_t Value;
|
||||
};
|
||||
|
||||
#define This_Decoder_Address 24
|
||||
|
||||
CVPair FactoryDefaultCVs [] =
|
||||
{
|
||||
{CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address&0x7F },
|
||||
|
||||
// These two CVs define the Long DCC Address
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, ((This_Decoder_Address>>8)&0x7F)+192 },
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF },
|
||||
|
||||
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
|
||||
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
|
||||
{CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
|
||||
|
||||
{CV_DECODER_MASTER_RESET, 0},
|
||||
{30, 0}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio
|
||||
{31, 10}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30)
|
||||
{32, 0}, //F0 Start Position F0=0,Audio=Audio Track/Clip#
|
||||
{33, 8}, //F0 End Position F0=1
|
||||
{34, 1}, //F0 Current Position
|
||||
{35, 6}, //F1 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio
|
||||
{36, 22}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30)
|
||||
{37, 1}, // Start Position Fx=0,Audio=Audio Track/Clip#
|
||||
{38, 8}, // End Position Fx=1
|
||||
{39, 1}, // Current Position
|
||||
{40, 6}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio
|
||||
{41, 22}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30)
|
||||
{42, 2}, // Start Position Fx=0,Audio=Audio Track/Clip#
|
||||
{43, 140}, // End Position Fx=1
|
||||
{44, 0}, // Current Position
|
||||
{45, 6}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio
|
||||
{46, 22}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30)
|
||||
{47, 3}, // Start Position Fx=0,Audio=Audio Track/Clip#
|
||||
{48, 140}, // End Position Fx=1
|
||||
{49, 0}, // Current Position
|
||||
{50, 6}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio
|
||||
{51, 22}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30)
|
||||
{52, 4}, // Start Position Fx=0,Audio=Audio Track/Clip#
|
||||
{53, 140}, // End Position Fx=1
|
||||
{54, 0}, // Current Position
|
||||
{55, 6}, //F5 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio
|
||||
{56, 22}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30)
|
||||
{57, 5}, // Start Position Fx=0,Audio=Audio Track/Clip#
|
||||
{58, 140}, // End Position Fx=1
|
||||
{59, 28}, // Current Position
|
||||
{60, 7}, //F6 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio
|
||||
{61, 22}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30)
|
||||
{62, 6}, // Start Position Fx=0,Audio=Audio Track/Clip#
|
||||
{63, 140}, // End Position Fx=1
|
||||
{64, 28}, // Current Position
|
||||
{65, 0}, //F7 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio
|
||||
{66, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30)
|
||||
{67, 28}, // Start Position Fx=0,Audio=Audio Track/Clip#
|
||||
{68,140}, // End Position Fx=1
|
||||
{69, 28}, // Current Position
|
||||
{70, 0}, //F8 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio
|
||||
{71, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30)
|
||||
{72, 28}, // Start Position Fx=0,Audio=Audio Track/Clip#
|
||||
{73, 140}, // End Position Fx=1
|
||||
{74, 28}, // Current Position
|
||||
{75, 0}, //F9 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade,6=Audio
|
||||
{76, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate,Audio=Volume(0-30)
|
||||
{77, 28}, // Start Position Fx=0,Audio=Audio Track/Clip#
|
||||
{78, 140}, // End Position Fx=1
|
||||
{79, 28}, // Current Position
|
||||
};
|
||||
|
||||
uint8_t FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
|
||||
void notifyCVResetFactoryDefault()
|
||||
{
|
||||
// Make FactoryDefaultCVIndex non-zero and equal to num CV's to be reset
|
||||
// to flag to the loop() function that a reset to Factory Defaults needs to be done
|
||||
FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
|
||||
};
|
||||
|
||||
// NOTE: NO PROGRAMMING ACK IS SET UP TO MAXIMAIZE
|
||||
// OUTPUT PINS FOR FUNCTIONS
|
||||
|
||||
void setup() //******************************************************
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Serial.begin(115200);
|
||||
#endif
|
||||
pinMode (busy_pin, INPUT);
|
||||
mySerial.begin (9600);
|
||||
mp3_set_serial (mySerial); //set softwareSerial for DFPlayer-mini mp3 module
|
||||
mp3_reset ();
|
||||
delay(100);
|
||||
mp3_set_volume (18);
|
||||
delay(50);
|
||||
audio_on = 0;
|
||||
uint8_t cv_value;
|
||||
// initialize the digital pins as outputs
|
||||
for (int i=0; i < numfpins; i++) {
|
||||
pinMode(fpins[i], OUTPUT);
|
||||
digitalWrite(fpins[i], 0);
|
||||
}
|
||||
// Setup which External Interrupt, the Pin it's associated with that we're using
|
||||
Dcc.pin(0, 2, 0);
|
||||
// Call the main DCC Init function to enable the DCC Receiver
|
||||
Dcc.init( MAN_ID_DIY, 601, FLAGS_MY_ADDRESS_ONLY, 0 );
|
||||
delay(800);
|
||||
|
||||
#if defined(DECODER_LOADED)
|
||||
if ( Dcc.getCV(CV_DECODER_MASTER_RESET)== CV_DECODER_MASTER_RESET )
|
||||
#endif
|
||||
|
||||
{
|
||||
for (int j=0; j < FactoryDefaultCVIndex; j++ )
|
||||
Dcc.setCV( FactoryDefaultCVs[j].CV, FactoryDefaultCVs[j].Value);
|
||||
digitalWrite(fpins[14], 1);
|
||||
delay (1000);
|
||||
digitalWrite(fpins[14], 0);
|
||||
}
|
||||
for ( i=0; i < num_active_fpins; i++) {
|
||||
cv_value = Dcc.getCV( 30+(i*5)) ;
|
||||
#ifdef DEBUG
|
||||
Serial.print(" cv_value: ");
|
||||
Serial.println(cv_value, DEC) ;
|
||||
#endif
|
||||
switch ( cv_value ) {
|
||||
case 0: // LED on/off
|
||||
ftn_queue[i].inuse = 0;
|
||||
break;
|
||||
case 1: // LED Blink
|
||||
{
|
||||
ftn_queue[i].inuse = 0;
|
||||
ftn_queue[i].current_position = 0;
|
||||
ftn_queue[i].start_value = 0;
|
||||
ftn_queue[i].increment = int (char (Dcc.getCV( 31+(i*5))));
|
||||
digitalWrite(fpins[i], 0);
|
||||
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5))) ;
|
||||
}
|
||||
break;
|
||||
case 2: //servo
|
||||
{
|
||||
ftn_queue[i].current_position =int (Dcc.getCV( 34+(i*5)));
|
||||
ftn_queue[i].stop_value = int (Dcc.getCV( 33+(i*5)));
|
||||
ftn_queue[i].start_value = int (Dcc.getCV( 32+(i*5)));
|
||||
ftn_queue[i].increment = -int (char (Dcc.getCV( 31+(i*5))));
|
||||
// attaches servo on pin to the servo object
|
||||
servo[i].attach(fpins[i]);
|
||||
|
||||
#ifdef DEBUG
|
||||
Serial.print("InitServo ID= ");
|
||||
Serial.println(i, DEC) ;
|
||||
#endif
|
||||
servo[i].write(ftn_queue[i].start_value);
|
||||
for (t=0; t<servo_start_delay; t++)
|
||||
{SoftwareServo::refresh();delay(servo_init_delay);}
|
||||
ftn_queue[i].inuse = 0;
|
||||
servo[i].detach();
|
||||
}
|
||||
break;
|
||||
case 3: // DOUBLE ALTERNATING LED Blink
|
||||
{
|
||||
ftn_queue[i].inuse = 0;
|
||||
ftn_queue[i].current_position = 0;
|
||||
ftn_queue[i].start_value = 0;
|
||||
ftn_queue[i].increment = Dcc.getCV( 31+(i*5));
|
||||
digitalWrite(fpins[i], 0);
|
||||
digitalWrite(fpins[i+1], 0);
|
||||
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5)));
|
||||
}
|
||||
break;
|
||||
case 4: // Simple Pulsed Output based on saved Rate =10*Rate in Milliseconds
|
||||
{
|
||||
ftn_queue[i].inuse = 0;
|
||||
ftn_queue[i].current_position = 0;
|
||||
ftn_queue[i].increment = 10 * int (char (Dcc.getCV( 31+(i*5))));
|
||||
digitalWrite(fpins[i], 0);
|
||||
}
|
||||
break;
|
||||
case 5: // Fade On
|
||||
{
|
||||
ftn_queue[i].inuse = 0;
|
||||
ftn_queue[i].start_value = 0;
|
||||
ftn_queue[i].increment = int (char (Dcc.getCV( 31+(i*5))));
|
||||
digitalWrite(fpins[i], 0);
|
||||
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5))) *10.;
|
||||
}
|
||||
break;
|
||||
case 6: // Audio Track Play
|
||||
ftn_queue[i].inuse = 0;
|
||||
ftn_queue[i].increment = int (char (Dcc.getCV( 31+(i*5))));
|
||||
ftn_queue[i].start_value = int (Dcc.getCV( 32+(i*5)));
|
||||
audio_on = 0;
|
||||
break;
|
||||
case 7: // Audio Random Track Play
|
||||
ftn_queue[i].inuse = 0;
|
||||
ftn_queue[i].increment = int (char (Dcc.getCV( 31+(i*5))));
|
||||
ftn_queue[i].start_value = int (Dcc.getCV( 32+(i*5)));
|
||||
audio_on = 0;
|
||||
break;
|
||||
case 8: // NEXT FEATURE to pin
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loop() //**********************************************************************
|
||||
{
|
||||
//MUST call the NmraDcc.process() method frequently
|
||||
// from the Arduino loop() function for correct library operation
|
||||
Dcc.process();
|
||||
SoftwareServo::refresh();
|
||||
delay(2);
|
||||
#ifdef DEBUG
|
||||
Serial.print("Motor1Speed= ");
|
||||
Serial.println(Motor1Speed, DEC) ;
|
||||
Serial.print("Motor2Speed= ");
|
||||
Serial.println(Motor2Speed, DEC) ;
|
||||
#endif
|
||||
if (Motor1Speed != 0) {
|
||||
if (Motor1ForwardDir == 0) gofwd1 (fwdtime, Motor1Speed<<4);
|
||||
else gobwd1 (bwdtime, Motor1Speed<<4);
|
||||
}
|
||||
else {
|
||||
digitalWrite(m2h, LOW); //Motor1 OFF
|
||||
digitalWrite(m2l, LOW); //Motor1 OFF
|
||||
}
|
||||
if (Motor2Speed != 0) {
|
||||
if (Motor2ForwardDir == 0) gofwd2 (fwdtime, Motor2Speed<<4);
|
||||
else gobwd2 (bwdtime, Motor2Speed<<4);
|
||||
}
|
||||
else {
|
||||
digitalWrite(m0h, LOW); //Motor1 OFF
|
||||
digitalWrite(m0l, LOW); //Motor1 OFF
|
||||
}
|
||||
//
|
||||
for (int i=0; i < num_active_fpins; i++) {
|
||||
if (ftn_queue[i].inuse==1) {
|
||||
|
||||
switch (Dcc.getCV( 30+(i*5))) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment;
|
||||
if (ftn_queue[i].current_position > ftn_queue[i].stop_value) {
|
||||
ftn_queue[i].start_value = ~ftn_queue[i].start_value;
|
||||
digitalWrite(fpins[i], ftn_queue[i].start_value);
|
||||
ftn_queue[i].current_position = 0;
|
||||
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5)));
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
if (servo_slow_counter++ > servo_slowdown)
|
||||
{
|
||||
ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment;
|
||||
if (ftn_queue[i].increment > 0) {
|
||||
if (ftn_queue[i].current_position > ftn_queue[i].stop_value) {
|
||||
ftn_queue[i].current_position = ftn_queue[i].stop_value;
|
||||
ftn_queue[i].inuse = 0;
|
||||
servo[i].detach();
|
||||
}
|
||||
}
|
||||
if (ftn_queue[i].increment < 0) {
|
||||
if (ftn_queue[i].current_position < ftn_queue[i].start_value) {
|
||||
ftn_queue[i].current_position = ftn_queue[i].start_value;
|
||||
ftn_queue[i].inuse = 0;
|
||||
servo[i].detach();
|
||||
}
|
||||
}
|
||||
servo[i].write(ftn_queue[i].current_position);
|
||||
servo_slow_counter = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment;
|
||||
if (ftn_queue[i].current_position > ftn_queue[i].stop_value) {
|
||||
ftn_queue[i].start_value = ~ftn_queue[i].start_value;
|
||||
digitalWrite(fpins[i], ftn_queue[i].start_value);
|
||||
digitalWrite(fpins[i]+1, ~ftn_queue[i].start_value);
|
||||
ftn_queue[i].current_position = 0;
|
||||
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5)));
|
||||
}
|
||||
i++;
|
||||
break;
|
||||
case 4: // Simple Pulsed Output based on saved Rate =10*Rate in Milliseconds
|
||||
{
|
||||
ftn_queue[i].inuse = 0;
|
||||
ftn_queue[i].current_position = 0;
|
||||
ftn_queue[i].increment = 10 * int (char (Dcc.getCV( 31+(i*5))));
|
||||
digitalWrite(fpins[i], 0);
|
||||
}
|
||||
break;
|
||||
case 5: // Fade On
|
||||
|
||||
break;
|
||||
case 6: // Audio Track Play
|
||||
if (digitalRead(busy_pin)== HIGH) {
|
||||
ftn_queue[i].inuse = 0;
|
||||
}
|
||||
break;
|
||||
case 7: // Audio Random Track/Clip Play
|
||||
if (digitalRead(busy_pin)== HIGH) {
|
||||
ftn_queue[i].inuse = 0;
|
||||
/* Insert the following code if you want continuous random play as long as F6 is selected
|
||||
if (ftn_queue[i].inuse ==1) { // Audio Off continue playing clips
|
||||
mp3_play (random(1,num_clips)); // play random clip
|
||||
delay(5);
|
||||
}
|
||||
*/
|
||||
}
|
||||
break;
|
||||
case 8: // NEXT FEATURE to pin
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void gofwd1(int fcnt,int fcycle) {
|
||||
int icnt;
|
||||
int delta_tp,delta_tm;
|
||||
delta_tp = fcycle+loopdelay<<2;
|
||||
delta_tm = cyclewidth-fcycle-loopdelay;
|
||||
icnt = 0;
|
||||
while (icnt < fcnt)
|
||||
{
|
||||
digitalWrite(m2h, HIGH); //Motor1
|
||||
delayMicroseconds(delta_tp);
|
||||
digitalWrite(m2h, LOW); //Motor1
|
||||
delayMicroseconds(delta_tm);
|
||||
icnt++;
|
||||
}
|
||||
}
|
||||
void gobwd1(int bcnt,int bcycle) {
|
||||
int icnt;
|
||||
int delta_tp,delta_tm;
|
||||
delta_tp = bcycle+loopdelay<<2;
|
||||
delta_tm = cyclewidth-bcycle-loopdelay;
|
||||
icnt=0;
|
||||
while (icnt < bcnt)
|
||||
{
|
||||
digitalWrite(m2l, HIGH); //Motor1
|
||||
delayMicroseconds(delta_tp);
|
||||
digitalWrite(m2l, LOW); //Motor1
|
||||
delayMicroseconds(delta_tm);
|
||||
icnt++;
|
||||
}
|
||||
}
|
||||
void gofwd2(int fcnt,int fcycle) {
|
||||
int icnt;
|
||||
int delta_tp,delta_tm;
|
||||
delta_tp = fcycle+loopdelay<<2;
|
||||
delta_tm = cyclewidth-fcycle-loopdelay;
|
||||
icnt = 0;
|
||||
while (icnt < fcnt)
|
||||
{
|
||||
digitalWrite(m0h, HIGH); //Motor2
|
||||
delayMicroseconds(delta_tp);
|
||||
digitalWrite(m0h, LOW); //Motor2
|
||||
delayMicroseconds(delta_tm);
|
||||
icnt++;
|
||||
}
|
||||
}
|
||||
void gobwd2(int bcnt,int bcycle) {
|
||||
int icnt;
|
||||
int delta_tp,delta_tm;
|
||||
delta_tp = bcycle+loopdelay<<2;
|
||||
delta_tm = cyclewidth-bcycle-loopdelay;
|
||||
icnt=0;
|
||||
while (icnt < bcnt)
|
||||
{
|
||||
digitalWrite(m0l, HIGH); //Motor2
|
||||
delayMicroseconds(delta_tp);
|
||||
digitalWrite(m0l, LOW); //Motor2
|
||||
delayMicroseconds(delta_tm);
|
||||
icnt++;
|
||||
}
|
||||
}
|
||||
void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_DIRECTION ForwardDir, DCC_SPEED_STEPS SpeedSteps ) {
|
||||
if (Function13_value==1) {
|
||||
Motor1Speed = (Speed & 0x7f );
|
||||
if (Motor1Speed == 1) Motor1Speed=0;
|
||||
Motor1ForwardDir = ForwardDir;
|
||||
}
|
||||
if (Function14_value==1) {
|
||||
Motor2Speed = (Speed & 0x7f );
|
||||
if (Motor2Speed == 1) Motor2Speed=0;
|
||||
Motor2ForwardDir = ForwardDir;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) {
|
||||
#ifdef DEBUG
|
||||
Serial.print("Addr= ");
|
||||
Serial.println(Addr, DEC) ;
|
||||
Serial.print("FuncState= ");
|
||||
Serial.println(FuncState, DEC) ;
|
||||
#endif
|
||||
switch(FuncGrp)
|
||||
{
|
||||
case FN_0_4: //Function Group 1 F0 F4 F3 F2 F1
|
||||
exec_function( 0, FunctionPin0, (FuncState & FN_BIT_00)>>4 );
|
||||
exec_function( 1, FunctionPin1, (FuncState & FN_BIT_01));
|
||||
exec_function( 2, FunctionPin2, (FuncState & FN_BIT_02)>>1);
|
||||
exec_function( 3, FunctionPin3, (FuncState & FN_BIT_03)>>2 );
|
||||
exec_function( 4, FunctionPin4, (FuncState & FN_BIT_04)>>3 );
|
||||
break;
|
||||
|
||||
case FN_5_8: //Function Group 1 S FFFF == 1 F8 F7 F6 F5 & == 0 F12 F11 F10 F9 F8
|
||||
exec_function( 5, FunctionPin5, (FuncState & FN_BIT_05));
|
||||
exec_function( 6, FunctionPin6, (FuncState & FN_BIT_06)>>1 );
|
||||
exec_function( 7, FunctionPin7, (FuncState & FN_BIT_07)>>2 );
|
||||
exec_function( 8, FunctionPin8, (FuncState & FN_BIT_08)>>3 );
|
||||
break;
|
||||
|
||||
case FN_9_12:
|
||||
exec_function( 9, FunctionPin9, (FuncState & FN_BIT_09));
|
||||
// exec_function( 10, FunctionPin10, (FuncState & FN_BIT_10)>>1 );
|
||||
// exec_function( 11, FunctionPin11, (FuncState & FN_BIT_11)>>2 );
|
||||
// exec_function( 12, FunctionPin12, (FuncState & FN_BIT_12)>>3 );
|
||||
break;
|
||||
|
||||
case FN_13_20: //Function Group 2 FuncState == F20-F13 Function Control
|
||||
Function13_value = (FuncState & FN_BIT_13);
|
||||
Function14_value = (FuncState & FN_BIT_14)>>1;
|
||||
// exec_function( 15, FunctionPin15, (FuncState & FN_BIT_15)>>2 );
|
||||
// exec_function( 16, FunctionPin16, (FuncState & FN_BIT_16)>>3 );
|
||||
break;
|
||||
|
||||
case FN_21_28:
|
||||
break;
|
||||
}
|
||||
}
|
||||
void exec_function (int function, int pin, int FuncState) {
|
||||
switch ( Dcc.getCV( 30+(function*5)) ) { // Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
case 0: // On - Off LED
|
||||
digitalWrite (pin, FuncState);
|
||||
ftn_queue[function].inuse = 0;
|
||||
break;
|
||||
case 1: // Blinking LED
|
||||
if ((ftn_queue[function].inuse==0) && (FuncState==1)) {
|
||||
ftn_queue[function].inuse = 1;
|
||||
ftn_queue[function].start_value = 0;
|
||||
digitalWrite(pin, 0);
|
||||
ftn_queue[function].stop_value = int(Dcc.getCV( 33+(function*5)));
|
||||
} else {
|
||||
if ((ftn_queue[function].inuse==1) && (FuncState==0)) {
|
||||
ftn_queue[function].inuse = 0;
|
||||
digitalWrite(pin, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2: // Servo
|
||||
if (ftn_queue[function].inuse == 0) {
|
||||
ftn_queue[function].inuse = 1;
|
||||
servo[function].attach(pin);
|
||||
}
|
||||
if (FuncState==1) ftn_queue[function].increment = char ( Dcc.getCV( 31+(function*5)));
|
||||
else ftn_queue[function].increment = - char(Dcc.getCV( 31+(function*5)));
|
||||
if (FuncState==1) ftn_queue[function].stop_value = Dcc.getCV( 33+(function*5));
|
||||
else ftn_queue[function].stop_value = Dcc.getCV( 32+(function*5));
|
||||
break;
|
||||
case 3: // Blinking LED PAIR
|
||||
if ((ftn_queue[function].inuse==0) && (FuncState==1)) {
|
||||
ftn_queue[function].inuse = 1;
|
||||
ftn_queue[function].start_value = 0;
|
||||
digitalWrite(fpins[function], 0);
|
||||
digitalWrite(fpins[function+1], 1);
|
||||
ftn_queue[function].stop_value = int(Dcc.getCV( 33+(function*5)));
|
||||
} else {
|
||||
if (FuncState==0) {
|
||||
ftn_queue[function].inuse = 0;
|
||||
digitalWrite(fpins[function], 0);
|
||||
digitalWrite(fpins[function+1], 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4: // Pulse Output based on Rate*10 Milliseconds
|
||||
if ((ftn_queue[function].inuse==0) && (FuncState==1)) { //First Turn On Detected
|
||||
digitalWrite(fpins[function], 1);
|
||||
delay (10*ftn_queue[function].increment);
|
||||
digitalWrite(fpins[function], 0);
|
||||
ftn_queue[function].inuse = 1; //inuse set to 1 says we already pulsed
|
||||
} else
|
||||
if (FuncState==0) ftn_queue[function].inuse = 0;
|
||||
break;
|
||||
case 5: // Fade On
|
||||
#define fadedelay 24
|
||||
if ((ftn_queue[function].inuse==0) && (FuncState==1)) {
|
||||
ftn_queue[function].inuse = 1;
|
||||
for (t=0; t<ftn_queue[function].stop_value; t+=ftn_queue[function].increment) {
|
||||
digitalWrite( fpins[function], 1);
|
||||
delay(fadedelay*(t/(1.*ftn_queue[function].stop_value)));
|
||||
digitalWrite( fpins[function], 0);
|
||||
delay(fadedelay-(fadedelay*(t/(1.*ftn_queue[function].stop_value))));
|
||||
}
|
||||
digitalWrite( fpins[function], 1 );
|
||||
} else {
|
||||
if ((ftn_queue[function].inuse==1) && (FuncState==0)) {
|
||||
ftn_queue[function].inuse = 0;
|
||||
digitalWrite(fpins[function], 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 6: // Audio Play
|
||||
#ifdef DEBUG
|
||||
Serial.print("function= ");
|
||||
Serial.println(function, DEC) ;
|
||||
Serial.print("FuncState= ");
|
||||
Serial.println(FuncState, DEC) ;
|
||||
#endif
|
||||
if ((digitalRead(busy_pin)==HIGH)&&(FuncState!=0)) { // Audio Off = Not Playing
|
||||
ftn_queue[function].inuse = 1;
|
||||
mp3_set_volume (ftn_queue[function].increment);
|
||||
delay(8);
|
||||
mp3_play (ftn_queue[function].start_value); // play clip function
|
||||
delay(5);
|
||||
}
|
||||
if ((digitalRead(busy_pin)==LOW)&&(FuncState==0)) { // Audio On = Playing
|
||||
ftn_queue[function].inuse = 0; // Fuunction turned off so get ready to stop
|
||||
}
|
||||
break;
|
||||
case 7: // Random Audio Function
|
||||
#ifdef DEBUG
|
||||
Serial.print("function= ");
|
||||
Serial.println(function, DEC) ;
|
||||
Serial.print("FuncState= ");
|
||||
Serial.println(FuncState, DEC) ;
|
||||
#endif
|
||||
if ((digitalRead(busy_pin)==HIGH)&&(FuncState!=0)) { // Audio Off = Not Playing
|
||||
ftn_queue[function].inuse = 1;
|
||||
mp3_set_volume (ftn_queue[function].increment);
|
||||
delay(8);
|
||||
mp3_play (random(1,num_clips+1)); // play random clip
|
||||
delay(5);
|
||||
}
|
||||
if ((digitalRead(busy_pin)==LOW)&&(FuncState==0)) { // Audio On = Playing
|
||||
ftn_queue[function].inuse = 0; // Fuunction turned off so get ready to stop
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ftn_queue[function].inuse = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
mp3_play (); //start play
|
||||
mp3_play (5); //play "mp3/0005.mp3"
|
||||
mp3_next (); //play next
|
||||
mp3_prev (); //play previous
|
||||
mp3_set_volume (uint16_t volume); //0~30
|
||||
mp3_set_EQ (); //0~5
|
||||
mp3_pause ();
|
||||
mp3_stop ();
|
||||
void mp3_get_state (); //send get state command
|
||||
void mp3_get_volume ();
|
||||
void mp3_get_u_sum ();
|
||||
void mp3_get_tf_sum ();
|
||||
void mp3_get_flash_sum ();
|
||||
void mp3_get_tf_current ();
|
||||
void mp3_get_u_current ();
|
||||
void mp3_get_flash_current ();
|
||||
void mp3_single_loop (boolean state); //set single loop
|
||||
void mp3_DAC (boolean state);
|
||||
void mp3_random_play ();
|
||||
*/
|
42
examples/SMA/Dec_7Serv_10LED_6Ftn/Dec_7Serv_10LED_6Ftn.ino
Executable file → Normal file
42
examples/SMA/Dec_7Serv_10LED_6Ftn/Dec_7Serv_10LED_6Ftn.ino
Executable file → Normal file
@@ -1,5 +1,5 @@
|
||||
// Production 17 Function DCC Decoder
|
||||
// Version 5.4 Geoff Bunza 2014,2015,2016
|
||||
// Production 17 Function DCC Decoder Dec_7Serv_10LED_6Ftn.ino
|
||||
// Version 6.01 Geoff Bunza 2014,2015,2016
|
||||
// NO LONGER REQUIRES modified software servo Lib
|
||||
// Software restructuring mods added from Alex Shepherd and Franz-Peter
|
||||
// With sincere thanks
|
||||
@@ -10,8 +10,7 @@
|
||||
|
||||
// ******** EMOVE THE "//" IN THE FOOLOWING LINE TO SEND DEBUGGING
|
||||
// ******** INFO TO THE SERIAL MONITOR
|
||||
//#define DEBUG
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#include <NmraDcc.h>
|
||||
#include <SoftwareServo.h>
|
||||
@@ -19,7 +18,7 @@
|
||||
SoftwareServo servo[17];
|
||||
#define servo_start_delay 50
|
||||
#define servo_init_delay 7
|
||||
#define servo_slowdown 3 //servo loop counter limit
|
||||
#define servo_slowdown 12 //servo loop counter limit
|
||||
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
|
||||
|
||||
int tim_delay = 500;
|
||||
@@ -49,7 +48,6 @@ NmraDcc Dcc ;
|
||||
DCC_MSG Packet ;
|
||||
uint8_t CV_DECODER_MASTER_RESET = 120;
|
||||
int t; // temp
|
||||
#define This_Decoder_Address 24
|
||||
struct QUEUE
|
||||
{
|
||||
int inuse;
|
||||
@@ -65,12 +63,22 @@ struct CVPair
|
||||
uint16_t CV;
|
||||
uint8_t Value;
|
||||
};
|
||||
|
||||
#define This_Decoder_Address 24
|
||||
|
||||
CVPair FactoryDefaultCVs [] =
|
||||
{
|
||||
{CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address},
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
|
||||
{CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address&0x7F },
|
||||
|
||||
// These two CVs define the Long DCC Address
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, ((This_Decoder_Address>>8)&0x7F)+192 },
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF },
|
||||
|
||||
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
|
||||
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
|
||||
{CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
|
||||
|
||||
{CV_DECODER_MASTER_RESET, 0},
|
||||
{30, 2}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
@@ -130,28 +138,28 @@ CVPair FactoryDefaultCVs [] =
|
||||
{85, 1}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{86, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{87, 1}, // Start Position Fx=0
|
||||
{88, 5}, // End Position Fx=1
|
||||
{88, 50}, // End Position Fx=1
|
||||
{89, 1}, // Current Position
|
||||
{90, 1}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{91, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{92, 1}, // Start Position Fx=0
|
||||
{93, 20}, // End Position Fx=1
|
||||
{93, 100}, // End Position Fx=1
|
||||
{94, 1}, // Current Position
|
||||
{95, 3}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{96, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{97, 1}, // Start Position Fx=0
|
||||
{98, 35}, // End Position Fx=1
|
||||
{98, 200}, // End Position Fx=1
|
||||
{99, 2}, // Current Position
|
||||
{100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{101, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{102, 1}, // Start Position Fx=0
|
||||
{103, 4}, // End Position Fx=1
|
||||
{103, 200}, // End Position Fx=1
|
||||
{104, 1}, // Current Position
|
||||
{105, 3}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{106, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{107, 1}, // Start Position Fx=0
|
||||
{108, 60}, // End Position Fx=1
|
||||
{109, 20}, // Current Position
|
||||
{109, 1}, // Current Position
|
||||
{110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{111, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{112, 1}, // Start Position Fx=0
|
||||
@@ -199,7 +207,7 @@ void setup() //******************************************************
|
||||
// Setup which External Interrupt, the Pin it's associated with that we're using
|
||||
Dcc.pin(0, 2, 0);
|
||||
// Call the main DCC Init function to enable the DCC Receiver
|
||||
Dcc.init( MAN_ID_DIY, 100, FLAGS_MY_ADDRESS_ONLY, 0 );
|
||||
Dcc.init( MAN_ID_DIY, 601, FLAGS_MY_ADDRESS_ONLY, 0 );
|
||||
delay(800);
|
||||
|
||||
#if defined(DECODER_LOADED)
|
||||
@@ -295,7 +303,7 @@ void loop() //****************************************************************
|
||||
// from the Arduino loop() function for correct library operation
|
||||
Dcc.process();
|
||||
SoftwareServo::refresh();
|
||||
delay(4);
|
||||
delay(3);
|
||||
for (int i=0; i < numfpins; i++) {
|
||||
if (ftn_queue[i].inuse==1) {
|
||||
|
||||
|
32
examples/SMA/Dec_Dir_and_Fade/Dec_Dir_and_Fade.ino
Executable file → Normal file
32
examples/SMA/Dec_Dir_and_Fade/Dec_Dir_and_Fade.ino
Executable file → Normal file
@@ -1,6 +1,8 @@
|
||||
// Production 17 Function DCC Decoder
|
||||
// Version 5.4 Geoff Bunza 2014,2015,2016
|
||||
// LED control is dependent on direction of travel
|
||||
// Production 17 Function DCC Decoder Dec_Dir_and_Fade.ino
|
||||
// Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
|
||||
// Now works with both short and long DCC Addesses
|
||||
// LED control is dependent on direction of travel and Fade can be added
|
||||
|
||||
// ******** UNLESS YOU WANT ALL CV'S RESET UPON EVERY POWER UP
|
||||
// ******** AFTER THE INITIAL DECODER LOAD REMOVE THE "//" IN THE FOOLOWING LINE!!
|
||||
//#define DECODER_LOADED
|
||||
@@ -11,11 +13,12 @@ int tim_delay = 500;
|
||||
#define numleds 17
|
||||
byte ledpins [] = {3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; //Defines all possible LED pins
|
||||
|
||||
// IMPORTANT:
|
||||
// The following list defines how each of the 17 function pins operate:
|
||||
// a 0 allows for normal On/Off control with fade on and fade off
|
||||
// a 1 allows for normal control when the decoder sees a forward speed setting, reverse turns the LED off
|
||||
// a 2 allows for normal control when the decoder sees a reverse speed setting, forward turns the LED off
|
||||
byte led_direction [] = {0,1,2,0,1,1,1,1,2,2,2,2,0,0,0,0,0}; //0=On/Off, 1=On Forward, 2=On Reverse
|
||||
byte led_direction [] = {0,1,2,0,1,1,1,1,2,2,2,1,1,1,2,0,0}; //0=On/Off, 1=On Forward, 2=On Reverse
|
||||
|
||||
boolean led_last_state [] = {false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false}; //last state of led
|
||||
boolean Last_Function_State[] = {false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false}; //These hold the last Fx assignments
|
||||
@@ -46,18 +49,27 @@ NmraDcc Dcc ;
|
||||
DCC_MSG Packet ;
|
||||
uint8_t CV_DECODER_MASTER_RESET = 120;
|
||||
|
||||
#define This_Decoder_Address 24
|
||||
struct CVPair
|
||||
{
|
||||
uint16_t CV;
|
||||
uint8_t Value;
|
||||
};
|
||||
|
||||
#define This_Decoder_Address 24
|
||||
|
||||
CVPair FactoryDefaultCVs [] =
|
||||
{
|
||||
{CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address},
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
|
||||
{CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address&0x7F },
|
||||
|
||||
// These two CVs define the Long DCC Address
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, ((This_Decoder_Address>>8)&0x7F)+192 },
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF },
|
||||
|
||||
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
|
||||
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
|
||||
{CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
|
||||
|
||||
{CV_DECODER_MASTER_RESET, 0},
|
||||
};
|
||||
uint8_t FactoryDefaultCVIndex = 0;
|
||||
@@ -98,7 +110,7 @@ void setup()
|
||||
// Setup which External Interrupt, the Pin it's associated with that we're using and enable the Pull-Up
|
||||
Dcc.pin(0, 2, 0);
|
||||
// Call the main DCC Init function to enable the DCC Receiver
|
||||
Dcc.init( MAN_ID_DIY, 100, FLAGS_MY_ADDRESS_ONLY, 0 );
|
||||
Dcc.init( MAN_ID_DIY, 601, FLAGS_MY_ADDRESS_ONLY, 0 );
|
||||
}
|
||||
void loop()
|
||||
{
|
||||
|
49
examples/SMA/Dec_SMA12_LED_Groups/Dec_SMA12_LED_Groups.ino
Executable file → Normal file
49
examples/SMA/Dec_SMA12_LED_Groups/Dec_SMA12_LED_Groups.ino
Executable file → Normal file
@@ -1,5 +1,7 @@
|
||||
// Production 17 Function DCC Decoder
|
||||
// Version 5.4 Geoff Bunza 2014,2015,2016
|
||||
// Production 17 Function DCC Decoder Dec_SMA12_LED_Groups.ino
|
||||
// Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
|
||||
// Now works with both short and long DCC Addesses
|
||||
|
||||
// NO LONGER REQUIRES modified software servo Lib
|
||||
// Software restructuring mods added from Alex Shepherd and Franz-Peter
|
||||
// With sincere thanks
|
||||
@@ -13,8 +15,8 @@
|
||||
//#define DEBUG
|
||||
|
||||
#include <NmraDcc.h>
|
||||
|
||||
int tim_delay = 500;
|
||||
|
||||
#define numleds 17
|
||||
byte ledpins [] = {3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
|
||||
byte FPins_Assigned [12][5] = { // This array defines the pins controlled by each function
|
||||
@@ -52,14 +54,17 @@ const int FunctionPin1 = 4;
|
||||
const int FunctionPin2 = 5;
|
||||
const int FunctionPin3 = 6;
|
||||
const int FunctionPin4 = 7;
|
||||
|
||||
const int FunctionPin5 = 8;
|
||||
const int FunctionPin6 = 9;
|
||||
const int FunctionPin7 = 10;
|
||||
const int FunctionPin8 = 11;
|
||||
|
||||
const int FunctionPin9 = 12;
|
||||
const int FunctionPin10 = 13;
|
||||
const int FunctionPin11 = 14; //A0
|
||||
const int FunctionPin12 = 15; //A1
|
||||
|
||||
const int FunctionPin13 = 16; //A2
|
||||
const int FunctionPin14 = 17; //A3
|
||||
const int FunctionPin15 = 18; //A4
|
||||
@@ -67,24 +72,31 @@ const int FunctionPin16 = 19; //A5
|
||||
NmraDcc Dcc ;
|
||||
DCC_MSG Packet ;
|
||||
uint8_t CV_DECODER_MASTER_RESET = 120;
|
||||
|
||||
#define This_Decoder_Address 24
|
||||
|
||||
struct CVPair
|
||||
{
|
||||
uint16_t CV;
|
||||
uint8_t Value;
|
||||
};
|
||||
|
||||
#define This_Decoder_Address 24
|
||||
|
||||
CVPair FactoryDefaultCVs [] =
|
||||
{
|
||||
{CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address},
|
||||
{CV_ACCESSORY_DECODER_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, 0},
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, 0},
|
||||
{CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address&0x7F },
|
||||
|
||||
// These two CVs define the Long DCC Address
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, ((This_Decoder_Address>>8)&0x7F)+192 },
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF },
|
||||
|
||||
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
|
||||
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
|
||||
{CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
|
||||
|
||||
{CV_DECODER_MASTER_RESET, 0},
|
||||
};
|
||||
|
||||
uint8_t FactoryDefaultCVIndex = 0;
|
||||
uint8_t FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
|
||||
void notifyCVResetFactoryDefault()
|
||||
{
|
||||
// Make FactoryDefaultCVIndex non-zero and equal to num CV's to be reset
|
||||
@@ -112,7 +124,11 @@ void setup()
|
||||
delay (tim_delay/10);
|
||||
}
|
||||
delay( tim_delay);
|
||||
|
||||
// Setup which External Interrupt, the Pin it's associated with that we're using and enable the Pull-Up
|
||||
Dcc.pin(0, 2, 0);
|
||||
// Call the main DCC Init function to enable the DCC Receiver
|
||||
Dcc.init( MAN_ID_DIY, 601, FLAGS_MY_ADDRESS_ONLY, 0 );
|
||||
delay(800);
|
||||
#if defined(DECODER_LOADED)
|
||||
if ( Dcc.getCV(CV_DECODER_MASTER_RESET)== CV_DECODER_MASTER_RESET )
|
||||
#endif
|
||||
@@ -123,18 +139,12 @@ void setup()
|
||||
delay (1000);
|
||||
digitalWrite(ledpins[14], 0);
|
||||
}
|
||||
// Setup which External Interrupt, the Pin it's associated with that we're using and enable the Pull-Up
|
||||
Dcc.pin(0, 2, 0);
|
||||
// Call the main DCC Init function to enable the DCC Receiver
|
||||
Dcc.init( MAN_ID_DIY, 100, FLAGS_MY_ADDRESS_ONLY, 0 );
|
||||
delay(800);
|
||||
}
|
||||
void loop()
|
||||
{
|
||||
// You MUST call the NmraDcc.process() method frequently from the Arduino loop() function for correct library operation
|
||||
Dcc.process();
|
||||
}
|
||||
|
||||
void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) {
|
||||
int f_index;
|
||||
switch (FuncGrp) {
|
||||
@@ -145,20 +155,17 @@ switch (FuncGrp) {
|
||||
exec_function( 3, (FuncState & FN_BIT_03)>>2 );
|
||||
exec_function( 4, (FuncState & FN_BIT_04)>>3 );
|
||||
break;
|
||||
|
||||
case FN_5_8: //Function Group 1 S FFFF == 1 F8 F7 F6 F5 & == 0 F12 F11 F10 F9 F8
|
||||
exec_function( 5, (FuncState & FN_BIT_05));
|
||||
exec_function( 6, (FuncState & FN_BIT_06)>>1 );
|
||||
exec_function( 7, (FuncState & FN_BIT_07)>>2 );
|
||||
exec_function( 8, (FuncState & FN_BIT_08)>>3 );
|
||||
break;
|
||||
|
||||
case FN_9_12:
|
||||
exec_function( 9, (FuncState & FN_BIT_09));
|
||||
exec_function( 10,(FuncState & FN_BIT_10)>>1 );
|
||||
exec_function( 11,(FuncState & FN_BIT_11)>>2 );
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
void exec_function (int f_index, int FuncState) {
|
||||
|
508
examples/SMA/Dec_Stepper_6Ftn/Dec_Stepper_6Ftn.ino
Normal file
508
examples/SMA/Dec_Stepper_6Ftn/Dec_Stepper_6Ftn.ino
Normal file
@@ -0,0 +1,508 @@
|
||||
// Production Stepper Drive DCC Decoder Dec_Stepper_6Ftn.ino
|
||||
// Version 6.01 Geoff Bunza 2014,2015,2016,2017,2018
|
||||
// Now works with both short and long DCC Addesses
|
||||
|
||||
// NO LONGER REQUIRES modified software servo Lib
|
||||
// Software restructuring mods added from Alex Shepherd and Franz-Peter
|
||||
// With sincere thanks
|
||||
/*
|
||||
* Stepper Motor Drive (4 Pins Bi dirrectional) uses the 2 Motor controls MOT1 and MOT2
|
||||
* F0 LED Pin 5
|
||||
* This is a “mobile/function” decoder that controls a single four wire stepper motor
|
||||
* (5/12 Volt) via throttle speed setting and a multiplier which can be set in CV121.
|
||||
* Stepper speed is pre-set in the sketch but can be changed. The library also supports
|
||||
* setting acceleration/deceleration for the stepper. The other functions are configurable
|
||||
* but are preset for LED on/off control. No servo motor control is available.
|
||||
* Steppers whose coils need less than 500 ma can be accommodated. Each coil of the
|
||||
* stepper attaches to MOT1 and MOT2. You may have to reverse the connections of one
|
||||
* or the other until you get the connections right. The number of steps moved is set
|
||||
* by the speed setting multiplied by the contents of CV 121.
|
||||
* Every Off to On activation of F2 will move the stepper the specified number of steps,
|
||||
* in the direction set by the DCC speed direction.
|
||||
*/
|
||||
// ******** UNLESS YOU WANT ALL CV'S RESET UPON EVERY POWER UP
|
||||
// ******** AFTER THE INITIAL DECODER LOAD REMOVE THE "//" IN THE FOOLOWING LINE!!
|
||||
//#define DECODER_LOADED
|
||||
|
||||
// ******** EMOVE THE "//" IN THE FOOLOWING LINE TO SEND DEBUGGING
|
||||
// ******** INFO TO THE SERIAL MONITOR
|
||||
//#define DEBUG
|
||||
|
||||
#include <NmraDcc.h>
|
||||
#include <AccelStepper.h>
|
||||
AccelStepper stepper(AccelStepper::FULL4WIRE, 3, 4, 9, 10);
|
||||
|
||||
int servo_slow_counter = 0; //servo loop counter to slowdown servo transit
|
||||
long Motor1Speed = 0;
|
||||
uint8_t Motor1ForwardDir = 1;
|
||||
uint8_t Motor1MaxSpeed = 127;
|
||||
long Motor2Speed = 0;
|
||||
uint8_t Motor2ForwardDir = 1;
|
||||
uint8_t Motor2MaxSpeed = 127;
|
||||
int kickstarton = 1400; //kick start cycle on time
|
||||
int kickstarttime = 5; //kick start duration on time
|
||||
int fwdon = 0;
|
||||
int fwdtime = 1;
|
||||
int bwdon = 0;
|
||||
int bwdtime = 1;
|
||||
int bwdshift = 0;
|
||||
int cyclewidth = 2047;
|
||||
int m2h = 3; //R H Bridge //Motor1
|
||||
int m2l = 4; //B H Bridge //Motor1
|
||||
int m0h = 9; //R H Bridge //Motor2
|
||||
int m0l = 10; //B H Bridge //Motor2
|
||||
|
||||
int speedup = 112; //Right track time differntial
|
||||
int deltime = 1500;
|
||||
int tim_delay = 100;
|
||||
int numfpins = 17;
|
||||
int num_active_fpins = 13;
|
||||
byte fpins [] = {3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
|
||||
const int FunctionPin0 = 5;
|
||||
const int FunctionPin1 = 6;
|
||||
const int FunctionPin2 = 7;
|
||||
const int FunctionPin3 = 8;
|
||||
const int FunctionPin4 = 11;
|
||||
|
||||
const int FunctionPin5 = 12;
|
||||
const int FunctionPin6 = 13;
|
||||
const int FunctionPin7 = 14; //A0
|
||||
const int FunctionPin8 = 15; //A1
|
||||
|
||||
const int FunctionPin9 = 16; //A2
|
||||
const int FunctionPin10 = 17; //A3
|
||||
const int FunctionPin11 = 18; //A4
|
||||
const int FunctionPin12 = 19; //A5
|
||||
|
||||
byte Function2_value = 0;
|
||||
int Function13_value = 0;
|
||||
int Function14_value = 0;
|
||||
|
||||
NmraDcc Dcc ;
|
||||
DCC_MSG Packet ;
|
||||
uint8_t CV_DECODER_MASTER_RESET = 120;
|
||||
uint8_t Motor_Multiplier = 121;
|
||||
int t; // temp
|
||||
|
||||
struct QUEUE
|
||||
{
|
||||
int inuse;
|
||||
int current_position;
|
||||
int increment;
|
||||
int stop_value;
|
||||
int start_value;
|
||||
};
|
||||
QUEUE *ftn_queue = new QUEUE[16];
|
||||
struct CVPair
|
||||
{
|
||||
uint16_t CV;
|
||||
uint8_t Value;
|
||||
};
|
||||
|
||||
#define This_Decoder_Address 24
|
||||
|
||||
CVPair FactoryDefaultCVs [] =
|
||||
{
|
||||
{CV_MULTIFUNCTION_PRIMARY_ADDRESS, This_Decoder_Address&0x7F },
|
||||
|
||||
// These two CVs define the Long DCC Address
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_MSB, ((This_Decoder_Address>>8)&0x7F)+192 },
|
||||
{CV_MULTIFUNCTION_EXTENDED_ADDRESS_LSB, This_Decoder_Address&0xFF },
|
||||
|
||||
// ONLY uncomment 1 CV_29_CONFIG line below as approprate DEFAULT IS SHORT ADDRESS
|
||||
// {CV_29_CONFIG, 0}, // Short Address 14 Speed Steps
|
||||
{CV_29_CONFIG, CV29_F0_LOCATION}, // Short Address 28/128 Speed Steps
|
||||
// {CV_29_CONFIG, CV29_EXT_ADDRESSING | CV29_F0_LOCATION}, // Long Address 28/128 Speed Steps
|
||||
|
||||
{CV_DECODER_MASTER_RESET, 0}, // CV 120
|
||||
{Motor_Multiplier, 10}, // CV 121
|
||||
{30, 0}, //F0 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{31, 1}, //F0 Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{32, 0}, //F0 Start Position F0=0
|
||||
{33, 8}, //F0 End Position F0=1
|
||||
{34, 1}, //F0 Current Position
|
||||
{35, 0}, //F1 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{36, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{37, 0}, // Start Position Fx=0
|
||||
{38, 8}, // End Position Fx=1
|
||||
{39, 1}, // Current Position
|
||||
{40, 0}, //F2 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{41, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{42, 28}, // Start Position Fx=0
|
||||
{43, 140}, // End Position Fx=1
|
||||
{44, 0}, // Current Position
|
||||
{45, 0}, //F3 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{46, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{47, 28}, // Start Position Fx=0
|
||||
{48, 140}, // End Position Fx=1
|
||||
{49, 0}, // Current Position
|
||||
{50, 0}, //F4 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{51, 10}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{52, 28}, // Start Position Fx=0
|
||||
{53, 140}, // End Position Fx=1
|
||||
{54, 0}, // Current Position
|
||||
{55, 0}, //F5 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{56, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{57, 28}, // Start Position Fx=0
|
||||
{58, 140}, // End Position Fx=1
|
||||
{59, 28}, // Current Position
|
||||
{60, 0}, //F6 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{61, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{62, 1}, // Start Position Fx=0
|
||||
{63, 255}, // End Position Fx=1
|
||||
{64, 28}, // Current Position
|
||||
{65, 0}, //F7 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{66, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{67, 28}, // Start Position Fx=0
|
||||
{68,140}, // End Position Fx=1
|
||||
{69, 28}, // Current Position
|
||||
{70, 0}, //F8 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{71, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{72, 28}, // Start Position Fx=0
|
||||
{73, 140}, // End Position Fx=1
|
||||
{74, 28}, // Current Position
|
||||
{75, 0}, //F9 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{76, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{77, 28}, // Start Position Fx=0
|
||||
{78, 140}, // End Position Fx=1
|
||||
{79, 28}, // Current Position
|
||||
{80, 0}, //F10 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{81, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{82, 1}, // Start Position Fx=0
|
||||
{83, 5}, // End Position Fx=1
|
||||
{84, 1}, // Current Position
|
||||
{85, 0}, //F11 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{86, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{87, 1}, // Start Position Fx=0
|
||||
{88, 5}, // End Position Fx=1
|
||||
{89, 1}, // Current Position
|
||||
{90, 0}, //F12 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{91, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{92, 1}, // Start Position Fx=0
|
||||
{93, 10}, // End Position Fx=1
|
||||
{94, 1}, // Current Position
|
||||
{95, 0}, //F13 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{96, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{97, 1}, // Start Position Fx=0
|
||||
{98, 6}, // End Position Fx=1
|
||||
{99, 1}, // Current Position
|
||||
{100, 0}, //F14 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{101, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{102, 1}, // Start Position Fx=0
|
||||
{103, 6}, // End Position Fx=1
|
||||
{104, 1}, // Current Position
|
||||
{105, 0}, //F15 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{106, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{107, 1}, // Start Position Fx=0
|
||||
{108, 10}, // End Position Fx=1
|
||||
{109, 1}, // Current Position
|
||||
{110, 0}, //F16 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{111, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{112, 1}, // Start Position Fx=0
|
||||
{113, 10}, // End Position Fx=1
|
||||
{114, 1}, // Current Position
|
||||
//FUTURE USE
|
||||
{115, 0}, //F17 Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
{116, 1}, // Rate Blink=Eate,PWM=Rate,Servo=Rate
|
||||
{117, 28}, // Start Position Fx=0
|
||||
{118, 50}, // End Position Fx=1
|
||||
{119, 28}, // Current Position
|
||||
};
|
||||
|
||||
uint8_t FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
|
||||
void notifyCVResetFactoryDefault()
|
||||
{
|
||||
// Make FactoryDefaultCVIndex non-zero and equal to num CV's to be reset
|
||||
// to flag to the loop() function that a reset to Factory Defaults needs to be done
|
||||
FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs)/sizeof(CVPair);
|
||||
};
|
||||
|
||||
// NOTE: NO PROGRAMMING ACK IS SET UP TO MAXIMAIZE
|
||||
// OUTPUT PINS FOR FUNCTIONS
|
||||
|
||||
void setup() //******************************************************
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Serial.begin(115200);
|
||||
#endif
|
||||
int i;
|
||||
uint8_t cv_value;
|
||||
// initialize the digital pins as outputs
|
||||
for (int i=0; i < numfpins; i++) {
|
||||
pinMode(fpins[i], OUTPUT);
|
||||
digitalWrite(fpins[i], 0);
|
||||
}
|
||||
|
||||
// Setup which External Interrupt, the Pin it's associated with that we're using
|
||||
Dcc.pin(0, 2, 0);
|
||||
// Call the main DCC Init function to enable the DCC Receiver
|
||||
Dcc.init( MAN_ID_DIY, 601, FLAGS_MY_ADDRESS_ONLY, 0 );
|
||||
delay(800);
|
||||
|
||||
#if defined(DECODER_LOADED)
|
||||
if ( Dcc.getCV(CV_DECODER_MASTER_RESET)== CV_DECODER_MASTER_RESET )
|
||||
#endif
|
||||
{
|
||||
for (int j=0; j < FactoryDefaultCVIndex; j++ )
|
||||
Dcc.setCV( FactoryDefaultCVs[j].CV, FactoryDefaultCVs[j].Value);
|
||||
digitalWrite(fpins[14], 1);
|
||||
delay (1000);
|
||||
digitalWrite(fpins[14], 0);
|
||||
}
|
||||
for ( i=0; i < num_active_fpins; i++) {
|
||||
cv_value = Dcc.getCV( 30+(i*5)) ;
|
||||
#ifdef DEBUG
|
||||
Serial.print(" cv_value: ");
|
||||
Serial.println(cv_value, DEC) ;
|
||||
#endif
|
||||
stepper.setMaxSpeed(100.0);
|
||||
stepper.setAcceleration(50.0);
|
||||
stepper.moveTo(1);
|
||||
switch ( cv_value ) {
|
||||
case 0: // LED on/off
|
||||
ftn_queue[i].inuse = 0;
|
||||
break;
|
||||
case 1: // LED Blink
|
||||
{
|
||||
ftn_queue[i].inuse = 0;
|
||||
ftn_queue[i].current_position = 0;
|
||||
ftn_queue[i].start_value = 0;
|
||||
ftn_queue[i].increment = int (char (Dcc.getCV( 31+(i*5))));
|
||||
digitalWrite(fpins[i], 0);
|
||||
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5))) ;
|
||||
}
|
||||
break;
|
||||
case 2: //servo NOT AVAILABLE WITH THIS DECODER - STEPPER ONLY
|
||||
break;
|
||||
case 3: // DOUBLE ALTERNATING LED Blink
|
||||
{
|
||||
ftn_queue[i].inuse = 0;
|
||||
ftn_queue[i].current_position = 0;
|
||||
ftn_queue[i].start_value = 0;
|
||||
ftn_queue[i].increment = Dcc.getCV( 31+(i*5));
|
||||
digitalWrite(fpins[i], 0);
|
||||
digitalWrite(fpins[i+1], 0);
|
||||
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5)));
|
||||
}
|
||||
break;
|
||||
case 4: // Simple Pulsed Output based on saved Rate =10*Rate in Milliseconds
|
||||
{
|
||||
ftn_queue[i].inuse = 0;
|
||||
ftn_queue[i].current_position = 0;
|
||||
ftn_queue[i].increment = 10 * int (char (Dcc.getCV( 31+(i*5))));
|
||||
digitalWrite(fpins[i], 0);
|
||||
}
|
||||
break;
|
||||
case 5: // Fade On
|
||||
{
|
||||
ftn_queue[i].inuse = 0;
|
||||
ftn_queue[i].start_value = 0;
|
||||
ftn_queue[i].increment = int (char (Dcc.getCV( 31+(i*5))));
|
||||
digitalWrite(fpins[i], 0);
|
||||
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5))) *10.;
|
||||
}
|
||||
break;
|
||||
case 6: // NEXT FEATURE to pin
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
void loop() //**********************************************************************
|
||||
{
|
||||
//MUST call the NmraDcc.process() method frequently
|
||||
// from the Arduino loop() function for correct library operation
|
||||
Dcc.process();
|
||||
delay(2);
|
||||
stepper.run();
|
||||
//*************************Normal Function Processing follows
|
||||
for (int i=0; i < num_active_fpins; i++) {
|
||||
if (ftn_queue[i].inuse==1) {
|
||||
switch (Dcc.getCV( 30+(i*5))) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment;
|
||||
if (ftn_queue[i].current_position > ftn_queue[i].stop_value) {
|
||||
ftn_queue[i].start_value = ~ftn_queue[i].start_value;
|
||||
digitalWrite(fpins[i], ftn_queue[i].start_value);
|
||||
ftn_queue[i].current_position = 0;
|
||||
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5)));
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
ftn_queue[i].current_position = ftn_queue[i].current_position + ftn_queue[i].increment;
|
||||
if (ftn_queue[i].current_position > ftn_queue[i].stop_value) {
|
||||
ftn_queue[i].start_value = ~ftn_queue[i].start_value;
|
||||
digitalWrite(fpins[i], ftn_queue[i].start_value);
|
||||
digitalWrite(fpins[i]+1, ~ftn_queue[i].start_value);
|
||||
ftn_queue[i].current_position = 0;
|
||||
ftn_queue[i].stop_value = int(Dcc.getCV( 33+(i*5)));
|
||||
}
|
||||
i++;
|
||||
break;
|
||||
case 4: // Simple Pulsed Output based on saved Rate =10*Rate in Milliseconds
|
||||
{
|
||||
ftn_queue[i].inuse = 0;
|
||||
ftn_queue[i].current_position = 0;
|
||||
ftn_queue[i].increment = 10 * int (char (Dcc.getCV( 31+(i*5))));
|
||||
digitalWrite(fpins[i], 0);
|
||||
}
|
||||
break;
|
||||
case 5: // Fade On
|
||||
|
||||
break;
|
||||
case 6: // NEXT FEATURE to pin
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void notifyDccSpeed( uint16_t Addr, DCC_ADDR_TYPE AddrType, uint8_t Speed, DCC_DIRECTION ForwardDir, DCC_SPEED_STEPS SpeedSteps ) {
|
||||
//if (Function13_value==1) {
|
||||
Motor1Speed = Speed * Dcc.getCV( Motor_Multiplier);
|
||||
//Motor1ForwardDir = ForwardDir & 1;
|
||||
if (ForwardDir == DCC_DIR_REV) Motor1Speed = -Motor1Speed;;
|
||||
//}
|
||||
}
|
||||
void notifyDccFunc( uint16_t Addr, DCC_ADDR_TYPE AddrType, FN_GROUP FuncGrp, uint8_t FuncState) {
|
||||
if (FuncGrp==FN_0_4 && ((FuncState & FN_BIT_02)>>1) == 1) {
|
||||
if (Function2_value == 0) {
|
||||
Function2_value=1;
|
||||
stepper.move(Motor1Speed);
|
||||
return;
|
||||
}
|
||||
} else if (FuncGrp==FN_0_4 && ((FuncState & FN_BIT_02)>>1) == 0) {
|
||||
Function2_value = 0;
|
||||
return;
|
||||
}
|
||||
switch(FuncGrp)
|
||||
{
|
||||
case FN_0_4: //Function Group 1 F0 F4 F3 F2 F1
|
||||
exec_function( 0, FunctionPin0, (FuncState & FN_BIT_00)>>4 );
|
||||
exec_function( 1, FunctionPin1, (FuncState & FN_BIT_01));
|
||||
//exec_function( 2, FunctionPin2, (FuncState & FN_BIT_02)>>1);
|
||||
exec_function( 3, FunctionPin3, (FuncState & FN_BIT_03)>>2 );
|
||||
exec_function( 4, FunctionPin4, (FuncState & FN_BIT_04)>>3 );
|
||||
break;
|
||||
|
||||
case FN_5_8: //Function Group 1 S FFFF == 1 F8 F7 F6 F5 & == 0 F12 F11 F10 F9 F8
|
||||
exec_function( 5, FunctionPin5, (FuncState & FN_BIT_05));
|
||||
exec_function( 6, FunctionPin6, (FuncState & FN_BIT_06)>>1 );
|
||||
exec_function( 7, FunctionPin7, (FuncState & FN_BIT_07)>>2 );
|
||||
exec_function( 8, FunctionPin8, (FuncState & FN_BIT_08)>>3 );
|
||||
break;
|
||||
|
||||
case FN_9_12:
|
||||
exec_function( 9, FunctionPin9, (FuncState & FN_BIT_09));
|
||||
exec_function( 10, FunctionPin10, (FuncState & FN_BIT_10)>>1 );
|
||||
exec_function( 11, FunctionPin11, (FuncState & FN_BIT_11)>>2 );
|
||||
exec_function( 12, FunctionPin12, (FuncState & FN_BIT_12)>>3 );
|
||||
break;
|
||||
|
||||
case FN_13_20: //Function Group 2 FuncState == F20-F13 Function Control
|
||||
// Function13_value = (FuncState & FN_BIT_13);
|
||||
// Function14_value = (FuncState & FN_BIT_14)>>1;
|
||||
// exec_function( 15, FunctionPin15, (FuncState & FN_BIT_15)>>2 );
|
||||
// exec_function( 16, FunctionPin16, (FuncState & FN_BIT_16)>>3 );
|
||||
break;
|
||||
|
||||
case FN_21_28:
|
||||
break;
|
||||
}
|
||||
}
|
||||
void exec_function (int function, int pin, int FuncState) {
|
||||
#ifdef DEBUG
|
||||
Serial.print(" function: ");
|
||||
Serial.println(function, DEC) ;
|
||||
Serial.print(" pin: ");
|
||||
Serial.println(pin, DEC) ;
|
||||
Serial.print(" FuncState: ");
|
||||
Serial.println(FuncState, DEC) ;
|
||||
Serial.print(" Dcc.getCV( 30+(function*5)): ");
|
||||
Serial.println(Dcc.getCV( 30+(function*5)), DEC) ;
|
||||
#endif
|
||||
if (function!=2)
|
||||
switch ( Dcc.getCV( 30+(function*5)) ) { // Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=Pulsed,5=fade
|
||||
case 0: // On - Off LED
|
||||
digitalWrite (pin, FuncState);
|
||||
#ifdef DEBUG
|
||||
Serial.print(" Dcc.getCV( 30+(function*5)): ");
|
||||
Serial.println(Dcc.getCV( 30+(function*5)), DEC) ;
|
||||
Serial.print(" pin: ");
|
||||
Serial.println(pin, DEC) ;
|
||||
Serial.print(" FuncState: ");
|
||||
Serial.println(FuncState, DEC) ;
|
||||
#endif
|
||||
ftn_queue[function].inuse = 0;
|
||||
break;
|
||||
case 1: // Blinking LED
|
||||
if ((ftn_queue[function].inuse==0) && (FuncState==1)) {
|
||||
ftn_queue[function].inuse = 1;
|
||||
ftn_queue[function].start_value = 0;
|
||||
digitalWrite(pin, 0);
|
||||
ftn_queue[function].stop_value = int(Dcc.getCV( 33+(function*5)));
|
||||
} else {
|
||||
if ((ftn_queue[function].inuse==1) && (FuncState==0)) {
|
||||
ftn_queue[function].inuse = 0;
|
||||
digitalWrite(pin, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2: // Servo
|
||||
break;
|
||||
case 3: // Blinking LED PAIR
|
||||
if ((ftn_queue[function].inuse==0) && (FuncState==1)) {
|
||||
ftn_queue[function].inuse = 1;
|
||||
ftn_queue[function].start_value = 0;
|
||||
digitalWrite(fpins[function], 0);
|
||||
digitalWrite(fpins[function+1], 1);
|
||||
ftn_queue[function].stop_value = int(Dcc.getCV( 33+(function*5)));
|
||||
} else {
|
||||
if (FuncState==0) {
|
||||
ftn_queue[function].inuse = 0;
|
||||
digitalWrite(fpins[function], 0);
|
||||
digitalWrite(fpins[function+1], 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4: // Pulse Output based on Rate*10 Milliseconds
|
||||
if ((ftn_queue[function].inuse==0) && (FuncState==1)) { //First Turn On Detected
|
||||
digitalWrite(fpins[function], 1);
|
||||
delay (10*ftn_queue[function].increment);
|
||||
digitalWrite(fpins[function], 0);
|
||||
ftn_queue[function].inuse = 1; //inuse set to 1 says we already pulsed
|
||||
} else
|
||||
if (FuncState==0) ftn_queue[function].inuse = 0;
|
||||
break;
|
||||
case 5: // Fade On
|
||||
#define fadedelay 24
|
||||
if ((ftn_queue[function].inuse==0) && (FuncState==1)) {
|
||||
ftn_queue[function].inuse = 1;
|
||||
for (t=0; t<ftn_queue[function].stop_value; t+=ftn_queue[function].increment) {
|
||||
digitalWrite( fpins[function], 1);
|
||||
delay(fadedelay*(t/(1.*ftn_queue[function].stop_value)));
|
||||
digitalWrite( fpins[function], 0);
|
||||
delay(fadedelay-(fadedelay*(t/(1.*ftn_queue[function].stop_value))));
|
||||
}
|
||||
digitalWrite( fpins[function], 1 );
|
||||
} else {
|
||||
if ((ftn_queue[function].inuse==1) && (FuncState==0)) {
|
||||
ftn_queue[function].inuse = 0;
|
||||
digitalWrite(fpins[function], 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 6: // Future Function
|
||||
ftn_queue[function].inuse = 0;
|
||||
break;
|
||||
default:
|
||||
ftn_queue[function].inuse = 0;
|
||||
break;
|
||||
}
|
||||
}
|
@@ -1,47 +0,0 @@
|
||||
Release Notes for the 5.4 SMA Decoder Examples
|
||||
1. Buf fix to allow maximum of 17 servos
|
||||
|
||||
2. Bug Fix to correct 2 reload #define definitions
|
||||
|
||||
3. Change to major Loop Delay cut in half to allow for fewer misses of DCC packet detection
|
||||
|
||||
4. File Decoders_MultiFunction_Description.rtf has minor edits for new file names and 6FTN version.
|
||||
|
||||
Release Notes for the 5.1 SMA Decoder Examples
|
||||
|
||||
1. Automatic servo attachment and detachment has been implemented for all
|
||||
servo control functions. When a servo has stopped at the end of its traverse,
|
||||
it will be "detached" by the software. This has been demonstrated
|
||||
to reduce power consumption greatly and reduce servo "chatter."
|
||||
|
||||
2. Several bug fixes including all reported bugs as of May 2016
|
||||
|
||||
3. In the fully conficurable verions. all 17 pins now can be configured for any of 6 functions
|
||||
Config 0=On/Off,1=Blink,2=Servo,3=DBL LED Blink,4=variable Pulse ,5=fade on
|
||||
|
||||
4. Servo timing has a timing modifier added for extra slow servo traverse
|
||||
#define servo_slowdown 3 //servo loop counter limit
|
||||
Can be set from 0 to 255 -- the higher the number the slower the traverse
|
||||
|
||||
5. Software has been restructured to support new NmraDcc library releases
|
||||
including the NmraDcc-MicroBahner library version.
|
||||
|
||||
6. 18 Predefined decoder skectekes are included:
|
||||
Mobile Decoders:
|
||||
Dec_2MotDrive_12LED_1Srv_6Ftn Dual motor drive, 12 LED 6 Function
|
||||
Dec_7Serv_10LED_6Ftn 7 Servo 10 LED 6 Function
|
||||
Dec_10Serv_7LED_6Ftn 10 Servo 7 LED 6 Function
|
||||
Dec_13Serv_4LED_6Ftn 13 Servo 4 LED 6 Function
|
||||
Dec_15Serv_2LED_6Ftn 15 Servo 2 LED 6 Function
|
||||
Dec_17LED_1Ftn 17 LED ON/OFF Control
|
||||
Dec_17LED_6Ftn 17 LED 6 Function
|
||||
Dec_Dir_and_Fade 17 LED with Dual Direction Control and FADE
|
||||
Dec_SMA12_LED_Groups LED Group Control for Euro Signaling
|
||||
Accessory Decoders:
|
||||
AccDec_7ServoBackandForth6Ftn 7 Servo 10 LED 6 Function
|
||||
AccDec_7Servos_10LED_6Ftn 7 Servo 10 LED 6 Function
|
||||
AccDec_10Servos_7LED_6Ftn 10 Servo 7 LED 6 Function
|
||||
AccDec_13Servos_4LED_6Ftn 13 Servo 4 LED 6 Function
|
||||
AccDec_15Servos_2LED_6Ftn 15 Servo 2 LED 6 Function
|
||||
AccDec_17LED_1Ftn 17 LED ON/OFF Control
|
||||
AccDec_17LED_6Ftn 17 LED 6 Function
|
BIN
examples/SMA/SMA 6.01 Release Notes.rtf
Normal file
BIN
examples/SMA/SMA 6.01 Release Notes.rtf
Normal file
Binary file not shown.
11
keywords.txt
11
keywords.txt
@@ -22,12 +22,13 @@ isSetCVReady KEYWORD2
|
||||
notifyDccReset KEYWORD2
|
||||
notifyDccIdle KEYWORD2
|
||||
notifyDccSpeed KEYWORD2
|
||||
notifyDccSpeedRaw
|
||||
notifyDccSpeedRaw KEYWORD2
|
||||
notifyDccFunc KEYWORD2
|
||||
notifyDccAccState KEYWORD2
|
||||
notifyDccAccTurnoutBoard
|
||||
notifyDccAccTurnoutOutput
|
||||
notifyDccSigState KEYWORD2
|
||||
notifyDccAccTurnoutBoard KEYWORD2
|
||||
notifyDccAccTurnoutOutput KEYWORD2
|
||||
notifyDccAccBoardAddrSet KEYWORD2
|
||||
notifyDccAccOutputAddrSet KEYWORD2
|
||||
notifyDccSigOutputState KEYWORD2
|
||||
notifyDccMsg KEYWORD2
|
||||
notifyCVValid KEYWORD2
|
||||
notifyCVRead KEYWORD2
|
||||
|
@@ -1,9 +1,9 @@
|
||||
name=NmraDcc
|
||||
version=1.4.2
|
||||
author=Alex Shepherd, Wolfgang Kuffer, Geoff Bunza, Martin Pischky, Franz-Peter Müller, Sven (littleyoda)
|
||||
version=2.0.2
|
||||
author=Alex Shepherd, Wolfgang Kuffer, Geoff Bunza, Martin Pischky, Franz-Peter Müller, Sven (littleyoda), Hans Tanner
|
||||
maintainer=Alex Shepherd <kiwi64ajs@gmail.com>
|
||||
sentence=Enables NMRA DCC Communication
|
||||
paragraph=This library allows you to interface to a NMRA DCC track signal and receive DCC commands. The library currently supports the AVR ATTiny84/85 & ATMega88/168/328/32u4 and Teensy 3.x using the INT0/1 Hardware Interrupt and micros() ONLY and no longer uses Timer0 Compare Match B, which makes it much more portable to other platforms
|
||||
paragraph=This library allows you to interface to a NMRA DCC track signal and receive DCC commands. The library has been tested on AVR ATTiny84/85 & ATMega88/168/328/32u4, ESP8266 and Teensy 3.x using the INT0/1 Hardware Interrupt and micros() ONLY and no longer uses Timer0 Compare Match B, which makes it much more portable to other platforms.
|
||||
category=Communication
|
||||
url=http://mrrwa.org/dcc-decoder-interface/
|
||||
architectures=avr,esp8266
|
||||
url=https://github.com/mrrwa/NmraDcc
|
||||
architectures=*
|
||||
|
Reference in New Issue
Block a user