Debuggen

Hallo Leute,

wie debuggt ihr eigentlich eure Sketche ?

Einfach strategisch ein paar Zeilen auf die serielle Konsole,
scheitert aber beim debuggen von zyklisch aufgerufenen Interrupts,
da es da ja schnell gehen soll.

Schön wäre auch ein Softwaresimulator des Ardunio,
was ich bisher gesehen habe war aber nicht so begeisternd
(oder ich habe es nicht verstanden) ..

Welche Tipps habt ihr für einen Rookie ?

Viele Grüße

Harry

Schrittweise den Schritt aufbauen und immer wieder testen. Serielle Ausgaben kann man auch ausser der ISR ausgeben. Einfach in der ISR ein Flag setzen.

Ansonsten bleiben dir nur ordentliche Debugger im Atmel Studio

Von Softwaresimulationen halte ich nicht viel da ich glaube daß oft der Hardwareteil die probleme produziert.
zB ein fehlender Pullup/Pulldownwiderstand macht jede menge Probleme und den wirst du mit keinem auch noch so guten Simulator/Emulator erkennen.

Der Zero müßte eine Echzeitdebuggingmöglichkeit haben (hab erst einen ausgeschaltenen Zero gesehen) aber der hat dann einen anderen Kontroller als der UNO.

Es bleibt nur Serial oder eine LED zb Pin 13 bei bestimmten Ereignissen einschalten.

Grüße Uwe

Atmel-Studio hört sich gut an. Schau ich mir mal an.

Ja, die Software kann natürlich die Hardware niemals wirklich emulieren,
aber manchmal möchte man schon mal einzelne Programmteile ein wenig

  • ich sage mal - vortesten.

Viele Grüße

Harry

Die kostenpflichtige Version von Visual Micro hat auch einen Debugger:
http://www.visualmicro.com/page/Debugging-for-Arduino.aspx

Da wird aber auch über die serielle Schnittstelle kommuniziert

HarryR:
wie debuggt ihr eigentlich eure Sketche ?

Einfach strategisch ein paar Zeilen auf die serielle Konsole,
scheitert aber beim debuggen von zyklisch aufgerufenen Interrupts,
da es da ja schnell gehen soll.

Ja genau, Debug-Meldungen auf Serial senden.

In Interrupt-Routinen gibt es nichts zu debuggen, da steht ja allenfalls sowas drin wie:

count++;

oder

lastInterruptTime=micros();

oder andere kurze Codes, die für sich so wenig fehlerträchtig sind, dass kein weiteres "Debuggen im Interrupt" notwendig ist.

In Interrupt-Routinen gibt es nichts zu debuggen

Richtig.
Da ist es auch fast egal ob VisualMicro oder Atmel Studio Debugger.
Selbst ein digitalWrite() in einer ISR verändert das Verhalten unter Umständen sehr.

PORTx |= Bit; // zum Setzen und anschauen mit einem Logik-Analyzer oder einer LED.
PORTx &= ~Bit; // zum Löschen

“Vortesten” musst du ausserhalb einer ISR.

Hmm, das trifft nicht auf alle Interrupt-Routinen zu,
schau dir mal die (im case leicht gekürzte) von meinem Theremin an:

/* Externaly generated 31250 Hz Interrupt for WAVE generator (32us) */
ISR (INT1_vect)
{
  // Interrupt takes up a total of max 25 us
  EIMSK &= ~ (1 << INT1);   // Disable External Interrupt INT1 to avoid recursive interrupts
  interrupts();             // Enable Interrupts to allow counter 1 interrupts

  int16_t  temp_val;        // temporary variable 1
  uint32_t temp2_val;       // temporary variable 2

  switch (addr1)                    // set wave tables for reading
  {
      case 0:  temp_val = (signed int)pgm_read_word_near (sine_table0 + ((unsigned int)(pointer >> 6) & 0x3ff)); break; //Read next wave table value (3.0us)
      case 1: 
    // weitere cases
     case 9:; break; //Read next wave table value (3.0us)
  };
  if (temp_val > 0)
  { // multiply 16 bit wave number by 8 bit volume value (11.2us / 5.4us)
    temp2_val = mul_16_8(temp_val, vol8);
    temp2_val = temp2_val >> 9;
    temp2_val = temp2_val + 1748;
  }
  else
  {
    temp2_val = mul_16_8(-temp_val, vol8);
    temp2_val = temp2_val >> 9;
    temp2_val = 1748 - temp2_val;
  }

  mcpDacSend(temp2_val);        //Send result to Digital to Analogue Converter (audio out) (9.6 us)

  pointer = pointer + add_val;  // increment table pointer (ca. 2us)
  timer++;                      // update 32us timer

  if (PC_STATE) deb_p++;
  if (deb_p == 3)
  {
    cli();
    pitch_counter = ICR1;                      // Get Timer-Counter 1 value

    pitch = (pitch_counter - pitch_counter_l); // Counter change since last interrupt -> pitch value
    pitch_counter_l = pitch_counter;           // Set actual value as new last value
  };

  if (deb_p == 5)
  {
    flag_pitch = true;
  };

  if (INT0_STATE) deb_v++;
  if (deb_v == 3)
  {
    cli();
    vol_counter = vol_counter_i;           // Get Timer-Counter 1 value
    vol = (vol_counter - vol_counter_l);   // Counter change since last interrupt
    vol_counter_l = vol_counter;           // Set actual value as new last value
  };

  if (deb_v == 5)
  {
    flag_vol = true;
  };

  cli();                        // Turn of interrupts
  EIMSK |= (1 << INT1);         // Re-Enable External Interrupt INT1
}

Viele Grüße

Harry

// Interrupt takes up a total of max 25 us
EIMSK &= ~ (1 << INT1); // Disable External Interrupt INT1 to avoid recursive interrupts
interrupts(); // Enable Interrupts to allow counter 1 interrupts

Kann natürlich sein, dass das funktioniert.
Aber wenn nicht, hast du ein Problem, das durch Debuggen evtl. größer wird, und du kannst nicht allzuviel Hilfe erwarten …

:frowning:

michael_x:
Kann natürlich sein, dass das funktioniert.
Aber wenn nicht, hast du ein Problem, das durch Debuggen evtl. größer wird, und du kannst nicht allzuviel Hilfe erwarten ...

:frowning:

Meinst du jetzt den Teil des Codes, denn du da ausgeschnitten hast ?
Und wenn ja, was genau, ich versuche zur Zeit zu verstehen, was der
Original-Programmierer gemacht hat und vor allen Dingen - warum ?

Nicht vergessen, ich bin Arduino-Neuling ..
(und nur durch mein Eigenbau-Theremin hier "reingerutscht" ;D )

VG+

Harry

Meinst du jetzt den Teil des Codes, denn du da ausgeschnitten hast ?

Ja, schon.

Das mit den "max. 25 µs" ist natürlich nur ein Kommentar, der verschieden interpretiert werden kann:

  • So wie es jetzt programmiert ist, wird die ISR max. 25 µs dauern und damit funktioniert der Theremin wie gewünscht
  • Da die ISR so lange dauert, muss sie durch andere Interrupts (ausser sich selbst) unterbrochen werden können. ( Kein normaler Betriebszustand )

Die meisten Programmierer denken sich bei exotischen Konstruktionen was dabei. Ich würde nicht sagen, dass das alles Unsinn ist und viel einfacher geht, vor allem wenn man es nur theoretisch ansieht und keine Theremin-Klänge dabei hört :wink: Aber gerade wenn das Timing vermutlich heikel ist, kann man nicht viel Debuggen, ohne dass es sich dann anders verhält.

Für einen Arduino - Neuling recht anspruchsvoll.
Dein Nachbau funktioniert, und du willst "nur" einen Schalter für verschiedene Klangfarben hinzufügen?
Dann lass auf jeden Fall die Finger von dieser ISR (und heb dir ein Backup auf) 8)

hi,

nur durch mein Eigenbau-Theremin hier "reingerutscht"

könnte schlimmer sein.
sheldon mußte wegen seines theremins auf den flur...

gruß stefan

michael_x:
Ja, schon.

Das mit den "max. 25 µs" ist natürlich nur ein Kommentar, der verschieden interpretiert werden kann:

  • So wie es jetzt programmiert ist, wird die ISR max. 25 µs dauern und damit funktioniert der Theremin wie gewünscht
  • Da die ISR so lange dauert, muss sie durch andere Interrupts (ausser sich selbst) unterbrochen werden können. ( Kein normaler Betriebszustand )

Die meisten Programmierer denken sich bei exotischen Konstruktionen was dabei. Ich würde nicht sagen, dass das alles Unsinn ist und viel einfacher geht, vor allem wenn man es nur theoretisch ansieht und keine Theremin-Klänge dabei hört :wink: Aber gerade wenn das Timing vermutlich heikel ist, kann man nicht viel Debuggen, ohne dass es sich dann anders verhält.

Für einen Arduino - Neuling recht anspruchsvoll.
Dein Nachbau funktioniert, und du willst "nur" einen Schalter für verschiedene Klangfarben hinzufügen?
Dann lass auf jeden Fall die Finger von dieser ISR (und heb dir ein Backup auf) 8)

Ich denke das der Originalprogrammierer darauf geachtet hat, dass er die 25µs nicht überschreitet.

In der ISR werde ich fast nichts machen ausser:

a) Die Wavetables sind unsinnigerweise vorzeichenbehaftet, daher gibt Fallunterscheidungen

  • also kurz auf vorzeichenlos konvertiert und die Fallunterscheidungen können raus
    b) Die Wahl der Wavetable nicht mit einem case abfackeln sondern duch ein Zeigerarray auf die Wavetables
    einfach reinindizieren ...

So ist der Plan

Im übrigen wird man den Ausfall eines ISR wg. Zeitüberschreitung wahrscheinlich gar nicht hören

Nebenbei : Ich bin zwar Arduino-Neuling aber auch Informatiker (jedenfalls habe ich das studiert).
Ich werde beruflich leider eher als Sachbearbeiter-IT missbraucht .. schniff .. aber ich habe noch
nicht alles vergessen und versuche mit gelegentlich gefertigten Scripten in diversen
Sprachen programmiertechnisch warm zu bleiben.

Viele Grüße

Harry

Eisebaer:
hi,

könnte schlimmer sein.
sheldon mußte wegen seines theremins auf den flur...

gruß stefan

Da kommt man wg. einem harmlosen Theremin gleich in schlechte Gesellschaft :o
Das erste Lied das ich üben werde ist natürlich die Titelmelodie von Enterprise - Ehrensache !!!

VG Harry

  1. Unit Tests schreiben
  2. Serial.print
  3. Man kann auch auf einen PC als Target kompilieren wenn man weiss was man tut. Dann kann man "normal" debuggen

Probleme: das erwischt nur die Software und nicht die Hardware.

Hi Harry,

ich debugge meine Sketche mit UDP.

Habe mir selbst einen UDP-Empfänger und UDP-Sender in VB.NET gebastelt, um UDP-Ausgaben zu empfangen und UDP-Pakete zu senden. Hat mir auch geholfen, den ganzen UDP-Krams ein bischen zu verstehen. Im Internet oder als App gibt es sowas auch.

Der Vorteil ist, es kommt kaum zu Verzögerungen und es ist schnell. Seriell bremst doch ein bischen und
man kann die Ausgabe nicht auf mehreren Bildschirmen debuggen. Mit UDP geht das schon.

Der Nachteil ist, es ist am Anfang schwieriger und man benötigt einen Netzwerkshield oder etwas ähnliches. Ich benutze eigentlich nur den Mega 2560, auch weil das Teil so viele Anschlüsse hat und
ich dadurch einen Standard habe. Aber wenn man das Sketch dann anpasst, geht es natürlich auch
für die anderen Controller.

Bis ich ordentliche Ausgaben hatte, hat es aber schon eine Weile gedauert.

Als Beispiel für Debugging kann ich dir einen Link auf mein Projekt senden, Das ist ein Codebeispiel
für UDP und die Kommunikation mit einer App.

Grundprogramm-Arduino

Vielleicht kannst Du ja was davon gebrauchen . Wichtig ist : NICHT AUFGEBEN ...

Sah für mich am Anfang alles kompliziert aus. Komme auch aus der Informatik und musste erst
einmal "laufen lernen" , was die Microcontroller-Technik betrifft. Gott sei Dank habe ich kein Problem
mit dem Netzwerkgedönse gehabt, da ich als Admin den ganzen Tag zu tun habe.

Für mich hörte sich das ganze so an, als ob Du nur Scripte schreibst. Wenn das so wäre :

Fang wieder richtig zu programmieren an, es lohnt sich auf jeden Fall, weißt Du ja.

Wenn man es richtig bequem haben will, kann ich MS VS2015 .NET nur empfehlen.

VB.net ist schon Klasse, wird aber zu unrecht oft belächelt,

C# ist noch besser.

Und wenn Du auf die harte Tour stehst, C / C++. (Brauchst Du eh für Arduino)

Ich selbst bin gerade im "Softcorebereich .NET" unterwegs.

Muss mir aber langsam was einfallen lassen, Möchte mal richtig unter Linux programmieren bzw. Apps schreiben, aber das ist mir noch zu frickelig, was die Standards anbetrifft.

Hi,

ich schreibe nicht nur Scripte. Beruflich habe ich leider fast nichts mehr mit Prgrammierung zu tun.
Aber programmieren verlernt man nicht - wenn man es kann ist auch die Sprache (fast) egal -
soviel (neue) "Vokabeln" muss man meistens nicht lernen im Gegensatz zu einer echten Sprache.

Ich behersche Pascal, Modula-2 (beide nicht mehr uptodate), C, C++, Java , x86-Assembler
und Scriptsprachen, python, ruby, was einem halt so im IT-Alltag über den Weg läuft ....
ab und zu muss ich halt an die Programmierfront, weil ich quasi der einzige bin,
der von solchen Dingen Ahnung hat und sich schnell einarbeiten kann.

Für mich ist die Microcontroller-Programmierung noch neu und irgendwie restriktiv, siehe debugging.

Anyway, die UDP-Geschichte hört sich gut an, ich werde das demnächst mal testen.

Viele Grüße

Harry

irgendwie restriktiv

Das ist ja grade der Reiz:
Es gibt kein Betriebssystem, du hast 2kB RAM (beim 328), kannst aber C++ schreiben, wenn dir bewusst bleibt, wo die Grenzen sind. Und du bist (wahlweise) direkt an der Hardware.

Kannst du mal das VB proggi posten sowie die Routinen die man fürs udp debuggen einbinden muss?

Würde mich doch mal reizen, das auszuprobieren.

In dem von dir genannten Link hab ich es nicht gefunden.

Hi,

in dem Link findest Du die Beschreibung und den Sketch vom Arduino inkl. Debugging.

Mein selbstgeschriebenes Programm (UDP senden / UDP-Empfangen) ist Teil eines größeren Projektes, für das es bereits schon einige Interessenten gibt, daher kann ich dieses Zusatztool noch nicht veröffentlichen.

Hier der Link :

Programm-zur-zentralen-Ablage-von-Messwerten