Hallo Zusammen,
ich bräuchte mal eure Hilfe .
Bin auf der suche nach einem Programm für meine Drehscheibe hab aber noch nix richtiges gefunden. Da ich noch nicht so Fit bin in Programme selber schreiben frage ich mal hier nach Hilfe.
Die Drehscheibe sollte über DCC laufen mit einem Nema17 wo ich über die einzelnen DCC Adresse die Abgänge anfahren kann z.b Gleis 1 Adresse 200 Gleis 2 Adresse 201.
ich Würde gerne alles Gleise mit den jeweiligen Steps Programmieren z.b Gleis 1 100 Steps Gleis 2 150S Steps .
Gleis 0 soll Startpunkt sein über ein Hallsensor.
Habe in der NmraDCC Library ein Beispiel gefunden aber komme nicht mit den Positionen klar.
Vielen Dank schon mal im Voraus.
// DCC Stepper Motor Controller ( A4988 ) Example for Model Railroad Turntable Control
//
// See: https://www.dccinterface.com/product/arduino-model-railway-dcc-stepper-motor-controller-a4988-assembled/
//
// Author: Alex Shepherd 2020-06-01
//
// 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>
// Define the Arduino input Pin number for the DCC Signal
#define DCC_PIN 2
// The lines below define the pins used to connect to the A4988 driver module
#define A4988_STEP_PIN 4
#define A4988_DIRECTION_PIN 5
#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
// Uncomment the following line to enable Debug Print of DCC Messages
//#define NOTIFY_DCC_MSG
// 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_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... ;)
// --------------------------------------------------------------------------------------------
#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))
// 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;
int lastStep = 0;
void processTurnoutCommand(uint16_t Addr, uint8_t Direction, uint8_t OutputPower)
{
Serial.print(F("processTurnoutCommand: "));
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
int newStep;
if(Direction)
newStep = turnoutPositions[i].positionFront;
else
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;
}
}
}
// This function is called from the Library whenever a normal DCC Turnout Packet is received
void notifyDccAccTurnoutBoard (uint16_t BoardAddr, uint8_t OutputPair, uint8_t Direction, uint8_t OutputPower)
{
uint16_t Addr = ((BoardAddr - 1) * 4) + OutputPair + 1;
Serial.print(F("notifyDccAccTurnoutBoard: "));
Serial.print(Addr,DEC) ;
Serial.print(',');
Serial.print(Direction,DEC) ;
Serial.print(',');
Serial.println(OutputPower, HEX) ;
processTurnoutCommand(Addr, Direction, OutputPower);
};
#ifdef DISABLE_OUTPUTS_IDLE
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
stepper1.enableOutputs();
#endif
#ifdef DISABLE_OUTPUTS_IDLE
lastIsRunningState = stepper1.isRunning();
#endif
}
bool moveToHomePosition()
{
Serial.println(F("Finding Home Sensor...."));
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)
{
stepper1.stop();
stepper1.setCurrentPosition(0);
Serial.println(F("Found Home Position - Setting Current Position to 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
// Many Arduino Cores now support the digitalPinToInterrupt() function that makes it easier to figure out the
// Interrupt Number for the Arduino Pin number, which reduces confusion.
#ifdef digitalPinToInterrupt
Dcc.pin(DCC_PIN, 0);
#else
Dcc.pin(0, DCC_PIN, 1);
#endif
// Call the main DCC Init function to enable the DCC Receiver
Dcc.init( MAN_ID_DIY, 10, CV29_ACCESSORY_DECODER, 0 );
}
void setup()
{
Serial.begin(115200);
uint8_t maxWaitLoops = 255;
while(!Serial && maxWaitLoops--) // Wait for the USB Device to Enumerate
delay(20);
Serial.println(F("\nExample Stepper Motor Driver for DCC Turntable Control"));
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(F("DCC Addr: "));
Serial.print(turnoutPositions[i].dccAddress);
Serial.print(F(" Front: "));
Serial.print(turnoutPositions[i].positionFront);
Serial.print(F(" Back: "));
Serial.println(turnoutPositions[i].positionBack);
}
setupStepperDriver();
if(moveToHomePosition());
{
setupDCCDecoder();
// Fake a DCC Packet to cause the Turntable to move to Position 1
processTurnoutCommand(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 DISABLE_OUTPUTS_IDLE
if(stepper1.isRunning() != lastIsRunningState)
{
lastIsRunningState = stepper1.isRunning();
if(!lastIsRunningState)
{
stepper1.disableOutputs();
Serial.println(F("Disable Stepper Outputs"));
}
}
#endif
}
#ifdef NOTIFY_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