Schattenbahnhofsteuerung

Hallo Fony,
danke für den Hinweis, doch das Programm funktioniert so nicht. Ich habe ein paar Stunden versucht, es hinzubekommen, aber es sind zu viele Fehler beim kompilieren: z.B. pinmode statt pinmode1; MCP statt MCP23S17; pullupmode gibts in der library nicht ...
War leider nicht erfolgreich.

https://forum.arduino.cc/t/reading-mcp23s17/1213890
Da hatte jemand ein ähnliches Problem, seine Lösung hat mir leider auch nicht geholfen.

Hallo Noiasca,

danke nochmal für deine Zeit und den Sketch. Ich habe ihn kopiert, die Adesse des cs von 6 auf 53 geändert constexpr uint8_t csPinA {53}; und kompiliert.
Die Schalter funktionieren,
Serial Monitor:
gerade 0
abschalten
abbiegen 1
abschalten

nur die LEDs am A0 und A1 gehen nicht für die 2s an. Woran kann das liegen?
LG Andy

Theoretisch fehlen in der Weichenklasse bei den Hardwarezugriffen (pinmode, digitalWrite, digitalread) die Verweise auf den jeweiligen MCP.

sollte z.B. mcp.digitalWrite() heißen.

ich habs mal upgedated

vieleicht fehlt noch was - hab hier keine Hardware...

Hallo Noiasca,
vielen Dank für den prompten Fix. Ich hab ihn mal als neuen "Sketch V3" ebenfalls mit pin 53 statt 6 angelegt.
Leider blinkt nichts und auch der serial monitor zeigt nichts mehr an.
V2 (vor dem Fix) tut dies.

2 Möglichkeiten warum nichts blinkt:

  1. Die Spannung am MCP liegt bei 2,7V. Da werde ich morgen mal eine 5V externe Spannung anlegen.
  2. Muss der Reset beim MCP auf Plus gezogen werden? Das habe ich weder bei der Fix auf der Platine aufgebauten MCPs, noch bei dem am Breadboard getan.
    LG Andy

ich vermute dass die SPI Kommunikation nicht funktioniert.

hattest du schon einen Sketch mit dem du einen Ausgang auf einem MCP mit der aktuellen Hardware ansteuern konntest? ein ganz einfaches "Blink" Programm? Wenn ja - bitte posten.

Da hast Du sicher recht! Inzwischen habe ich (mit meinem Sohn) ein Beispielprogramm zum Laufen gebracht, LED am MCP blinkt! Da wir das bei meinem Sohn gemacht haben, habe ich den Sketch noch nicht.

Meine Fehler:
Die Adressierung des MCP am Breadboard hatte ich nicht mit GND verbunden und auch den Reset nicht auf +.

Noch eine andere Geschichte: die 5 Mega2560, die ich bei AZ-Delivery gekauft habe sind leider unbrauchbar. Um sie anzusprechen zu können, muss man von einer chinesischen Seite den Treiber herunterladen. Dann geht es immer noch nicht, weil das Board nicht bekannt gibt, wenn der Sketch fertig geladen ist. Billig war zu teuer!

Ich melde mich wieder, wenn es neues gibt. (Ich hab dieses Wochenende Enkel da).
LG Andy

Das mit dem Treiber ist normal. Es haben schon tausende gelöst.
Ich weis nicht was du mit „Sketch fertig geladen ist“ meinst. Aber ich denke das deine Mega2560 nicht defekt sind.

Nach dem Kompilieren verschwindet das "Hochladen" nicht mehr. Das ist am PC bei meinem Sohn passiert. Ich habe den Treiber gerade an meinem PC geladen und da wurde dann das Hochladen des Sketches "erfolgreich abgeschlossen". Funktioniert jetzt also.
Danke für den Hinweis.

Das ist der funktionierende Sketch, den wir als Beispiel für die Adafruit MCPX2317 gefunden haben:

// Blinks an LED attached to a MCP23XXX pin.

// ok to include only the one needed
// both included here to make things simple for example
//#include <Adafruit_MCP23X08.h>
#include <Adafruit_MCP23X17.h>

#define LED_PIN 8     // MCP23XXX pin LED is attached to

// only used for SPI
#define CS_PIN 53

// uncomment appropriate line
//Adafruit_MCP23X08 mcp;
Adafruit_MCP23X17 mcp;

void setup() {
  Serial.begin(115200);
  while (!Serial);
  Serial.println("MCP23xxx Blink Test!");

  // uncomment appropriate mcp.begin
  //if (!mcp.begin_I2C()) {
  if (!mcp.begin_SPI(CS_PIN)) {
    Serial.println("Error.");
    while (1);
  }

  // configure pin for output
  mcp.pinMode(LED_PIN, OUTPUT);

  Serial.println("Looping...");
}

void loop() {
  mcp.digitalWrite(LED_PIN, HIGH);
  delay(500);
  mcp.digitalWrite(LED_PIN, LOW);
  delay(500);
}

Dein Sketch funktioniert leider nur ohne dass die LED an Port 0 (gerade) bzw. 1 (abbiegen) angeht und nach 2s wieder aus.
Dein Sketch wär mir lieber, weil die Zuordnung der Ports als Class durchgeführt wird.
LG Andy

Laut Library sind die Portadressen wie folgt:

Ich hab mal aus Interesse ein paar N-Weichen von Arnold mit Netzgerät angesteuert um zu sehen, wieviel Gleichspannung es braucht, um zuverlässig zu schalten: Eine braucht nur 15V und die schlechteste schaltet erst bei über 21V zuverlässig! Ich glaube da bleib ich dann doch bei den geplanten 24V.

Genau lesen:
wenn der Pin 8 ein AUSGANG sein soll, dann wäre das bei meiner Klasse einer der ersten zwei Parameter! (!!!) weil:

WeicheMCP(Adafruit_MCP23X17 &mcpA, uint8_t pinGerade, uint8_t pinAbbiegen, uint8_t pinRueckGerade, uint8_t pinRueckAbbiegen /*, welcher MCP*/)

ergo nicht

{mcpA, 0, 1, 8, 9},         // Anlage einer Weiche

sondern vieleicht so:

{mcpA, 8, 9, 0, 1},         // Anlage einer Weiche

verstehst was ich meine?

Dieses Missverständnis tut mir leid ! Ich habe (irgendwo oben mal) meinen Breadboard Aufbau beschrieben, Dort sind 8 LEDs mit Vorwiderstand an den Ports 0-3 und 8-11 angeschlossen, es müsste auf jeden Fall mit deinem Sketch ohne Umbenennen eine LED für 2sec angehen, wenn ein Taster gedrückt wird, (dem Mega wird es egal sein, ob eine LED am Input ist). Aber es geht keine an. Warum?
Nix für ungut! LG Andy

Hallo Noiasca,

ich hoffe du bist nicht sauer, ich wollte und will niemanden verärgern!
Ich bin mit besonders deiner Hilfe im Projekt schon viel weiter gekommen.

Ich habe festgestellt, dass bei Deinem Sketch Post #27 die Schalter "funktionieren", d.h. ich sehe am Serial Monitor, welcher gedrückt wird und nach 2s "abschalten". Beim Sketch #45 passiert nichts, keine Meldung am Serial und keine Led geht an.

Gehe ich recht in der Annahme, dass die Bezeichnung mcpA im Sketch die Vorbereitung für die anderen mcp sind?

Ich werde übrigens doch jedem Schattenbahnhof einen eigenen Mega spendieren, die Programme sind ident und ich spare mir den Aufwand auch für die Gleistaster und -LEDs zusätzliche Portexpander vorsehen zu müssen.

Ich hatte bei meinen Versuchen mit dem Testboard von post #1 und #47 (Foto) wieder einen Fehlschlag, ein Arnold Weichenantrieb hatte einen internen Kurzschluß, sodass der Stellhebel aus Kunststoff in derSpule angeschmolzen ist. (Wenn es jemand interessiert kann ich Fotos vom Innenleben posten.) Der ULN2803 ist auch sehr heiß geworden. Kann es sein, dass die Eingänge auf jeden Fall auf Low sein müssen? Ich werde wegen dieses Fehlers aus Vorsicht ein Relais vorschalten, dass die 24V= (oder weniger) erst zuschaltet, wenn die Weichen gestellt werden müssen.
Eventuell war dieser Antrieb der Kandidat, der die hohe Stellspannung (s.oben post #70) benötigt hat.

LG Andy

PS: ich habe versucht, mit Eagle einen lesbaren Schaltplan (post #1) zu zeichnen, aber wenn man mit dem Programm nicht fit ist, braucht das Zeit und da habe ich aufgegeben.
In meinem Schaltplan ist die Bezeichnung der Pins am mcp falsch herum nummeriert. Die Anschlüsse sind aber korrekt.

ja das wäre die Idee gewesen.

Da ich noch immer nicht das Problem in meinem Code sehe tu ich mich schwer nachzuvollziehen was da nicht funktioniert. Ohne Hardware kann ich das nicht wirklich testen. Die 16bit MCP hab ich nur in I2C, in SPI hab ich nur den 8bitter.

P.S.: ich würde zunächst nur mit LEDs testen und Weichenantriebe erst dann anschließen wenn alles funktioniert.

Ich tue mich auch schwer. Wie geschrieben, beim 1. Sketch von Dir funktioniert auf derselben Hardware (Breadboard, MCP23S17, 8 LEDs und 2 Taster, Mega2560 mit über Shield angesteckten Leitungen) die Kommunikation mit dem Serial Monitor, während es mit der letzten Version gar nicht geht (weder Kommunikation, noch blinken). Den einzigen, für mich erkennbaren Unterschied zwischen den Sketches ist mcp. vor digitalWrite und pinMode.
Falls Du bitte den Sketch mit Hardware probieren würdest: Mit dem MCP23S08 müsste das gleiche auch funktionieren, wenn die Inputs auf A4-A7 8-bitter gerecht adressiert werden:

WeicheMCP weiche[] {
  {mcpA, 0, 1, 4, 5},        
  {mcpA, 2, 3, 6, 7},  

Mit deinem Rat, erst einmal nur mit LEDs zu testen hast Du recht. Es ist nur so, dass ich beim Sketch nicht mehr weiter wusste und ich den simplen, weil nicht zukunftsfähigen, funktionierenden (mcp blink test) Sketch mit den Weichen auf meiner Hardware probieren wollte und das Malheur vor dem Anschluss des Mega passiert ist.

Ich komm erst Morgen wieder zum Thema.

Vielen Dank und lG
Andy

das hat mir jetzt keine Ruhe gelassen.
Glücklicherweise habe ich ein Packerl mit MCP23S17 gefunden. Was nicht so alles rumliegt.

das ist jetzt mein Testaufbau:

Im Sketch war eine Referenz falsch. Jetzt müsste es klappen.
Zumindest bleiben bei mir jetzt die LEDs nur kurz an.
Zum testen gibts jetzt auch ein Serial Interface.

Probier mal MIT LEDs (!!!) und berichte.

getestet mit Hardware daher auch mal direkt im Forum:

/*
    POC Weiche, Fahrstraße, Zieltaste
    https://forum.arduino.cc/t/schattenbahnhofsteuerung/1208510/46
    Simulation: https://wokwi.com/projects/386439244339395585

    by noiasca
    2024-01-09 Grundgerüst
    2024-01-11 MCP23S17 eingebunden, Debug Meldungen, erstes Time Management
    2024-02-15 fixed class WeicheMCP  https://forum.arduino.cc/t/schattenbahnhofsteuerung/1208510/63
    2024-03-03 fixed class WeicheMCP, 4 turnouts

    Anmerkung: durch die fehlende SPI Kommunikation wird der Sketch im Wokwi Simualtor nicht funktionieren
*/

#include <Streaming.h>                // Streaming by Peter Polidoro (boardmanager) - macht das Serial.print einfacher.
#include <Adafruit_MCP23X17.h>

constexpr uint8_t csPinA {5};         // chip select für ersten MCP23S17
constexpr uint8_t buttonPinA {A0};    // nur mal ein Test Button
constexpr uint8_t buttonPinB {A1};    // noch ein Test Button
constexpr uint8_t buttonPinC {A2};    // noch ein Test Button
constexpr uint8_t buttonPinD {A3};    // noch ein Test Button

Adafruit_MCP23X17 mcpA;               // ein MCP Objekt muss angelegt werden - @todo: Umbauen auf Array

// Weichen an einem MCP23S17
class WeicheMCP {
    Adafruit_MCP23X17 &mcp;           // Referenz auf ein MCP Objekt - ein konkreter MCP23S17
    const uint8_t pinGerade;          // Ausgang für Gerade - 0..15
    const uint8_t pinAbbiegen;        // Ausgang für abbiegen
    const uint8_t pinRueckGerade;     // Rückmeldung für Gerade
    const uint8_t pinRueckAbbiegen;   // Rückmeldung für Abbiegen
    uint32_t previousMillis = 0;      // Zeitmanagement
    const uint16_t interval = 2000;   // hard off der Magnetantriebe
    bool isActive = false;            // Magnetantrieb ist ein oder aus
    uint8_t direction = 0;            // 0 gerade, 1 abbiegen
  public:
    WeicheMCP(Adafruit_MCP23X17 &mcp, uint8_t pinGerade, uint8_t pinAbbiegen, uint8_t pinRueckGerade, uint8_t pinRueckAbbiegen /*, welcher MCP*/) :
      mcp{mcp},
      pinGerade {pinGerade},
      pinAbbiegen {pinAbbiegen},
      pinRueckGerade {pinRueckGerade},
      pinRueckAbbiegen {pinRueckAbbiegen} {}

    // Einstellungen im setup() - könnte auch für das Rücklesen der Stellung z.B. aus dem EEPROM genutzt werden
    void begin() {
      mcp.pinMode(pinGerade, OUTPUT);
      mcp.pinMode(pinAbbiegen, OUTPUT);
      mcp.pinMode(pinRueckGerade, INPUT);   // tbc INPUT_PULLUP?
      mcp.pinMode(pinRueckAbbiegen, INPUT); // tbc INPUT_PULLUP?
    }

    // Aktion für Geradeausfahrt
    int gerade() {
      if (!isActive) {
        mcp.digitalWrite(pinGerade, HIGH);
        direction = 0;
        isActive = true;
        previousMillis = millis();
        Serial << "gerade " << pinGerade << '\n';
        return 0; // OK
      }
      return -1;  // befehl nicht angenommen
    }

    // Aktion für abbiegen
    // @todo - codeduplikate von gerade/abbieben in eine Funktion auslagern
    int abbiegen() {
      if (!isActive) {
        mcp.digitalWrite(pinAbbiegen, HIGH);
        direction = 1;
        isActive = true;
        previousMillis = millis();
        Serial << "abbiegen " << pinAbbiegen << '\n';
        return 0; // ok
      }
      return -1;  // befehl nicht angenommen
    }

    // Rückgabe des aktuellen Status
    int getStatus() {
      return direction;
    };

    // RUN: automatische Abschaltung der Magnetartikel
    void update(uint32_t currentMillis = millis()) {
      if (isActive && currentMillis - previousMillis > interval) {
        mcp.digitalWrite(pinGerade, LOW);
        mcp.digitalWrite(pinAbbiegen, LOW);
        isActive = false;
        Serial << "abschalten " << '\n';
      }
    }
};

WeicheMCP weiche[] {
  {mcpA, 0, 1, 8, 9},       // Anlage einer Weiche
  {mcpA, 2, 3, 10, 11},     // Anlage einer weiteren Weiche (am gleichen MCP)
  {mcpA, 4, 5, 12, 13},     // Anlage einer weiteren Weiche (am gleichen MCP)
  {mcpA, 6, 7, 14, 15},     // Anlage einer weiteren Weiche (am gleichen MCP)
};

// Eingänge der Buttons initialisieren
void buttonBegin() {
  pinMode(buttonPinA, INPUT_PULLUP);
  pinMode(buttonPinB, INPUT_PULLUP);
  pinMode(buttonPinC, INPUT_PULLUP);
  pinMode(buttonPinD, INPUT_PULLUP);
}

// Buttons abfragen und etwas ausführen
void buttonRead() {
  if (digitalRead(buttonPinA) == LOW) weiche[0].gerade();
  if (digitalRead(buttonPinB) == LOW) weiche[0].abbiegen();
  if (digitalRead(buttonPinC) == LOW) weiche[1].gerade();
  if (digitalRead(buttonPinD) == LOW) weiche[1].abbiegen();
}

// Befehle über die serielle Schnittstelle
void serialRead() {
  int c = Serial.read();
  switch (c) {
    case -1 : break;
    case '1': weiche[0].gerade(); break;
    case '2': weiche[0].abbiegen(); break;
    case '3': weiche[1].gerade(); break;
    case '4': weiche[1].abbiegen(); break;
    case '5': weiche[2].gerade(); break;
    case '6': weiche[2].abbiegen(); break;
    case '7': weiche[3].gerade(); break;
    case '8': weiche[3].abbiegen(); break;
  }
}

void setup() {
  Serial.begin(115200);
  Serial << "Weichensteuerung\n";
  delay(500);
  SPI.begin();

  if (!mcpA.begin_SPI(csPinA)) {
    Serial << "mcpA Error.\n";
  }

  for (auto &i : weiche)  {
    i.begin();  // jede Weiche initialisieren
  }
  buttonBegin();
  Serial << "ende setup\n";
}

void loop() {
  buttonRead(); // taster auslesen
  serialRead();

  // Hintergrund-Aktivitäten auslösen
  for (auto &i : weiche) i.update();  // jeder Weiche etwas Zeit für Hintergrundaktivitäten geben
}
//
1 Like

[quote="noiasca, post:76, topic:1208510"]

Super, vielen herzlichen Dank! csPinA auf 53 gesetzt und funktioniert (LEDs leuchten 2s)!!! Sowohl mit Taster, als auch serialRead!
Da geht jetzt endlich was weiter.

Gehe ich recht in der Annahme, dass ich die Zuordnung Gleistaster, GleisLEDs und Weichen ebenfalls in eine Class packen kann?

Ich musste (wieder einmal) Fehler bei meinem Testboard feststellen. Das hätte mir beinahe die Freude am Basteln geraubt. Nicht nur, dass die ULN2803 verkehrt herum gesteckt waren und jetzt Ausgänge bei den 2 ICs defekt sind, sondern auch die Pins aller ICs in meinem Schaltplan falsch benummert sind. (Ich werde, wenn es funktioniert, eine korrigierte Schaltung posten)
Zusätzlich habe ich herausgefunden, dass die Rückmeldung über den LTV844 nicht wie beabsichtigt funktioniert.
Zum Ausprobieren habe ich anstatt Weichen 2 LEDs über 3kOhm Vorwiderstand an 24V an den Ausgängen des ULN (gerade und abbiegen) angeschlossen und beide leuchten gleichzeitig, obwohl die Eingänge des ULN auf low liegen. Wenn ich den LTV aus dem Stecksockel entferne, reagieren die Ausgänge korrekt, 5V am Eingang lässt die betreffende LED am korrespondierenden Ausgang angehen.
Bei angestecktem LTV leuchten die LEDs über den 2,7KOhm Widerstand und die internen LEDs im LTV.
Also so geht es nicht! Entweder die Rückmeldung der Weichenstellung eliminieren oder Die Schaltung ändern.

Eine Idee wäre, pro Weichenspule 2 Dioden in Serie zu schalten und die Eingänge vom LTV jeweils davor und danach anschließen. So wären die Ausgänge vom ULN voneinander entkoppelt und die internen LEDs des LTV würden vom Spannungsabfall über die Dioden gespeist. Das probiere ich bald aus und berichte wieder.

Nochmals vielen Dank und lG Andy


Nachtrag: das war ein Schnellschuss und kann so nicht funktionieren, weil ein Stromfluß über die Dioden und damit Detektion am LTV nur bei schaltendem MCP passieren kann und das ist nicht zielführend!

Theoretisch ja.
Aber aus dem Satz verstehe ich noch nicht was du genau machen willst.


HW Seitig kann ich dir nicht helfen.
Dass der ULN2803 zwischen Ein und Ausgang invertiert sollte aber klar sein.

Ich erhoffe mir eine Vereinfachung dadurch, dass in der Class die Gleistaster, Weichen und GleisLEDs in einem Array zugeordnet werden können, so in etwa:

class Gleiszuordnung
Gleistaster 1-10 ...
Weiche 1g ...
Weiche 1a ...
...
Weiche 9g
Weiche 9a
GleisLED 1-10

Gleiszuordnung (Gleistaster pro Gleis eine Zeile 1-10, alle Weichenspulen der Reihe nach: 0 für keine Aktion 1 für schalten, GleisLED 0 für aus, 1 für ein)

wenn Du damit meinst, dass der gemeinsame Anschluss der Spulen an +24V angeschlossen sind und vom ULN2803 beim Schalten des korrespondierenden Pins auf high auf GND geschlossen werden, ja.