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

Toon hier je nieuwe (model-) spooraanwinst(en)... door Nullus
Vandaag om 16:29:51
MARDEC, de Multifunctionele ARduino dcc DECoder. door bord4kop
Vandaag om 16:29:12
Gebruik je Arduino zonder te "programmeren" ;) door fleischmann1
Vandaag om 16:18:39
Ombouw/Pimpen Bolle neuzen door bollen neus
Vandaag om 15:58:15
Welke Vallejo kleur voor drijfstangen van een DB stoomlocomotief? door aad52
Vandaag om 15:33:13
Al mijn goede ideeën... door bask185
Vandaag om 15:23:03
US diorama in H0 door VAM65
Vandaag om 15:22:05
Beekdaelen in H0 door VulcanRaven
Vandaag om 15:15:11
Hengelo in 1981-1982, maar dan anders: Kassenberg in N door spoorijzer
Vandaag om 15:08:30
Kleine Baan in H0 (≤ 0.5m²) door Jack Black (NS1220)
Vandaag om 15:06:14
U-vorm beperkte ruimte (H0 C-rails) door Jelmer
Vandaag om 14:58:04
Onlangs gespot - gefotografeerd, de links door Jeroen Water
Vandaag om 14:33:00
N spur scenery elementen maken van gips of klei? door Dave.......
Vandaag om 14:30:06
De overeenkomst tussen een Ovaalramer en een Motorpost. door RK
Vandaag om 14:28:54
Onlangs gespot - gefotografeerd, de foto's door mass am see
Vandaag om 14:18:46
BMB-Module: “Corfe Castle Station” door Hans van de Burgt
Vandaag om 14:07:52
welk jaar ging Marklin OVP voor wagons van blauw naar wit door Railman
Vandaag om 13:40:42
GSS Jubileumbaantje (0e / 0n30) door MacArthur
Vandaag om 12:55:30
NTM P1 in Schaal-1 door MaraNCS
Vandaag om 11:39:38
Mijn eerste H0-modeltreinbaan in aanbouw door Jack Black (NS1220)
Vandaag om 11:33:00
Rio Grande Southern - Lizard Head Pass door Hans GJ
Vandaag om 11:30:20
Bauarbeiten im gange door Dave.......
Vandaag om 10:55:26
Variaties op Station Zetten Andelst in HO door Duikeend
Vandaag om 10:54:40
De IJmuider spoorlijn - korte geschiedenis en plaatjes door Vislijn
Vandaag om 10:42:29
Internationale Spoor 0 en 1 dagen in Gießen, 23 en 24 maart, 2024 door bernhard67
Vandaag om 08:42:53
De Hondsrugbaan door mass am see
Vandaag om 08:15:11
Pfarrerwinkel bahn door Jelmer
Vandaag om 08:00:19
M.s.v. De Percee bouwt aan nieuwe clubbaan door J. Moors
Vandaag om 01:00:05
30 maart Modelspoorbeurs Houten & HCC Kennisdag door WimM
Vandaag om 00:42:50
Raadplaatje door Magic
27 maart 2024, 23:27:03
  

Auteur Topic: Zelfbouw DCC++ Handregelaar  (gelezen 2815 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: 4007
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: 4007
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: 4007
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: 4007
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: 4007
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.