Forum: Mikrocontroller und Digitale Elektronik Loop-Schleife unterbrechen?


von Thomas E. (Gast)


Lesenswert?

Hallo!

Ich habe folgende Schaltung auf einem Attiny26 am Laufen:
1
$regfile = "Attiny26.dat"
2
$crystal = 1000000
3
4
5
Config Pinb.6 = Input
6
Portb.6 = 1
7
Config Porta.7 = Output
8
Config Porta.6 = Output
9
Config Porta.5 = Output
10
11
Led1 Alias Porta.5
12
Led2 Alias Porta.6
13
Led3 Alias Porta.7
14
Taster Alias Pinb.6
15
16
17
Do
18
   If Taster = 1 Then
19
      Gosub Tasteraus
20
   Else
21
      Gosub Tasterein
22
   End If
23
Loop
24
25
Tasteraus:
26
   Led1 = 0
27
   Led2 = 0
28
   Led3 = 0
29
   Wait 1
30
   Led1 = 1
31
   Led2 = 1
32
   Led3 = 1
33
   Wait 1
34
Return
35
36
Tasterein:
37
   Led1 = 0
38
   Led2 = 1
39
   Led3 = 1
40
   Waitms 50
41
   Led1 = 1
42
   Led2 = 0
43
   Led3 = 1
44
   Waitms 50
45
   Led1 = 1
46
   Led2 = 1
47
   Led3 = 0
48
   Waitms 50
49
Return
50
51
End

Wenn ich jetzt den Taster drücke, läuft erst das Programm Tasteraus 
fertig, ERST DANN springt der Controller auf das Programm Tasterein. Da 
das Programm Tasteraus 2 Sekunden dauert, und ich beispielsweise bei dem 
Umschaltvorgang von Led123=0 auf Led123=1 den Taster drücke, dauert es 
noch eine Sekunde, bis das Programm Tasterein aufgeruden wird.

Wie könnte ich diese Wartezeit verhindern?

Thomas

von Matthias L. (Gast)


Lesenswert?

>Wie könnte ich diese Wartezeit verhindern?

Anders Programmieren!

So, dass keine Totzeiten durch Delay(wait) entstehen.

von Thomas E. (Gast)


Lesenswert?

Und was für Alternativen würden sich da bieten?

Thomas

von Fabian B. (fabs)


Lesenswert?

Solches "warten" macht man mit Timern. Das geht bestimmt auch in bascom.
Dann brauchste auch gar keine Subs mehr sondern nur den Timerinterrupt 
und eine globale Variable.

Gruß
Fabian

von Matthias L. (Gast)


Lesenswert?

>Und was für Alternativen würden sich da bieten?


Keine. SOnst bleibts Spaghetticode.

Wie  Fabian B. (fabs) sagte:
-Die Ausgabedaten für die Leds in eine Tabelle packen.
-Über einen Timerinterrupt neue Daten an den AUsgang schaufeln.
-Die Taster ändern nur den Zeiger, der in die Tabelle zeigt.

=> Kein Delay/Wait mehr nötig.

von Timmo H. (masterfx)


Lesenswert?

>Keine. SOnst bleibts Spaghetticode.
Kann man mit Basic eigentlich Nicht-Spaghetticode machen? ;-)


>Und was für Alternativen würden sich da bieten?
Wie bereits gesagt. Mach dir einen Timer und für die Taster irgendwie 
globale Flags, die du in der ISR abfragst und entsprechend reagierst.

von Matthias L. (Gast)


Lesenswert?

>Kann man mit Basic eigentlich Nicht-Spaghetticode machen? ;-)

Stimmt. Wohl eher nicht ;-)

Naja, wollen ja keine Diskussion Bascom/Nicht_bascom lsobrechen hier..

Ich will mal was produktives beisteuern. Ich würds etwa so machen:
(pseudocode)
1
Tabelle_aus =
2
(1000, 0,0,0   // für Taste aus
3
 1000, 1,1,1
4
    0 );
5
Tabelle_ein =
6
(  50, 0,1,1  // für Taste ein
7
   50, 1,0,1
8
   50, 1,1,0
9
    0 );
10
*******************
11
globale Variable:  
12
pointer     = 0
13
abgelZeit   = 0;
14
*******************
15
timer_interrupt_alle_eine_millisekunde
16
{
17
  if ( pointer=0) then return;
18
  if (*pointer=0) then return;
19
  abgelZeit=abgelZeit + 1;
20
  if (abgelZeit = *pointer)
21
  {
22
    pointer   = pointer + 1;
23
    led1      = *pointer;
24
    pointer   = pointer + 1;
25
    led2      = *pointer;
26
    pointer   = pointer + 1;
27
    led3      = *pointer;
28
    pointer   = pointer + 1;
29
    abgelZeit = 0;
30
  }
31
}
32
*******************
33
main
34
{
35
  init timer;
36
  endlosschleife
37
  {
38
    if (positiveFlanke_Taste aus) pointer = adresse(Tabelle_aus)
39
    if (positiveFlanke_Taste ein) pointer = adresse(Tabelle_ein)
40
  }
41
}

von Peter (Gast)


Lesenswert?

Matthias Beispiel ist aber in C und nicht in Basic. Aber der Ansatz mit 
einem Timer-Interrupt ist sicher die schönste Variante, ich weiss aber 
nicht ob man das mit Basic kann, bzw. weiss nicht wie man das in Basic 
macht.

Aber ich hätte noch einen alternativen Vorschlag:

$regfile = "Attiny26.dat"
$crystal = 1000000


Config Pinb.6 = Input
Portb.6 = 1
Config Porta.7 = Output
Config Porta.6 = Output
Config Porta.5 = Output

Led1 Alias Porta.5
Led2 Alias Porta.6
Led3 Alias Porta.7
Taster Alias Pinb.6

Do
  For i=1 to 10
     If Taster = 1 Then
       If i<6
         Gosub TasterausOff
       Else
         Gosub TasterausOn
       Ensdif
     Else
       Gosub Tasterein
     End If
  next i
Loop

TasterausOff:
   Led1 = 0
   Led2 = 0
   Led3 = 0
   Waitms 100
Return

TasterausOn:
   Led1 = 1
   Led2 = 1
   Led3 = 1
   Waitms 100
Return

Tasterein:
   Led1 = 0
   Led2 = 1
   Led3 = 1
   Waitms 50
   Led1 = 1
   Led2 = 0
   Led3 = 1
   Waitms 50
   Led1 = 1
   Led2 = 1
   Led3 = 0
   Waitms 50
Return

End

von Peter (Gast)


Lesenswert?

Oups...

Eine Sekunde ist 10x100ms! Für eine Sekunde sollte es natürlich so sein:

Do
  For i=1 to 20
     If Taster = 1 Then
       If (i < 11)
         Gosub TasterausOff
       Else
         Gosub TasterausOn
       Ensdif
     Else
       Gosub Tasterein
     End If
  next i
Loop

von Matthias L. (Gast)


Lesenswert?

>Matthias Beispiel ist aber in C und nicht in Basic.

Deshalb habe ich pseudocode drübergeschrieben, weil es nicht exakt C 
ist. DIese bascom kann doch keiner...

@Peter:
Dort sind auch auf wieder Warteschleifen drin, in der Zeit kann nix 
anderes passieren...
Also nur anders programmiert, aber immernoch dasselbe Problem.

von Peter (Gast)


Lesenswert?

>Deshalb habe ich pseudocode drübergeschrieben, weil es nicht exakt C
>ist. DIese bascom kann doch keiner...
Ich kenne Bascom auch nicht und benutze C. Aber ich habe früher viel in 
Basic programmiert (Atari, Taschenrechner, VBA) und finde es ist bei 
weitem nicht so schlecht wie sein Ruf, schon gar nicht für erste 
Schritte. Es gibt keinen Grund, abschätzig auf den Basic-Programmierern 
rum zu hacken, wie dies hier im Forum offenbar üblich ist. Spagetticode 
hängt vom Programmierer ab, nicht von der Programmiersprache!

>Dort sind auch auf wieder Warteschleifen drin, in der Zeit kann nix
>anderes passieren...
Ich schreibe ja, dass eine Lösung mit Timer-Interrupt die bessere Lösung 
ist.

Meine Variante lösst einfach mal das Problem, dass man bis zu zwei 
Sekunden warten muss, bis ein Tastendruck erkannt wird. Nun wird die 
Taste immerhin alle 100...150ms abgefragt, was im Normalfall schon recht 
praktikabel ist.

von Thomas E. (Gast)


Lesenswert?

Hallo Peter!

Besten Dank dür deine Hilfe!
Leider gibt mir Bascom eine Fehlermeldung aus, wenn ich versuche, den 
Code zu kompilieren. Weißt du eventuell, woran das liegen könnte?

Thomas

von Paul Baumann (Gast)


Lesenswert?

Vielleicht an "Ensdif" statt "Endif" in der Schleife? ;-)

Wenn Du in Bascom mit der Maus ganz unten auf die Fehlermeldung gehst
und darauf klickst, hüpft der Compiler in die Zeile mit dem Fehler und 
färbt sie rot.

MfG Paul

von Thomas E. (Gast)


Lesenswert?

Hallo Paul!

Den Schreibfehler bei "End If" habe ich schon lange ausgebessert. Beim 
draufklicken auf die Fehlermeldung springt der in die Zeile
1
For i=1 to 10

Thomas

von Peter (Gast)


Lesenswert?

>Vielleicht an "Ensdif" statt "Endif" in der Schleife? ;-)


Tja, das ist natürlich ein Tippfehler und muss natürlich  "End If" 
heissen. Vielleicht gibt's noch weitere Fehler. Der Compiler wird Dir 
schon sagen, wo's noch was zu mekern gibt.

Ich denke du musst auch die Variable i für den Schleifenzähler 
deklarieren, zum Beispiel als Byte.

von Peter (Gast)


Lesenswert?

Geht es so auch nicht...?

___________________________________________________

$regfile = "Attiny26.dat"
$crystal = 1000000


Config Pinb.6 = Input
Portb.6 = 1
Config Porta.7 = Output
Config Porta.6 = Output
Config Porta.5 = Output

Led1 Alias Porta.5
Led2 Alias Porta.6
Led3 Alias Porta.7
Taster Alias Pinb.6

Dim i As Byte

Do
  For i = 1 To 20
     If Taster = 1 Then
       If i<11
         Gosub TasterausOff
       Else
         Gosub TasterausOn
       End If
     Else
       Gosub Tasterein
     End If
  Next i
Loop

TasterausOff:
   Led1 = 0
   Led2 = 0
   Led3 = 0
   Waitms 100
Return

TasterausOn:
   Led1 = 1
   Led2 = 1
   Led3 = 1
   Waitms 100
Return

Tasterein:
   Led1 = 0
   Led2 = 1
   Led3 = 1
   Waitms 50
   Led1 = 1
   Led2 = 0
   Led3 = 1
   Waitms 50
   Led1 = 1
   Led2 = 1
   Led3 = 0
   Waitms 50
Return

End

von Thomas E. (Gast)


Lesenswert?

Nein leider funktioniert auch dieser Code nicht. Jetzt gibt er schon 
vier Meldungen aus, die alle entweder zu "< 11" führen, oder gegen den 
Befehl "End If" gehen.

Thomas

von Peter (Gast)


Lesenswert?

Da hab ich wohl noch das "Then" beim "If i < 11 Then" vergessen...

von AVRFan (Gast)


Lesenswert?

Welches Verhalten soll das Programm überhaupt realisieren?

von Thomas E. (Gast)


Lesenswert?

Werds heute mal versuchen, Peter.

von Karl H. (kbuchegg)


Lesenswert?

Thomas E. wrote:
> Nein leider funktioniert auch dieser Code nicht. Jetzt gibt er schon
> vier Meldungen aus, die alle entweder zu "< 11" führen, oder gegen den
> Befehl "End If" gehen.^

Nur so als Hinweis:
Sehr oft ist der Text einer Fehlermeldung hilfreich beim Suchen
nach dem Fehler

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.