Forum: Mikrocontroller und Digitale Elektronik Schleife + Verzögerung (mega8/Bascom)


von GMB (Gast)


Lesenswert?

Hallo zusammen!

Habe ein "kleines programmiertechnisches Problem":

Möchte gerne ein Programm haben, mit folgender "Teilfunktion":

Es soll den Wert von einem ADC einlesen, vergleichen ob sich dieser im
Gegensatz zu vorher geändert hat (ob also am Poti "gedreht" wurde),
wenn nein, dann soll das Programm fortlaufen die Werte 2er anderer ADCs
auslesen + anzeigen, ist dies aber nicht der Fall (und da tritt dann
auch mein "Problem" auf), also wenn am Poti "gedreht" wurde, soll
er eine neue "Anzeige" starten, bei der dann der Poti-Wert angezeigt
wird (soweit im Prinzip auch kein Thema), er soll jedoch wenn das Poti
wieder "losgelassen" wird, erst noch ein bisschen warten, bis er zur
Anzeige der beiden anderen ADCs wieder zurück kehrt.

Hat da jemand eine "Grundidee" für mich?!! Brauche keine konkrete
Syntax für Bascom, das ist kein Problem, eher so eine Idee wie:

"Schleife starten"...

"Schleife beenden"...

etc.

Danke schonmal im Voraus!

von Rahul (Gast)


Lesenswert?

Schleifenbeginn
  ADC1 einlesen
  wenn ADC1 sich veränndert hat:
      ADC2 und ADC3 einlesen
      Anzeige aktualisieren
  wenn ADC1 sich nicht verändert hat:
      warte ein gewisse Zeit ([OT] auf den Weihnachtsmann,
                                   die Bahn [/OT]
Schleifenende

Und wo ist das Problem?

von GMB (Gast)


Lesenswert?

Du hast das glaube ich falsch verstanden:

Schleifenbeginn

ADC1 einlesen

Wenn ADC1 unverändert:
             ADC2 und ADC3 einlesen
             ADC2 und ADC3 ausgeben auf Display

Wenn ADC1 verändert:
           ADC1 einlesen
           ADC1 auf Display ausgeben

Schleifenende

So, wenn ich jetzt vor das Schleifenende die Verzögerung lege, dann
verzögert er das ja bei jedem Durchlauf der Schleife, und ich kann am
Poti drehen, aber es tut sich nichts...

Ich hoffe das Problem ist jetzt klar geworden?!?!

von Rahul (Gast)


Lesenswert?

Schleifenbeginn

ADC1 einlesen

Wenn ADC1 unverändert:
             ADC2 und ADC3 einlesen
             ADC2 und ADC3 ausgeben auf Display

Wenn ADC1 verändert:
           ADC1 einlesen
           ADC1 auf Display ausgeben
           Warten

ADC2 und ADC3 ausgeben auf Display

Schleifenende
So vielleicht?

von GMB (Gast)


Lesenswert?

Dann habe ich ja auch wieder das Problem: ich drehe am Poti, der
Controller "registriert" eine Veränderung des Werte, springt in den
2. Teil der Abfrage ("ADC1 verändert"), gibt auch den ADC1-Wert aus,
und wartet dann => wenn ich jetzt weiter am Poti drehe, bekomme ich die
Änderung erst nach der Wartezeit wieder... :-/
Aber danke soweit für die Hilfe!

Hat noch jemand eine Idee?!?

von Peter Schwarz (Gast)


Lesenswert?

Sprich, solange am Poti gedreht wird, soll dieser Wert angezeigt werden.
Wenn dann nicht mehr gedreht wird, soll dieser Wert noch eine gewisse
Zeit angezeigt werden.

Dann sollen wieder die anderen 2 Werte angezeigt werden. Korrekt ?

Schleifenbeginn

ADC1 einlesen

IF ADC1 verändert:
           ADC1 einlesen
           ADC1 auf Display ausgeben
           ADC1-Flag setzen
END IF

IF ADC1 unverändert:
     IF ADC1-Flag gesetzt
             Warten
             ADC1-Flag löschen
     ELSE
             ADC2 und ADC3 einlesen
             ADC2 und ADC3 ausgeben auf Display
     END IF
END IF


ADC2 und ADC3 ausgeben auf Display

Schleifenende

von Peter Schwarz (Gast)


Lesenswert?

Das ADC2 und ADC3 ausgeben auf Display am Ende gehört natürlich weg.

von GMB (Gast)


Lesenswert?

Aber so wie ich das sehe, würde er ja dann zuerst (also wenn ADC1
verändert ist) das hier machen:

(IF ADC1 verändert:)
           ADC1 einlesen
           ADC1 auf Display ausgeben
           ADC1-Flag setzen

Aber er macht das dann doch nur ein mal, oder?!? (Ist ja soweit auch
"gewollt" denke ich, ich frage nur wegen des Verständnisses)

Aber er geht ja dann weiter im Programm, fragt ob ob das "Flag"
gesetzt ist, was ja dann der Fall ist, und wartet also...

Aber das soll er ja gerade nicht?!? Weil dann wartet er ja, geht dann
wieder raus, zeigt ADC2 und ADC3 an, und fragt dann erneut ab...

Aber so die "Grundidee" mit dem "Flag" (Ich denke du meinst damit
einfach nur eine Variable, die ich setze?!?!) könnte man ja mal
"weiterdenken"...

von Rahul (Gast)


Lesenswert?

Im Prinzip brauchst du dann eine Art Entprell-Routine für ADC1: solange
ADC1 sich ändert, ADC1 anzeigen. Danach einen Moment warten und die
beiden anderen anzeigen.
Scheifenbeginn
   Schleifenbeginn
     frage ADC1 ab
     zeige ADC1-Wert an
   Schleifenende, wenn ADC1 sich nicht verändert hat.
   warte einen Moment
   Schleifenbeginn
      Zeige ADC2 und ADC3 an
   beende Schleife, wenn ADC1 sich verändert hat
Schleifenende

von GMB (Gast)


Lesenswert?

Mmmmh...ich hatte mir folgendes gedacht (ist so ähnlich wie da von Peter
Schwarz):

Schleifenanfang

     ADC1-Abfragen
     Wenn ADC1 = Verändert
     ADC1 anzeigen
     ADC1-"Flag" setzen
     Wenn ADC1 = unverändert
        wenn ADC1-Flag = gesetzt
                Warten
                ADC1-"Flag" zurück setzen
       Sonst
         ADC2 und ADC3 anzeigen
       Ende Wenn-Abfrage
Ende schleife

So (oder so ähnlich) sollte es klappen...oder ich versuch einfach mal
in Bascom über die Simulation, aber ob es das bringt?!?!

von GMB (Gast)


Lesenswert?

Also, ich hab das jetzt mal versucht, aber irgendwie klappt das alles
nicht, bin momentan auch etwas "unschlüssig", wie ich die Abfrage
"ADC1 verändert oder nicht" hinbekommen soll... :-/

Wenn da vielleicht jemand nen Tip hätte!??!?!

von Rahul (Gast)


Lesenswert?

Ich will ja nicht rumnölen, aber eigentlich solltest du wissen, wie du
das haben willst. Um sich den Ablauf klarzumachen benutzt man auch
gerne solche altmodischen Gerätschaften wie einen Bleistift und ein
Blatt Papier. (oder auch mehrere...).
Auf dieses Blatt kann man solche Sachen wie Ablaufpläne oder
Struktogramme, also Programme ohne Programmiersprachenbezug aufmalen.
Ausserdem solltest du dir darüber im Klaren sein, welche
Funktionsblöcke du hast/brauchst.
Übrigens macht meine Version exakt das Gleiche...nur dass ich mir ein
Flag spare, und im Einschaltmoment die Pause gemacht wird, da die
Variable in der der ADC1-Wert zwecks Vergleich enthält ("Hat ADC1 sich
verändert?") noch nicht den ADC1-Wert enthält.
Das kann man entweder dadurch abstellen, dass man vor Beginn der
Schleife in diese Variable den ADC1-Wert einliest, oder man ignoriert
die Pause, verkauft sie als neues "Feature" (Es ist ja vielleicht
auch interessant zu Beginn des Betriebs den ADC1-Wert zu lesen).
Aber wenn du nicht mal weißt, wie du solche Probleme löst, solltest du
dir vielleicht lieber die Freizeitbeschäftigung "Briefmarken- /
Kronenkorkensammeln" aussuchen.
Merkt man, dass ich etwas angepestet bin?
Schön...

von GMB (Gast)


Lesenswert?

Super, genau den Beitrag habe ich gebraucht, nachdem ich vorhin ungefähr
10 Blatt Papier vollgeschrieben hab, und jetzt immer noch hier sitze,
und es mal "live" probiert habe, also im Simulationsmodus von
Bascom!!

Aber danke für deinen geistreichen Beitrag, hat mich echt aufgebaut,
und ich bin frohen Mutes, da jetzt mit vollem Elan weiter zu machen!!

TOP!!

Ich weiß doch wie ich es haben will! Hab ich doch schon 3 mal gepostet
mindestens!!

von Rahul (Gast)


Lesenswert?

Poste doch mal deinen Code bisher...
Freut mich, dich aufgebaut zu haben...

von GMB (Gast)


Lesenswert?

Also, bis lang habe ich das hier:

$regfile = "m8def.dat"
$crystal = 3686400

Dim X As Word
Dim Y As Word
Dim Z As Word
Dim B As Bit


Do
While Y = Y      'Einfach mal "laufen" lassen



If X <> X Then  ' Wenn X sich geändert hat

X = Getadc(0)

Cls
Upperline
Lcd X
B = 1                      '"Flag" setzen

Else

If B = 1 Then

Waitms 500

B = 0

Else

Z = Getadc(1)

Cls
Upperline
Lcd Z

End If
End If
Wend


Loop



So mal "ganz grob" für mich programmiert...

Habe es mal simuliert, aber wie gesagt, da ändert sich nichts, wenn ich
am ADC0 was ändere...

von GMB (Gast)


Lesenswert?

Hab mal den ersten Fehler "selber" gefunden:

X ist ja immer gleich X, weil selbst wenn er am Anfang die Variable
"irgendwie" setzt, sind sie ja gleich, also springt er da schonmal
nicht rein... :-/

Aber wie löse ich es dann?

von Rahul (Gast)


Lesenswert?

Versuchs mal damit:

$regfile = "m8def.dat"
$crystal = 3686400

Dim X As Word
Dim Y As Word
Dim Z As Word
Dim B As Bit

X = Getadc(0)
Do
While Y = Y      'Einfach mal "laufen" lassen Endlosschleife?
   b=0
   If X <> Getadc(0) Then  '
    X = Getadc(0)
    Cls
    Upperline
    Lcd X          'ADC1-Wert anzeigen
    B = 1          '"Flag" setzen
  End If
  If B = 1 Then
   Waitms 500
   B = 0
  End If
  Z = Getadc(1)
  Cls
  Upperline
  Lcd Z
Wend
Loop  '2 Endlosschleifen?

Meine Variante:

$regfile = "m8def.dat"
$crystal = 3686400

Dim X As Word
Dim Y As Word
Dim Z As Word
Dim B As Bit

X = Getadc(0)

While 1      'Endlosschleife
  do
    Y = Getadc(0)
    Cls
    Upperline
    Lcd X          'ADC1-Wert anzeigen
  loop while X<>Y
  Waitms 500 'ADC1 hat sich nicht mehr verändert
  do
    Z = Getadc(1)
    Y = Getadc(0)
    Cls
    Upperline
    Lcd Z
  loop while X<>Y
Wend

von Rahul (Gast)


Lesenswert?

Vielleicht fällt dir noch was auf: Grupppiere Anweisungen durch
Einrückungen. Und spare nicht an sinnvollen Kommentaren. Selbst wenn du
nur so für dich was machst, helfen Kommentare meistens zu verstehen, was
man eigentlich mit dem erreichen will, was man da gerade geschrieben
hat, und wenn man später ins Programm guckt, muß man nicht erst wieder
den Code "aufdröseln", um zu verstehen, was da steht...

von GMB (Gast)


Lesenswert?

Ja, da hast du wohl recht...habe auch leider den Code gelöscht, wo ich
es am laufen hatte, nur halt ohne die Verzögerung...aber ich mach für
heute sowieso erstmal Ende, das bringt nix mehr, hab gar keinen Elan
mehr irgendwie...

Danke soweit für die Hilfe, ich meld mich morgen mal wieder, wenn ich
wieder klar denken kann... ;-)

von Rahul (Gast)


Lesenswert?

Gute Idee.

von GMB (Gast)


Lesenswert?

Dein Code will übrigens nicht so ganz, bzw. Bascom "kennt" die
Anweisung nicht, der macht nur "Loop Until [Bedingung]"

Aber auch wenn ich das "umstricke" klappt dat irgendwie nicht...

Aber der Akku ist bei mir jetzt echt "alle", ich geh mal lieber
pennen, und morgen dann "frisch" ans Werk... ;-)

von Peter Schwarz (Gast)


Lesenswert?

Ich glaube den Ansatz mit dem wait würde ich schon gar nicht machen. In
der Zeit, tut das Program nämlich gar nix, auch wenn man am Poti dreht
und ich würde schon gerne eine Echtzeitanzeige haben wollen.

Vielleicht würde ich es so machen:

Zaehler = 0
NeuADC1 = <ADC1 einlesen>
While 1=1 'um bei dem Beispiel oben zu bleiben mit der Endlosschleife
  AltADC1 = NeuADC1
  NeuADC1 = <ADC1 einlesen>
  ADC2 = <ADC2 einlesen>
  ADC3 = <ADC3 einlesen>
  If Zaehler > 0
     Display NeuADC1
     Zaehler = Zaehler - 1
  Else
    If NeuADC1 <> AltADC1
       Display NeuADC1 'könnte man hier aber auch weglassen
       Zaehler = <StartWert wieder> 'ausprobieren was passt
    Else
       Display ADC2
       Display ADC3
    End If
Wend

Nach dem Start passiert erst mal nix und ADC2+3 werden ausgegeben. Wenn
sich dann was am Poti ändert (ADC1) gehts los in der Schleife.
Der Zaehler wird runtergezählt und der aktuelle Wert ausgegeben.
Passiert in dieser Zeit dann irgenwann nix mehr, läuft der Zähler
komplett runter bis auf 0 und dann werden wieder ADC2+3 ausgegeben.

Wahrscheinlich kommt jetzt wieder einer mit 'Ja, aber geht doch viel
einfacher'. Mag sein, aber so auf die schnelle würde ich erst mal
machen. Sollte jetzt noch ein Fehler drin sein, dann selbst debuggen,
Fehler ausmerzen und freuen.

von Peter Schwarz (Gast)


Lesenswert?

Da fehlt noch ein End If vor dem Wend, aber das meckert Bascom schon an
;)

von GMB (Gast)


Lesenswert?

Hallo Peter!!

Dein Ansatz klingt echt vernünftig und verständlich, werde ich direkt
zu Hause mal versuchen!!

Mit den "Feinheiten" von Bascom etc. komme ich schon klar (habe heute
wieder einen wesentlich klareren Kopf als gestern. ;-)), das
Grundprinzip von dir scheint "auf dem Papier" auch zu laufen, ich
denke das wird am Controller selber auch laufen...

Melde mich dann später mal, wie es so "läuft"... ;-)

von GMB (Gast)


Lesenswert?

Also, hab's ausprobiert, es funktioniert!

Danke dir vielmals! Ärgere mich zwar, das ich nicht selber drauf
gekommen bin, aber gestern war echt der Akku "leer"...

von Peter Schwarz (Gast)


Lesenswert?

Freut mich :) Diese simplen Funktionen sind manchmal doch mit etwas
'Hirnschmalz' zu lösen, vor allem weil man sowas ja wirklich
tagtäglich bei allen möglichen Geräten sieht z.B. Lautstärkeanzeige bei
einem Radio.

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.