www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik µC zu langsam?


Autor: Gast (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi Leute,

ich habe folgendes Problem: Ich sende Packete vom PC zum µC und dann 
soll der µC darauf reagieren. Schicke ich die Packete per Hand über 
Console, dann funktioniert alles. Schicke ich allerdings die Packete per 
PC, bleibt das Programm hängen in der Abfrage.
Beispiel für ein Packet:
FF 00 01 02 03

FF = Startbedingung
00 = Seq. Nr.
01 = Länge des Packetes (wieviele Befehle bzw. Daten)
02 = Befehlsnr. (z.b. Live Übertragung)
03 = Checksumme (Länge+Befehlsnr. + eventuele Daten)

Schicke ich das per Hand, funktioniert alles (also zuerst FF, dann 
00,...) Schicke ich allerdings alles per PC oder in der Konsole direkt 
FF00010203, dann bleibt das Programm vor der Abfrage nach der Befehlsnr. 
hängen. (und wartet auf weitere Daten).

Hier die Abfragefunktion:
/*******************************************************
  Funktion :    Hole Packet / Reagiere auf Befehlscode
  Eigenschaften:  Gib Befehlsnummer zurück
  Übergabewert:  -
  Rückgabewert:  1 Byte Befehlsnummer (0xFF = Fehler)
********************************************************/
uint8_t usart_recieve_packet(void)
{
  uint8_t data;
  length = 0;

  data = usart_get();                    // Hole Start-Signal
  if (data == COMMAND_START)                 // Wurde Start übermittelt?
  {
    data = usart_get();                  // Hole Seq Nr
    if(data == seq_nr)                  // Stimmen Seq Nummern überein?
    {
      length = usart_get();              // Hole Länge
      data = usart_get();                // Hole Befehlsnr.
      switch(data)
      {
        case COMMAND_SEND_ALL_DATA:          //Schicke alle Daten
        {
          data = usart_get();              // Hole Pruefsumme
          checksum = length + COMMAND_SEND_ALL_DATA;  // Berechne Pruefsumme

          if (data == checksum)
          {
            usart_seq_plus();          // Erhöhe Sequenz nr.
            return COMMAND_SEND_ALL_DATA;    // Return Befehlsnr.
          }
          else
          {
            usart_error(EC_USART_SEND_ALL_DATA);
            return 0xFF;            // Fehler
          }
        } break;

        case COMMAND_LIVE_MODUS:          //Live Übertragung
        {
          data = usart_get();            // Hole Pruefsumme
          checksum = length + COMMAND_LIVE_MODUS;  // Berechne Pruefsumme
  
          if (data == checksum)
          {
            usart_seq_plus();          // Erhöhe Sequenz nr.
            return COMMAND_LIVE_MODUS;      // Return Befehlsnr.
          }
          else
          {
            usart_error(EC_USART_LIVE_MODUS);
            return 0xFF;            // Fehler
          }
        } break;

        case COMMAND_LIVE_MODUS_STOP:        // Live Stopp
        {
          data = usart_get();            // Hole Pruefsumme
          checksum = length + COMMAND_LIVE_MODUS_STOP;  // Berechne Pruefsumme

          if (data == checksum)
          {
            usart_seq_plus();          // Erhöhe Sequenz nr.
            return COMMAND_LIVE_MODUS_STOP;    // Return Befehlsnr.
          }
          else
          {
            usart_error(EC_USART_LIVE_MODUS_STOP);
            return 0xFF;            // Fehler
          }
        } break;

        case COMMAND_RECEIVE_TIME:           //Uhrzeit empfangen
        {
          //Hole Uhrzeit-Daten
          pc.year = usart_get();
          pc.month = usart_get();
          pc.date = usart_get();
          pc.hours = usart_get();
          pc.minutes = usart_get();
          pc.seconds = usart_get();

          data = usart_get();            // Hole Pruefsumme
          checksum = length + COMMAND_RECEIVE_TIME + pc.year + pc.month + pc.date + pc.hours 
                + pc.minutes + pc.seconds;   // Berechne Pruefsumme

          if (data == checksum)
          {
            usart_seq_plus();          // Erhöhe Sequenz nr.
            flag.right_values = 1;        // Werte waren richtig (wegen Prüfsumme)
            return COMMAND_RECEIVE_TIME;    // Return Befehlsnr.
          }
          else
          {
            flag.right_values = 0;        // Werte waren falsch (wegen Prüfsumme)
            usart_error(EC_USART_RECEIVE_TIME);
            return 0xFF;            // Fehler
          }
        } break;

        case COMMAND_RECEIVE_ACK:           // ACK empfangen
        {
          pc_seq_nr = usart_get();        // Hole Seq Nr
          data = usart_get();            // Hole Pruefsumme
          checksum = length + COMMAND_RECEIVE_ACK + pc_seq_nr; // Berechne Pruefsumme

          if(data == checksum)
          {
            usart_seq_plus();          // Erhöhe Sequenz nr.
            return COMMAND_RECEIVE_ACK;      // Return Befehlsnummer
          }
          else
          {
            usart_error(EC_USART_RECEIVE_ACK);
            return 0xFF;            // Fehler
          }              
        } break;

        case COMMAND_PARAMETERS:          //Paramters
        {
          
          // Hole Startzeit
          start.year = usart_get();
          start.month = usart_get();
          start.date = usart_get();
          start.hours = usart_get();
          start.minutes = usart_get();
          start.seconds = usart_get();

          //Hole Endzeit
          end.year = usart_get();
          end.month = usart_get();
          end.date = usart_get();
          end.hours = usart_get();
          end.minutes = usart_get();
          end.seconds = usart_get();

          // Hole Sampling Rate
          // Speichere in Zwischenvariablen für Pruefsumme
          sampling_rate_array[0] = usart_get();
          sampling_rate_array[1] = usart_get();
          sampling_rate_array[2] = usart_get();

          sampling_rate = sampling_rate_array[0];        // Schreibe 1tes Byte
          sampling_rate = (sampling_rate << 8);        // Verschiebe 1tes Byte
          sampling_rate |= sampling_rate_array[1];      // Schreibe 2tes Byte
          sampling_rate = (sampling_rate << 8);        // Verschiebe 2tes Byte
          sampling_rate |= sampling_rate_array[2];      // Schreibe 3tes Byte
          
          // Hole Messwertemaske
          // Speichere in Zwischenvariablen für Pruefsumme
          measurement_mask_array[0] = usart_get();
          measurement_mask_array[1] = usart_get();
          measurement_mask_array[2] = usart_get();
          measurement_mask_array[3] = usart_get();
          measurement_mask_array[4] = usart_get();
          measurement_mask_array[5] = usart_get();

          measurement_mask_high = measurement_mask_array[0];  // Wie bei sampling rate (oben)
          measurement_mask_high = (measurement_mask_high << 8);
          measurement_mask_high |= measurement_mask_array[1];

          measurement_mask_low = measurement_mask_array[2];
          measurement_mask_low = (measurement_mask_low << 8);
          measurement_mask_low |= measurement_mask_array[3];
          measurement_mask_low = (measurement_mask_low << 8);
          measurement_mask_low |= measurement_mask_array[4];
          measurement_mask_low = (measurement_mask_low << 8);
          measurement_mask_low |= measurement_mask_array[5];
          
          data = usart_get();                  // Hole Pruefsumme
          
          // Berechne die Pruefsumme
          checksum = length + COMMAND_PARAMETERS + start.year + start.month + start.date + start.hours + start.minutes + start.seconds
                 + end.year + end.month + end.date + end.hours + end.minutes + end.seconds + sampling_rate_array[0]
                 + sampling_rate_array[1] + sampling_rate_array[2] + measurement_mask_array[0] 
                 + measurement_mask_array[1] + measurement_mask_array[2] + measurement_mask_array[3] 
                 + measurement_mask_array[4] + measurement_mask_array[5];

          if(data == checksum)
          {
            usart_seq_plus();                // Erhöhe Sequenz nr.
            flag.right_values = 1;              // Werte richtig (wegen Prüfsumme)
            return COMMAND_PARAMETERS;            // Return Befehlsnr.
          }
          else
          {
            flag.right_values = 0;              // Werte falsch (wegen Prüfsumme)
            usart_error(EC_USART_COMMAND_PARAMETERS);
            return 0xFF;                  // Fehler
          }
        } break;
        
        case COMMAND_STATUS_REQUEST:          // Status-senden Aufforderung
        {
          data = usart_get();              // Hole Pruefsumme
          checksum = length + COMMAND_STATUS_REQUEST;  // Berechne Pruefsumme

          if (data == checksum)
          {
            usart_seq_plus();          // Erhöhe Sequenz nr.
            return COMMAND_STATUS_REQUEST;    // Return Befehlsnr.
          }
          else
          {
            usart_error(EC_USART_STATUS_REQUEST);
            return 0xFF;            // Fehler
          }
        } break;
        
        case COMMAND_RESET:
        {
          goto packet_reset;
        }
        default:            // Falscher Befehlscode
        {
          usart_error(EC_USART_WRONG_CODE);
          return 0xFF;        // Fehler
        }
      }
    }
    else
    {
      length = usart_get();              // Hole Länge
      data = usart_get();

      if(data == COMMAND_RESET)
      {
        packet_reset:
        data = usart_get();              // Hole Pruefsumme
        checksum = length + COMMAND_RESET;      // Berechne Pruefsumme
        
        if (data == checksum)
        {
          usart_seq_plus();          // Erhöhe Sequenz nr.
          return COMMAND_RESET;        // Return Befehlsnr.
        }
        else
        {
          usart_error(EC_USART_RESET);
          return 0xFF;            // Fehler
        }

      }
      else
      {
        usart_error(EC_USART_WRONG_SEQ);  // Falsche Seq Nr. ==> Error
        return 0xFF;            // FEHLER
      }
    }
  }
  else
  {
    usart_error(EC_USART_NO_START);      // Kein Start erhalten ==> Error
    return 0xFF;              // FEHLER
  }
}

Ich benutze übrigens einen 8 MHz Quarz und eine Baudrate von 19200. (bei 
höheren Baudraten werden immer falsche Daten übertragen) Wenn ich im PC 
Programm ein Delay von 50 ms einbaue, funktioniert es wieder... aber 50 
ms ist schon sehr sehr groß....

Hat jemand eine Idee, woran es liegen kann? Im Prinzip mache ich ja 
zwischen den Abfragen nicht viel! Also warum ist der µC zu langsam?
Sicherheitshalber habe ich das ganze Projekt noch angehängt. (fehler ist 
in usart.c)

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Probiers mal mit nem Baudratenquarz. Der Fehler ist zwar jetzt 
(8MHz/19200Baud) nur bei 0.2%, aber vielleicht schaukelt sich das bei 
vielen Bytes hintereinander auf. Mit der Pause dazwischen entzerrt sich 
das ganze dann wieder.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Baudratenquarz ist nicht. Das ganze muss bis morgen funktionieren oO 
Können die 2 if Abfragen daran Schuld sein? Sprich, dass während dennen 
kein Signal empfangen wird?

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oder probiere es mal mit 9600 Baud...

Schon möglich dass der uC bzw Dein Programm zu langsam ist! Ich würde 
die UART-Kommunikation in eine ISR packen, dann kannst Du auch locker 
mit 115200 Baud arbeiten.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
leider ist dein Programm nicht so leicht zu verstehen, viel zu viel 
geschachtelt. Die vermutung ist das der Fehler nicht in der funktion 
usart_recieve_packet ist sondern schon vorher, der Atmel kann ja bloss 
1byte buffern, wenn du jetzt zu lange braucht um in die funktion 
usart_recieve_packet zu kommen dann gehen dir zeichen verloren.

Warum macht du die ganze sache nicht in einer ISR, jedesmal wenn ein 
zeichen ankommt?

Autor: Uwe ... (uwegw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es könnte helfen, die Daten vom UART erst mal in einem Ringbuffer zu 
speichern, und sie dann in Ruhe zu bearbeiten. Es könnte nämlich sein, 
dass du mit irgendeiner Berechnung länger brauchst als die Zeit zwischen 
zwei Bytes. Du wartest ja immer auf ein Byte, dann passiert was, und 
dann wird wieder gewartet. Wenn nun die Berechnung nach einem Byte so 
lange dauert, dass inzwischen mehr als ein Byte angekommen ist, gehen 
Bytes verloren.

Schau dir mal die UART-Lib von http://jump.to/fleury an. Dort ist so ein 
Ringbuffer drin. Die Daten werden im Interrupt empfangen, und das 
Hauptprogramm kann sie dann verarbeiten, wenn es Zeit dafür hat.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, wenn er z.b. ein Live Packet schickt, dann sendet er:

FF 00 01 02 03

Er sendet FF, danach gibt es eine IF Abfrage.
Danach sendet er 00, und es gibt wieder eine If Abfrage.
Anschließend kommt 01 und 02. Und dann ein Select Case.
Anschließend würde er die Checksum holen (also 03).

Fakt ist, er bleibt aber schon nach der 3ten Abfrage hängen (also nach 
01). Dazwischen befinden sich nur 2 IF Abfragen und sonst gar nichts.

Ich habe diese 2 IF Abfragen jetzt sogar rausgenommen und hole direkt 
alle Werte von USART, allerdings fehlen wieder die letzteren!

Die Funktion wird allgemein erst gestartet, wenn etwas im USART Speicher 
ist.
Das FF erhalte ich richtig, genauso die Seq Nr (00) und auch die Länge 
(01) nur ich erhalte einfach kein 02 und 03 mehr! Obwohl keine Befehle 
dazwischen sind!


Wie schauts mit diesem 1k Byte Buffer aus??? Ich benutze einen atmega32L 
und habe 47% Programmspeicher voll und 96,8% Variablenspeicher.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
bist auch sicher das du die bytes in der Reihenfolge empfängst? Denn die 
IF anweissung ist auf jeden Fall schnell genug.
Es ist aber nicht genau zu erkennen wieviel Zeit dein Programm von dem 
FF bis zu aufruf der Funktion usart_recieve_packet braucht. Wenn diese 
Zeit zu lang ist, dann kannst du später auch nichts mehr retten.

Autor: Ulrich (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn man einen kleinen Fehler in der Bautrate hat, hilft es manchmal 
beim Sender (PC) 2 Stoppbits einzustellen. Dann können sich Fehler duch 
ein zu kurzes Stopbit nicht aufaddieren.

Der Ringpuffer ist ein Speicher mit z.B. 32 Bytes Länge, der immer Reihe 
rum genutzt wird. Dazu gibts einen Index zum Schreiben und eine zu 
Lesen. Das könnte aber eng werden mit nur noch rund 3% freiem RAM.


Ein Problem in dem Programm könnte sein, zum Teil etwas auch einer 
anderen UART ausgegeben wird, wenn die Daten nicht dem Mustser 
entsprechen. Dann gibt es natürlich probleme, denn dann kommen die daten 
schneller als man sie auswertet.

Autor: Benjamin S. (recycler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
meiner meinung, braucht die abarbeitung länger als dein isr
deshalb wird in der isr der alte wert (der buffer) überschreiben und 
deine statemachine läuft sonst wo hin.

ich würde es so machen.
_______________________________________
isr_uart:
wenn neues byte -> puffer + got_data=1
_______________________________________
statemachine:

while (!got_data);
data = buffer;

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmmm hab jetzt den Fehler... das erste Packet ist 08. D.h. die vorrigen 
werden überschrieben und der Grund liegt in einer Joystick Abfrage, 
welche zu Lange dauert. Ohne dieser Abfrage funktioniert alles!

Aber wie löse ich jetzt das Problem?? Ich benötige diesen Joystick... 
Und Ringbuffer wie gesagt, 3% nur noch frei außerdem empfange ich 
x-beliebig viele Daten... sprich bei Befehlsnr 03 nur 1 Byte Daten, bei 
Befehlsnr. 08 dann schon 20 Byte Daten?

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Ich benutze einen atmega32L und habe 47% Programmspeicher voll
>und 96,8% Variablenspeicher.

96,8% ? Da würde ich mal davon ausgehen, dass es knallt, weil Du zuwenig 
Speicher für den Stack hast!

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
die musst vermutlich einige Teile des Programmes umschreiben. Du hast 
jetzt einige Timingprobleme. Wenn du in der Funktion 
usart_recieve_packet bist dann wartet er auf jedes Zeichen einzeln in 
der Zeit ist deine Main stillgelegt.

Verlagere das Empfangen von Daten auf der UART in die ISR, eventuell 
auch das Prüfen des Paketes aber nicht die Komplette bearbeitung.

Setzte ein Flag das die Main weiss, das ein neues Paket empfangen wurde 
und verarbeite es.

In der gleichen Art und weisse musst du das mit dem Joystick machen. In 
der Main sollte also die die Ababreitung von den Daten erfolgen das 
Erfassen der Daten kann man meist in die ISR auslagern, damit sollte es 
dann schon gehen

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry Leute wenn ich jetzt nerve, aber kann mir bitte jemand kurz ein 
Codestück geben, wie ich das Interrupt einprogrammiere?

Also nur was ich machen muss, damit Funtkion xy beim Interrupt ausgelöst 
wird oO
(habe vorher noch nie mit interrupts programmiert :/ und ich sollte das 
heute noch fertig bekommen)

Danke aufjedenfall schon

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Am besten schaust du dir wirklich die UART Lib vom Peter Fleury (danach 
googeln) an. Dort solltest du alles finden was du brauchst.

Autor: rene (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zwar in pascal, aber...
http://www.ibrtses.com/embedded/avruart.html
dafuer auch mit einer Zustandsmaschine im Interrupt und der 
nichtblockierenden verarbeitung im Main.

Autor: Benjamin S. (recycler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
http://www.avrfreaks.net/index.php?name=PNphpBB2&f...

Als erstes Einstellungen vornehmen und Interrupt aktivieren.
Die Empfangsroutine könnte so aussehen:
char ReceivedByte; // globales byte
uint8_t got_byte;

ISR(USART_RXC_vect)
{
      ReceivedByte = UDR;
      got_byte = 1;
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Fleury-UART-Lib:

Und wenn irgendwie geht, würde ich sie so verwenden wie sie dir vom 
Peter gegeben wird. D.h. incl Ringbuffer.
Irgendwo wirst du schon noch ein paar Bytes SRAM freischaufeln können, 
um dir den Ringbuffer leisten zu können. Und wenn es nur 10 Bytes 
Ringbuffer sind, die dich davon befreien jedes einzelne Byte just in 
Time abholen zu müssen.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry ich verstehs immer noch nicht ganz.... (und im Datenblatt ist das 
in meinen Augen blöd beschrieben...)

Also zuerst aktiviere ich die Interrupts mit sei();
Außerdem muss ich die Header Datei avr/interrupt.h includen

Anschließend komme ich automatisch in die Funktion:

ISR(USART_RXC_vect)
{
}

wenn ich Daten empfange??????? Oder muss ich davor noch irgendetwas 
machen?
Wenn ich diese Funktion einbaue, bekomme ich gleich mal 3 Warrnings:

../usart.c:819: warning: return type defaults to 'int'
../usart.c:819: warning: type of '__vector_13' defaults to 'int'
../usart.c:821: warning: control reaches end of non-void function


Ok 2 Fehlermeldungen kann ich weg machen, indem ich int vor dem 
Funktionsnamen schreibe und ein return einbaue. Aber was soll diese 2te 
Fehlermeldung????

Stimmt das so, wie ich es geschrieben habe? (ich will nicht wissen, was 
in der Funktion stehen soll, sondern wie ich über ein Interrupt diese 
Funktion aufrufe!)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gast schrieb:
> Also zuerst aktiviere ich die Interrupts mit sei();

Nein. Das machst du zum Schluss, wenn alles konfiguriert ist.

> Außerdem muss ich die Header Datei avr/interrupt.h includen

Ja

> Anschließend komme ich automatisch in die Funktion:

Nein. Kommst du nicht. Du musst die UART Interrupts auch noch spezifisch 
freigeben.

>
> ISR(USART_RXC_vect)
> {
> }
>
> ../usart.c:819: warning: return type defaults to 'int'
> ../usart.c:819: warning: type of '__vector_13' defaults to 'int'
> ../usart.c:821: warning: control reaches end of non-void function

Dann stimmt wahrscheinlich der ISR Name nicht.
Sieh in der spezifischen io.h nach, wie er wirklich heisst.

> Stimmt das so, wie ich es geschrieben habe? (ich will nicht wissen, was
> in der Funktion stehen soll, sondern wie ich über ein Interrupt diese
> Funktion aufrufe!)

Warum holst du dir nicht die Fleury Lib? Da ist das alles bereits 
fertig, inkl funktionierendem Testprogram.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und wie kann ich die Interrupts freigeben (bzw. dieses spezielle für 
USART receive)? Habs jetzt schon hinbekommen, dass der name usw. passt, 
allerdings komme ich eben nicht in diese Funktion (wegen der fehlenden 
Konfiguration) Und im Datenblatt finde ich dazu nichts (oder ich bin 
einfach nur blind) Kann mir bitte das jemand kurz sagen, wird bestimmt 
eh nur 1-2 Zeilen sein oO (atmega32)

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Datenblatt Seite 152
When the Receive Complete Interrupt Enable (RXCIE) in UCSRB is set, the USART Receive
Complete Interrupt will be executed as long as the RXC Flag is set (provided that global inter-
rupts are enabled). When interrupt-driven data reception is used, the receive complete routine
must read the received data from UDR in order to clear the RXC Flag, otherwise a new interrupt
will occur once the interrupt routine terminates.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.