Abtürze des Arduino Uno

Hallo liebe Mitglieder

Ich habe mit einem Arduino Uno ein Programm geschrieben, mit dessen Hilfe ich einen Zeilendetektor (S9226-03) auslesen kann. Das Ganze funktioniert auch eigentlich recht gut, allerdings sind bei dem Projekt einige Probleme aufgetreten, die ich mir nicht erklären kann und sicherlich auf unsachgemäße Programmierung zurückzuführen sind.

Hier erstmal der Code

 byte startstop = 12;
 word wellenlaenge;
 byte wert[1024];
 word analog;
 boolean endmeasurement;
// Define various ADC prescaler
const unsigned char PS_16 = (1 << ADPS2);
const unsigned char PS_32 = (1 << ADPS2) | (1 << ADPS0);
const unsigned char PS_64 = (1 << ADPS2) | (1 << ADPS1);
const unsigned char PS_128 = (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);

void setup(){
 Serial.begin(115000);
 pinMode(startstop, OUTPUT);         //Start-Stop Trigger  PIN 12
 attachInterrupt(0, video, FALLING); //Interrupt 0:        PIN  2
 tone(13, 24000);                     //Clk:                PIN 13
  // set up the ADC
  ADCSRA &= ~PS_128;  // remove bits set by Arduino library
  
  // you can choose a prescaler from above.
  // PS_16, PS_32, PS_64 or PS_128
  ADCSRA |= PS_32;    // set our own prescaler to 64 
}

void loop(){
  digitalWrite(startstop, LOW);
  digitalWrite(startstop, HIGH);
  wellenlaenge=0;
  endmeasurement=false;
  do
{
  delay(5);
} while (endmeasurement==false);
  digitalWrite(startstop, LOW);
  Serial.write(wert, 1024);
  Serial.write(255);
}

void video(){
  wellenlaenge++;
  analog=analogRead(0)/4;              //Analoger Eingang:   PIN A0
  if(analog>254){analog=254;};
  wert[wellenlaenge]=analog;
  if(wellenlaenge>1023){endmeasurement=true;}
  }

Grobe Funktionsübersicht:
Der Zeilendetektor sendet über einen Trigger Zeitpunkte an denen der Mikrokontroller die Daten auslesen soll. Dieses wird in meinem Programm per Interrupt Funktion durchgeführt. Nachdem der Detektor 1024 Ereignisse eingelesen hat werden die Daten an den PC gesendet.

Problem 1:
Ich musste innerhalb der While Schleife ein delay von 5ms einfügen, weil sich sonst das Programm nach einem kompletten Signal aufgehangen hat. Ich habe keine Ahnung warum das so ist!? Vielleicht kann mir das einer erklären?

Problem 2:
Wenn ich am PC eine serielle Verbindung zum Arduino starte stürzt dieser ab. Wenn ich danach den Arduino resette, funktioniert alles tadellos. Hat auch dafür eine eine Erklärung?

Für beide Probleme gilt natürlich: Wie macht man es besser?

Danke für die Hilfe

tschaka81: Problem 1: Ich musste innerhalb der While Schleife ein delay von 5ms einfügen, weil sich sonst das Programm nach einem kompletten Signal aufgehangen hat. Ich habe keine Ahnung warum das so ist!? Vielleicht kann mir das einer erklären?

Schwer zu sagen. Vielleicht ja, weil das Programm nicht die Mindestanforderungen für Variablenzugriffe in Interruptroutinen einhält? Wenn Du auf globale Variablen sowohl vom "normalen Programm" als auch von einer "Interrupt-Behandlungsroutine" aus zugreifst, dann müssen alle diese Variablen zwingend als "volatile" deklariert sein. Probier's mal aus, soweit ich das sehe, sind diese Variablen betroffen: volatile word wellenlaenge; volatile byte wert[1024];

tschaka81: Problem 2: Wenn ich am PC eine serielle Verbindung zum Arduino starte stürzt dieser ab. Wenn ich danach den Arduino resette, funktioniert alles tadellos. Hat auch dafür eine eine Erklärung?

Wenn Du eine serielle Verbindung auf dem PC öffnest, stürzt der Arduino nicht ab, sondern er macht automatisch einen Reset. Auto-Reset. Dann startet der Bootloader und versucht, einen neuen Sketch auf das Board zu laden. Wenn Du zu diesem Zeitpunkt, kurz nach dem Reset, Daten über die serielle Schnittstelle an den Arduino sendest, kann er im Bootloader hängenbleiben.

Denkbare Abhilfen wären beispielsweise: a) Nach dem Öffnen einer Schnittstelle am PC mindestens zwei Sekunden lang keine seriellen Daten senden, während der Bootloader nach dem Reset läuft. b) Bootloader auf dem Arduino plattmachen und Sketche nur mit einem ISP-Programmer hochladen c) Autoreset am Arduino verhindern, z.B. einen 100?F Kondensator zwischen die RESET und GND Pins schalten (achtung: Während der Kondensator da steckt, ist ein Upload per Bootloader dann nicht möglich)

hi,

Du kannst auch einen anderen seriellen monitor verwenden, der nicht automatisch ein DTR-signal sendet, wenn er die verbindung aufbaut. HTerm (gratis) hat zb einen knopf, bei dem man das ein- und ausschalten kann.

gruß stefan

jurs: Schwer zu sagen. Vielleicht ja, weil das Programm nicht die Mindestanforderungen für Variablenzugriffe in Interruptroutinen einhält? Wenn Du auf globale Variablen sowohl vom "normalen Programm" als auch von einer "Interrupt-Behandlungsroutine" aus zugreifst, dann müssen alle diese Variablen zwingend als "volatile" deklariert sein. Probier's mal aus, soweit ich das sehe, sind diese Variablen betroffen: volatile word wellenlaenge; volatile byte wert[1024];

Das hat nichts verändert, wobei ich allerdings den array wert nicht als volatile deklarieren konnte.

jurs: Wenn Du eine serielle Verbindung auf dem PC öffnest, stürzt der Arduino nicht ab, sondern er macht automatisch einen Reset. Auto-Reset. Dann startet der Bootloader und versucht, einen neuen Sketch auf das Board zu laden. Wenn Du zu diesem Zeitpunkt, kurz nach dem Reset, Daten über die serielle Schnittstelle an den Arduino sendest, kann er im Bootloader hängenbleiben.

Denkbare Abhilfen wären beispielsweise: a) Nach dem Öffnen einer Schnittstelle am PC mindestens zwei Sekunden lang keine seriellen Daten senden, während der Bootloader nach dem Reset läuft. b) Bootloader auf dem Arduino plattmachen und Sketche nur mit einem ISP-Programmer hochladen c) Autoreset am Arduino verhindern, z.B. einen 100?F Kondensator zwischen die RESET und GND Pins schalten (achtung: Während der Kondensator da steckt, ist ein Upload per Bootloader dann nicht möglich)

Ich sende keinerlei Daten vom PC zum Mikrokontroller, sondern empfange lediglich. Ich werde aber mal die Sache mit dem 100µF Kondensator ausprobieren

Ich sende keinerlei Daten vom PC zum Mikrokontroller, sondern empfange lediglich

DTR ist ein zusätzliches Signal, neben Rx /Tx, und wird in der Regel beim Öffnen der seriellen Schnittstelle auf dem PC gesetzt.

Mir reicht übrigens schon ein 10 µF Kondensator (Gibt beim ersten Aufstecken erstmal einen Reset, aber das sollte mit einem dickeren erst recht passieren... )

tschaka81:
Das hat nichts verändert, wobei ich allerdings den array wert nicht als volatile deklarieren konnte.

Verstehe, Dein “Serial.write” ist nicht für die Ausgabe von volatile deklarierten Byte-Arrays vorgesehen. Dann gibst Du die Bytes eben einzeln in einer Schleife aus, also statt:
Serial.write(wert, 1024);
Setze:

  for (int i=0;i<1024;i++)
    Serial.write(wert[i]);

Dann frißt der Compiler die Werte auch, wenn sie volatile sind.

Und diese Variable habe ich auch noch gefunden, die natürlich volatile sein muß, weil sowohl von der ISR als auch vom normalen Programm aus darauf zugegriffen wird:
volatile boolean endmeasurement;

Du kannst auch einen anderen seriellen monitor verwenden, der nicht automatisch ein DTR-signal sendet, wenn er die verbindung aufbaut. HTerm (gratis) hat zb einen knopf, bei dem man das ein- und ausschalten kann.

Diese Funktion sollte man auch in der nächsten Arduino IDE Version realisieren !