Compare commits
16 Commits
AdvancedCV
...
2.0.5
Author | SHA1 | Date | |
---|---|---|---|
|
a09c6b1002 | ||
|
29bc2aa1c0 | ||
|
3abb683d8d | ||
|
f3da07c739 | ||
|
dead808af2 | ||
|
38194c0148 | ||
|
7819716ac0 | ||
|
5349a21e2e | ||
|
36418f4d66 | ||
|
a8081526ba | ||
|
7063e4e7e7 | ||
|
d8fb99ed91 | ||
|
794128fe4b | ||
|
1542a6fe6c | ||
|
462025b9fe | ||
|
71bb657e3a |
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.development
|
||||
*.zip
|
3262
NmraDcc.cpp
3262
NmraDcc.cpp
File diff suppressed because it is too large
Load Diff
29
NmraDcc.h
29
NmraDcc.h
@@ -2,11 +2,21 @@
|
||||
//
|
||||
// Model Railroading with Arduino - NmraDcc.h
|
||||
//
|
||||
// Copyright (c) 2008 - 2018 Alex Shepherd
|
||||
// Copyright (c) 2008 - 2020 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
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
@@ -44,15 +54,15 @@
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
|
||||
#include "EEPROM.h"
|
||||
|
||||
#ifndef NMRADCC_IS_IN
|
||||
#define NMRADCC_IS_IN
|
||||
|
||||
#define NMRADCC_VERSION 201 // Version 2.0.1
|
||||
#define NMRADCC_VERSION 205 // Version 2.0.5
|
||||
|
||||
#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 ;
|
||||
@@ -105,6 +115,9 @@ typedef struct
|
||||
#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.
|
||||
#endif
|
||||
@@ -113,7 +126,7 @@ typedef enum {
|
||||
CV29_LOCO_DIR = 0b00000001, /** bit 0: Locomotive Direction: "0" = normal, "1" = reversed */
|
||||
CV29_F0_LOCATION = 0b00000010, /** bit 1: F0 location: "0" = bit 4 in Speed and Direction instructions, "1" = bit 4 in function group one instruction */
|
||||
CV29_APS = 0b00000100, /** bit 2: Alternate Power Source (APS) "0" = NMRA Digital only, "1" = Alternate power source set by CV12 */
|
||||
CV29_ADV_ACK = 0b00001000, /** bit 3: ACK, Advanced Acknowledge mode enabled if 1, disabled if 0 */
|
||||
CV29_RAILCOM_ENABLE = 0b00001000, /** bit 3: BiDi ( RailCom ) is active */
|
||||
CV29_SPEED_TABLE_ENABLE = 0b00010000, /** bit 4: STE, Speed Table Enable, "0" = values in CVs 2, 4 and 6, "1" = Custom table selected by CV 25 */
|
||||
CV29_EXT_ADDRESSING = 0b00100000, /** bit 5: "0" = one byte addressing, "1" = two byte addressing */
|
||||
CV29_OUTPUT_ADDRESS_MODE = 0b01000000, /** bit 6: "0" = Decoder Address Mode "1" = Output Address Mode */
|
||||
|
@@ -1,8 +1,8 @@
|
||||
// DCC Stepper Motor Controller ( A4988 ) Example for Model Railroad Turntable Control
|
||||
//
|
||||
// See: https://www.dccinterface.com/how-to/assemblyguide/
|
||||
// See: https://www.dccinterface.com/product/arduino-model-railway-dcc-stepper-motor-controller-a4988-assembled/
|
||||
//
|
||||
// Author: Alex Shepherd 2017-12-04
|
||||
// Author: Alex Shepherd 2020-06-01
|
||||
//
|
||||
// This example requires two Arduino Libraries:
|
||||
//
|
||||
@@ -22,12 +22,22 @@
|
||||
// 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
|
||||
|
||||
#ifdef A4988_ENABLE_PIN
|
||||
// Uncomment the next line to enable Powering-Off the Stepper when its not running to reduce heating the motor and driver
|
||||
#define DISABLE_OUTPUTS_IDLE
|
||||
#endif
|
||||
|
||||
// By default the stepper motor will move the shortest distance to the desired position.
|
||||
// If you need the turntable to only move in the Positive/Increasing or Negative/Decreasing step numbers to better handle backlash in the mechanism
|
||||
// Then uncomment the appropriate line below
|
||||
//#define ALWAYS_MOVE_POSITIVE
|
||||
//#define ALWAYS_MOVE_NEGATIVE
|
||||
|
||||
// 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_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
|
||||
@@ -92,6 +102,9 @@ TurnoutPosition turnoutPositions[] = {
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// You shouldn't need to edit anything below this line unless you're needing to make big changes... ;)
|
||||
// --------------------------------------------------------------------------------------------
|
||||
#if defined(ALWAYS_MOVE_POSITIVE) && defined(ALWAYS_MOVE_NEGATIVE)
|
||||
#error ONLY uncomment one of ALWAYS_MOVE_POSITIVE or ALWAYS_MOVE_NEGATIVE but NOT both
|
||||
#endif
|
||||
|
||||
#define MAX_TURNOUT_POSITIONS (sizeof(turnoutPositions) / sizeof(TurnoutPosition))
|
||||
|
||||
@@ -104,11 +117,12 @@ NmraDcc Dcc ;
|
||||
// Variables to store the last DCC Turnout message Address and Direction
|
||||
uint16_t lastAddr = 0xFFFF ;
|
||||
uint8_t lastDirection = 0xFF;
|
||||
int lastStep = 0;
|
||||
|
||||
// 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(F("notifyDccAccTurnoutOutput: "));
|
||||
Serial.print(Addr,DEC) ;
|
||||
Serial.print(',');
|
||||
Serial.print(Direction,DEC) ;
|
||||
@@ -131,23 +145,50 @@ void notifyDccAccTurnoutOutput( uint16_t Addr, uint8_t Direction, uint8_t Output
|
||||
#ifdef A4988_ENABLE_PIN
|
||||
stepper1.enableOutputs();
|
||||
#endif
|
||||
if (Direction)
|
||||
{
|
||||
Serial.println(turnoutPositions[i].positionFront, DEC);
|
||||
stepper1.moveTo(turnoutPositions[i].positionFront);
|
||||
break;
|
||||
}
|
||||
|
||||
int newStep;
|
||||
if(Direction)
|
||||
newStep = turnoutPositions[i].positionFront;
|
||||
else
|
||||
{
|
||||
Serial.println(turnoutPositions[i].positionBack, DEC);
|
||||
stepper1.moveTo(turnoutPositions[i].positionBack);
|
||||
break;
|
||||
}
|
||||
newStep = turnoutPositions[i].positionBack;
|
||||
|
||||
Serial.print(newStep, DEC);
|
||||
|
||||
Serial.print(F(" Last Step: "));
|
||||
Serial.print(lastStep, DEC);
|
||||
|
||||
int diffStep = newStep - lastStep;
|
||||
Serial.print(F(" Diff Step: "));
|
||||
Serial.print(diffStep, DEC);
|
||||
|
||||
#if defined ALWAYS_MOVE_POSITIVE
|
||||
Serial.print(F(" Positive"));
|
||||
if(diffStep < 0)
|
||||
diffStep += FULL_TURN_STEPS;
|
||||
|
||||
#elif defined ALWAYS_MOVE_NEGATIVE
|
||||
Serial.print(F(" Negative"));
|
||||
if(diffStep > 0)
|
||||
diffStep -= FULL_TURN_STEPS;
|
||||
#else
|
||||
if(diffStep > HALF_TURN_STEPS)
|
||||
diffStep = diffStep - FULL_TURN_STEPS;
|
||||
|
||||
else if(diffStep < -HALF_TURN_STEPS)
|
||||
diffStep = diffStep + FULL_TURN_STEPS;
|
||||
#endif
|
||||
|
||||
Serial.print(F(" Move: "));
|
||||
Serial.println(diffStep, DEC);
|
||||
stepper1.move(diffStep);
|
||||
|
||||
lastStep = newStep;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef A4988_ENABLE_PIN
|
||||
#ifdef DISABLE_OUTPUTS_IDLE
|
||||
bool lastIsRunningState ;
|
||||
#endif
|
||||
|
||||
@@ -161,8 +202,12 @@ void setupStepperDriver()
|
||||
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
|
||||
stepper1.enableOutputs();
|
||||
#endif
|
||||
|
||||
#ifdef DISABLE_OUTPUTS_IDLE
|
||||
lastIsRunningState = stepper1.isRunning();
|
||||
#endif
|
||||
}
|
||||
@@ -173,14 +218,19 @@ bool moveToHomePosition()
|
||||
|
||||
pinMode(HOME_SENSOR_PIN, INPUT_PULLUP);
|
||||
|
||||
#ifdef ALWAYS_MOVE_NEGATIVE
|
||||
stepper1.move(0 - (FULL_TURN_STEPS * 2));
|
||||
#else
|
||||
stepper1.move(FULL_TURN_STEPS * 2);
|
||||
#endif
|
||||
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.stop();
|
||||
stepper1.setCurrentPosition(0);
|
||||
Serial.println(F("Found Home Position - Setting Current Position to 0"));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@@ -210,28 +260,32 @@ void setup()
|
||||
Serial.print(F("Full Rotation Steps: "));
|
||||
Serial.println(FULL_TURN_STEPS);
|
||||
|
||||
Serial.print(F("Movement Strategy: "));
|
||||
#if defined ALWAYS_MOVE_POSITIVE
|
||||
Serial.println(F("Positive Direction Only"));
|
||||
#elif defined ALWAYS_MOVE_NEGATIVE
|
||||
Serial.println(F("Negative Direction Only"));
|
||||
#else
|
||||
Serial.println(F("Shortest Distance"));
|
||||
#endif
|
||||
|
||||
for(uint8_t i = 0; i < MAX_TURNOUT_POSITIONS; i++)
|
||||
{
|
||||
Serial.print("DCC Addr: ");
|
||||
Serial.print(F("DCC Addr: "));
|
||||
Serial.print(turnoutPositions[i].dccAddress);
|
||||
|
||||
Serial.print(" Front: ");
|
||||
Serial.print(F(" Front: "));
|
||||
Serial.print(turnoutPositions[i].positionFront);
|
||||
|
||||
Serial.print(" Back: ");
|
||||
Serial.print(F(" 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);
|
||||
}
|
||||
@@ -245,7 +299,7 @@ void loop()
|
||||
// Process the Stepper Library
|
||||
stepper1.run();
|
||||
|
||||
#ifdef A4988_ENABLE_PIN
|
||||
#ifdef DISABLE_OUTPUTS_IDLE
|
||||
if(stepper1.isRunning() != lastIsRunningState)
|
||||
{
|
||||
lastIsRunningState = stepper1.isRunning();
|
||||
|
@@ -1,5 +1,5 @@
|
||||
name=NmraDcc
|
||||
version=2.0.2
|
||||
version=2.0.5
|
||||
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
|
||||
|
Reference in New Issue
Block a user