Model Railway Sliding Fiddle Yard

Hi. Below is a sketch I cannot claim all the credit for, as i have had help and borrowed bits and bobs.

I am using Arduino Nano and communicating using RS485.

I have a control panel in a train control program JMRI/CMRI controlling the sliding fiddle yard “SFY”.
A keypad entry or switch in the panel is thrown and a bit is sent to the arduino and the SFY moves to its new position.

In the sketch after declarations the SFY moves to its endstop to set the steppers starting point.
The program then waits for either a keypad entry or a bit to be received from CMRI. cmri.get_bit.
Once keypad or bit received the case num is executed and the SFY moves to its new position.
Once in new position track polarity is set by the relayPin

Once a new position and relay are set, I send a bit to CMRI cmri.set_bit(1, HIGH); which changes a sensor in my panel to show on in its new position.
So far all this works as should.

Now my problem. Once I have moved to new position I want to set the previous sensor bit LOW before setting the new sensor HIGH. But not sure how to achieve this.

case 11:
{ stepper.runToNewPosition(24470);
digitalWrite (relayPin, LOW); // Turns relay on.
Turn previous CMRI bit to LOW turn sensor off in panel.
cmri.set_bit(0, HIGH);
break;
}
case 12:
{ stepper.runToNewPosition(28430);
digitalWrite (relayPin, HIGH); // Turns relay off.
Turn previous CMRI bit to LOW turn sensor off in panel.
cmri.set_bit(1, HIGH);
break;

Thanks Eddy

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Auto485.h>
#include <CMRI.h>
#include <AccelStepper.h>

#define dirPin  12  //A4988 Direction Pin // Define stepper motor connections and motor interface type. Motor interface type must be set to 1 when using a driver:
#define stepPin 11  //A4988 Step Pin
#define motorInterfaceType 1  //Stepper Type

LiquidCrystal_I2C lcd(0x27, 16, 2); // Set the LCD address to 0x27 for a 16 chars and 2 line display
Auto485 bus(2); // Arduino pin 2 -> MAX485 DE and RE pins
CMRI cmri(6, 24, 192, bus); // Node setup

#include <Keypad.h>
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'},
};
byte colPins[COLS] = {6, 5, 4, 3}; //connect to the colum pinouts of the keypad
byte rowPins[ROWS] = {10, 9, 8, 7}; //connect to the row pinouts of the keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

char constexpr enter_value_prompt[] {"Enter TK/SFY Num "};
int constexpr SFY_unobstructed_detector = A3;       //All SLF IRD's connected to this pin
int endStop = A0;         // connect output to push button & end stop switch
int pushed = 1;           //push status to move stepper to new position
long initial_homing = -1; // Used to Home Stepper at startup
int relayPin = A1;        //SFY relay to change track polarity


AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin);  //defines stepper setup

void setup() {
  pinMode(relayPin, OUTPUT);// set pin as output
  digitalWrite(relayPin, HIGH); // set initial state OFF for low trigger relay
  lcd.begin(); // initialize the LCD,
  lcd.backlight();  // Turn on the blacklight.
  pinMode(SFY_unobstructed_detector, INPUT);
  Serial.begin(19200);
  bus.begin(19200, SERIAL_8N2);    // open the RS485 bus at 19200bps
  pinMode(endStop, INPUT_PULLUP);  //pullup switch and endstop switch

  stepper.setMaxSpeed(10000);
  stepper.setAcceleration(14000);

  while (digitalRead(endStop)) {
    stepper.moveTo(initial_homing);  // Set the position to move to
    initial_homing--;                // Decrease by 1 for next move if needed
    stepper.run();                   // Start moving the stepper

  }
  while (!digitalRead(endStop)) {    // Make the Stepper move CW until the switch is deactivated
    stepper.moveTo(initial_homing);
    stepper.run();
    initial_homing++;
  }
  stepper.setCurrentPosition(0);
  //stepper.runToNewPosition(3000);    //SFY move thrn fo a manual reset 

  Serial.println("Homing Completed");
  lcd.print("Homing Completed");
  Serial.println(enter_value_prompt);
  lcd.setCursor(0, 1);
  lcd.print(enter_value_prompt);
}

int get_value_from_keypad(int value = 0)
{
  char keyval = keypad.getKey();

  if (keyval)
  {
    lcd.setCursor (0, 1);
    lcd.clear();

    int position = 0;
    while (keyval >= '0' && keyval <= '9')
    {
      Serial.print(keyval);
      lcd.setCursor (position++, 0);
      lcd.print(keyval);

      value = (value * 10) + (keyval - '0');
      keyval = keypad.waitForKey();
    }
    Serial.println();
    Serial.print("Move > ");
    Serial.println(value);
    Serial.println(enter_value_prompt);
    lcd.clear();
    lcd.print("Move > ");
    lcd.print(value);
    lcd.setCursor (0, 1);
    lcd.print(enter_value_prompt);
  }
  return value;
}


int update_value_from_cmri(int original_value)
{
  int static value_for_cmri_bit[] = { 11, 12, 13, 14, 15, 16, 17, //CMRI bit 6001-6007
                                      21, 22, 23, 24, 25, 26, 27, 28, //CMRI bit 6008-6015
                                      31, 32, 33, 34, 35, 36, 37, 38, 39, //CMRI bit 6016-6024
                                      41, 42, 43, 44, 45, 46, 47, 48, 49, 410, //CMRI bit 6025-6034
                                      51, 52, 53, 54, 55, 56, 57, 58, 59, 510, 511, 512, //CMRI bit 6035-6046
                                      61, 62, 63, 64, 65, 66, 67, 68, 69, 610, 611, 612, 613, //CMRI bit 6047-6059
                                      76, 77, 78, 79, 710, 711, 712, 713, 714, 715, 716, 717, 718, //CMRI bit 660-6072
                                      89, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, //CMRI bit 6073-6085
                                      912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, //CMRI bit 6086-6098
                                      1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, //CMRI bit 6099-6110
                                      1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129, //CMRI bit 6111-6122
                                      1220, 1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231, 1232, // CMRI bit 6123-6135
                                      1324, 1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, //CMRI bit 6136-6144
                                      1425, 1426, 1427, 1428, 1429, 1430, 1431, 1432, //CMRI bit 6145-6152
                                      1526, 1527, 1528, 1529, 1530, 1531, 1532, //CMRI bit 6153-6159
                                      1627, 1628, 1629, 1630, 1631, 1632, //CMRI bit 6160-6165
                                    };
  int constexpr number_of_cmri_bits =
    sizeof(value_for_cmri_bit) / sizeof(value_for_cmri_bit[0]);

    cmri.process();

  for (int cmri_bit = 0; cmri_bit < number_of_cmri_bits; cmri_bit++)
  {
    if (cmri.get_bit(cmri_bit) == 1)
    {
      return value_for_cmri_bit[cmri_bit];
    }
  }

  return original_value;
}
void move_stepper_to_position_for_value(int value) //Max49500 Min
{
   switch (value)
  { 
    case 11:
      { stepper.runToNewPosition(24470);
        digitalWrite (relayPin, LOW); // Turns relay on.
        cmri.set_bit(0, HIGH);
        break;
      }
    case 12:
      { stepper.runToNewPosition(28430);
        digitalWrite (relayPin, HIGH); // Turns relay off.
        cmri.set_bit(1, HIGH);
        break;
      }
    case 13:
      { stepper.runToNewPosition(32360);
        break;
      }

    case 1632:
      { stepper.runToNewPosition(20920);
        break;
      }
      cmri.set_bit(0, !digitalRead(HIGH));

    default:
      {
        Serial.print("Invalid position request: ");
        Serial.println(value);
        break;
      }
  }
}


void loop()
{          
  int value = get_value_from_keypad();

  value = update_value_from_cmri(value);

  if (value > 0)
  {
    if (LOW == digitalRead(SFY_unobstructed_detector))
    {
      move_stepper_to_position_for_value(value);
    }
    else
    {
      Serial.println("Obstruction");
      
      lcd.clear();
      lcd.print ("**Obstruction**");
    }
  }
}

Now my problem. Once I have moved to new position I want to set the previous sensor bit LOW before setting the new sensor HIGH. But not sure how to achieve this.

what ever that is, but you could remember the previous sensor after you have set it in a dedicated Variable

previousSensor = theBitWhichWasSet;

and thereforedo a set low:

cmri.set_bit(previousSensor , LOW);

before you set the new one.

The problem with “remembering” the previous bit set is that when powered on, a bit may previously have been set and you won’t know which one.

Maybe that’s not a problem in your application (maybe, whatever the CMRI is, it is powered on and in a known all LOW state when the Arduino starts), or maybe it isn’t…

You should probably start by turning them all off.

for (int b = 0; b < number_of_cmri_bits; b++) {
  cmri.set_bit(b, LOW);
}

Thanks all sorted. I think I need to use my brain more :smiley: :smiley:

Eddy

Eddy99:
I think I need to use my brain more :smiley: :smiley:

Don't we all! :smiley:

Now, post some pics. Because RAILROAD!

Building a mobile layout so its small but I wanted to get lots of stuff in it.
Its based around a canal with working barges and the main part is a brick works, all will be covered with plaster so only rails on show.
Turnouts and mini turntables 3d printed 3d printed locos with supercaps to negate the 3d printed points.
Sliding fiddle yard to give me lots of movement options.
JMRI, CMRI, DCC++ Arduino's and RS485 bus.
Next project add a turntable to the SFY.
My biggest hurdle Arduino programming but I muddle through and ask lots of questions.
Eddy

Sorry wrong picture in previous post

:o
Great work!
Thanks for the pics