Doel:€250.00
Donaties:€50.00

Per saldo:€-200.00

Steun ons nu!

Laatst bijgewerkt
op 03-01-2024

Vacature: secretaris bestuur
Algemeen

De stichting

Recente berichten

Onlangs gespot - gefotografeerd, de foto's door Keska
Vandaag om 14:48:26
Werps Soldeerworkshop door Marco Staartjes
Vandaag om 14:47:12
Zoekfunctie ? door nighttrain1
Vandaag om 14:34:20
Geluid NS Mat'46 vs NS Mat'54 door Peter Kleton
Vandaag om 14:27:30
De (3d) knutsels van Ronald. door MaraNCS
Vandaag om 14:25:44
FFA koelwagen door Duoblock
Vandaag om 14:19:55
Bentheimer Eisenbahn, gisteren, vandaag en morgen. door Hans Reints
Vandaag om 14:03:01
De IJmuider spoorlijn - korte geschiedenis en plaatjes door sncf231e
Vandaag om 13:45:43
Piko NS 2015 stroomafname probleem door Rick
Vandaag om 13:24:51
Punt- en hartstukken door 1200blauw
Vandaag om 13:12:58
welk jaar ging Marklin OVP voor wagons van blauw naar wit door Bahn-AG
Vandaag om 12:42:50
US diorama in H0 door moonlicht
Vandaag om 12:40:54
Doornvliet door raymond erdtsieck
Vandaag om 12:23:03
U-vorm beperkte ruimte (H0 C-rails) door eitreb
Vandaag om 12:06:06
Leids spoor (voorheen Blauwpoortsbrug) door gdh
Vandaag om 11:55:50
7 april De Karel on tour door NL-modelspoor
Vandaag om 11:51:04
NS Tals wagons (kalktrein) door Arjan6511
Vandaag om 11:41:59
Ombouw/Pimpen Bolle neuzen door bollen neus
Vandaag om 11:19:47
Beekdaelen in H0 door VulcanRaven
Vandaag om 11:00:45
Stroomdetectie bij goederenwagens door henk
Vandaag om 10:32:03
MARDEC, de Multifunctionele ARduino dcc DECoder. door NTeering
Vandaag om 10:23:47
nieuw te leggen sporen passend maken door Jelmer
Vandaag om 10:05:07
MSV Post B, even voorstellen... door Rsd1000
Vandaag om 10:01:44
30 maart Modelspoorbeurs Houten & HCC Kennisdag door Jelmer
Vandaag om 09:52:49
Mijn eerste H0-modeltreinbaan in aanbouw door DJV
Vandaag om 09:42:59
Bouw van materieel 40 treinstellen door Pauldg
Vandaag om 07:52:09
NS 8400 van Werps door MathynK
Vandaag om 07:05:15
Al mijn goede ideeën... door bask185
28 maart 2024, 23:12:12
Gebruik je Arduino zonder te "programmeren" ;) door bask185
28 maart 2024, 22:51:58
21 april Het stoomgenootschap door bloemenvelden door Seinhuis
28 maart 2024, 22:46:29
  

Auteur Topic: Zelfbouw DCC++ Handregelaar  (gelezen 2818 keer)

Ronald1974

  • Gast
Zelfbouw DCC++ Handregelaar
« Gepost op: 20 april 2020, 18:59:12 »
In de afgelopen 6 maanden ben ik bezig geweest met de ontwikkeling en de bouw van een DCC++ handregelaar voor het aansturen van DCC++ basis station.
In middels heb ik de laatste hand gelegd aan de software (code).

Ik heb al een paar keer de vraag gekregen of ik wat meer hier over wil vertellen en laten zien.
Dat wil ik wel doen maar dan is mij vraag zijn er meer mensen die hier interesse in hebben ??

Hieronder alvast de code hoe ik het heb gedaan. (deel1)


///////////////////////////////////////////////////////////////////////////////////
//  Programmanaam   : DCC++ handregelaar
//  Versie          : 2.6
//  Datum versie    : 20 - 04 - 2020
//  Autheur         : Ronald Hofmeester
//  Auteursrecht (c): licentievrije, vrij te gebruiken
///////////////////////////////////////////////////////////////////////////////////

// Configuratie locomotieven.
// Pas het aantal aan.
// Toevoegen of verwijderen in LocAD, Rijrichting en Snelheid en SnelheidDCC.
// RegelaarRijStappen instelbaar tussen 0 tot max 255. default = 50.

const int Aantal = 5; // max 16
const int LocAD[Aantal] = {343, 351, 352, 1315, 2218};
byte Rijrichting[Aantal] = { 1, 1, 1, 1, 1};
int Snelheid[Aantal] = {0, 0, 0, 0, 0};
int SnelheidDCC[Aantal] = {0, 0, 0, 0, 0};
byte RegelaarRijStappen = 50;

// Library
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>

// Rotaryswitch
const int IO_pinCLK = 2;
const int IO_pinDT = 3;
int LaatsteStand = 0; // Laatste stand rotary switch
volatile int RotaryStand1 = 0;
volatile int RotaryStand2 = 0;
volatile int RotaryStand3 = 0;

// Drukknopen
const int AantalInputs = 7;
const int IO_pin[AantalInputs] = {4, 5, 6, 7, 8, 9, 10};
int InputStatus[AantalInputs];
int LaatsteInputStatus[AantalInputs] = {LOW, LOW, LOW, LOW, LOW, LOW, LOW};
bool InputVlag[AantalInputs] = {LOW, LOW, LOW, LOW, LOW, LOW, LOW};
int InputTeller[AantalInputs];
long LaatsteDebounceTijd[AantalInputs] = {0, 0, 0, 0, 0, 0, 0};
long DebounceVertraging = 50;

// Overige variabelen
bool Aan = 0, Functie = 0, MultiTractie = 0, Knop1 = 0, Knop2 = 0;
bool SetAllToZero = 0, SetStart = 0;
byte Reset1 = 0, Reset2 = 0;
int Rijstappen;
int KeuzeFunctie;
int KeuzeMultiTractie;
byte Parameter[Aantal];
byte ActieveLoc, LezenActieveLoc, TempActieveLoc;
byte FN0to4[Aantal];
byte FN5to8[Aantal];
byte FN9to12[Aantal];
byte FN13to20[Aantal];
byte FN21to28[Aantal];
const byte AantalGeheugenPlaatsen = 9;
byte Geheugen[AantalGeheugenPlaatsen] = {1, 0, 0, 0, 0, 0, 0, 0, 0};
bool Bezet1 = 0, Bezet2 = 0, Bezet3 = 0, Bezet4 = 0;
bool Lock = 0, LockMT = 0;
bool SetOpslaan = 0;

LiquidCrystal_I2C lcd(0x27, 16, 2);

void isr () {
  static unsigned long lastInterruptTime = 0;
  unsigned long interruptTime = millis();
  if (interruptTime - lastInterruptTime > 5) { // 5,
    if (digitalRead(IO_pinCLK) == LOW) {
      RotaryStand1-- ;
      RotaryStand2-- ;
      RotaryStand3-- ;
    }
    else {
      RotaryStand1++ ;
      RotaryStand2++ ;
      RotaryStand3++ ;
    }
  }
  RotaryStand1 = min(RegelaarRijStappen, max(0, RotaryStand1)); // Rijstappen
  RotaryStand2 = min(28, max(0, RotaryStand2)); // Functie
  RotaryStand3 = min(4, max(0, RotaryStand3)); // MultiTractie
  lastInterruptTime = interruptTime;
  if (Lock == 1) { // Let op lock door multitractie Slave 1 en of 2
    RotaryStand1 = 0;
  }
}
void setup() {
  Serial.begin(115200);
  Serial.print("<0>");
  Serial.println();

  for (int i = 0; i < AantalInputs; i++) {
    pinMode(IO_pin[i], INPUT);
    digitalWrite(IO_pin[i], HIGH);
  }
  pinMode (IO_pinCLK, INPUT);
  pinMode (IO_pinDT, INPUT);
  for (int i = 0; i < AantalGeheugenPlaatsen; i++) {
    Geheugen[i] = EEPROM.read(i);
  }
  for (int i = 0; i < Aantal; i++) {
    int A = ((i + 1) * 10);
    Parameter[i] = EEPROM.read(0 + A);
    Rijrichting[i] = EEPROM.read(1 + A);
    FN0to4[i] = EEPROM.read(2 + A);
    FN5to8[i] = EEPROM.read(3 + A);
    FN9to12[i] = EEPROM.read(4 + A);
    FN13to20[i] = EEPROM.read(5 + A);
    FN21to28[i] = EEPROM.read(6 + A);
  }

  lcd.begin();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("     DCC++      ");
  lcd.setCursor(0, 1);
  lcd.print("  Rijregelaar   ");
  delay(2200);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("     Versie     ");
  lcd.setCursor(0, 1);
  lcd.print("      2.6       ");
  delay(1500);
  lcd.clear();

  attachInterrupt(digitalPinToInterrupt(IO_pinDT), isr, LOW);
}
void loop() {
  SetInputVlag();
  ResultaatInputVlag();
  if (Aan == 0) {
    Main();
    Zero();
  }
  else if (Aan == 1) {
    Serial.print("<1>");
    Serial.println();
    if (Functie == 1) {
      RotaryStand1 = Rijstappen;
      KeuzeFunctie = RotaryStand2;
      SetFunctie();
    }
    if (MultiTractie == 1) {
      RotaryStand1 = Rijstappen;
      KeuzeMultiTractie = RotaryStand3;
      Parameter[ActieveLoc] = KeuzeMultiTractie;
      Reset2 = 0;
      SetMultiTractie();
    }
    if (Functie == 0 && MultiTractie == 0) {
      if (Reset2 <= 20) {
        Reset2++ ;
      }
      Rijstappen = RotaryStand1;
      RotaryStand2 = KeuzeFunctie;
      RotaryStand3 = Parameter[ActieveLoc];
      Rijden();
    }
  }

  // Geheugen Multitrctie

  if (Geheugen[1] - 1 == ActieveLoc) {
    Bezet1 = 1;
    if (Parameter[ActieveLoc] != 1) {
      Bezet1 = 0;
    }
  }
  if (Geheugen[2] - 1 == ActieveLoc) {
    Bezet2 = 1;
    if (Parameter[ActieveLoc] != 2) {
      Bezet2 = 0;
    }
  }
  if (Geheugen[3] - 1 == ActieveLoc) {
    Bezet3 = 1;
    if (Parameter[ActieveLoc] != 3) {
      Bezet3 = 0;
    }
  }
  if (Geheugen[4] - 1 == ActieveLoc) {
    Bezet4 = 1;
    if (Parameter[ActieveLoc] != 4) {
      Bezet4 = 0;
    }
  }
}
void Zero() { // zet alle locomotieven snelheid op nul.
  if (SetStart == 0) {
    SetAllToZero = 1;
  }
  if (SetAllToZero == 1) {
    Reset1++;
    for (int i = 0; i < Aantal; i++) {
      Serial.print("<1> <t1 ");
      Serial.print(LocAD[i] );
      Serial.print(" ");
      Serial.print("0");
      Serial.print(" ");
      Serial.print(Rijrichting[i] );
      Serial.write(" >");
      Serial.println();
      Snelheid[i] = 0;
    }
    if (Reset1 >= 10) {
      SetAllToZero = 0;
      SetStart = 1;
      Serial.print("<0>");
      Serial.println();
    }
  }
}
void SetInputVlag() {
  for (int i = 0; i < AantalInputs; i++) {
    int Lezen = digitalRead(IO_pin[i]);
    if (Lezen != LaatsteInputStatus[i]) {
      LaatsteDebounceTijd[i] = millis();
    }
    if ((millis() - LaatsteDebounceTijd[i]) > DebounceVertraging) {
      if (Lezen != InputStatus[i]) {
        InputStatus[i] = Lezen;
        Knop1 = !InputStatus[5];
        Knop2 = !InputStatus[6];
        if (InputStatus[i] == HIGH) {
          InputVlag[i] = HIGH;
        }
      }
    }
    LaatsteInputStatus[i] = Lezen;
  }
}
void ResultaatInputVlag() {
  for (int i = 0; i < AantalInputs; i++) {
    if (InputVlag[i] == HIGH) {
      InputTeller[i]++;
      Statusdrukknop(i);
      InputVlag[i] = LOW;
    }
  }
}
void Statusdrukknop(int input) {
  if (input == 0 && RotaryStand1 == 0 && SetStart == 1) { // Aan.
    if (Aan == 0) {
      Aan = 1;
    }
    else {
      Aan = 0;
      RotaryStand1 = 0;
    }
  }
  else if (input == 0 && Aan == 1) { // Uit.
    Aan = 0;
    RotaryStand1 = 0;
    Functie = 0;
    MultiTractie = 0;
  }
  else if (input == 4 && Rijstappen > 0 && Aan == 1 && Functie == 0 && MultiTractie == 0) { // Noodstop.
    Aan = 0;
    RotaryStand1 = 0;
    Reset1 = 0;
    SetStart = 0;
    Zero();
  }
  else if (input == 1 && Aan == 1 && Functie == 0 && MultiTractie == 0) { // Keuze locomotief
    if (Geheugen[0] == Aantal) {
      Geheugen[0] = 1;
    }
    else {
      Geheugen[0]++;
    }
  }
  else if (input == 2 && Aan == 1 && MultiTractie == 0) { // Doe functie
    if (Functie == 0) {
      Functie = 1;
    }
    else {
      Functie = 0;
    }
  }
  else if (((input == 3 && MultiTractie == 0) || (Knop2 == 1 && MultiTractie == 1)) && Aan == 1 && Rijstappen == 0 && Functie == 0) { //  Doe Multitractie
    if (MultiTractie == 0) {
      MultiTractie = 1;
    }
    else {
      MultiTractie = 0;
    }
  }
}
void SetFunctie() {
  if (KeuzeFunctie <= 4) {
    if (bitRead(FN0to4[ActieveLoc], KeuzeFunctie) == 0 ) {
      if (Knop1 == 1) {
        bitWrite(FN0to4[ActieveLoc], KeuzeFunctie, 1);
      }
    }
    else if (bitRead(FN0to4[ActieveLoc], KeuzeFunctie) == 1 ) {
      if (Knop2 == 1) {
        bitWrite(FN0to4[ActieveLoc], KeuzeFunctie, 0);
      }
    }
  }
  else if (KeuzeFunctie >= 5 && KeuzeFunctie <= 8) {
    if (bitRead(FN5to8[ActieveLoc], KeuzeFunctie - 5) == 0 ) {
      if (Knop1 == 1) {
        bitWrite(FN5to8[ActieveLoc], KeuzeFunctie - 5, 1);
      }
    }
    else if (bitRead(FN5to8[ActieveLoc], KeuzeFunctie - 5) == 1 ) {
      if (Knop2 == 1) {
        bitWrite(FN5to8[ActieveLoc], KeuzeFunctie - 5, 0);
      }
    }
  }
  else if (KeuzeFunctie >= 9 && KeuzeFunctie <= 12) {
    if (bitRead(FN9to12[ActieveLoc], KeuzeFunctie - 9) == 0 ) {
      if (Knop1 == 1) {
        bitWrite(FN9to12[ActieveLoc], KeuzeFunctie - 9, 1);
      }
    }
    else if (bitRead(FN9to12[ActieveLoc], KeuzeFunctie - 9) == 1 ) {
      if (Knop2 == 1) {
        bitWrite(FN9to12[ActieveLoc], KeuzeFunctie - 9, 0);
      }
    }
  }
  else if (KeuzeFunctie >= 13 && KeuzeFunctie <= 20) {
    if (bitRead(FN13to20[ActieveLoc], KeuzeFunctie - 13) == 0 ) {
      if (Knop1 == 1) {
        bitWrite(FN13to20[ActieveLoc], KeuzeFunctie - 13, 1);
      }
    }
    else if (bitRead(FN13to20[ActieveLoc], KeuzeFunctie - 13) == 1 ) {
      if (Knop2 == 1) {
        bitWrite(FN13to20[ActieveLoc], KeuzeFunctie - 13, 0);
      }
    }
  }
  else if (KeuzeFunctie >= 21 && KeuzeFunctie <= 28) {
    if (bitRead(FN21to28[ActieveLoc], KeuzeFunctie - 21) == 0 ) {
      if (Knop1 == 1) {
        bitWrite(FN21to28[ActieveLoc], KeuzeFunctie - 21, 1);
      }
    }
    else if (bitRead(FN21to28[ActieveLoc], KeuzeFunctie - 21) == 1 ) {
      if (Knop2 == 1) {
        bitWrite(FN21to28[ActieveLoc], KeuzeFunctie - 21, 0);
      }
    }
  }
  lcd.setCursor(0, 0);
  lcd.print("Set Functie      ");
  lcd.setCursor(0, 1);
  lcd.print("#");
  lcd.print(ActieveLoc + 1, DEC);
  lcd.print("  ");
  lcd.setCursor(4, 1);
  lcd.print("F=");
  if (KeuzeFunctie >= 0 && KeuzeFunctie <= 3) {
    lcd.print(KeuzeFunctie + 1, DEC);
    lcd.print("  ");
    lcd.setCursor(9, 1);
    if (bitRead(FN0to4[ActieveLoc], KeuzeFunctie) == 0) {
      lcd.print("UIT");
    }
    else if (bitRead(FN0to4[ActieveLoc], KeuzeFunctie) == 1) {
      lcd.print("AAN");
    }
  }
  else if (KeuzeFunctie == 4) {
    lcd.print(0, DEC);
    lcd.print("  ");
    lcd.setCursor(9, 1);
    if (bitRead(FN0to4[ActieveLoc], KeuzeFunctie) == 0) {
      lcd.print("UIT");
    }
    else if (bitRead(FN0to4[ActieveLoc], KeuzeFunctie) == 1) {
      lcd.print("AAN");
    }
  }
  else if (KeuzeFunctie >= 5 && KeuzeFunctie <= 8) {
    lcd.print(KeuzeFunctie, DEC);
    lcd.print("  ");
    lcd.setCursor(9, 1);
    if (bitRead(FN5to8[ActieveLoc], KeuzeFunctie - 5) == 0) {
      lcd.print("UIT");
    }
    else if (bitRead(FN5to8[ActieveLoc], KeuzeFunctie - 5) == 1) {
      lcd.print("AAN");
    }
  }
  else if (KeuzeFunctie >= 9 && KeuzeFunctie <= 12) {
    lcd.print(KeuzeFunctie, DEC);
    lcd.print("  ");
    lcd.setCursor(9, 1);
    if (bitRead(FN9to12[ActieveLoc], KeuzeFunctie - 9) == 0) {
      lcd.print("UIT");
    }
    else if (bitRead(FN9to12[ActieveLoc], KeuzeFunctie - 9) == 1) {
      lcd.print("AAN");
    }
  }
  else if (KeuzeFunctie >= 13 && KeuzeFunctie <= 20) {
    lcd.print(KeuzeFunctie, DEC);
    lcd.print("  ");
    lcd.setCursor(9, 1);
    if (bitRead(FN13to20[ActieveLoc], KeuzeFunctie - 13) == 0) {
      lcd.print("UIT");
    }
    else if (bitRead(FN13to20[ActieveLoc], KeuzeFunctie - 13) == 1) {
      lcd.print("AAN");
    }
  }
  else if (KeuzeFunctie >= 21 && KeuzeFunctie <= 28) {
    lcd.print(KeuzeFunctie, DEC);
    lcd.print("  ");
    lcd.setCursor(9, 1);
    if (bitRead(FN21to28[ActieveLoc], KeuzeFunctie - 21) == 0) {
      lcd.print("UIT");
    }
    else if (bitRead(FN21to28[ActieveLoc], KeuzeFunctie - 21) == 1) {
      lcd.print("AAN");
    }
  }
  if (KeuzeFunctie >= 0 && KeuzeFunctie <= 4) {
    Serial.print("<f ");
    Serial.print(LocAD[ActieveLoc] );
    Serial.print(" ");
    int fx = FN0to4[ActieveLoc] + 128;
    Serial.print(fx);
    Serial.write(" >");
    Serial.println();
  }
  if (KeuzeFunctie >= 5 && KeuzeFunctie <= 8) {
    Serial.print("<f ");
    Serial.print(LocAD[ActieveLoc] );
    Serial.print(" ");
    int fx = FN5to8[ActieveLoc] + 176;
    Serial.print(fx);
    Serial.write(" >");
    Serial.println();
  }
  if (KeuzeFunctie >= 9 && KeuzeFunctie <= 12) {
    Serial.print("<f ");
    Serial.print(LocAD[ActieveLoc] );
    Serial.print(" ");
    int fx = FN9to12[ActieveLoc] + 160;
    Serial.print(fx);
    Serial.write(" >");
    Serial.println();
  }
  if (KeuzeFunctie >= 13 && KeuzeFunctie <= 20) {
    Serial.print("<f ");
    Serial.print(LocAD[ActieveLoc] );
    Serial.print(" ");
    Serial.print("222");
    Serial.print(" ");
    int fx = FN13to20[ActieveLoc];
    Serial.print(fx);
    Serial.write(" >");
    Serial.println();
  }
  if (KeuzeFunctie >= 21 && KeuzeFunctie <= 28) {
    Serial.print("<f ");
    Serial.print(LocAD[ActieveLoc] );
    Serial.print(" ");
    Serial.print("223");
    Serial.print(" ");
    int fx = FN21to28[ActieveLoc];
    Serial.print(fx);
    Serial.write(" >");
    Serial.println();
  }
}
void SetMultiTractie() {
  if ((KeuzeMultiTractie == 1 && Bezet1 == 1) || (KeuzeMultiTractie == 2 && Bezet2 == 1) || (KeuzeMultiTractie == 3 && Bezet3 == 1) || (KeuzeMultiTractie == 4 && Bezet4 == 1)) {
    LockMT = 1;
  }
  else LockMT = 0;
  if (Knop2 == 1 && LockMT == 0) {
    if (Parameter[ActieveLoc] == 1) {
      Geheugen[1] = ActieveLoc + 1;
      bitWrite(Geheugen[5], 0, Rijrichting[ActieveLoc]);
    }
    else if (Parameter[ActieveLoc] == 2) {
      Geheugen[2] = ActieveLoc + 1;
      bitWrite(Geheugen[5], 1, Rijrichting[ActieveLoc]);
    }

    else if (Parameter[ActieveLoc] == 3) {
      Geheugen[3] = ActieveLoc + 1;
      bitWrite(Geheugen[6], 0, Rijrichting[ActieveLoc]);
    }
    else if (Parameter[ActieveLoc] == 4) {
      Geheugen[4] = ActieveLoc + 1;
      bitWrite(Geheugen[6], 1, Rijrichting[ActieveLoc]);
    }
    if (Geheugen[1] - 1 == ActieveLoc) {
      if (Parameter[ActieveLoc] != 1) {
        Geheugen[1] = 0;
      }
    }
    else if (Geheugen[2] - 1 == ActieveLoc) {
      if (Parameter[ActieveLoc] != 2) {
        Geheugen[2] = 0;
      }
    }
    else if (Geheugen[3] - 1 == ActieveLoc) {
      if (Parameter[ActieveLoc] != 3) {
        Geheugen[3] = 0;
      }
    }
    else if (Geheugen[4] - 1 == ActieveLoc) {
      if (Parameter[ActieveLoc] != 4) {
        Geheugen[4] = 0;
      }
    }
    MultiTractie = 0;
  }
  lcd.setCursor(0, 0);
  lcd.print("Set Multitractie");
  lcd.setCursor(0, 1);
  lcd.print("#");
  lcd.print(ActieveLoc + 1, DEC);
  lcd.print("  ");
  lcd.setCursor(3, 1);
  lcd.print("=");
  if (Parameter[ActieveLoc] == 0) {
    lcd.setCursor(4, 1);
    lcd.print("Geen        ");
  }
  else if (Parameter[ActieveLoc] == 1) {
    lcd.setCursor(4, 1);
    lcd.print("Master1");
    lcd.setCursor(11, 1);
    if (Bezet1 == 1) {
      lcd.print("Bezet");
    }
    else lcd.print("Vrij ");
  }
  else if (Parameter[ActieveLoc] == 2) {
    lcd.setCursor(4, 1);
    lcd.print("Slave1 ");
    lcd.setCursor(11, 1);
    if (Bezet2 == 1) {
      lcd.print("Bezet");
    }
    else lcd.print("Vrij ");
  }
  else if (Parameter[ActieveLoc] == 3) {
    lcd.setCursor(4, 1);
    lcd.print("Master2");
    lcd.setCursor(11, 1);
    if (Bezet3 == 1) {
      lcd.print("Bezet");
    }
    else lcd.print("Vrij ");
  }
  else if (Parameter[ActieveLoc] == 4) {
    lcd.setCursor(4, 1);
    lcd.print("Slave2 ");
    lcd.setCursor(11, 1);
    if (Bezet4 == 1) {
      lcd.print("Bezet");
    }
    else lcd.print("Vrij ");
  }
}









Mvg Ronald Hofmeester.

Ronald1974

  • Gast
Re: Zelfbouw DCC++ Handregelaar
« Reactie #1 Gepost op: 20 april 2020, 19:00:12 »
Deel2

void Rijden() {
  ActieveLoc = Geheugen[0] - 1;
  LocAD[ActieveLoc];
  if (TempActieveLoc != ActieveLoc) {
    RotaryStand1 = Snelheid[ActieveLoc];
  }
  TempActieveLoc = ActieveLoc;
  if (TempActieveLoc == ActieveLoc) {
    Snelheid[ActieveLoc] = Rijstappen;
  }
  SnelheidDCC[ActieveLoc] = map(Snelheid[ActieveLoc], 0, RegelaarRijStappen, 0, 126);
  if (RotaryStand1 == 0 && Reset2 >= 20) { // Rijrichting
    if (Rijrichting[ActieveLoc] == 1 && Knop1 == 1) {
      Rijrichting[ActieveLoc] = 0;
    }
    if (Rijrichting[ActieveLoc] == 0 && Knop2 == 1) {
      Rijrichting[ActieveLoc] = 1;
    }
  }
  if (Geheugen[1] > 0 && Geheugen[2] > 0) {
    if (Geheugen[5] == 0 || Geheugen[5] == 3) {
      Geheugen[7] = 1;
    }
    else if (Geheugen[5] == 1 || Geheugen[5] == 2) {
      Geheugen[7] = 0;
    }
  }
  if (Geheugen[3] > 0 && Geheugen[4] > 0) {
    if (Geheugen[6] == 0 || Geheugen[6] == 3) {
      Geheugen[8] = 1;
    }
    else  if (Geheugen[6] == 1 || Geheugen[6] == 2) {
      Geheugen[8] = 0;
    }
  }
  if ((Geheugen[2] - 1 == ActieveLoc) || (Geheugen[4] - 1 == ActieveLoc)) {
    Lock = 1;
  }
  else Lock = 0;
  lcd.setCursor(0, 0); // LCD Rijden
  lcd.print("L=");
  lcd.print(LocAD[ActieveLoc], DEC);
  lcd.print("    ");
  if (MultiTractie == 0) {
    if (Parameter[ActieveLoc] == 0) {
      lcd.setCursor(6, 0);
      lcd.print("       ");
    }
    else if (Parameter[ActieveLoc] == 1 && Bezet1 == 1) {
      lcd.setCursor(6, 0);
      lcd.print("Master1");
    }
    else if (Parameter[ActieveLoc] == 2 && Bezet2 == 1) {
      lcd.setCursor(6, 0);
      lcd.print("Slave1 ");
    }
    else if (Parameter[ActieveLoc] == 3 && Bezet3 == 1) {
      lcd.setCursor(6, 0);
      lcd.print("Master2");
    }
    else if (Parameter[ActieveLoc] == 4 && Bezet4 == 1) {
      lcd.setCursor(6, 0);
      lcd.print("Slave2 ");
    }
  }
  lcd.setCursor(13, 0);
  lcd.print("#");
  lcd.print(ActieveLoc + 1, DEC);
  lcd.print("  ");
  lcd.setCursor(0, 1);
  lcd.print("S=");
  if (Lock == 0) {
    lcd.print(Snelheid[ActieveLoc], DEC);
    lcd.print("   ");
  }
  else if (Lock == 1) {
    lcd.print("Lock");
  }
  if (Rijrichting[ActieveLoc] == 1) {
    lcd.print(" >>>        ");
  }
  else lcd.print(" <<<       ");
  Serial.print("<t1 ");
  Serial.print(LocAD[ActieveLoc]);
  Serial.print(" ");
  Serial.print(SnelheidDCC[ActieveLoc]);
  Serial.print(" ");
  Serial.print(Rijrichting[ActieveLoc] );
  Serial.write(">");
  Serial.println();
  if (Geheugen[1] > 0 && Geheugen[2] > 0) {
    if (Geheugen[1] - 1 == ActieveLoc) {
      Serial.print("<t1 ");
      Serial.print(LocAD[Geheugen[2] - 1] );
      Serial.print(" ");
      Serial.print(SnelheidDCC[ActieveLoc] );
      Serial.print(" ");
      if (Geheugen[7] == 1) {
        Serial.print(Rijrichting[ActieveLoc] );
      }
      else if (Geheugen[7] == 0) {
        Serial.print(!Rijrichting[ActieveLoc] );
      }
      Serial.write(">");
      Serial.println();
    }
  }
  if (Geheugen[3] > 0 && Geheugen[4] > 0) {
    if (Geheugen[3] - 1 == ActieveLoc) {
      Serial.print("<t1 ");
      Serial.print(LocAD[Geheugen[4] - 1] );
      Serial.print(" ");
      Serial.print(SnelheidDCC[ActieveLoc] );
      Serial.print(" ");
      if (Geheugen[8] == 1) {
        Serial.print(Rijrichting[ActieveLoc] );
      }
      else if (Geheugen[8] == 0) {
        Serial.print(!Rijrichting[ActieveLoc] );
      }
      Serial.write(">");
      Serial.println();
    }
  }
}
void Main() {
  if (Knop1 == 1) {
    SetOpslaan = 1 ;
  }
  if (SetOpslaan == 1) {
    lcd.setCursor(0, 0);
    lcd.print(" Om op te slaan ");
    lcd.setCursor(0, 1);
    lcd.print(" Druk op Enter  ");
  }
  if (SetOpslaan == 1 && Knop2 == 1) {
    Opslaan();
  }
  if (SetOpslaan == 0) {
    lcd.setCursor(0, 0);
    lcd.print("Stop (Noodstop)");
    lcd.setCursor(0, 1);
    lcd.print("                ");
  }
  if (SetStart == 1) {
    Serial.print("<0>");
    Serial.println();
  }
}
void Opslaan() {
  for (int i = 0; i < AantalGeheugenPlaatsen; i++) {
    EEPROM.write(i, Geheugen[i]);
  }
  for (int i = 0; i < Aantal; i++) {
    int A = ((i + 1) * 10);
    EEPROM.write(0 + A, Parameter[i]);
    EEPROM.write(1 + A, Rijrichting[i]);
    EEPROM.write(2 + A, FN0to4[i]);
    EEPROM.write(3 + A, FN5to8[i]);
    EEPROM.write(4 + A, FN9to12[i]);
    EEPROM.write(5 + A, FN13to20[i]);
    EEPROM.write(6 + A, FN21to28[i]);
  }
  SetOpslaan = 0;
}

PeterC

  • Offline Offline
  • Berichten: 244
Re: Zelfbouw DCC++ Handregelaar
« Reactie #2 Gepost op: 20 april 2020, 20:59:48 »
Hallo Ronald,

Ik heb zeker interesse in deze handregelaar. Ik heb jouw bouwkunsten ook in stilte gevolgd in jouw draadje echter, nooit gereageerd. Maar ik heb bewondering wat jij allemaal kunt maken en de wijze waarop je het doet, ik doe het je niet na.  (y)

PeterC

Duikeend

  • Team forummoderators
  • Offline Offline
  • Berichten: 2314
Re: Zelfbouw DCC++ Handregelaar
« Reactie #3 Gepost op: 20 april 2020, 21:35:48 »
uiteraard ben ik ook geïnteresseerd! ik had al eens zoiets op youtube gezien en me voor genomen daar mee te gaan stoeien maar zoals bij velen.. te weinig tijd  ;) maar dat gaat zeker nog gebeuren dus ik ga je volgen  ;D
Huidige projectje: mijn knutsels, 1500 in parts en een
hondekop

bask185

  • Offline Offline
  • Berichten: 4009
Re: Zelfbouw DCC++ Handregelaar
« Reactie #4 Gepost op: 21 april 2020, 09:52:14 »
het is grappig, want ik heb de mijne ook aan de praat gekregen vorig weekend. Ik had alleen nog wat ruzie met mijn eigen DCC software van de centrale. Ik heb nog steeds het probleem dat herhaal instructies niet altijd aankomen. Maar nieuwe instructies komen wel binnen dus ik kan iig rijden. En het geheel is draadloos  (y)

Ik kan er misschien vanavond nog wel wat over vertellen? Ik heb wel wat minder functionaliteiten. Mijn handcontroller is meer een soort doorgeefluik. Ik druk dingen in, dat stuur ik op en de centrale geeft antwoord. Dit antwoord zet bij de texten op het LCD van de hand controller. Zo weet ik 100% zeker wat de huidige stand van zaken is. Dit heeft als voordeel dat de handcontroller zelf nauwelijks geheugen nodig heeft.

Ik kan er bijvoorbeeld geen multitracties meemaken of treinen mee programmeren. Ik heb dan wel weer een keypad met getalletjes. Ik heb van de MS1 geleerd dat het scrollen en zoeken naar locs ellendig is en dat het beter is om gewoon een adres in te voeren en meteen controlle over te nemen. Met een potmeter kan ik naar links en naar rechts rijden. Ik ben zelf minder van de encoder, maar dit komt ook door slechte ervaringen met M* apparatuur.

Ik heb inmiddels ook een handshake protocol. Als de verbinding wordt verbroken, dan valt de boel stil. Op een paar fine tune dingen na ben ik erg tevreden.

Mvg,

Bas
Train-Science.com
Train-Science github
It ain't rocket science ;-)

Ronald1974

  • Gast
Re: Zelfbouw DCC++ Handregelaar
« Reactie #5 Gepost op: 21 april 2020, 13:12:07 »
Hoi Bas,

Citaat
Ik kan er bijvoorbeeld geen multitracties meemaken of treinen mee programmeren

Programmeren doe ik met JMRI en gebruik dan alleen de Basis station zonder handregelaar.
Ben wel aan het experimenteren om CV's te kunnen uit lezen als dat werkt dan is de volgende stap Schrijven.

Multitractie of dubbeltractie is maar hoe je het wil noemen.
Daar heb ik best wel veel tijd in gestoken om dit goed werkend te krijgen.
Je kan kiezen of de loc de master of de slave is of geen van beide.
Ook wordt er gekeken of de rijrichting van de master en de slave gelijk zijn of verschillend.
Is deze gelijk dan krijg de slave de rijrichting van de master is deze verschillend dan krijg de slave de rijrichting van de master geïnverteerd.
Ook de snelheids regeling van de slave krijg een lock en volgt de master.
Heb nu de mogelijkheid om twee multitracties uit te voeren en op te slaan.

De toevoeging waar ik nog aan werk is.
Bediening accessoires (wissels en seinen).
Bediening Vaste rijwegen.

Verder ben ik bezig met DCC naar I2C, AccDecoderPacket naar twee bytes via i2c bus naar de twee bedienings panelen.
Locaal de baan (wissels en seinen)bedienen via twee panelen.
Of remote vanaf de handregelaar of via JMRI server met de tablet of vanuit JMRI panelPro.

Nog genoeg te doen de komende maanden.

Mvg Ronald Hofmeester.


bask185

  • Offline Offline
  • Berichten: 4009
Re: Zelfbouw DCC++ Handregelaar
« Reactie #6 Gepost op: 21 april 2020, 14:05:42 »
Hallo Ronald,

ik snapte deze zin niet helemaal:
Citaat
verder ben ik bezig met DCC naar I2C, AccDecoderPacket naar twee bytes via i2c bus naar de twee bedienings panelen.

Als ik het goed begrijp wil je met arduino DCC signalen voor accessories uitlezen om wissels en dergelijken te schakelen, maar je wilt ook op deze I2C bus een schakelpaneel hebben zodat je ipv DCC signalen een knopje kan gebruiken om ook deze dingen te schakelen. Dat scheelt natuurlijk draadjes trekken.

Weet je al wat voor I2C chips ga je gebruiken? Ik ben zelf erg gelukkig met de MCP23017.
Ik heb er ook al code voor gemaakt waarmee je ontzettend makkelijk die dingen kan aansturen.
mcpWrite(pin, state);
mcpRead(pin);
Ze doen hetzelfde als digitalWrite/digitalRead. Het mooie is dat deze functies het I2C adres, de port en het pinnummer berekent. Je hoeft dan nooit meer te onthouden, welke IO op welke port van welke chip zit. optioneel kan ik met een pyhton script alle initialisatie code voor die MCP dingen ook nog voor me laten maken door mn computer.

pin nummers 0 t/m 15 zitten op de eerste chip, 16 t/m 31 op de 2e chip etc. De enige voorwaarde is dat de I2C chips oplopende adressen moeten hebben van 0x20 t/m 0x27. Maar dat zou geen probleem moeten zijn.

Ik doe voor mijn baan precies hetzelfde, alleen heb ik DCC vervangen door mijn eigen rs485 bus die 2 kanten op kan praten.


In dit schakel paneel heb ik 2 van die MCP23017 chips zitten. Daarmee heb ik 32 inputs en outputs in dat schakel paneel zitten. Dat printje rechts onder heeft de 3e MCP23017 daarin gaan de bezetmelders en ik kan er relais mee schakelen.  Dat losse ding helemaal onderin (is inmiddels ook op een print gesoldeerd) kan 16 servo motors aansturen en werkt ook via diezelfde I2C bus. Die print rechts boven heeft een arduino nano, een max485 module voor de communicatie bus naar de centrale en 2 I2C aansluitingen voor de flatcables.

Die knopjes bedienen ook geen wissels maar hele wisselstraten tegelijk. Tot op heden laat ik een raspberry pi opslaan welke wissels er bij welke drukknop horen, maar dat zou ook op de arduino zelf kunnen geschieden. Ik stuur dus een 'knopjesdruk' naar de centrale, die kijkt welke wissels er omgezet moeten  worden en de centrale stuurt de wissel instructies dan terug.

Als ik dit lokaal zou willen doen (daar heb ik over nagedacht) dan zou ik een I2C EEPROM nemen (de onboard eeprom heeft te weinig geheugen hiervoor). Dan kan op die EEPROM alle informatie opslaan die je wilt (wisselstraten, servo posities noem het op). En elke arduino kan een universeel programma krijgen. Dan kan je achter je computer met een andere arduino die EEPOM voor je branden en dan kan je die EEPROM op je arduino onder je baan prikken in een IC voet. Als je dan IO aanpast, extra wisseltje, extra seintje, dan kan je die EEPROM er uit halen, opnieuw branden met de nieuwe dingetjes, en je prikt de EEPROM terug.

Dan hoef je nooit meer het programma van de arduino's die onder je baan zitten aan te passen.

In ieder geval ideeen zat en tijd te kort voor mij :(. Als je (of iemand anders) code nodig heb of vragen heb, vraag maar raak!

Mvg,

Bas







Train-Science.com
Train-Science github
It ain't rocket science ;-)

Ronald1974

  • Gast
Re: Zelfbouw DCC++ Handregelaar
« Reactie #7 Gepost op: 21 april 2020, 14:59:30 »
Bas,
Citaat
ik snapte deze zin niet helemaal:
Als ik het goed begrijp wil je met arduino DCC signalen voor accessories uitlezen om wissels en dergelijken te schakelen, maar je wilt ook op deze I2C bus een schakelpaneel hebben zodat je ipv DCC signalen een knopje kan gebruiken om ook deze dingen te schakelen. Dat scheelt natuurlijk draadjes trekken.

Dit is wat ik heb.



Het volgende wil ik gaan toevoegen zodat ik ook remote kan gaan bedienen.
Een dcc accessory decoder met in plaats van I/O uitgangen een I²C bus.



Mvg Ronald Hofmeester.

bask185

  • Offline Offline
  • Berichten: 4009
Re: Zelfbouw DCC++ Handregelaar
« Reactie #8 Gepost op: 21 april 2020, 15:54:09 »
Wat je wilt, kan natuurlijk, maar je doet wel iets moeilijker dan nodig is.

Die hele linker arduino is overbodig. Kan je niet net zo makkelijk postT de DCC signalen laten afsnoopen? Is er ook een rede waarom je perse I2C wilt gebruiken? Je zou in dit geval ook afkunnen met een software serial Rx/Tx verbindinkje. Ik gebruik zelf I2C omdat ik geen 100 draden wil trekken van schakel paneel -> arduino -> alle baan accesoires.


Ik zou het dan zo doen. Nu had ik in je Hoekdam draadje al gezien dat de verbindingen tussen arduino en schakelpanelen al lagen. Dus die I2C lijntjes van en naar schakelpanelen moet je maar wegdenken.

Je kan ook overwegen om een Rs485 bus te gebruiken omdat die makkelijker uitbreidbaar is naar meer Arduino's (+ die max485 modules kosten iets van €1,50 p/s). Die werken gewoon met je standaard Rx/Tx pinnen en je hebt geen aparte libraries nodig. Als je nu een derde arduino wilt toevoegen dan zou dat wss via software serial moeten. Doe je dat met Rs485 dan krijg je zo'n topology:

Je kan met Rs485 ook meters overbruggen zonder fouten, met I2C kan je misschien tot een meter zonder problemen te ervaren. En je kan zo een nieuwe arduino op de bus aansluiten.

Belangrijkste is dat je natuurlijk doet wat jij makkelijk vindt, ik wil je er alleen op wijzen dat postT ook prima DCC signalen kan afluisteren en dat bespaart je 1 arduino en wat werk. Als je met je IO in de knoop zit, je kan ook alle analoge pinnen (ook A4 en A5 die je voor I2C gebruikt) als digitale pinnen inzetten.

Mvg,

Bas
Train-Science.com
Train-Science github
It ain't rocket science ;-)

Ronald1974

  • Gast
Re: Zelfbouw DCC++ Handregelaar
« Reactie #9 Gepost op: 21 april 2020, 18:31:48 »
Hoi Bas,

Heb net nog even goed gekeken, de Arduino Post T heeft alleen A4 en A5 vrij vandaar de gedachte van een toevoeging van een Arduino via i²c omdat ik geen interrupt pin vrij hebt.
Maar bij Arduino Post I blijkt dat daar I/O pin 9 vrij is, dus als ik pin 2 t/m pin 8 opschuift naar pin 3 t/m pin 9.
Daarmee  komt interrupt pin 2 vrij welke ik nodig hebt voor het aanbieden van het DCC signaal via optocopper.

De kabel van de seriële verbinding is 2,8 meter lang, heb gemerkt dat boven de 5 meter de communicatie ging haperen dus met 3 meter er tussen zijn er geen problemen.

Mvg Ronald Hofmeester.
« Laatst bewerkt op: 21 april 2020, 18:46:19 door Ronald1974 »

Ronald1974

  • Gast
Re: Zelfbouw DCC++ Handregelaar
« Reactie #10 Gepost op: 21 april 2020, 18:41:12 »
Bij deze,

Deel 1 zelfbouw DCC++ Handregelasr

Het aansluitschema.



Binnen kort weer meer.

Mvg Ronald Hofmeester.

bask185

  • Offline Offline
  • Berichten: 4009
Re: Zelfbouw DCC++ Handregelaar
« Reactie #11 Gepost op: 21 april 2020, 19:16:33 »
In principe heeft elke pin een op de UNO een interrupt functie alleen is de functionaliteit iets meer beperkt dan de 'echte' interrupt pinnen. Zo reageren ze ook standaard op zowel opgaande als neergaande flanken. Die software serial library maakt daar ook gebruik maken.

Die 16 pulsjes per omwenteling encoders hebben overigens niet echt een interrupt nodig. Die kan je rustig pollen + het is geen ramp als je een pulsje mist.

Wat je trouwens ook nog kan doen. Dingen als drukknopjes kan je allemaal inlezen met 1 analoge ingang. Dan hang je alle knopjes met ~1000ohm aan de 5V. En de kant van de knopjes verbind je ook met een analoge ingang. Vervolgens moet je de schakelkant van elke knop met een verschillende weerstandswaarde per knop verbinden aan de ground. Zo maakt elk knopje een unieke spanningsdeling.

Ik kan zo wel even een tekening maken. Zit nu naar Rutte te luisteren. Maar zo kan je dus met 1 ingang meer knoppen inlezen dan dat een UNO io pinnen heeft.
Train-Science.com
Train-Science github
It ain't rocket science ;-)

Ronald1974

  • Gast
Re: Zelfbouw DCC++ Handregelaar
« Reactie #12 Gepost op: 21 april 2020, 19:38:09 »
Bas de panelen zijn voorzien van spanning delers.





Voor dit paneel gebruik ik 1 digitale uitgang voor de LED en twee analoge ingangen voor de schakelaars.
Vier schakelaars per ingang.

Mvg Ronald Hofmeester.

bask185

  • Offline Offline
  • Berichten: 4009
Re: Zelfbouw DCC++ Handregelaar
« Reactie #13 Gepost op: 21 april 2020, 20:41:32 »
 (y) (y)
Train-Science.com
Train-Science github
It ain't rocket science ;-)

Ronald1974

  • Gast
Re: Zelfbouw DCC++ Handregelaar
« Reactie #14 Gepost op: 08 mei 2020, 13:00:57 »
Ik zal volgende week deel 2 van de zelfbouw DCC++ handregelaar hier gaan plaatsen.
Deel 2 zal gaan over de functionele tijd en de bediening van de handregelaar.
Voor wie het gemist heeft deel 1 staat in reactie #10

Mvg Ronald Hofmeester.