Guten Morgen,
ich habe da mal ein kleines Anliegen. Zurzeit arbeite ich an meiner
Abschlussprüfung als Systeminformatiker. Das Programm, welches wir
programmieren sollten, ist eine Überwachungskamerasteuerung.
Das Programm an sich ist nicht die Problematik, es ist schon fertig
geschrieben und die gewünschten Funktionen sind alle einwandfrei.
(OSD Sensoren UART ...)
Allerdings hat der Mikrocontroller (ATmega32) Probleme bei
Langzeitbetrieb. Sobald der Mikrocontroller länger als 20 Minuten
arbeitet hört die main-Routine auf zu arbeiten. In dieser Routine sollen
die Kameras im 5-Sekunden Takt wechseln.
Als Funktion sollte eine Heartbeat-Anzeige über einen Timer laufen.
Diese funktioniert einwandfrei, selbst nach stundenlangem Betrieb.
Die Sensoren haben allerdings dann keinen Einfluss mehr auf das
Programm, ebenso hört der automatische Wechsel der Kameras auf.
Hier also die Frage:
Was ist da sinnvoller: Den µC über den Timer immer wieder neustarten zu
lassen, oder den Speicher hzu säubern im Betrieb? Bei zweiterem wüsste
ich nicht wie das funktionieren sollte...
Meinen Code poste ich noch nicht, da ich nicht weiß, ob es auch wirklich
erlaubt ist. Das Programm wurde schon zur Bewertung abgegeben, nächste
Woche erfolgt ein Änderungsauftrag des Programms.
Vielen dank für eure Hilfe und Grüße aus dem Norden!
Timm S. schrieb:> Was ist da sinnvoller: Den µC über den Timer immer wieder neustarten zu> lassen, oder den Speicher hzu säubern im Betrieb?
Weder noch.
Du mußt schon den Fehler suchen und beseitigen.
Vermutlich ein Atomicity Problem oder ein Deadlock.
Das Programm so schreiben, dass nicht nach 20 Minuten der Speicher voll
laeuft? Das muss ja irgendeinen Grund haben.
Da du den Code nicht posten willst/kannst, musst du dich wohl selber auf
die Suche nach dem Problem begeben.
Hi
>Was ist da sinnvoller: Den µC über den Timer immer wieder neustarten zu>lassen, oder den Speicher hzu säubern im Betrieb?
Keins von beiden. Dein Programm hat Fehler. Die musst du finden und
beheben.
MfG Spess
Ihr habt moeglicherweise ein Software problem, moeglicherweise ein EMV
Problem. Ich verwende auch Mega32, und die laufen jahrelang durch, ohne
reboot.
Boevor ich eine reboot massnahmen andenken und testen wuerde, wuerde ich
versuchen den Fehler beheben. Das einzige was man periodisch neu
initialisierent kann/sollte ist allenfalls ein LCD, da diese EMV
empfindlich sind. Sobald die eingestrahlte Welle in den LCD Ausschnitt
passt., dh gegen 1GHz und drueber. Ja, die EMV Vorschriften gehen bis
3GHz. Jeden will ja mit einem Mobiltelephon rumlaufen ... das sendet
wahlweise bei 800, 900, 1800, 1900MHz. Dann kommt WLAN bei 2.4GHz und
5GHz.
Als ersten nimmt man den Watchdog raus. Mit dem sieht man nichts. Dann
baut man eine Laufzeit messung ein, dh einen Zaehler, der per timer
incrementiert, und den fragt man per kommunikation periodisch ab. Und
dann sucht man den Zustand, wo der Controller abstuerzt.
die variable interrupted wird von zwei interrupts gespiesen ?
Uart ist blockierend ? Sollte man nie machen... ist nicht mehr debugbar.
In welchem Zustand ist das programm? Nimm eine Zustandsmaschine.
Von Zustandsmaschine hatte ich vorher noch nichts gehört, habe
eigentlich nur mit Struktogrammen und PAP's gearbeitet.
Das 2 Interrupts für 1 Varriable verwendet wird ist bedingt durch die
vordefinierte Hardware, zu der wir das Programm schreiben sollten.
(Jeder Interrupt = 1 Sensor)
UART ist hier allerdings Nebensache, habe das Programm auch ohne UART
laufen lassen und das gleiche Resultat erhalten.
Was mir im Programm auffällt:
PD2 und PD3 werden als Eingang benutzt. Aber nur für PD2 wird ein
Pullup eingeschaltet.
Dann natürlich und nicht zu übversehen: pal_write bzw. die
Adressumschaltung wird von main UND von der ISR aufgerufen.
Ist das Zulässig? ist pal_write reentrant? Was passiert, wenn gerade die
Funktion pal_write läuft und der Interrupt ausgelöst wird, der
seinersseits pal_write aufruft?
Auch interessant: was passier, wenn hier
1
display_memory_address=413;
2
pal_write("Cam2 ");// [OSD] Gebe "Cam2" auf Bildschirm aus
genau nach dem Zuweisen der neuen Adresse und vor dem Aufruf von
pal_write ein Interrupt auftritt, der seinerseits
1
ISR(TIMER1_COMPA_vect)
2
{
3
Heartbeat=!Heartbeat;// Invertiert den Schalter "Heartbeat" bei jedem Timer-Überlauf
4
display_memory_address=393;// Position auf dem Bildschirm für OSD
5
...
die Adresse wieder umsetzt?
Alles das sind genau die Dinge, die bei ersten Tests gut gehen, die aber
irgendwann zeitlich sich genau so ausgehen, dass es zu Fehlsituationen
kommt.
Warum habt ihr euch denn nicht an eine der Grundregeln gehalten: In
einer ISR werden keine Ausgaben gemacht. Oder, wenn schon, dann NUR in
dieser ISR. Bei "Shared Resourcen" also Dingen, die sich mehrere
Programmteile 'teilen', muss man ein wenig vorsichtig sein! Das führt
sonst ganz schnell zu massiven Synchronisations bzw. Reentrance
Problemen.
if((PIND&(1<<PD2))&&!(PIND&(1<<PD3)))// Wenn Sensor 1 HIGH und Sensor 2 LOW ist, schalte auf Kamera 2 (halten)
2
CamSelect=true;
3
if(!(PIND&(1<<PD2))&&(PIND&(1<<PD3)))// Wenn Sensor 1 LOW und Sensor 2 HIGH ist, schalte auf Kamera 1
4
CamSelect=false;
ist sowieso seltsam.
Wenn PD2 immer das Gegenteil von PD3 sein muss, dann frage ich mich:
wozu überhaupt 2 Eingänge? Offenbar tut es ja auch einer. Dann erhebt
sich dann auch nicht die Frage: was passiert, wenn PD2 und PD3 den
gleichen Pegel haben? (ok, in dem Fall ändert dann CamSelect seinen
Zustand nicht. Aber: ist das auch so gewollt?)
Zuerst mal danke für die konstruktiven Beiträge!
Der Pullup war eigentlich nicht nötig, da Hardwaremäßig ein Widerstand
verbaut wurde. Wird also bei meiner nächsten Revision entfernt.
Bei den rare occurrences wie du beschrieben hast ist die Formatierung
teils durcheinander... bin schon dabei das zu beheben.
Ich probiere mal den Code umzuschreiben und dies aus der Timer-Routine
zu entfernen, melde mich wenn es geklappt hat.
Hast du einen Debugger? Wo bleibt der stehen?
Ich erkenne hier kein Speicherleck.
Dein Heartbeat kommt weiter regelmäßig?
Hast du sonst irgendwo eine While Schleife oder ähnliches in den
Treibern?
Wenn du keinen Debugger hast, dann erstelle einen Zähler in der
Hauptschleife. Stürzt das Programm dann immer exakt nach xxx durchläufen
ab? Erstelle an verschiedenen Punkten der Hauptschleife eine UART
Ausgabe. Wo stürzt er ab.
Wie sehen die PAL-write Rountinen aus. Kann es sein dass er dort hängen
bleibt?
Die ganze Sache mit dem 5 Sekunden Delay, der durch Interrupt
abgebrochen werden kann ... man kann es so machen, mit etwas Bauchweh.
Aber so richtig 'nach den Regeln der Kunst' ist das nicht wirklich.
Letzten Endes ist das doch ein: wenn einer von 2 Eingängen eine Flanke
aufweist, dann bewerte die Schalterstellungen (bzw. Sensorstellung) neu
und schalte gegebenenfalls die Kameras um, spätestens aber alle 5
Sekunden.
Man würde das anders programmieren. Das Stichwort Statemachine ist ja
schon gefallen.
Der Grund dafür ist einfach: mit dem delay verbaut ihr euch zukünftige
Erweiterungen massiv. Damit da in diesen Zeittakt noch was anderes
reinpasst, muss man sowieso das Programm umbauen. Da kann man das auch
jetzt gleich nach den Regeln der Kunst machen.
Karl Heinz schrieb:> Das hier ist sowieso seltsam.> ist das auch so gewollt?
Das ist so gewollt. Wenn exklusiv ein Sensor aktiv ist, soll die Kamera
explizit auf den zugewiesenen Sensor zugewiesen werden. Sind beide
Sensoren aktiv, soll wie bei inaktiven Sensoren hin- und hergeschaltet
werden. Nur die Aufnahme soll dann noch erfolgen.
Habe nun relativ simpel die Heartbeat-Funktion in meine Delay-Funktion
eingebaut. Bisher läuft die Platine einwandfrei. (15 Minuten läuft er
bereits)
Wenn nicht mit Delay, wie dann? Wie soll ich "in den Regeln der Kunst"
einen 5-Sekunden-Takt erzeugen, wobei die Kamerastellung wechselt ?
Groß erweitert soll das Programm eh nicht mehr. (Auch wenn diese
Einstellung nicht gerade löblich ist, das weiß ich)
Ich denke, dass beim Änderungsauftrag nur noch zusätzlich der
Watchdog-Sensor angeschlossen werden soll, der fehlt noch bei der
fertigen Platine. Den Code dafür habe ich mir auch schon vorgeschrieben.
@ Timm S. (atrocty)
>Wenn nicht mit Delay, wie dann? Wie soll ich "in den Regeln der Kunst">einen 5-Sekunden-Takt erzeugen, wobei die Kamerastellung wechselt ?
Siehe Statemachine>Groß erweitert soll das Programm eh nicht mehr. (Auch wenn diese>Einstellung nicht gerade löblich ist, das weiß ich)
Mag sein, aber du willst ja was Gescheites für deine berufliche Zukunft
lernen und nicht in BASCOM-Arduino-Style was zusammenfrickeln.
Timm S. schrieb:> Habe nun relativ simpel die Heartbeat-Funktion in meine Delay-Funktion> eingebaut. Bisher läuft die Platine einwandfrei. (15 Minuten läuft er> bereits)>> Wenn nicht mit Delay, wie dann? Wie soll ich "in den Regeln der Kunst"> einen 5-Sekunden-Takt erzeugen, wobei die Kamerastellung wechselt ?
Du hast einen Timer laufen, der den Heartbeat erzeugt.
Die 5 Sekunden kann man auch als 'Anzahl von aufgetretenen Heartbeats'
ausdrücken.
Wann immer in einem Programm Zeiten (hinreichender Größe, alles über ein
paar µs) vorkommen, dann kannst du deinen Allerwertesten darauf
verwetten, dass die Lösung über Timer führt und nicht über delays.
Delays sind oft nicht die Lösung, sie sind aber oft das Problem.
In deinem Fall musstest du zu einem Kunstgriff greifen, indem du den
Delay mittels Interrupt von hinten durch die Brust ins Auge abwürgen
musstest, nur damit du auch zeitnah auf das Ansprechen eines Sensors
reagieren kannst. Drückst die die Umschaltzeiten als Anzahl von
Heartbeats aus und schaltest du in main nur dann um, wenn diese Anzahl
erreicht ist, dann fällt der delay flach und damit auch die ganze
Interrupt Geschichte, die du nur brauchtest um den Delay vorzeitig
abwürgen zu können. Das Programm wird also eigentlich sogar einfacher,
auch wenn sich das bei dir nicht viel schenken wird.
Aber: da du die externen Interrupts gar nicht mehr brauchst, hast du
auch die Einschränkung auf lediglich 2 von ihnen weg. Du kannst also
beliebig viele (im Rahmen der Pins deines µC) derartige Kameras und
Sensoren anhängen, ohne dass sich an der Programmstruktur groß was
ändert.
So arbeiten Profis: sie lassen sich Optionen für die Zukunft offen, wenn
ihnen das in der Programmstruktur praktisch nichts kostet.
> Groß erweitert soll das Programm eh nicht mehr. (Auch wenn diese> Einstellung nicht gerade löblich ist, das weiß ich)
Ist kein Argument. Du bist kein Bastler, sondern das ist deine
Abschlussarbeit, die dir bescheinigt, dass du eine Fachkraft bist.
Schlimm genug, dass dir der Begriff Statemachine (oder das deutsche
Zustandsautomat) nichts sagt.
Karl Heinz schrieb:> Ist kein Argument. Du bist kein Bastler, sondern das ist deine> Abschlussarbeit, die dir bescheinigt, dass du eine Fachkraft bist.> Schlimm genug, dass dir der Begriff Statemachine (oder das deutsche> Zustandsautomat) nichts sagt.
Dem stimme ich auch vollkommen zu.
Leider wird meist nur nach IHK-Richtlinien gelehrt, und dabei haben wir
hier noch das Glück, dass wir einige Sachen lernen, die nicht unbedingt
direkt was mit dem Berufsfeld zu tun haben. Und in den IHK-Richtlinien
gabs wohl die Zustandsautomaten nicht. (Auch nicht in vielen Jahren
vorher laut den Prüfungen, haben Sommer/Winter von 2004-2013
durchgearbeitet)
Mal schauen ob sich einiges ändert sobald das Studium losgeht...
Zum Programm: Ich gehe davon aus, dass du meinst, wenn ich ohne delays
arbeite die Interrupts nicht brauche.
Bin am überlegen:
Gehen wir mal davon aus ich entferne den delay. Der Timer ist auf exakt
1 Hz getaktet.
Um ein Flackern durch OSD und UART zu verhindern wird ein Schalter als
Bedingung gesetzt, der immer nur bei Änderungen schaltet.
Ist das so der richtige Ansatz?
@
>Zum Programm: Ich gehe davon aus, dass du meinst, wenn ich ohne delays>arbeite die Interrupts nicht brauche.
Nein, den Timer-Interrupt brauchst du auf jeden Fall. Aber die Externen
Interrupts nicht.
>Gehen wir mal davon aus ich entferne den delay. Der Timer ist auf exakt>1 Hz getaktet.
Kann man machen, ist aber eher zu langsam. Praktisch wird man eher
10-1000Hz anstreben.
>Um ein Flackern durch OSD und UART zu verhindern wird ein Schalter als>Bedingung gesetzt, der immer nur bei Änderungen schaltet.>Ist das so der richtige Ansatz?
So in etwa.