Reiner SCT Pinpad amd64

Hello,

if using the citizen software mocca with ubuntu and a pcsc reader like the “Reiner SCT Pinpad” you should notice that java searches in the wrong dirs for the pcsclite lib.

So you can do following:

ln -sf /lib/x86_64-linux-gnu/libpcsclite.so.1.0.0 /usr/lib64/libpcsclite.so

Have fun!

Super Grub Disk

A super live boot manager.

See http://www.supergrubdisk.org/

Have fun!

Railcom(R) module

See http://www.opendcc.de/s88/gbm_bidi/gbm_bidi.html

Have fun!

Home brew fiddle yard controller

-3 rails
-dc motor
-10 turn poti for position
-arduino uno board
-controlled by rocrail
-minimized feedback sensors (see T4 to T6)

The code:

#include <NmraDcc.h>

//init DCC
NmraDcc  Dcc;
DCC_MSG  Packet ;
//Addresses
const byte Addr1 = Dcc.getCV(CV_ACCESSORY_DECODER_ADDRESS_LSB);
const byte Addr2 = Addr1 + 1;

//declaring outputs
const int MotorPinPWMA =  9;     // PWM motor pin
const int MotorPinPWMB =  6;     // motor relais
const int fb0 = 12;              // feedback to rocrail positon reached
const int CVAckPin = 13;         // dcc ack pin for programming the cv's
const byte rails = 3;            // number of rails
const int rail[] = {7,8,11};     // disconnecting/connection the rail feedback sensors
int railPos[] = {                // positions of the rails
  (Dcc.getCV(519) << 8) | Dcc.getCV(520),
  (Dcc.getCV(521) << 8) | Dcc.getCV(522),
  (Dcc.getCV(523) << 8) | Dcc.getCV(524)
};

//declaring analog inputs
int sensorPin = A3;              // poti pin for position detection
int MotorPinCurrent = A0;        // motor current measurement

// variables will change:
int posState[] = {0,0,0,0};      // setting correct position from dcc to motor function 0,1,2,3
byte posNew = 0;                 // new position
int i = 0;                       // loops
int j = 0;                       // loops
int pos;                         // var for position
byte railtimes = 1;              // loop breaker
int posIST;                      // position registered
int posSOLL;                     // position should be
int DIFF;                        // difference between position registered and position should be
long previousMillis = 0;         // breaking var within the millis() funtion
byte maxCurrent = Dcc.getCV(515);// maximum current the motor drives
byte maxSpeed = Dcc.getCV(516);  // maximum voltage the motor drives
byte minSpeed = Dcc.getCV(517);  // minimum voltage the motor drives
byte Speed = 0;                  // actual speed set motor
int Current = 0;                 // actual current motor
byte CVbyte1;                    // helper var for CVSet()
byte CVbyte2;                    // helper var for CVSet()

void setup() {

  // init the serial port
  Serial.begin(115200);          //  setup serial

  // init dcc
  Dcc.init( MAN_ID_DIY, 10, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER | FLAGS_ENABLE_INT0_PULL_UP, 0);
  // Configure the DCC CV Programing ACK pin for an output
  pinMode( CVAckPin, OUTPUT );

  // initialize the outputs:
  pinMode(MotorPinPWMA, OUTPUT);
  pinMode(MotorPinPWMB, OUTPUT);
  // initialize the feedback outputs
  pinMode(fb0, OUTPUT);          // position reached output
  for (i = 0; i < rails; i++) {  // actual rail sensor outputs
    pinMode(rail[i], OUTPUT);
  }
  
}

void loop(){

  // keep the dcc lib running
  Dcc.process();
  
  // read the motor current
  Current =  readAO(MotorPinCurrent);
  // read the actual position value 
  posIST = readAO(sensorPin);
  
  if (posNew==2) {                // if order to change the rail 
    
    posSOLL=railPos[pos];         // get the correct destination value
    DIFF=posIST-posSOLL;          // compute the difference to drive to

    if (DIFF >= 0) {              // positive difference setting the relais to low
      digitalWrite(MotorPinPWMB, LOW);
    }
    else {                        // negative difference setting the relais to low
      digitalWrite(MotorPinPWMB, HIGH);
    }

    if (abs(DIFF) > 20) {         // high speed motor control dir a
      Speed = maxSpeed;
    }

    if (abs(DIFF) <= 20) {        // low speed motor control dir a + b
      Speed = minSpeed;
    }  

    if (DIFF != 0) {              // destination not arrived
      while(railtimes) {
        for (j=0;j<rails;j++) {
          digitalWrite(rail[j],LOW);
        }
        railtimes=0;
      }
    }

    if (DIFF == 0) {              // destination arrived
      Speed = 0;
      digitalWrite(fb0, HIGH);
      delay (100);
      railtimes=1;
      while(railtimes) {
        for (j=0;j<rails;j++) {
          if (pos==j) {
            digitalWrite(rail[j],HIGH);
          }
          else {
            digitalWrite(rail[j],LOW);
          }
        }
        railtimes=0;
      }
      saveposIST();
      delay(300);
      posNew=0;
    }
    analogWrite(MotorPinPWMA, Speed);
  }

  else {
    digitalWrite(fb0, LOW);
    railtimes=1;
  }

  if (posNew==3) {              // pusbutton low speed dir a; addr2 - output 2 - straight
    digitalWrite(MotorPinPWMB, LOW);
    analogWrite(MotorPinPWMA, minSpeed);
    delay (400);
    analogWrite(MotorPinPWMA, 0);
    posNew = 0;
    saveposIST();
  }

  if (posNew==4) {              // pusbutton low speed dir b; addr2 - output 2 - turnout
    digitalWrite(MotorPinPWMB, HIGH);
    analogWrite(MotorPinPWMA, minSpeed);
    delay (400);
    analogWrite(MotorPinPWMA, 0);
    digitalWrite(MotorPinPWMB, LOW);
    posNew = 0;
    saveposIST();
  }
  
  if (posNew==5) {              // pusbutton high speed dir a; addr2 - output 3 - straight
    digitalWrite(MotorPinPWMB, LOW);
    analogWrite(MotorPinPWMA, maxSpeed);
    delay (200);
    analogWrite(MotorPinPWMA, 0);
    posNew = 0;
  }

  if (posNew==6) {              // pusbutton high speed dir b; addr2 - output 3 - turnout
    digitalWrite(MotorPinPWMB, HIGH);
    analogWrite(MotorPinPWMA, maxSpeed);
    delay (200);
    analogWrite(MotorPinPWMA, 0);
    digitalWrite(MotorPinPWMB, LOW);
    posNew = 0;
  }

  if (posNew==7) {              // save positions; addr2 - output 4 - straight
    switch (pos) {
      case 0:
      Dcc.setCV(519,Dcc.getCV(513));
      Dcc.setCV(520,Dcc.getCV(514));
      case 1:
      Dcc.setCV(521,Dcc.getCV(513));
      Dcc.setCV(522,Dcc.getCV(514));
      case 2:
      Dcc.setCV(523,Dcc.getCV(513));
      Dcc.setCV(524,Dcc.getCV(514));
    }
    posNew = 0;
  }
  
  if (Current >= maxCurrent) {
    analogWrite(MotorPinPWMA, 0);
  }
}

//FUNCTIONS

// 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) ;*/

  if (BoardAddr == Addr1 && State == 8) { // Sollposition
    switch (OutputAddr) { // ungerade Zahl ist gerade (0) und abzweigend ist gerade Zahl (1)
    case 1: 
      posState[0] = 0;
      break;
    case 0: 
      posState[0] = 1;
      break;
    case 3: 
      posState[1] = 0;
      break;
    case 2: 
      posState[1] = 1;
      break;
    case 5:
      posState[2] = 0;
      break;
    case 4:
      posState[2] = 1;
      break;
    case 7:
      posState[3] = 0;
      break;
    case 6:
      posState[3] = 1;
      break;
    }
  }

  if (BoardAddr == Addr2 && OutputAddr == 0 && State == 8) {
    posNew = 1;
  }
  /*if (BoardAddr == Addr2 && OutputAddr == 0 && State == 0) {
   posNew = 3;
   }*/
  if (BoardAddr == Addr2 && OutputAddr == 1 && State == 8 && posNew == 1) {
    bitWrite(pos, 3, posState[3]); //binary to decimal int nr. of rail
    bitWrite(pos, 2, posState[2]);
    bitWrite(pos, 1, posState[1]);
    bitWrite(pos, 0, posState[0]);
    posNew = 2;
  }
  if (BoardAddr == Addr2 && OutputAddr == 3 && State == 8) {
    posNew = 3;
  }
  if (BoardAddr == Addr2 && OutputAddr == 2 && State == 8) {
    posNew = 4;
  }
  if (BoardAddr == Addr2 && OutputAddr == 5 && State == 8) {
    posNew = 5;
  }
  if (BoardAddr == Addr2 && OutputAddr == 4 && State == 8) {
    posNew = 6;
  }
  if (BoardAddr == Addr2 && OutputAddr == 7 && State == 8) {  //Save position to CV
    posNew = 7;
  }
  
}

// reads the analogue inputs
int readAO(int AI){
  
  int sum = 0;
  int temp;
  int i;
  
  for (i=0; i<10; i++) {            // loop through reading raw adc values AVG_NUM number of times  
    if (analogRead(AI) > 0) { 
      temp = analogRead(AI);        // read the input pin  
      sum += temp;                  // store sum for averaging
      //delayMicroseconds(10);      // pauses for 50 microseconds  
    }
  }
  return(sum / 10);                // divide sum by AVG_NUM to get average and return it
}

// saves actual position value
void saveposIST() {
  CVbyte1 = (posIST >> 8) & 0x03;
  CVbyte2 = posIST & 0xff;
  Dcc.setCV(513,CVbyte1);
  Dcc.setCV(514,CVbyte2);
}

// at programming sends acknowledge
void notifyCVAck(void)
{
  Serial.println("notifyCVAck") ;

  digitalWrite(CVAckPin,HIGH); 
  delay(6);  
  digitalWrite(CVAckPin,LOW);
}

// Uncomment to print all DCC Packets
/*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();
}*/

/*
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > 1000) {
    // save the last time you blinked the LED 
    previousMillis = currentMillis;   
    Serial.print(" posIST ");
    Serial.print(posIST);
  }
*/

The schematic:

fy.png

Have fun!

Home brew turn table

It’s controlled by an arduino uno controller.
Software controlling is rocrail.
Hardware is very basic an supports programming in the pt mode (currently only for the address).

The arduino’s program:
tt.pde:

#include <NmraDcc.h>
#include <Stepper.h>

#define EN1 10
#define EN2 11

//init stepper
//Stepper stepper(48,3, 5, 6, 9);
Stepper stepper(48,5, 3, 6, 9);

//init DCC
NmraDcc  Dcc;
DCC_MSG  Packet ;
//Addresses
const byte Addr1 = Dcc.getCV(CV_ACCESSORY_DECODER_ADDRESS_LSB);
const byte Addr2 = Addr1 + 1;
const byte Addr3 = Addr1 + 2;

//declaring outputs
byte fb0 = 4;             // feedback to rocrail positon reached
byte CVAckPin = 13;        // dcc ack pin for programming the cv's
//int offset = { (Dcc.getCV(112) << 8) | Dcc.getCV(113) };// steps from point 0 to rail 0

//declaring inputs
byte sensorPin = 7;              // pin for position detection

// variables will change:
int posState[6];  // setting correct position from dcc to motor function 0-23
int steps = 518;                   // steps for one lap
byte posNew = 0;                 // new position
byte pos;                         // var for position
long previousMillis = 0;         // breaking var within the millis() funtion
byte CVbyte1;                    // helper var for CVSet()
byte CVbyte2;                    // helper var for CVSet()
int i;
int stepperarray[48];
int offset[48];
 
void setup() {

  
  // init the serial port
  Serial.begin(115200);          //  setup serial
  
  // init dcc
  Dcc.init( MAN_ID_DIY, 10, FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER | FLAGS_ENABLE_INT0_PULL_UP, 0);
  // Configure the DCC CV Programing ACK pin for an output
  pinMode(CVAckPin, OUTPUT);

  // initialize the outputs
  pinMode(fb0, OUTPUT);          // position reached output
  pinMode(EN1, OUTPUT);
  pinMode(EN2, OUTPUT);
  
  // initialize the inputs
  pinMode(sensorPin, INPUT);
  
  stepper.setSpeed(30);
  
}

void loop() {
  
  offset[0] = 26;
  offset[24] = 26;
  
  offset[2] = 27;
  offset[26] = 27;
  
  
  offset[46] = 25;
  offset[22] = 25;
  
  offset[44] = 24;
  offset[20] = 24;
  
  offset[25] = 23;
  offset[1] = 24;

  for (i=0;i<48;i++) {
    stepperarray[i] = (int (float(steps) / float(48) * float(i)) +.5) + offset[i];
  } 
  
  // keep the dcc lib running
  Dcc.process();
  
  if (posNew==2) { // if order to change the rail
    digitalWrite(fb0, LOW);

    analogWrite(EN1,150);
    analogWrite(EN2,150);
    
    if (pos == 63) {
      // stepping to point zero
      stepper.step(10);
      while (digitalRead(sensorPin) == HIGH) {
        stepper.step(1); 
      }
      stepper.step(stepperarray[Dcc.getCV(114)]);
      pos=Dcc.getCV(114);
    }
    else {
      stepper.step(10);
      while (digitalRead(sensorPin) == HIGH) {
        stepper.step(1); 
      }
      stepper.step(stepperarray[pos]);
    }
     
    delay(50); 
    analogWrite(EN1,0);
    analogWrite(EN2,0);
  
    // position - ready
    digitalWrite(fb0, HIGH);
     
    // save position
    Dcc.setCV(114,pos);
    posNew=0;
  }
   
  if (posNew==3) {              // pusbutton step 1 left
    Serial.println("stepping 1 left");
    analogWrite(EN1,255);
    analogWrite(EN2,255);
    stepper.step(1);
    delay(100);
    analogWrite(EN1,0);
    analogWrite(EN2,0);
    posNew=0;
  }

  if (posNew==4) {              // pusbutton step 1 left
    Serial.println("stepping 1 right");
    analogWrite(EN1,255);
    analogWrite(EN2,255);
    stepper.step(-1);
    delay(100);
    analogWrite(EN1,0);
    analogWrite(EN2,0);
    posNew=0;
  }  
   
}

//FUNCTIONS

  // count the steps for one lap
  /*stepper.step(10);  //go out of the sensor
  steps = 10;
  while (digitalRead(sensorPin) == HIGH) {
    stepper.step(1);
    steps = steps++;
  }
  Serial.println(steps,DEC);
  */

// 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) ;*/

  if (BoardAddr == Addr1 && State == 8) { // Sollposition
    switch(OutputAddr) { // ungerade Zahl ist gerade (0) und abzweigend ist gerade Zahl (1)
    case 1: 
      posState[0] = 0;
      break;
    case 0: 
      posState[0] = 1;
      break;
    case 3: 
      posState[1] = 0;
      break;
    case 2: 
      posState[1] = 1;
      break;
    case 5:
      posState[2] = 0;
      break;
    case 4:
      posState[2] = 1;
    break;
    case 7:
      posState[3] = 0;
      break;
    case 6:
      posState[3] = 1;
      break;
    }
  }

  if (BoardAddr == Addr2 && State == 8) { // Sollposition
    switch(OutputAddr) { // ungerade Zahl ist gerade (0) und abzweigend ist gerade Zahl (1)
      case 1: 
        posState[4] = 0;
        break;
      case 0: 
        posState[4] = 1;
        break;
      case 3: 
        posState[5] = 0;
        break;
      case 2: 
        posState[5] = 1;
        break;
      }
  }

  if (BoardAddr == Addr2 && OutputAddr == 5 && State == 8) {
    posNew = 1;
  }

  if (posNew == 1) {
    bitWrite(pos, 5, posState[5]); //binary to decimal int nr. of rail
    bitWrite(pos, 4, posState[4]);
    bitWrite(pos, 3, posState[3]);
    bitWrite(pos, 2, posState[2]);
    bitWrite(pos, 1, posState[1]);
    bitWrite(pos, 0, posState[0]);
    posNew = 2;
  }
  
  if (BoardAddr == Addr2 && OutputAddr == 7 && State == 8 ) { //Step 1 left
    posNew = 3;
  }

  if (BoardAddr == Addr2 && OutputAddr == 6 && State == 8 ) { //Step 1 left
    posNew = 4;
  }
}

// saves actual position value
/*
void saveposIST() {
  CVbyte1 = (posIST >> 8) & 0x03;
  CVbyte2 = posIST & 0xff;
  Dcc.setCV(513,CVbyte1);
  Dcc.setCV(514,CVbyte2);
}
*/

//while programming sends acknowledge
void notifyCVAck(void) {
  Serial.println("notifyCVAck");
  digitalWrite(CVAckPin,HIGH); 
  delay(6);  
  digitalWrite(CVAckPin,LOW);
}

// Uncomment to print all DCC Packets
/*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();
}*/

/*
unsigned long currentMillis = millis();
if (currentMillis - previousMillis > 1000) {
    //save the last time you blinked the LED 
    previousMillis = currentMillis;   
    Serial.print(" sensorPin ");
    int a = digitalRead(sensorPin);
    Serial.print(a);
}
*/

Here’s the schematic:

tt.jpg

Have fun!