Problem mit mehreren Optokopplern zur Verbindung zwischen Siemens SPS (24V) und Arduino (5V)

Hallo zusammen,

ich bin gerade an einem Projekt, bei dem ich eine Siemens SPS (mit 24V Digitalausgängen) mit einem Arduino (5V) verbinden möchte. Die Idee ist, dass der Arduino ein Signal an einem seiner digitalen Eingänge erkennt, sobald ein digitaler Ausgang der SPS aktiv wird.

Um eine galvanische Trennung zu erreichen, habe ich mich entschieden, Optokoppler zu verwenden. Der erste Test mit einem einzelnen Optokoppler hat perfekt funktioniert – das Signal wurde vom Arduino wie gewünscht erkannt.

Daraufhin habe ich das Ganze größer aufgebaut, um insgesamt 28 digitale Signale zu verarbeiten. Bisher habe ich davon 8 Optokoppler auf einer Platine zusammengelötet. Wenn ich die Platine nun teste, funktioniert es jedoch überhaupt nicht mehr – obwohl der Test mit einem einzelnen Kanal zuvor problemlos lief.

Ich habe zuerst nur einen Kanal auf der neuen Platine getestet – dieser hat wie im ersten Test funktioniert. Doch sobald ich mehrere oder alle anschließe, klappt es nicht mehr. Für mich ist das aktuell nicht nachvollziehbar. Warum funktioniert es mit einem Optokoppler, aber nicht mit mehreren?

Was mir außerdem auffällt: Auch wenn kein Ausgang der SPS aktiv ist, leuchten manche der Optokoppler-LEDs trotzdem – andere wiederum nicht. Wenn ich dann gezielt einen SPS-Ausgang aktiviere, passiert nichts – der Zustand ändert sich nicht, und der Arduino erkennt kein Signal.

Zur Stromversorgung: Ich habe den Arduino sowohl mit einem 12V-Netzteil (über den VIN-Pin) als auch testweise direkt über den USB-Anschluss am Laptop betrieben – in beiden Fällen zeigt sich jedoch kein Unterschied im Verhalten.

Im Anhang findet ihr:

int taster1=21;
int taster2=22;
int taster3=23;
int taster4=24;
int tasterStatus1=0;
int tasterStatus2=0;
int tasterStatus3=0;
int tasterStatus4=0;
void setup() {
  // put your setup code here, to run once:
pinMode(taster1, INPUT);
pinMode(taster2, INPUT);
pinMode(taster3, INPUT);
pinMode(taster4, INPUT);
Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
tasterStatus1=digitalRead(taster1);
Serial.print("Q4.1: ");
Serial.println(tasterStatus1);

tasterStatus1=digitalRead(taster2);
Serial.print("Q4.0: ");
Serial.println(tasterStatus2);

tasterStatus1=digitalRead(taster3);
Serial.print("Q4.3: ");
Serial.println(tasterStatus3);

tasterStatus1=digitalRead(taster4);
Serial.print("Q4.2: ");
Serial.println(tasterStatus4);
delay(2500);
Serial.println(" ");

}

Ich freue mich über jeden Hinweis oder Tipp – vielleicht habe ich irgendwo einen Denkfehler oder einen Lötfehler übersehen.
Viele Grüße
Cédric

  • Schade das du das entfernt hast:

  • Die 200 Ohm Widerstände sind viel zu klein --> 1200 Ohm sollten es sein

  • Zum Code: du kennst den Spruch "Doppelter Code ist schlechter Code"? Benutze doch Arrays und for Schleifen (oder die neuen each)

  • Serial.begin(9600); kann man gerne auf 115200 setzen

1 Like

Bei 200 Ohm liegt dein Strom durch die Optokoppler-LED um mehr als das doppelte über dem absoluten Maximum lt. Datenblatt (50mA). Fraglich, ob die das überlebt haben ...

Danke für die Rasche Antwort. Die Led habe ich bewusst weggelassen da an der SPS schon agezeigt wird wenn der Digitale Ausgang an ist. Welchen widerstand meinst du sollte ich mit 1200 ohm ersetzen (vorwiderstand Led oder vorwiderstand Optokoppler). Beim Optokoppler ist aktuell ein 1200 Ohm widerstand mit 1W und als LED vorwiderstand ein 220 Ohm mit 0,25W. Ich bin leider nicht gerade der beste Programmschreiber könntest du mir da bitte ein Beispiel SKetch machen. Macht das einen grossen Unterschied wenn ich die Serial kommunikation erhöhe?

Dein Schaltbild zeigt was anderes.
Der Widerstand für den OK hat 220 Ohm und das ist def. zu wenig.

Zum Sketch, da würde ich für die Eingänge

wählen.

AHA ja auf dem Schaltbild ist der Buchstabe eins unter dem Widerstand versteckt habe es auch noch einmal nachgemessen und ich habe wirklich 1200 Ohm widerstand eingebaut sieht man auch am Strichcode vom widerstand auf der Platine

Aber auch die 1200 Ohm sind für 24 Volt zu "wenig". Da bekommen die OK 20 mA, was nicht nötig tut.

Danke für die rasche Antwort was würdest den du für einen nehmen?

Da reichen 3k9 und das sind ca. 6 mA.

constexpr uint8_t tasterPins{ 4 };
constexpr uint8_t tasterPin[tasterPins] { 21, 22, 23, 24 };
uint8_t tasterStatus[tasterPins];


void setup() {
  Serial.begin(115200);
  Serial.println(F("Start..."));
  for (byte b = 0; b < tasterPins; b++) {
    pinMode(tasterPin[b], INPUT_PULLUP);
  }
}

void loop() {
  for (byte b = 0; b < tasterPins; b++) {
    tasterStatus[b] = digitalRead(tasterPin[b]);
    Serial.print(F("Q4."));
    Serial.print(b + 1);
    Serial.print(F(": "));
    Serial.println(tasterStatus[b]);
  }
  delay(2500);
  Serial.println(" ");
}

Ich hab mal auch was gebaut.
Wenn Du kein delay() brauchst, gehört da auch kein delay() rein :slight_smile:

struct BTNIN                       // Was zusammen gehört bildet eine Structur; Jeder Eingang besteht aus:
{
  const uint8_t pin;               // Eingangspin, an dem das Signal abgenommen wird
  char name[8];                    // Bezeichnung, für die Ausgabe - Hier bis zu 7 Zeichen
  bool lastState;                  // Status, erklärt sich von selbst :-)
};

constexpr uint8_t btnNums {4};     // Aktuell sind 4 Eingänge genutzt. Die Konstante wird zum durchzählen benutzt
BTNIN btnIn[btnNums]               // Die Structur wird zu einem Array mit [Anzahl Elemente]
{
  {21, "Q4.1", false,},            // In jeder Zeile findet sich jetzt die Structur BTNIN wieder
  {22, "Q4.0", false,},            // Die Reihenfolge der Inhalte muss hier der Rehenfolge in der Structur entsprechen
  {23, "Q4.3", false,},            // Anzahl der Zeilen muss mit der Zählkonstanten übereinstimmen
  {24, "Q4.2", false,},            // ACHTUNG! Gezählt wird von 0! Das letzte Element hat also den numerischen Wert btnNums-1! (hier 3)
};                                 

/*
 * btnIn[0].pin        ist also der erste pin und hat den Wert 21
 * btnIn[1].name       ist die Bezeichnung für den zweiten Pin und lautet Q4.0
 * btnIn[3].lastState  ist der letzte gemerkte Status am vierten Pin
 */

void setup()
{
  Serial.begin(9600);
  Serial.println(F("Start..."));

  for (uint8_t b = 0; b < btnNums; b++) // Durch alle Elemente zählen
  {
    pinMode(btnIn[b].pin, INPUT);       // Für jedes Element den .pin auswählen und entsprechend setzen 
  }
}

void loop()
{
  /*
     Wenn Du diese einzelne Zeile auskommentierst, wird der gesamte Code der sich in der Funktion versteckt nicht ausgeführt
     Das macht das debuggen einfacher, als würdest Du Teile aus Codeblöcken einzeln kommentieren
  */
  getBtnStatus();                       // Funktionsaufruf
}

void getBtnStatus()
{
  for (uint8_t b = 0; b < btnNums; b++)                   // Zähle durch alle Elemente (hier 0 ... 3)
  {
    bool btnState = digitalRead(btnIn[b].pin);            // Fragt den PIN des Elementes ab; speichert den Wert in einer lokalen Variable

    if (btnState != btnIn[b].lastState)                   // Vergleicht den inhalt mit dem bestehenden Status des Elementes auf Ungleichnis
    {
      Serial.print(btnIn[b].name);                        // Ausgabe des Inhaltes
      Serial.print(": ");
      Serial.print(btnState);
      btnIn[b].lastState = btnState;                      // Merken des aktuellen Zustandes
    }
  }
}

Hier erfolgt eine Ausgabe nur, wenn sich der tatsächliche Status ändert.

Ich habe Deine 9600 im serMOn gelassen, ich selbst benutze lieber 115200 - aber für den Sketch hier macht das keinen großen Unterschied.
Wie Du eine weitere Optokopplerstufe antackerst, sollte ersichtlich sein.

Wenn Du Fragen hast, frag...
@wwerner wird Dir da schon helfen.

// edit - code kommentiert

2 Likes

okay werde es mal ausprobieren.
Ich frage mich einfach noch wieso es dan eizeln geht mit einem 1,2kOhm widerständen.

Danke für den Sketch sieht bisschen kompiziert aus werde mich da aber mal durchschauen um es zu verstehen das ich es nächstesmal auch hinbringe.

Soll ich den kommentieren, damit das verständlicher wird?

wie viel Leistung braucht den der Widerstand. Hab leider nur 0.25W von diesen.

Die Leistung ist ok.

joa wäre sehr nett

Funktionieren wird es auch mit 1k2, nur muss der Strom durch die Led im OK nicht so hoch sein. Dann hällt der länger.

Okay werde es jetzt mal testen oder denkst du das die OK schon kaputt sind

Das sie kaputt sind ist bei 1200 Ohm unwahrscheinlich. Die Aussage bezog sich auf die 200 Ohm. Hast du ein Multimeter? Dann messe doch mal die verschiedenen Spannungen nach.