www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Überlastet Reziproke ATTiny?


Autor: David Hebbeker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe meinen ATTiny 26 mit BASCOM AVR 1.11 programmiert.
Ich habe eine SUB, die einen Wert überprüft, 100ms wartet und sich dann
selber neu aufruft, bis ein bestimmter Wert erreicht ist (Reziproke).
Das sieht dann so aus:

Sub Untens()           'Sub Beginn
   Waitms 100          'Warte 100ms
   Porta.0 = 1         'Setze den ersten Port auf 1 (5V)
   Unten = Getadc(7)   'Setzt die Variable Unten auf den Wert
   If Unten < 900 Then 'Fragt den Wert ab
      Call Untens()    'Ruft sich selbst noch mal aus
      Exit Sub         'Beendet sich selbst
   End If              '
   Waitms 400          'Warte 400ms
   Porta.0 = 0         'Setze ersten Port auf 0 (0V)
   Fertig = 1          'Setze Variable Fertig auf 1
End Sub                '

Das Ganze funktioniert auch, doch wenn die Subrutine länger als 6000ms
läuft ca. 60 mal sich selbst aufruft, stürtzt das ganze Programm ab.
Ist es möglich, dass der ATTiny 26 mit solch einer Aufgabe überfordert
ist und deswegen neu startet?
Wie kann ich das Problem umgehen? Mit GoTo?

Danke, MfG Ringelkrat

PS: Konnte den Soucecode nicht als Dateianhang anhängen, da ich den auf
einem anderen PC habe.

Autor: A.K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stack overflow. Jeder Aufruf kostet 2 Bytes auf dem Stack. 128 Byte
gibt's.

Autor: nides (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hi

bei jedem neuen funktionsaufruf wird die rücksprungadresse auf den
stack kopiert, der deshalb immer größer wird, und irgendwann wirst du
dir damit das gesamte sram vollgestackt haben.
rekursive programme sind bei systemen mit sehr kleinem ram (stack)
nicht zu empfehlen!

nides

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
jeder neue Aufruf belastet den Stack - irgendwann ist Schluss. Immer ein
Problem bei Rekursionen. Man muss die max. Tiefe begrenzen, sonst kann
es aus dem Ruder laufen. Dabei auch Interrupts beachten, die kosten
auch nochmal Stack. Ebenso wichtig: wieviele Funktionsaufrufe hast du
schon hinter dir, wenn du bei der rekursiven Funktion angelangt bist?
Nützlich sind stack-end-marker, da kannst du in der Simulation sehen,
ob das stackende erreicht wurde.

Autor: David Hebbeker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und was mach ich jetzt?
Wie soll ich das jetzt lösen? Mit GOTO, oder WHILE?

Autor: David Hebbeker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich eine While-Schleife mach, wartet er dann, oder macht er mit dem
Programm weiter (was unter der schleife steht)?

while (unten < 900)
   unten = getadc(7)
   waitms 100
Wend

Ringelkrat

Autor: Uwe Große-Wortmann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das wär schon richtig so... er wartet, bis der adc einen wert größer
oder gleich 900 liefert und macht dann erst weiter. und der stack
bleibt wie er ist...
alternativ könnte man das ganze auch mit nem goto lösen


untens:
unten = getadc(7)
waitms 100
if unten < 900 then goto untens

(ob das von der syntax her in ordnung ist kann ich nicht sagen weil ich
seit langem kein bascom mehr benutzt hab...)

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also bevor man goto nimmt, müssen schon drei Rechner explodiert sein und
20 Internetforen nicht mehr weiterwissen.

Nimm while.

Autor: David Hebbeker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank für die Hilfe und Erläuterung!
Ich hab es jetzt mit einer While-Schleife gemacht und es funktioniert
sehr gut.

MfG Ringelkrat

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
möchte mal wissen, warum immer so ein Theater mit dem GOTO gemacht wird.
 Verteufelt bis zum geht nicht mehr, steht in vielen Büchern, und ganz
viele plappern es plump nach. Klar, lässt sich eigentlich immer
vermeiden, aber WARUM sollte man es vermeiden? Konnte mir noch keiner
schlüssig erklären. Sprünge (unbedingte und bedingte) Sprünge kommen in
jedem Programm vor, in Hochsprachen mehr oder weniger versteckt, in
Assembler unvermeidbar (und sogar nützlich:-)
Ich sehe ja ein, dass man nicht kreuz und quer durchs Programm springt,
aber was spricht innerhalb einer Funktion dagegen?
Und wo ist der Unterschied zwischen

switch (test){
case 1:
case 2:
}

oder
if (test==1) goto ...
  else if (test==2)goto ...
?

Das 1. hat den offiziellen Segen, mehr Unterschiede erkenne ich nicht.

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wäre "Rekursion" nicht ein treffenderer Titel für das Thema gewesen?

"Reziprok" in diesem Zusammenhang lässt mich an Honoria Lucasta, der
Dowager Duchess of Denver aus Dorothy L. Sayers vorzüglichen
Kriminalromanen denken ...

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das erste ist viel übersichtlicher und zudem weniger Schreibarbeit als
das zweite.

Es hat schon seinen Sinn, dass goto "verteufelt" wird.

Es mag sein, dass es bei embedded-Systemen, wenn man mit C programmiert
ganz selten für ein Problem einfach keine elegantere/kleinere/schnellere
Lösung als goto gibt. Dann sollte man aber genau wissen, was man tut und
wieso es nicht anders geht.

Ich halte es allerdings für falsch, einem Anfänger zu goto zu raten, da
das gerade bei Beginnern zu einem schrecklichen Programmierstil führen
kann, der dann beibehalten wird.

Autor: Michael (ein anderer) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wirf' den Basic-Compiler weg, denn er ist Schrott.

Wenn er kein Schrott wäre, dann hätte der Compiler die Tail-Rekursion
erkannt und die Stack-Benutzung weg optimiert.

Ordentliche C-Compiler können das, z.B. der gcc... ;-)

Es gibt aber auch viele Script-Sprachen, die Tail-Rekursion-Optimierung
beherschen. Oder man verwendet gleich eine ordentliche
Programmiersprache, z.B. Ocaml oder so.

Denn so wie Du Dein Programm geschrieben hast, scheinst Du sehr
fortschrittlich (funktional und rekursiv) zu denken. Nutze die Chance
und verlasse das Imperative Lager so lange Deine Gedankengänge noch
nicht versaut sind. Du scheinst Talent zu haben!

Ich meine das übrigens ernst, nur für den Fall dass das jemand in den
falschen Hals bekommen sollte!

Autor: Michael (ein anderer) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@crazy horse:

Versuch' die Sache mal aus einem anderem Blickwinkel zu betrachten:

1.) Für wen programmierst Du, bzw. wer liest Deinen Code?

a.) Ein Computer
b.) Ein Mensch (Du selbst zählst auch)

2.) Wer führt Dein Programm aus?

a.) Ein Computer
b.) Ein Mensch

3.) Bevorzugt der Computer ein bestimmte Variante, oder ist ihm
schurz-piep egal?

4.) Wie denkt ein Mensch, wie organisiert und plant er seine Welt?

Lebt er so:

   Schritt 1:  Höre auf den Wecker.
   Schritt 2:  Hat der Wecker geglingelt?
   Schritt 3:  Wenn nein, gehe zu Schritt 1.
   Schritt 4:  ...

Oder so:

   - Solange der Wecker nicht klingelt, schlafe.

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
recht nettes Beispiel, aber programmtechnisch sehe ich auch da keinen
Unterschied, denn bei deinem "solange der Wecker nicht klingelt"
machst du ja auch nichts anders, als zu horchen, ob der Wecker nun
klingelt und dann zurückzuspringen (oder eben nicht).
Für Schleifen, gleich welcher Art, nutze ich goto auch nicht,
ebensowenig käme ich auf die Idee, eine switch-Anweisung zu ersetzen,
einen logischen Unterschied sehe ich aber nicht.
Allerdings kommen mir immer wieder mal verschachtelte Schleifen unter,
und dann scheint mir goto sehr nützlich.
Sagen wir mal 3 Schleifen, Abbruchkriterien für das gesamte Konstrukt
können in allen 3 Schleifen entstehen. Wie löst du das? Die äussere
Schleife kann ich mit break (was ja auch wieder nur ein verkappter goto
ist) verlassen - was mache ich, wenn ich auch aus der 2. oder 3.
Schleife heraus das Ganze verlassen will?

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
variable setzten, in allen schleifen abfragen und wieder break. ist aber
auch murks, da hast du vollkommen recht. da würd ich auch eher goto
nehmen.
mitlerweile wird einem ja leider sogar erzählt, dass man sogar ganz
ohne break/continue auskommen soll, wäre ja alles
keine 'strukturierte programmierung'* mehr

* hiermit schlage ich dieses wort als computer-unwort des jahres vor

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> bei deinem "solange der Wecker nicht klingelt"
> machst du ja auch nichts anders, als zu horchen, ob der Wecker
> nun klingelt und dann zurückzuspringen (oder eben nicht).

Also ich schlafe nicht so. Das passiert interruptgesteuert und nicht
gepollt.

Autor: David Hebbeker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schön gesagt, aber wenn Du schläfst dann 'achtet' ja dein Körper auch
auf die Umgebungsgeräusche. Sonst würdest du ja vom Klingeln nicht
aufwachen. Mit diesem 'achten auf Umgebung' ist auch nur die abfrage
eines sensors gemeint. um das ergebnis der abfrage zu interpretieren
muss du auch (ggf in eine variable packen) und dann den wert mit einer
if oder while bedingung überprüfen.
damit heißt es doch auch dass du also ständig deinen umgebungssensor
abfragst, oder eine variable, die die schlaf-subroutine unterbricht.
wie auch immer, ihr werdet schon sehen, wie roboter besser schlafen
werden als menschen.... ^^

Guten Morgen, Ringelkrat

Antwort schreiben

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

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.