Hallo Forumisten,
seit einiger Zeit treibt mich ein Problem fast zum Wahnsinn. Es handelt
sich um eine Tochteruhrsteuerung mit einem PIC16F876A mit 4MHz. Schema
und Layout beiliegend.
Problembeschreibung: Ich kann nicht mehr genau sagen, ab wann
(gefühlsmässig seit Anfang) der PIC nur sporadisch das Programm startet,
oder nach kürzester Zeit abbricht (einige Sekunden). Vereinzelt lief er
stundenlang ohne Probleme.
Zuerst hatte ich den Quarz in Verdacht. Aus stromspargründen verwende
ich einen 4Mhz-Quarz im XT-Mode. Aber der HS-Mode brachte keine
Aenderung. Auch Wechseln brachte nichts. Im Oszillogramm schwingt er
schön in beiden Modi. Gemessen an OSC2/Pin 10 mit 10:1 Tastkopf (siehe
Bilder). Ich nehme an, der kleinen Pegel ist normal im XT-Modus? Kanal 2
zeigt die Versorgungsspannung 5V im AC-Modus. Ein wenig Rauschen.
Langsam kommt der Verdacht auf, es liegt an der Software. Ist sie doch
komplex, mit 2 Interrupt-Quellen (einmal Timer0 jede ms, und einmal
USART-Empfang). So habe ich ein Testprogramm mit dem nötigsten gemacht.
Das läuft sauber an, immer! Die LEDs blinken abwechselnd. ABER: Meistens
kommt LED1 zuerst (wie es sollte) und 200ms lang(!) und manchmal kommt
ZUERST LED2 (im richtigen Takt)! Screenshot von LA leigt bei.
Beide Programme sind angehängt. Geschrieben in "mikroBasic for PIC" von
mikroE. Ich habe schon viele Projekte damit gemacht, auch mit dem
PIC16F876A, immer ging alles wunderbar. Nur einmal hatte in einen PIC,
der zog -MCLR intern mit ca. 0mA5 runter. Der hat dann dauernd
geresettet...
Kann mal jemand drüberschauen, oder einen Denkanstoss geben.
Warscheinlich habe ich mich irgendwie verrannt...
Danke und einen schönen Tag, Feiertag (Vereinigung moldau und Walachei)
Gruss Chregu
Ich habe es mal kurz überflogen:
Du solltest auf keinen Fall im Interrupt + im main-Loop auf die selbe
Variable zugreifen, solange die Interrupts aktiv sind. (zB puls)
Christian M. schrieb:> ABER: Meistens> kommt LED1 zuerst (wie es sollte) und 200ms lang(!) und manchmal kommt> ZUERST LED2 (im richtigen Takt)! Screenshot von LA leigt bei.
schreib mal folgendes vor die while
Michael .. schrieb:> auf keinen Fall im Interrupt + im main-Loop auf die selbe> Variable zugreifen, solange die Interrupts aktiv sind.
Kann jetzt grad nicht nachvollziehen, warum nicht. Und wie löse ich
sonst so ein Problem? Flag setzen und abfragen geschieht ja IMMER
sequentiell.
Michael .. schrieb:> schreib mal folgendes vor die while> LED1 = 0> LED2 = 0
Ja logisch, danke! Zuerst kommt ein Delay, und vorher hat der Ausgang
noch irgendeinen Wert von vorher...
Gruss Chregu
Christian M. schrieb:> Kann jetzt grad nicht nachvollziehen, warum nicht. Und wie löse ich> sonst so ein Problem? Flag setzen und abfragen geschieht ja IMMER> sequentiell.
Weil durch solche effekte können Programme sich sehr unberechenbar
verhalten. zB nach wenigen Sekunden oder nach Tagen.
https://www.mikrocontroller.net/articles/Interrupt#Atomarer_Datenzugriff
einfachste möglichkeit das zu beheben ist, im main-loop jeweils vor dem
Zugriff auf die Variable, die Interupts zu deaktivieren. (INTCON -> GIE)
Servus Chregu,
die Unsicherheit beim Start des Testprogramms kommt mir so vor, als ob
der Prozessor nicht zuverlässig resettet wird. Du solltest die Brown-Out
Detection aktivieren (hast Du? Sorry kann das Config-Word gerade nicht
selbst auseinanderklamüsern....)
Thomas E. schrieb:> Unsicherheit beim Start des Testprogramms
Das hat sich ja weiter oben schon erledigt.
Thomas E. schrieb:> Du solltest die Brown-Out> Detection aktivieren
Ist Enabled! :-))
Gruss Chregu
Christian M. schrieb:> Beide Programme sind angehängt.
Also wenn Prog 2 nicht läuft würde ich bei der Hardware bleiben.
Bei dem LA-schrieb würde ich auf Spannungversorgung tippen.
Also z.B. IC1 raus und über den ICSP versorgen.
Hast du mal versucht, testweise das Messen der Spannung wegzulassen.
Sobald sie deinen vorgegebenen Wert unterschreitet, sendet das
Hauptprogrammm nur noch Messwerte.
Und wenn dann puls auf 0 heruntergezählt wurde, passiert beim timer
nichts mehr.
Christian M. schrieb:> Langsam kommt der Verdacht auf, es liegt an der Software.
Hast du den Watchdog in Benutzung?
Wie hast du den Prescaler in Benutzung? Also für den Timer oder den WD?
Ich habe diese PIC's bislang ausschließlich in Assembler programmiert
und hatte damit noch nie Probleme. Auch die Stack-Tiefe hat bei mir
bislang problemlos ausgereicht. Aber zu Micro-Basic kann ich dir nix
sagen - außer daß du mal guckst, wie dort der Stack tatsächlich benutzt
wird.
W.S.
W.S. schrieb:> Hast du den Watchdog in Benutzung?
Nein, der käme erst am Schluss, wenn alles läuft.
W.S. schrieb:> Wie hast du den Prescaler in Benutzung?
Prescaler 1:4 für Timer0
W.S. schrieb:> hatte damit noch nie Probleme
Hatte ich auch noch nie. Eigentlich nimmt einem der Compiler die ganzen
Bank-Umschaltungen, Stack usw. Probleme ab. Lief immer alles perfekt!
Bugs waren immer ganz dumme, selbstgemachte, die man schon lange hätte
sehen sollen :-))
Wilhelm S. schrieb:> Hast du mal versucht, testweise das Messen der Spannung wegzulassen.
Ja, habe das Unterprogramm commented, und den Aufruf gesperrt. Auch das
Unterprogramm "schreiben".
X4U schrieb:> Also wenn Prog 2 nicht läuft würde ich bei der Hardware bleiben.
Läuft perfekt!
Das Problem besteht immer noch. Eingekreist dass das Programm manchmal
kaum bis zur Initialisierung kommt (mit blinkenden LEDs festgestellt)
wo noch kein Interrupt freigegeben ist. Manchmal läuft es 2...3
Durchgänge in der Hauptschleife, manchmal 10...20 Mal.
Vor dem Zugriff auf Variablen, die auch in der Int vorkommen, habe ich
jetzt den Int gesperrt. Alle Variablen werden am Anfang der main:
gelöscht/auf Null gesetzt, damit keine Effekte von einem vorherigen
Start reinspielen (sollten).
Ich weiss nicht mehr weiter. Mach wieder ein zwei Tage Pause, das hilft
manchmal. Zu lange nicht, sonst ist man wieder draussen...
Gruss Chregu
Es war ein Stack-Overflow!!!
Der Interrupt braucht schon vier Ebenen, und wenn das zusammenkommt mit
dem Hauptprogramm, wo es über vier Ebenen sind, crasht's!
Mein Workaround war jetzt die ganze Hauptschleife in einen Rattenschwanz
absolut ohne Funktionen und Prozeduren zu pferchen.
Alternativ könnte man einen 18F nehmen.
Danke an alle!
Gruss Chregu
Servus Chregu,
kenne mich zwar mit mikroBasic nicht aus, aber wenn ich mir die ISR
anschaue, sieht die für mich ziemlich flach aus - keinerlei
Unterprogramm-Aufrufe oder komplexe Funktionen. Wenn mikroBasic da 4
Stacklevel draus macht, würde das mein Vertrauen in dieses Werkzeug
nicht gerade stärken...
Gruß
Thomas
Hallo Thomas,
tut mir leid, ich habe vergessen zu Erwähnen, dass ich das ganze
Programm in den Oshonsoft-Compiler transferiert habe. Dabei hatte ich
ähnliche Probleme, bis ich mit dem LA das Problem eingekreist habe. Die
Stacktiefe hat sich in der Simulation gezeigt, wobei das Projekt sehr
schwierig zu simulieren ist. Ich hatte da schon die volle Stacktiefe von
8 Ebenen ausgenutzt, und es war noch ohne Unterfunktionen in Funktionen.
Ich werde auf jeden Fall in Zukunft gröbere PICs benutzen, obwohl ich
eigentlich immer das einfachstmögliche einzusetzen versuche. Ich mag
keinen Overhead von irgendwelchen Klickibunti, die dann 90% der
Resourcen verbrauchen.
Auf jeden Fall läuft jetzt die Uhr! Steuerung noch in ein schönes
Gehäuse und an die Wand damit! :-))
Gruss Chregu
Christian M. schrieb:> Alternativ könnte man einen 18F nehmen.
Eine Alternative wären evtl. die Enhanced Midrange Typen (12F1xxx,
16F1xxx). Pinkompatibel zu den alten Midrange Typen, aber u.a. 16 Level
Stack.
Die Sparschaltung der Spannungsversorgung ist aber auch nicht aktueller
Stand der Technik, so der Eindruck, auch wenns funktioniert.
Wenn die Siebelkos schleichend schlapp machen, wird es sich zeigen
ob da nicht am falschen Ende gespart wurde.
Thomas E. schrieb:> Wenn mikroBasic da 4> Stacklevel draus macht, würde das mein Vertrauen in dieses Werkzeug> nicht gerade stärken...
mikroBasic macht die ISR direkt bei 0x0004, Oshonsoft macht im ASM:
1
ORG 0x0004
2
CALL L0003
3
RETFIE
und im L0003 (nach END) dann viele CALLs! Wie tief die jetzt
verschachtelt sind, habe ich nicht mehr verfolgt.
Gruss Chregu
Hallo Christian,
kannst Du dem Tool nicht sagen, dass es anstatt des CALLs ein GOTO
einfügen soll, und das RETFIE dann dort hinlegt?
Somit spart man sich eine Stackebene.
Ich glaube auch, die CALLs nach dem END sind hier nicht mehr wichtig, da
das wahrscheinlich die OPCODES für 0x3FFF sind (also eine leere
Speicherstelle repräsentieren)
Gruß
TK
Christian M. schrieb:> mikroBasic macht die ISR direkt bei 0x0004, Oshonsoft macht im ASM:
Ist schon heftig, bei einer Maschine mit winzigem Hardware-Stack diesen
auch noch mit überflüssigen calls zu vergeuden! Die wollen ja auch Geld
sehen für ihre Software, da kann man nichtmal entschuldigend sagen "was
nix kosten, taugt auch nix" oder "einem geschenkten Gaul usw..."
Wie gesagt, ich würde wohl einfach einen pinkompatiblem
Enhanced-Midrange PIC nehmen, in der Hoffnung, daß Oshonsoft die
Stackvergeudung nicht abhängig von verfügbaren Stacklevels betreibt.
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