- Labornetzteil AliExpress         
Seite 1 von 3 123 LetzteLetzte
Ergebnis 1 bis 10 von 69

Thema: Welche Möglichkeiten der Fehlersuche hat man beim Arduino?

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Robotik Einstein Avatar von i_make_it
    Registriert seit
    29.07.2008
    Ort
    Raum DA
    Alter
    56
    Beiträge
    2.814
    Zitat Zitat von fredyxx Beitrag anzeigen
    "void Setup()" nach "void loop()" nützt auch nichts.
    Davon hatte ich auch nichts gesagt.
    Sondern das was in "void Setup()" steht nach "void loop()" zu verschieben.
    Also

    void Setup() {

    bla
    bla
    von hier
    bla
    bla
    }

    void loop() {

    nach hier
    code
    code
    noch mehr code
    }

    Bei Arduino wird "void Setup()" immer genau einmal beim Start ausgeführt. "void loop()"dagegen wird in Endlosschleife ausgeführt bis der Strom weg ist ode rein Reset erfolgt.
    "void Setup()" kann man also sogar gezielt dazu nutzen um einen Code beim Einschalten immer genau einmal auszuführen.

    wenn Du allerdings mit Gotos um dich wirfst, dann ist Das was Du bekommen hast nicht weit.
    Gotos kann man nehmen wenn man damit klar kommt.
    Bei Assembler hat sogar nur Jump (also Goto) aber da muß man halt aufpassen das man auch immer wirklich da raus kommt wo man hin will (also zu der Situation)

    Um code in bestimmten Situationen zu überspringen gibt es z.B. IF und CASE. Da ist Quasi ein GOTO eingebaut.
    Dann gibt es noch Funktionen und Subroutinen (was Du Unterprogramme nennst). Bei einem Microcontroller mit genau einem Programm im Speicher gibt es keine Unterprogramme.
    Die Hauptschleife void loop() enthällt dann den code der immer durchlaufen werden muß und der Rest ist in Funktionen ausgelager.
    Das spart Laufzeit und verhindert Spagetti Code.

    Das von mir vorgeschlagene Verlagern der Initialisierung wird demnach vermutlich nichst bringen, kannst Du also lassen.

    Geh mal die Fehlersuche von Sisor durch und druck dir deinen Code aus.
    Dann nimm Textmarker und makiere alle Funktionsblöcke vom Beginn "{" bis Ende "}".
    Hast Du richtig codiert, darf sich keine Linie mit einer anderen überschneiden.
    Dann nimm Deine GoTOs und Deine Sprungmarken die Verbindungen dürfen dann auch nicht in verschiedenen Funktionsblöcken liegen.
    Wenn Ja liegt eigentlich ein bedingter Sprung vor also mußst Du vor dem GOTO oder nach der Sprungmarke dafür sorgen das die Bedingungen auch in jedem Fall immer erfüllt werden.
    Lustig wird es wenn von mehreren Gotos auf eine Sprungmarke gesprungen wird und dabei X Bedingungen vorliegen weil Variablenwerte nicht mehr korrekt verändert werden.

    Da ich sehr viele Quick and dirty Batch Scripte in Windows Umgebungen schreibe, bin ich mit den Fallstricken von GOTO ziemlich vertraut.
    Vor allem Da Notepad nicht wirklich eine IDE ist die auf Syntax oder Kontext prüft.
    Nur bin ich meist mit meinem Script schon am Arbeiten wenn die Programmierer in ihrer IDE ein Projekt eröffnet haben und anfangen wollen loszucoden.

    Also Analysier mal Deinen Code auf Papier, da wird vermutlich rauskommen das Deine Sprünge die Grenzen von Funktionsblöcken verletzen und deshalb Variablen nicht die richtigen Werte bekommen.
    Falls nicht ein Syntaxfehler vorliegt den die IDE nicht als solchen erkennt.
    Wie bei Vergleich und Zuweisung. Beides an sich syntaktisch richtig aber im Kontext eines Vergleichs ist die Syntax einer Zuweisung halt falsch.
    Geändert von i_make_it (19.09.2016 um 06:58 Uhr)

  2. #2
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    04.09.2011
    Ort
    Hessen
    Beiträge
    707
    Zitat Zitat von fredyxx Beitrag anzeigen
    Was soll das heißen?
    Ich programmiere schon seit über 35 Jahren und habe schon genug solcher Programme gesehen. Nach dem ersten Blick auf den Code in dem zitierten Thread und war damals schon klar, dass es zu einem Thread wie diesem kommen würde.

    Zitat Zitat von fredyxx Beitrag anzeigen
    Ich kann mir kein umfangreiches Programm ohne UP's vorstellen. Das trägt doch eindeutig zur Übersichtlichkeit bei
    Du redest davon, tust es aber nicht. Das Konzept in C um Programme zu Strukturieren sind Funktionen nicht gotos.

    Statt wie bei dir
    Code:
    switch(irgendwas)
    { 
      case 0:
        Mx =42;
        goto Mblub;
        break;
    	
        // ...
    	
    Mblub:
    
       // code ...
       
       goto Mbob;
       
       // anderes Zeug
       
    Mbob:
    
       // nochmehr Code
       
       goto Nochweiter;
    ist die Sprache eigentlich so gedacht
    Code:
    void blub(int paran)
    {
      // Der Code hinter dem einen Label
    }
    
    void bob()
    {
      // Der Code beim anderen
    }
    
    // ...
    
    switch(irgendwas)
    {
      case 0:
        blub(42);
        bob();
        break;
    
       // ...
    und nicht kilometerlanger Bandwurmcode in dem mit goto rumgehüpft wird.

    Dann hätten einmal mehr Leute überhaupt Lust sich das anzusehen und man kann jede Funktion mit Ausgaben versehen.
    Eventuell auch mit zusätzlichen Parametern, die nur dazu dienen in der Ausgabe anzuzeigen, woher der Aufruf kam.

    Also in der Art
    Code:
    void foo(int caller, int arg)
    {
      Serial.print("Aufruf von");
      Serial.print(caller);
      Serial.print(" mit ");
      Serial.println(arg);
    }
    und bei der Verwendung

    Code:
       // Eine Stelle
    
       foo(1, M42);
    
    
       // woanders
    
       foo(2, M42);

  3. #3
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    18.03.2013
    Beiträge
    242
    Hallo,

    während der Fehlersuche frage ich mich, wie ein Serial.Print-Befehl im Programm verarbeitet wird.
    Bleibt das Programm an dieser Stelle stehen, bis z.B. eine Quittung über den erfolgreichen Sendevorgang vorliegt oder wird der Befehl nur initiiert und das Programm setzt die Abarbeitung der folgenden Befehle unverzüglich fort.

    Wie ist das bei 4 -5 Serial.print's direkt hintereinander? Kann zwischen den einzelnen Serial.print's noch eine Programmabarbeitung erfolgen, so dass die auf dem Monitor angezeigten Werte nicht exakt den selben Programmzustand zeigen?
    Nur zur Info: ich habe " Serial.begin (250.000);" eingestellt.

    vG

    fredyxx

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    27.08.2013
    Ort
    Region Basel
    Alter
    67
    Beiträge
    2.435
    Hallo fredyxx,
    Zitat Zitat von fredyxx Beitrag anzeigen
    während der Fehlersuche frage ich mich, wie ein Serial.Print-Befehl im Programm verarbeitet wird.
    Bleibt das Programm an dieser Stelle stehen, bis z.B. eine Quittung über den erfolgreichen Sendevorgang vorliegt oder wird der Befehl nur initiiert und das Programm setzt die Abarbeitung der folgenden Befehle unverzüglich fort.
    Grundsätzlich benötigt die Ausgabe von Debug-Informationen etwas Zeit.
    Mit und ohne ist das Timing auf alle Fälle unterschiedlich!

    Zu deinem Grundproblem:
    Bevor noch irgendeine Zeile C ausgeführt wird, werden die globalen Variablen initialisiert. Die meisten bekommen den Wert 0
    int i;
    Bei
    int j = 3;
    Wird der entsprechende Wert (hier 3) zugewiesen.
    Dies wird aber nur nach einem Reset durchgeführt.
    Andernfalls haben dein globalen Variablen den letzten vom Programm zugewiesenen Wert.


    Wenn ich dein Programm noch richtig im Kopf habe hast du Hilfsvariablen in der Form
    Motor_fertig = TRUE;
    Womit du weiterschaltest.
    Bei einem zweiten Aufruf bleiben diese auf TRUE, wenn du sie nicht extra zurück setzt.
    Dann rasselt halt alles durch.

    MfG Peter(TOO)
    Manchmal frage ich mich, wieso meine Generation Geräte ohne Simulation entwickeln konnte?

  5. #5
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    18.03.2013
    Beiträge
    242
    Zitat Zitat von Peter(TOO) Beitrag anzeigen
    Hallo fredyxx,

    Grundsätzlich benötigt die Ausgabe von Debug-Informationen etwas Zeit.
    Mit und ohne ist das Timing auf alle Fälle unterschiedlich!


    MfG Peter(TOO)
    ok, aber kann man sicher sein, dass aufeinder folgende Serial.Print's auch direkt nacheinander gesendet werden und das Programm auch dann erst weiter geht?

    Wenn ich dein Programm noch richtig im Kopf habe hast du Hilfsvariablen in der Form
    Motor_fertig = TRUE;
    Womit du weiterschaltest.
    Alle Achtung! Das hast du noch genau richtig im Kopf. Deshalb setze ich in der LOOP mit dem STOP-Schalter auch alle Mx-fertig's auf false und erst wenn ich den wieder umschalte, kann das Justierprogramm wieder beginnen. Bei M1 ist das auch so, aber direkt danach sind alle Mx-fertig's auf true!!!???????????????????

    vG
    fredyx

  6. #6
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    27.08.2013
    Ort
    Region Basel
    Alter
    67
    Beiträge
    2.435
    Hallo fredyx,
    Zitat Zitat von fredyxx Beitrag anzeigen
    ok, aber kann man sicher sein, dass aufeinder folgende Serial.Print's auch direkt nacheinander gesendet werden und das Programm auch dann erst weiter geht?
    Im einfachsten Fall wartet man bis das Senderegister leer ist und schreibt dann das nächste Zeichen in das Sende-Register. So lange man wartet, ist die CPU blockiert, bzw. kann nur Interrupts bearbeiten. Das geht dann ganz ohne Interrupts, ist aber die langsamste Variante. Zudem hängen die Zeiten direkt von der Baudrate ab.

    Bei der eleganteren Art richtet man einen Puffer ein und der Print-Befehl kopiert die Zeichen in diesen Puffer. Nach dem Kopieren kann die CPU weiter das Programm abarbeiten. Wenn das Sende-Register leer ist erzeugt es einen Interrupt und die ISR kopiert dann das nächste Zeichen aus dem Puffer ins Sende-Register.
    Es braucht dann noch etwas Aufwand für die Pufferverwaltung. Wenn man das erste Zeichen in den leeren Puffer schreibt muss man den Interrupt anwerfen. Umgekehrt muss die ISR den Interrupt abschalten, wenn das letzte Zeichen aus dem Puffer gelesen wird.
    Wenn der Puffer voll ist, muss man warten, bis ein Zeichen gesendet wurde, dann ist man gleich langsam wie bei der einfachen Variante.
    Noch etwas schneller wird es, wenn man die Daten, sofern vorhanden, per DMA vom Puffer in das Sende-Register kopiert. Die Verwaltung wird dafür etwas aufwändiger, dafür wird die ISR seltener aufgerufen (Nur wenn die DMA fertig ist und somit nicht für jedes Zeichen).

    Die Technik mit dem Puffer funktioniert auch beim Empfangen und hat den Vorteil, dass man keine Zeichen verliert, besonders wenn man noch Handshake (XON XOFF) implementiert.

    Leider stehen viele Programmierer mit den Interrupts etwas auf Kriegsfuss und die erste Variante ist deshalb sehr häufig anzutreffen. Allerdings entwickelt man den Treiber eigentlich nur einmal im Leben für eine Programmiersprache. Die Anpassung an unterschiedliche µCs betrifft dann eigentlich nur die Handhabung des Interrupt-Controllers und des Sende-Registers, der Rest ändert sich eigentlich nicht.

    MfG Peter(TOO)
    Manchmal frage ich mich, wieso meine Generation Geräte ohne Simulation entwickeln konnte?

  7. #7
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    04.09.2011
    Ort
    Hessen
    Beiträge
    707
    Hallo,

    Zitat Zitat von fredyxx Beitrag anzeigen
    Bleibt das Programm an dieser Stelle stehen, bis z.B. eine Quittung über den erfolgreichen Sendevorgang vorliegt oder wird der Befehl nur initiiert und das Programm setzt die Abarbeitung der folgenden Befehle unverzüglich fort.
    Ganz allgemein erfolgt bei Arduiono kein Test auf erfolgreichen Sendevorgang. Wenn keiner empfängt sind die Daten halt weg.

    Ob das print wartet, hängt vom Arduino Modell ab:
    Bei den meisten Modellen gehen die Daten über UART vom Hauptcontroller zum USB-Controller auf dem Board. Das ist entweder ein zweiter Controller (meist ein 16U2) oder nur ein seriell zu USB Wandler (FTDI, CH340, ...). Das Print muss in diesem Falle warten, bis die Daten aus dem UART raus sind.

    Dieser Vorgang kann durch einen Interrupt unterbrochen werden, z.B. wenn ein Library verwendet wird, die damit arbeitet. Was hinter dem print steht, kommt aber erst dran, wenn das print fertig ist.

    Bei Arduinos mit Controllern, die selbst einen USB-Anschluss haben (Leonardo, Micro, Due, Teensy, ...), ist ein print meist nur ein sehr schneller Kopiervorgang, um den Rest kümmert sich die USB-Hardware im Chip.

  8. #8
    HaWe
    Gast
    switch/case ist nichts anderes als ein goto.
    Die case (irgendwas) sind nichts anderes als Sprungmarken für gotos, daher müssen es in C immer auch Integer-Konstanten sein (und keine Floats oder logische Ausdrücke).
    So ungern hier also manche das goto in C-Programmen sehen: es ist nur persönliches Ästhetikempfinden, nicht mehr und nicht weniger

    an fredyxx:
    wenn du sicher bist, dass deine Sprünge im richtigen Moment an die richtige Stelle führen, ist das kein Grund, sie durch switch/case Anweisungen zu ersetzen.
    Allerdings müssen sie beide in jedem Falle immer im richtigen Moment an die richtige Stelle führen.
    Bist du also sicher, dass sie stimmen, lass sie drinnen - und such den Fehler woanders.
    Goto Anweisungen innerhalb von switch/case ist allerdings reichlich doppelt gemoppelt und wirklich extrem unschöner Programmierstil.

    zum Debuggen mit serial:
    Du kannst Wartepunkte einfügen, indem du in dein Programm ein Warten auf einen Buttondruck und wieder loslassen einfügst:
    Code:
    #define testpin 13 // or whatever
    Code:
    while(!testpin);
    Serial.print(irgendwas);
    while(testpin);
    Geändert von HaWe (16.09.2016 um 14:03 Uhr)

  9. #9
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    18.03.2013
    Beiträge
    242
    Zitat Zitat von HaWe Beitrag anzeigen

    zum Debuggen mit serial:
    Du kannst Wartepunkte einfügen, indem du in dein Programm ein Warten auf einen Buttondruck und wieder loslassen einfügst:
    Code:
    #define testpin 13 // or whatever
    Code:
    while(!testpin);
    Serial.print(irgendwas);
    while(testpin);
    Hallo HaWe,

    funktioniert hat es so:

    Code:
    #define testpin 13 // or whatever
    Code:
    while(!testpin){
    Serial.print(irgendwas);
    }
    
    while(testpin);
    [/QUOTE]

    Nötig sind die geschweiften Klammern.

    Die letzte Zeile war bei mir nicht nötig.

    Aber prima die Idee!!

    vG

    fredyxx

  10. #10
    HaWe
    Gast
    mmmhhh... versuch es mal so wie ich ursprünglich schrieb -
    erst wartet er an der Stelle bis die Taste gedrückt wurde,
    sobald das der Fall war, macht er sein print,
    dann wartet er erneut, bis die Taste wieder losgelassen wurde.

    Zumindest war das meine ursprüngliche Idee.

Seite 1 von 3 123 LetzteLetzte

Ähnliche Themen

  1. 18 PWM Kanäle - Welche Möglichkeiten?
    Von Hardware-Entwickler im Forum Elektronik
    Antworten: 7
    Letzter Beitrag: 19.12.2015, 14:16
  2. Antworten: 8
    Letzter Beitrag: 21.10.2014, 09:18
  3. Möglichkeiten der AVR/Arduino PWM?
    Von ichbinsisyphos im Forum Arduino -Plattform
    Antworten: 10
    Letzter Beitrag: 23.02.2013, 09:03
  4. Spannungen mit PC-Computer Messen. Welche Möglichkeiten?
    Von petermetertr im Forum PC-, Pocket PC, Tablet PC, Smartphone oder Notebook
    Antworten: 14
    Letzter Beitrag: 26.08.2009, 16:36
  5. [ERLEDIGT] 20 mikrovolt-Hirnwellen registrieren-Welche möglichkeiten?
    Von Thomas Wellheim im Forum Allgemeines zum Thema Roboter / Modellbau
    Antworten: 13
    Letzter Beitrag: 18.12.2004, 18:43

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

fchao-Sinus-Wechselrichter AliExpress