Forum: Mikrocontroller und Digitale Elektronik Überlastet Reziproke ATTiny?


von David Hebbeker (Gast)


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.

von A.K. (Gast)


Lesenswert?

Stack overflow. Jeder Aufruf kostet 2 Bytes auf dem Stack. 128 Byte
gibt's.

von nides (Gast)


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

von crazy horse (Gast)


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.

von David Hebbeker (Gast)


Lesenswert?

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

von David Hebbeker (Gast)


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

von Uwe Große-Wortmann (Gast)


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...)

von Chris (Gast)


Lesenswert?

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

Nimm while.

von David Hebbeker (Gast)


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

von crazy horse (Gast)


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.

von Rufus T. Firefly (Gast)


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 ...

von Chris (Gast)


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.

von Michael (ein anderer) (Gast)


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!

von Michael (ein anderer) (Gast)


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.

von crazy horse (Gast)


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?

von Tobi (Gast)


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

von Rufus T. Firefly (Gast)


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.

von David Hebbeker (Gast)


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

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
Noch kein Account? Hier anmelden.