Hallo in die werte Runde, Es geht um einen attiny13a, welcher ein Lauflicht aus sechs LEDs (Charlieplexing) abhängig von der Umgebungshelligkeit ein- oder ausschaltet. Anbei ein handgezeichnetes Schaltbild. Die Schaltung existiert zwei mal. Einmal auf einem Steckbrett und einmal fest verlötet auf einer Lochrasterplatine. Erstere wird direkt aus dem AVR-Programmer mit Strom versorgt (3.3V), letztere aus einem kleinen einzelligen Li-Ion-Akku, welcher wiederum an einem TP4056-Modul hängt. Für Tests ist zusätzlich ein rs232-Pegelwandler-Modul (MAX3232) angeschlossen: Gnd und Vss direkt vom Programmer bzw. Akku, PB3 als serieller Ausgang des Mikrocontrollers (bitbanging). Zwischen Gnd und Vcc ist ein 100n-Keramikkondensator, zwischen Gnd und PB4 eine Fotodiode mit der Kathode an Gnd und der Anode am PB4. Das Programm ist auf beiden Umgebungen dasselbe (siehe Anhang, Kommentare stehen direkt im Quellcode. Entwickelt wurde das ganze im avr-Simulator von Gerhard Schmidt). Wenn ich das Programm starte (egal ob Steckbrett oder Lochraster), funktioniert es so wie erwartet. Das Lauflicht wird abhängig von der Helligkeit ein- bzw. ausgeschaltet. Den ADC-Wert bekomme ich alle zehn Sekunden am seriellen Ausgang ausgegeben, alles gut so weit. Allerdings hängt sich der Mikrocontroller nach einiger Zeit auf. Manchmal erst nach mehreren Stunden, manchmal nach schon vielleicht 30 Minuten. Konkret reagiert er nicht mehr, wenn es dunkel oder hell wird, und es kommen auch keine seriellen Daten mehr raus. Ich weiß leider nicht, warum. Ich vermute einen Programmfehler, denn das Problem tritt sowohl auf dem Steckbrett als auch der Lochrasterplatine im fest verlöteten Zustand auf, allerdings nach nicht reproduzierbaren Zeitabständen. Für sachdienliche Hinweise wäre ich sehr dankbar.
Stephan E. schrieb: > Für sachdienliche Hinweise wäre ich sehr dankbar. Wie hast du den Watchdog konfiguriert? Nicht jeder µC mag es, wenn sein Reset-Pin frei in der Luft hängt. Ziehst du den durch einen internen Pull-Up definiert auf High-Pegel?
Stephan E. schrieb: > https://www.mikrocontroller.net/attachment/694843/schaltplan.png Das ist kein Schaltplan.
Einen internen Pullup haben die AVRs. Ist nicht gerade extrem störsicher, aber sollte funktionieren – insbesondere kann das eher nicht zum beobachteten Verhalten (Firmware fährt sich fest) führen, sondern würde ja eher zu einem Reboot führen. Watchdog ist standardmäßig aus. Ich habe allerdings keine Lust, mich durch 500 Zeilen Assemblercode zu wuseln.
Jörg W. schrieb: > Ich habe allerdings keine Lust, mich durch 500 Zeilen Assemblercode zu > wuseln. Der ist so wie der "Schaltplan".
H. H. schrieb: > Stephan E. schrieb: >> https://www.mikrocontroller.net/attachment/694843/schaltplan.png > > Das ist kein Schaltplan. Er ist schrecklich (vor allem extrem pixelig klein skaliert und mit schlechtem Kontrast), aber die wesentlichen Details enthält er schon.
Rainer W. schrieb: > Stephan E. schrieb: >> Für sachdienliche Hinweise wäre ich sehr dankbar. > > Wie hast du den Watchdog konfiguriert? Der Watchdog ist als "interrupt-only" konfiguriert, er macht keinen reset. Er wird alle 0.125 Sekunden aufgerufen. Danach läuft die Hauptschleife ein mal durch und geht am Ende dieser Schleife in den Schlafmodus. Bis zum nächsten aufwecken durch den Watchdog. > Nicht jeder µC mag es, wenn sein Reset-Pin frei in der Luft hängt. > Ziehst du den durch einen internen Pull-Up definiert auf High-Pegel? Der Reset-Pin hängt auf der verlöteten Lochraster-Platine tatsächlich in der Luft. Am Programmer ist der Reset-Pin aber angeschlossen und wird mutmaßlich durch den Programmer oben gehalten.
Jörg W. schrieb: > Einen internen Pullup haben die AVRs. Ist nicht gerade extrem > störsicher, aber sollte funktionieren – insbesondere kann das eher nicht > zum beobachteten Verhalten (Firmware fährt sich fest) führen, sondern > würde ja eher zu einem Reboot führen. > > Watchdog ist standardmäßig aus. > > Ich habe allerdings keine Lust, mich durch 500 Zeilen Assemblercode zu > wuseln. Das würde ich natürlich auch nicht verlangen. Allerdings sieht das Forum vor, daß Quellcodes mitgeliefert werden - falls doch mal jemand einen Blick riskieren möchte. Vielleicht hat jemand mit Erfahrung einen Tipp für mich, der beim beschriebenen Problem der übliche Verdächtige sein könnte? Ggf. gibt's auch eine KI, die den Code mal durchschauen könnte.
- µC zusätzlich zum 100n KeKo noch mit einem kleinen Elko (Richtwert 47µ) puffern - Reset mit RC Glied 10n gegen Masse und 10K gegen Ub beschalten - serielle Schnittstelle mal probeweise im Code auskommentieren. Der Tinny hat die serielle Schnittstelle nicht in Hardware, sondern sie muß in SW emuliert werden. Da gibt es Implementierungen, die hängen sich gern auf. - die Fotodiode könnte man auch noch durch ein kleines RC-Glied beruhigen Immerhin hat er nicht nur Prosa, sondern überhaupt einen Schaltplan, der kein Wimmelbild ist und keine 6 MB groß ist. Also fast alles richtig gemacht ;-)
Stephan E. schrieb: > Am Programmer ist der Reset-Pin aber angeschlossen und wird mutmaßlich > durch den Programmer oben gehalten. Das wäre aber sehr ungewöhnlich. Wenn der Programmieradapter inaktiv ist, dann ist der Pin am Programmieradapter normalerweise hochohmig. Und dann reichen ein paar cm Leitung schon zum Empfang von Radiowellen. Der interne Pullup des Mikrocontrollers ist schwach, zudem reagiert er wesentlich empfindlicher als normale I/O Pins, da er anders definierte High/Low Pegel hat.
Hans W. schrieb: > Und dann reichen ein paar cm Leitung schon zum Empfang von Radiowellen. Ja, aber dann würde der Controller einen Reset machen, statt in einer Endlosschleife hängen zu bleiben. Gerald B. schrieb: > serielle Schnittstelle mal probeweise im Code auskommentieren. Der Tinny > hat die serielle Schnittstelle nicht in Hardware, sondern sie muß in SW > emuliert werden. Da gibt es Implementierungen, die hängen sich gern auf. Wäre natürlich ein Punkt. Wenn Stephan einen Logikanalysator hat, könnte man damit ein paar Testmuster stattdessen ausgeben und so ungefähr nachvollziehen, an welchen Stellen die Software noch lang kommt, bevor sie klemmen bleibt.
Gerald B. schrieb: > - µC zusätzlich zum 100n KeKo noch mit einem kleinen Elko (Richtwert > 47µ) puffern > - Reset mit RC Glied 10n gegen Masse und 10K gegen Ub beschalten > - serielle Schnittstelle mal probeweise im Code auskommentieren. Der > Tinny hat die serielle Schnittstelle nicht in Hardware, sondern sie muß > in SW emuliert werden. Da gibt es Implementierungen, die hängen sich > gern auf. > - die Fotodiode könnte man auch noch durch ein kleines RC-Glied > beruhigen Vielen Dank für die Tipps! Ich werde sie allesamt ausprobieren, testen und mich dann nochmal melden. @Jörg W.: Einen Logikanalysator besitze ich leider nicht. Ich bin nur ein kleiner Hobbybastler ohne nennenswerte Ausstattung (hat man ja schon am Schaltbild gesehen....).
Stephan E. schrieb: > Ich bin nur > ein kleiner Hobbybastler ohne nennenswerte Ausstattung (hat man ja schon > am Schaltbild gesehen....). Kein Papier, kein Kuli...
H. H. schrieb: > Kein Papier, kein Kuli... Das papierlose Büro wird schon seit Jahrzehnten beschworen - er hat es :P
Gerald B. schrieb: > H. H. schrieb: >> Kein Papier, kein Kuli... > > Das papierlose Büro wird schon seit Jahrzehnten beschworen Ja, das war alle paar Jahre aufs neue "das" große Thema der CeBIT. Anschließend stieg der Papierbedarf stark an... > - er hat es :P Allerdings in der grausamen Version.
Einen Watchdog in der ISR zu bedienen, ist zu 95% kontraproduktiv. Es kann nämlich durchaus sein, das das Hauptprogramm hängt, die WD ISR aber munter weiterläuft. Wenn ich mir das Programm so anschaue - warum einfach, wenns auch kompliziert geht?
:
Bearbeitet durch User
Matthias S. schrieb: > Einen Watchdog in der ISR zu bedienen, ist zu 95% kontraproduktiv. Ist halt ein Timer mehr – nicht als Watchdog im eigentlichen Sinne verwendet. Der ATtiny13 hat ja nun nicht so eine üppige Hardware-Ausstattung. (Allerdings würde ich ihn schon deshalb nicht unbedingt hobbymäßig nehmen. Es gibt bessere Alternativen, die deutlich mehr Hardware-Komfort bieten, auch bei AVR.)
Jörg W. schrieb: > Der ATtiny13 hat ja nun nicht so eine üppige > Hardware-Ausstattung. Ja, aber es gibt soooo wenig Alternativen, und die sind so teuer. Einfach mal die Scheuklappen abnehmen und über den Teller-Rand hinausschauen ....
Wastl schrieb: > Jörg W. schrieb: >> Der ATtiny13 hat ja nun nicht so eine üppige >> Hardware-Ausstattung. > > Ja, aber es gibt soooo wenig Alternativen, und die sind so teuer. Für Kinkerlitz nehm ich die immer mal wieder, aber auch nur weil mir vor Jahren ein Rest-Reel in die Hände fiel...
Stephan E. schrieb: > Ich bin nur > ein kleiner Hobbybastler ohne nennenswerte Ausstattung Naja, aber vielleicht auch ein reicher Hobbybastler ...
Habe mir die Frechheit herausgenommen, das Gerhard Schmidt'sche Programm einmal ins Studio 4 zu laden. (Ja, der mit dem Tutorial. Die Webseite ist aber jetzt anderweitig vergeben, Links stimmen nicht mehr.) Also Studio 4 Simulator bleibt schon direkt in der Loop hängen. Rein syntaxmäßig sieht es ja recht gut aus: ATtiny13A memory use summary [bytes]: Segment Begin End Code Data Used Size Use% [.cseg] 0x000000 0x00022c 556 0 556 1024 54.3% [.dseg] 0x000060 0x00006f 0 15 15 64 23.4% [.eseg] 0x000000 0x000000 0 0 0 64 0.0% 0 Errors 0 Warnings. Tipp: Wirf den Watchdog raus, und programmiere "vernünftige" Zeitschleifen. (Wurde oben schon angedeutet.) ciao gustav
:
Bearbeitet durch User
Wastl schrieb: > Einfach mal die Scheuklappen abnehmen und über den Teller-Rand > hinausschauen .... Muss man nichtmal, schrieb ich aber schon. Bereits ein ATtiny25 (fast genauso uralt wie der originale ATtiny13) würde schon deutlich mehr bieten. Gut, wenn es unbedingt ein DIP-8 als Gehäuse sein muss, dann hört es bei diesen (und den größeren Geschwistern des 25) auf. Wenn es auch ein SOIC-8 sein darf (um bei 8 Pins zu bleiben), dann hätte man mit ATtiny202 oder ATtiny212 dann immerhin schon MCUs, die man mit UPDI viel einfacher programmieren kann als die alten AVRs mit ISP – und selbst bei Reichelt sind die nur halb so teuer wie ein ATtiny13A.
Stephan E. schrieb: > Vielleicht hat jemand mit Erfahrung einen Tipp für mich, der beim > beschriebenen Problem der übliche Verdächtige sein könnte? Ziemlich wahrscheinlich Konflikte bei der Registernutzung. Warum? Wenn schon der Kommentar zur Registernutzung offensichtlich widersprüchlich ist, dann wird's im Programm selber sicher nicht ordentlicher zugehen...
Jörg W. schrieb: > Er ist schrecklich (vor allem extrem pixelig klein skaliert und mit > schlechtem Kontrast), aber die wesentlichen Details enthält er schon. Sind Versorgungsspannung kein "wesentliches Detail"? Von einem Schaltplan erwarte man z.B. auch, dass man die Funktion von Signalen anhand einer sinnvoll gewählten Bezeichnung erkennen kann und nicht so einen locker, mit einer Leitung an irgendeinen Pin angeklöppelten Max32?2, der ansonsten bezugslos in der Luft hängt :-(
Ob S. schrieb: > Registernutzung Sprichst mir aus dem Herzen: Was ich bei Gerhard S. Programmen so "schrecklich" finde, sind diese Abkürzungen in "Denglisch". Beim seinem DCF77 Decoder-Programm sind sogar ein paar Registerdefinitionen im Deklarationsteil angegeben, die im Programm selbst garnicht mehr auftauchen, also hätte man sie ganz weglassen können.(Das Programm, das mit steigenden und fallenden Flankeninterrupts arbeitet, und wahrscheinlich deswegen nicht mehr startet, wenn nach einer Empfangspause das Signal wieder decodierfähig wäre.) Mir drängt sich der Verdacht auf, dass jeder ASM-Programmierer eben so seinen ganz persönlichen "Stil" pflegt. Nicht unbedingt für "Bastler" schnell zu durchschauen. ciao gustav
Karl B. schrieb: > Mir drängt sich der Verdacht auf, dass jeder ASM-Programmierer eben so > seinen ganz persönlichen "Stil" pflegt. Assembler gilt mit Fug und Recht als eine eher sehr schlecht wartbare Programmiersprache. Auch in Hochsprachen geht das, aber Assembler ist da deutlich "mächtiger".
Harald K. schrieb: > Auch in Hochsprachen geht das Real programmers can write FORTRAN in any language. ;-)
Harald K. schrieb: > aber Assembler ist da deutlich > "mächtiger". Auch in C/C++ kann man sich prächtig ins Knie schießen. ASM bietet da erheblich mehr Möglichkeiten. Zudem ist Portabilität quasi nicht vorhanden.
Ob S. schrieb: > Stephan E. schrieb: > >> Vielleicht hat jemand mit Erfahrung einen Tipp für mich, der beim >> beschriebenen Problem der übliche Verdächtige sein könnte? > > Ziemlich wahrscheinlich Konflikte bei der Registernutzung. Warum? Wenn > schon der Kommentar zur Registernutzung offensichtlich widersprüchlich > ist, dann wird's im Programm selber sicher nicht ordentlicher zugehen... Das habe ich auch vermutet. Ich bin das gesamte Programm schon mehrmals Schritt für Schritt durchgegangen, finde das Problem aber leider nicht. Der etwas weiter oben erwähnte Pullup am Reset-Pin hat das Problem leider nicht behoben. Der Test ohne die serielle Ausgabe läuft noch.
Rainer W. schrieb: > Sind Versorgungsspannung kein "wesentliches Detail"? Wenn völlig offensichtlich ist, wo das rankommt, ist es nicht mehr wirklich wesentlich. Wenn nur ein Signal zu einem MAX23x geht, kann es auch nur TxD sein.
Jörg W. schrieb: > Wenn es > auch ein SOIC-8 sein darf (um bei 8 Pins zu bleiben), dann hätte man mit > ATtiny202 oder ATtiny212 dann immerhin schon MCUs, die man mit UPDI viel > einfacher programmieren kann als die alten AVRs mit ISP – und selbst bei > Reichelt sind die nur halb so teuer wie ein ATtiny13A. Ich bleibe lieber bei DIP. SMD ist für meine zwei linken Hände nur sehr bedingt geeignet. Trotzdem wollte ich mir die Series 0 mal irgendwann genauer anschauen - aber nicht heute. Die Kosten für einen Controller stufe ich für meine reinen Hobby- und Freizeitzwecke als eher vernachlässigbar ein. Da geht's in erster Linie um Lernerfolge und den Spaß am reinen "doing".
Stephan E. schrieb: > Ich bleibe lieber bei DIP. SMD ist für meine zwei linken Hände nur sehr > bedingt geeignet. SOIC mit 1,27 mm Pinraster ist ja nun für SMD-Verhältnisse noch richtig grobschlächtig. Auch Adapter von da auf DIP-8 gibt es ja zur Genüge. Die einfachere Programmiermöglichkeit via UPDI ist auf jeden Fall angenehm, im Prinzip brauchst du nicht mehr als einen USB-Seriell-Wandler und zwischen TxD und RxD noch einen Widerstand von 1 kΩ.
Jörg W. schrieb: > Die einfachere Programmiermöglichkeit via UPDI ist auf jeden Fall > angenehm, im Prinzip brauchst du nicht mehr als einen > USB-Seriell-Wandler und zwischen TxD und RxD noch einen Widerstand von 1 > kΩ. Wenn die Versorgungsspannung des µC passt. Ansonsten halt noch einen Pegelwandler, bidirektional.
H. H. schrieb: > Wenn die Versorgungsspannung des µC passt. Ansonsten muss man sie passend machen :-) oder einen USB-Seriell-Wandler mit passender Spannung suchen. Zumindest 3,3 V und 5 V sind ja beide gängig, teilweise kann man sie auch umjumpern oder umlöten. Ich habe aber auch schon einen FTDI mit 5 V genommen und einfach eine rote LED vor die Spannungszuführung geschaltet, weil ein auf der Schaltung befindlicher Sensor nicht mehr als 3,6 V haben möchte. Theoretisch ist dann zwar der Signalpegel von der MCU zum Wandler etwas niedrig, funktioniert aber trotzdem.
Jörg W. schrieb: > Ich habe aber auch schon einen FTDI mit 5 V genommen und einfach eine > rote LED vor die Spannungszuführung geschaltet, weil ein auf der > Schaltung befindlicher Sensor nicht mehr als 3,6 V haben möchte. > Theoretisch ist dann zwar der Signalpegel von der MCU zum Wandler etwas > niedrig, funktioniert aber trotzdem. Schweizer Taschenmesser und Kaugummi geht bestimmt auch. ;-)
Jörg W. schrieb: > Ansonsten muss man sie passend machen :-) oder einen USB-Seriell-Wandler > mit passender Spannung suchen. Zumindest 3,3 V und 5 V sind ja beide > gängig, teilweise kann man sie auch umjumpern oder umlöten. Oder einfach den Wandler vom Target aus speisen. Der olle FT232 kann 1,8-5V IO-Spannung. Problem gelöst.
Gerald B. schrieb: > - serielle Schnittstelle mal probeweise im Code auskommentieren. Wollte nochmal Rückmeldung geben - seit die serielle Ausgabe deaktiviert ist, keine Probleme mehr. Ich muß leider zugeben, daß ich nicht ganz nachvollziehen kann, warum das so ist, aber in der Praxis funktioniert jetzt alles so wie geplant.
Stephan E. schrieb: > Ich muß leider zugeben, daß ich nicht ganz > nachvollziehen kann, warum das so ist, Mein üblicher Rat wäre: Modularisieren! Module einzeln ausgiebig testen.
Arduino F. schrieb: > Mein üblicher Rat wäre: Modularisieren! > Module einzeln ausgiebig testen. Die serielle Ausgabe habe ich unverändert schon in vielen anderen Programmen verwendet - sie hat nie Probleme gemacht. Ich vermute, daß sich vielleicht die Interrupts in die Quere kommen. Ich werde dort weiter nachforschen.
Stephan E. schrieb: > Ich vermute, daß > sich vielleicht die Interrupts in die Quere kommen. Ich werde dort > weiter nachforschen. Wenn das mal nicht die falsche Baustelle ist.
Stephan E. schrieb: > Die serielle Ausgabe habe ich unverändert schon in vielen anderen > Programmen verwendet - sie hat nie Probleme gemacht. Ich vermute, daß > sich vielleicht die Interrupts in die Quere kommen. Ich werde dort > weiter nachforschen. Möglicherweise hängt dein nicht funktionierender Watchdog, wenn die Übertragung im ungünstigen Moment startet oder zu lange dauert. Schon witzig, ein Programm mit Watchdog, das festhängt. Finde den Fehler.
Falk B. schrieb: > Schon witzig, ein Programm mit Watchdog, das festhängt. Falk, lass dich doch nicht von dem Wort "Watchdog" ins Bockshorn jagen. Das ist einfach nur ein Timer, der 8mal in der Sekunde einen Interrupt triggert. Mit einem klassischen Watchdog, der den Programmfluss überwacht und ggf. einen Reset triggert, hat das nichts zu tun.
Ich rätsele gerade noch, wo 9k6 8N1 vorkommen als Übertragungsparameter. Das label serialsend ist wohl exakt auf die Taktfrequenz genagelt. ciao gustav
Karl B. schrieb: > Ich rätsele gerade noch, wo 9k6 8N1 vorkommen als > Übertragungsparameter. > Das label serialsend ist wohl exakt auf die Taktfrequenz genagelt. > ciao > gustav Bei einer reinen Software-UART gehts nicht halt nicht anders. Oliver
Ich sag mal, daß das Programm an der Stelle hier endgültig zu Ende sein wird: >sbr rmp, (1<<SM1)|(1<<SE) ; sleep-mode: powerdown >out MCUCR, rmp >loop_ende: >sleep Aus power down bräucht es einen Watchdog-Reset, einen brown-out-Reset, oder INT0 bzw pin change Interrupts zum wieder aufwecken. Keiner davon ist enabled. Oliver
Oliver S. schrieb: > Aus power down bräucht es einen Watchdog-Reset, einen brown-out-Reset, > oder INT0 bzw pin change Interrupts zum wieder aufwecken. Du solltest das Datenblatt richtig lesen lernen. ;-) Ja, mit "watchdog" war was (und natürlich befreit jeder Reset ihn aus dem Schlaf) – aber neben INT0 / PCINT kann eben auch ein Watchdog-Interrupt wieder aufwecken, und einen solchen hat er 8mal pro Sekunde. Ansonsten wäre es ja auch völlig unlogisch, dass die Firmware überhaupt erstmal läuft und erst nach längerer Zeit einfriert.
Oliver S. schrieb: > Ich sag mal, daß das Programm an der Stelle hier endgültig zu Ende sein > wird: > >>sbr rmp, (1<<SM1)|(1<<SE) ; sleep-mode: powerdown >>out MCUCR, rmp > >>loop_ende: >>sleep > > Aus power down bräucht es einen Watchdog-Reset, einen brown-out-Reset, > oder INT0 bzw pin change Interrupts zum wieder aufwecken. Der Watchdog-Interrupt (kein reset) reicht. Und der macht das ja auch. Ich verwende den Watchdog nicht als Watchdog, sondern nur als zweiten timer, welcher einen Interrupt auslöst. Die loop-Schleife wird somit jede 0.125 Sekunden ein mal durchlaufen.
:
Bearbeitet durch User
Oliver S. schrieb: > Karl B. schrieb: >> Ich rätsele gerade noch, wo 9k6 8N1 vorkommen als >> Übertragungsparameter. >> Das label serialsend ist wohl exakt auf die Taktfrequenz genagelt. >> ciao >> gustav > > Bei einer reinen Software-UART gehts nicht halt nicht anders. Genau so ist es. Ist ja auch nur bitbanging, einen "echten" seriellen Port hat der Controller nicht.
Jörg W. schrieb: > Du solltest das Datenblatt richtig lesen lernen. ;-) Tja, der Text sagt so, die Tabelle sagt anders. Ein typisches Atmel-Datenblatt… Oliver
Oliver S. schrieb: > Ein typisches Atmel-Datenblatt… Als ob andere Hersteller keine Ungenauigkeiten in Datenblättern hätten … aber warum reichst du dann nicht einen Bugreport bei Microchip ein? Schließlich haben sie ein Errata-Dokument, das auch Datenblatt-Korrekturen beinhalten kann.
Jörg W. schrieb: > aber warum reichst du dann nicht einen Bugreport bei Microchip ein? Habe ich dann einfach mal gemacht.
Jörg W. schrieb: > Harald K. schrieb: >> Auch in Hochsprachen geht das > > Real programmers can write FORTRAN in any language. > > ;-) Danke Jörg, ja das fällt mir gerade mein abgeschlossenens Studium ein, da hatten wir gleich im 1 oder 2 Semester eine FORTRAN Klausur. Man musst sich noch um solche Vorlesungen bewerben und konnte sie nicht hören, wenn man wollte..
Stephan E. schrieb: > Der Watchdog-Interrupt (kein reset) reicht. Und der macht das ja auch. > Ich verwende den Watchdog nicht als Watchdog, sondern nur als zweiten > timer, welcher einen Interrupt auslöst. Die loop-Schleife wird somit > jede 0.125 Sekunden ein mal durchlaufen. Und du hoffst, dass es niemals dadurch zu einem Problem kommt, dass du in beiden Interrupt-Routinen dasselbe Register zum Retten des Status benutzt?
Rolf schrieb: > Und du hoffst, dass es niemals dadurch zu einem Problem kommt, dass du > in beiden Interrupt-Routinen dasselbe Register zum Retten des Status > benutzt? Beim AVR wird defaultmässig beim Eintritt in eine ISR das globale Interrupt-Enable flag gelöscht. Da gibt es damit keine Probleme. Oliver
Oliver S. schrieb: > Beim AVR wird defaultmässig beim Eintritt in eine ISR das globale > Interrupt-Enable flag gelöscht. Da gibt es damit keine Probleme. Das ist zwar richtig, aber natürlich müssen ein paar weitere Bedingungen erfüllt sein, damit es wirklich keine Probleme gibt. - innerhalb aller ISRs, die das Register benutzen, darf nicht mit "sei" rumgespielt werden - zwischen dem "in" zu Begin und dem "out" am Ende der ISRs darf das Register natürlich nicht für andere Zwecke verwendet werden. - Und natürlich darf das Register auch nicht in main verwendet werden, jedenfalls nicht ohne zusätzliche Schutzmaßnahmen Allerdings: Wenn ich nichts übersehen habe, sind für rSreg/R15 alle diese Bedingungen erfüllt. Sollte also tatsächlich kein Problem sein.
Ob S. schrieb: > Wenn ich nichts übersehen habe, sind für rSreg/R15 alle > diese Bedingungen erfüllt. Sollte also tatsächlich kein Problem sein. So isses. Oliver
Ob S. schrieb: > Allerdings: Wenn ich nichts übersehen habe, sind für rSreg/R15 alle > diese Bedingungen erfüllt. Siehst du, du gehst davon aus, dass es womöglich doch nicht ok sein könnte. Eine Prüfung auf mögliche versteckte Fehler kostet unnötig Zeit, und solange man den Fehler nicht gefunden hat, muss man womöglich immer wieder mal drüber nachgrübeln. Zeit, die verschwendet ist. Ich programmiere aus Erfahrung*) grundsätzlich "defensiv". Solange der Speicher nicht bis zum allerletzten Byte ausgeknautscht ist, nehme ich in diesem konkreten Fall kein Register, sondern eine RAM-Zelle pro ISR. *) Die letzten Programme in Assembler habe ich vor Jahrzehnten geschrieben. Die liefen auch in Fabrikhallen in anderen Erdteilen. Jeder Stillstand beim Kunden war eine Katastrophe. "Defensiv codieren" war also Pflicht.
Rolf schrieb: > Ob S. schrieb: >> Allerdings: Wenn ich nichts übersehen habe, sind für rSreg/R15 alle >> diese Bedingungen erfüllt. > > Siehst du, du gehst davon aus, dass es womöglich doch nicht ok sein > könnte. Du übersiehst die Einschränkung meiner Einschätzung auf rSreg/R15. Dafür bin ich sicher, dass dessen Verwendung OK ist. Nur werden aber blöderweise auch noch etliche andere Register in dem Code benutzt. > Ich programmiere aus Erfahrung*) grundsätzlich "defensiv". Solange der > Speicher nicht bis zum allerletzten Byte ausgeknautscht ist, nehme ich > in diesem konkreten Fall kein Register, sondern eine RAM-Zelle pro ISR. Das ändert doch garnix, außer das jede ISR-Instanz mindestens vier Takte länger braucht. Erstens muß man für diese RAM-Zelle dann ganz genauso auf korrekte und exklusive Benutzung prüfen und zweitens braucht man immer noch ein MCU-Register zum Sichern, weil es keine Instruktionen gibt, mit der man SREG direkt in den RAM sichern bzw. von dort laden könnte. > "Defensiv codieren" war > also Pflicht. Richtig programmieren ist noch viel besser als defensiv programmieren. Bezüglich der MCU-Registernutzung bietet der Assembler mit der Möglichkeit zur Vergabe von Aliasnamen sehr gute Voraussetzungen dafür. Man muss sie nur konsequent auch in diesem Sinne nutzen. Das ist im vorliegenden Code für rSreg/R15 geschehen (weswegen sich die Sache hier auch leicht nachprüfen ließ), für andere Register hingegen leider nicht.
Moin, um den Fehler einzugrenzen, würde ich die LEDs erstmal über größere Widerstände anschließen. Dann in der Hauptschleife alles rausnehmen und mit CBI und SBI einen Pin toggeln und mit einem Oszilloskope den Pin beobachten. Wenn das längere Zeit stabil läuft nacheinander init, ADC, ISR, watchdog usw. dazu nehmen. Viel Erfolg Carsten
Ob S. schrieb: > Erstens muß man für diese RAM-Zelle dann ganz genauso auf korrekte > und exklusive Benutzung prüfen und zweitens braucht man immer noch > ein MCU-Register zum Sichern, weil es keine Instruktionen gibt, mit > der man SREG direkt in den RAM sichern bzw. von dort laden könnte. Kann man doch einfach PUSH / POP nehmen, so wie es zum Beispiel avr-gcc macht.
Johann L. schrieb: > Kann man doch einfach PUSH / POP nehmen, so wie es zum Beispiel avr-gcc > macht. Das Problem mit Buffer Underrun. Der Stapel wandert rückwärts in den Programmbereich rein, wenn zu viel push und pop. Oder pop vergessen wurde. Einrichtung von Stapelzeigerbereich lautet ja bekanntlich RAMEND. Zählt also runter. Wann der Crash erfolgen könnte, müsste man im Simulator (built and run) nachvollziehen können. ciao gustav
Stephan E. schrieb: > Wollte nochmal Rückmeldung geben - seit die serielle Ausgabe deaktiviert > ist, keine Probleme mehr. Ich muß mich korrigieren. Die serielle Ausgabe ist nicht das Problem. Nach etlichen Tests bin ich mir jetzt zu 99% sicher, daß das Problem mit dem deep-sleep zusammenhängt. Wenn ich statt dem deep-sleep nur den sleep mode "idle" nehme, läuft alles (läuft immer noch, inzwischen schon vier Tage, serielle Ausgabe ist aktiv). Die einzige Programmänderung: statt
1 | sbr rmp, (1<<SM1)|(1<<SE) ; sleep-mode: powerdown |
1 | sbr rmp, (1<<SE) |
Alles andere ist unverändert.
Deine serielle Ausgabe ist ja auch vergleichsweise überschaubar gestrickt. Da hätte ich mir höchstens noch vorstellen können, dass sie zu lange die Interrupts blockiert hält.
an Stephan E.:
> Alles andere ist unverändert.
Trotzdem möchte ich darum bitten, die aktuelle Programmversion
vorzustellen. Eine sieben Tage alte Basis ist erfahrungsgemäß
fragwürdig.
Aber gerne. Ich bin ja froh, wenn sich das jemand mit Erfahrung überhaupt mal anschaut.
ist jetzt nicht der Fehler, aber für was ist cli und sei in init_watchdog gut? sei wird doch auch noch Mal im main gemacht
> Die einzige Programmänderung ... Alles andere ist unverändert.
Pardon, aber ich sehe zusätzlich ein gutes Dutzend auskommentierte
Zeilen.
Eigentlich hatte ich vor, das Ganze mit/ohne Absturz nachzuvollziehen
(das aktuelle Programm (mit etwas Mühe) auf den nur verfügbaren ATtiny85
umgesetzt), dazu eben diese eine Zeile 'sbr rmp ...' umschaltend; aber
jetzt kommen mir doch Zweifel.
Ja, der deep-sleep ist auskommentiert. Es wird nicht mehr zwischen den Fällen "hell" und "dunkel" unterschieden, deshalb die Auskommentierungen. Stattdessen wird generell nach "loop_ende:" der idle-Modus aktiviert. Im Endeffekt läuft es darauf hinaus, daß nur noch der sleep-idle-Modus aktiviert wird. Ich habe die Gegenprobe bereits gemacht - mit deep-sleep steigt der Controller nach einer unbestimmten Zeit wieder aus. Ohne deep-sleep nicht mehr. Zumindest läuft er damit jetzt schon eine ganze Weile. Der Vollständigkeit halber noch diese kleinen Änderungen, die mit dem Absturz aber nichts zu tun haben dürften: Vorher ab Zeile 172:
1 | rcall get_from_sram |
2 | mov rmp, sramvalue |
3 | andi rmp,0x07 ; drei lsb aus unterem nibble |
4 | in temp, DDRB |
5 | or temp, rmp |
6 | out DDRB, temp |
Nachher ab Zeile 172:
1 | rcall get_from_sram |
2 | mov rmp, sramvalue |
3 | andi rmp,0x07 ; drei lsb aus unterem nibble |
4 | in temp, DDRB |
5 | cbr temp,0x07 ; letzte drei Bit löschen <==== neu |
6 | add temp, rmp ; und aus dem sram neu setzen <==== statt "or" |
7 | out DDRB, temp |
Analog dazu für PORTB etwas weiter unten. in "init_watchdog:" ein cli und sei rein, ein Versuch war's wert. Wie schon von Walter S. geschrieben können die wieder raus, die machen dort wirklich keinen Sinn. in "Main:" zwei Initialisierungen
1 | clr watchdogcounter |
2 | clr zero |
Ob S. schrieb: > Erstens muß man für diese RAM-Zelle dann ganz genauso > auf korrekte und exklusive Benutzung prüfen Du hast es nicht verstanden. Ich habe gesagt "eine Zelle pro ISR". Und prüfen muss man da lediglich im Editor, ob der Name dieser Zelle noch anderswo auftaucht (was er natürlich nicht darf). Register dagegen, für die ist es normal, an x Stellen benutzt zu werden. > zweitens braucht man immer noch ein MCU-Register zum Sichern, weil es > keine Instruktionen gibt, mit der man SREG direkt in den RAM sichern bzw. > von dort laden könnte. Ja und? Dafür kann man ein Register nehmen, welches in der ISR ohnehin benutzt wird. > Richtig programmieren ist noch viel besser als defensiv programmieren. > ... > Möglichkeit zur Vergabe von Aliasnamen sehr gute Voraussetzungen dafür. > Man muss sie nur konsequent auch in diesem Sinne nutzen Du hast es wirklich nicht verstanden. Es geht beim defensiven Programmieren darum, dass man möglichst alles vermeidet, was nur funktioniert, wenn man es richtig (dein "konsequent") macht. Auf Deutsch: Denkbare Schlampereien gar nicht erst ermöglichen. Aliasnamen sind da eine eher schlechte Lösung. Wenn man jedem Register nur einen Aliasnamen gibt, dann ist der im Kontext A vielleicht passend zur Bedeutung des gespeicherten Werts, im Kontext B aber nicht. Falls es nicht genügend Register für alle Kontexte gibt, muss man also manchen Registern mehr als einen Alias geben. Dann ist das Programm vielleicht korrekt, sicher aber unübersichtlich und fehlerisiko-behaftet. Oder man gibt dann einigen der Register gar keinen Alias - ist das wirklich besser? Und wo bliebe dabei deine Konsequenz?
Stephan E. schrieb: > Ich habe die Gegenprobe bereits gemacht - mit deep-sleep steigt der > Controller nach einer unbestimmten Zeit wieder aus. Ohne deep-sleep > nicht mehr. Zumindest läuft er damit jetzt schon eine ganze Weile. Wobei man aber nicht wissen kann, ob das DIREKT an dem Sleep-Modus liegt. Ja nach Sleep-Modus ändern sich ja Timing-Verhältnisse, die auch die Interrupts betreffen.
Johann L. schrieb: > Kann man doch einfach PUSH / POP nehmen, so wie es zum Beispiel avr-gcc > macht. Nö. Auch ein C-Compiler kann natürlich nur die Instruktionen nutzen, die das Target zur Verfügung stellt. D.h.: auch der avr-gcc wird nicht sowas wie etwa "push SREG" erzeugen können. Nö, der wird, wie auch der Asm-Programmierer, temporär ein MCU-Register beschäftigen und die Sache so umsetzen müssen: in reg, SREG push reg Auch wenn C-Gläubige immer wieder die fantastischsten Behauptungen über die immensen Fähigkeiten der Compiler verbreiten, müssen diese sich letztlich doch der normativen Kraft des Faktischen beugen...
> Ich habe die Gegenprobe bereits gemacht - mit deep-sleep ...
Und das Programm für diese Gegenprobe sah wie aus?
Karl B. schrieb: > Oder pop vergessen wurde. Wenn du nicht in der Lage bist, korrekten Code zu schreiben, dann hast du mit JEDEM Ansatz ein ziemliches Problem...
Rolf schrieb: > Wobei man aber nicht wissen kann, ob das DIREKT an dem Sleep-Modus > liegt. Tut es nicht. Es liegt daran, dass diverse Initialisierungsroutinen innerhalb der Hauptschleife immer mal wieder aufgerufen werden. Diese Initialisierungsroutinen sind allerdings so geschrieben, wie man sie für die Initialisierungsphase schreiben würde. Sprich: mit der stillschweigenden Annahme, das der Ausgangszustand der Hardware der Reset-Zustand ist und Interrupts noch nicht erlaubt sind. Hier müsste also nachgebessert werden. Am sinnvollsten wäre allerdings, gleich die gesamte Programmstruktur umzubauen. Alles sollte in den ISRs passieren und die Hauptschleife so aussehen: mainloop: sleep rjmp mainloop Diese Programmstruktur würde den größten Teil der potentiellen Probleme von ganz alleine lösen. Eins allerdings nicht: Re-Initialisierungen der Hardware müssten natürlich trotzdem noch explizit berücksichtigen, dass sich "ihre" Hardware halt nicht im Reset-Zustand befindet.
Rolf schrieb: > Aliasnamen sind da eine eher schlechte Lösung. LOL. Was glaubst du denn, was eine "Variable" ist? Nix anderes als ein Aliasame für eine Speicherstelle. Naja und ggf. eine Vereinbarung, dass da mehr als eine Speicherstelle dranhängen. > Wenn man jedem Register > nur einen Aliasnamen gibt, dann ist der im Kontext A vielleicht passend > zur Bedeutung des gespeicherten Werts, im Kontext B aber nicht. Das ist richtig. Genau deswegen gibt es die Möglichkeit, Register lokal mit einem anderen Alias zu belegen und am Ende der lokalen Bedeutung wieder mit dem ursprünglichen zu versehen. Man kann dies über entsprechende Makros sogar mit einer Sicherung der Registerinhalte verbinden (sollte sowas aber möglichst selten, am besten aber nie tun). > sicher aber unübersichtlich Ja, sowas macht das Programm zunächst mal unübersichtlicher. Es ermöglicht aber eine gezielte (ggf. sogar automatisierte) Suche nach fälschlicher konkurrierender Nutzung. Was aber vielleicht noch viel wichtiger ist: Bei diesem primitiven Programm wird man bei sinnvoller Programmierung überhaupt noch nicht auf die Situation treffen, dass Register mehrfach benutzt werden müssen. Es gibt halt schlicht und einfach mehr als genug für dieses simple Programm.
Ob S. schrieb: > LOL. Was glaubst du denn, was eine "Variable" ist? Nix anderes als ein > Aliasame für eine Speicherstelle. Für wie blöd hältst du mich? Register haben native Namen, die sind aus Bitmustern gebildet. Weil man sich diese Muster schlecht merken kann, haben die Register vom Assembler vergebene Aliasnamen (z. B. "R16"). Diese Namen nennt man aber in der Fachsprache üblicherweise nicht so: Wenn man da Alias sagt, meint man einen Alias, der eine Stufe höher ist (z. B. kann "Zähler" ein Alias für "R16" sein). Und nur von den letztgenannten Aliassen war bisher die Rede. :-P
Ob S. schrieb: > Am sinnvollsten wäre allerdings, gleich die gesamte Programmstruktur > umzubauen. Endlich kann ich dir mal vorbehaltlos zustimmen.
Ob S. schrieb: > Tut es nicht. Es liegt daran, dass diverse Initialisierungsroutinen > innerhalb der Hauptschleife immer mal wieder aufgerufen werden. > > Diese Initialisierungsroutinen sind allerdings so geschrieben, wie man > sie für die Initialisierungsphase schreiben würde. Sprich: mit der > stillschweigenden Annahme, das der Ausgangszustand der Hardware der > Reset-Zustand ist und Interrupts noch nicht erlaubt sind. Hier müsste > also nachgebessert werden. Dann mal Butter bei die Fisch: Welche Zeilen genau meinst du damit? Denn irgendwie scheinst du über ein anderes Programm zu sprechen, als ganz oben angehängt ist. Oliver
S. L. schrieb: >> Ich habe die Gegenprobe bereits gemacht - mit deep-sleep ... > > Und das Programm für diese Gegenprobe sah wie aus? Es ist das, was sieben Posts über Deinem steht (funktioniert). Das Original ist das im ersten Posting (steigt nach nicht reproduzierbarem Muster aus).
an Stephan E.: Das kann jetzt lange dauern, und vielleicht tritt der Fehler auf einem ATtiny85 gar nicht auf. Schau'n wir mal ... Dies allerdings kann ich fast nicht glauben: > Das Original ist das im ersten Posting Laden Sie mal exakt diese Programmdatei von hier aus dem Forum herunter, assemblieren und laden Sie in den ATtiny13A, und dann schreiben Sie uns, was die sechs LEDs anzeigen - also nach "Lauflicht" sieht das bei mir nicht aus ...
an Stephan E.:
> nach "Lauflicht" sieht das bei mir nicht aus
Entschuldigung, mein Fehler: ich hatte übersehen, dass REFS0/1 beim
ATtiny85 eine andere Bedeutung haben.
Ansonsten läuft es bei mir seit 14 Stunden; und solange hier kein Fehler
auftritt, möchte ich mich ungern nur theoretisch in Ihr Programm
einarbeiten.
S. L. schrieb: > Ansonsten läuft es bei mir seit 14 Stunden; und solange hier kein Fehler > auftritt, möchte ich mich ungern nur theoretisch in Ihr Programm > einarbeiten. Danke für die Info, das ist für mich eine sehr hilfreiche Information. Dann handelt es sich eventuell gar nicht um ein Softwareproblem. Vielen Dank für's testen!
an Stephan E.: Ihr ursprüngliches Programm (mutatis mutandis) lief hier bis jetzt ohne Absturz durch. Nun weiß ich nicht mehr weiter, bis auf diesen eher hilflosen Versuch: beigefügtes Programm muss bei Ihnen alle sechs LEDs dunkel lassen.
Also ich programmiere seit ca 15 jahren Attiny85 in Standard C und benutze dabei auch den watchdog um im Tiefschlaf-Modus Strom zu sparen. Solche Absturz-Probleme sind mir dabei noch nicht unter gekommen.
Mark S. schrieb: > Also ich programmiere seit ca 15 jahren Attiny85 in Standard C Möglicherweise benimmt sich der 85 aber im Tiefschlaf auch geringfügig anders als der 13.
S. L. schrieb: > Nun weiß ich nicht mehr weiter, bis auf diesen eher hilflosen Versuch: > beigefügtes Programm muss bei Ihnen alle sechs LEDs dunkel lassen. Vielen Dank erst mal für die Rückmeldung und insbesondere für die Beschäftigung mit dem Problem! Ihr Programm habe ich eben getestet - die LEDs bleiben aus.
S. L. schrieb: > an Stephan E.: > Ihr ursprüngliches Programm (mutatis mutandis) lief hier bis jetzt ohne > Absturz durch. Mit (mehrfachen) hell-dunkel Wechseln? Oliver
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.

