PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Mit Taster von einem Loop zum nächsten springen



Bow-Hunter
22.09.2014, 15:07
Ich hab gesucht, wurde aber nicht fündig. Das Thema wurde bestimmt schon einmal besprochen. Ich hoffe jemand kann meine Frage beantworten.

Ich habe in Bascom verschiedene Lauflichter programmiert (LED Blinklichter). Eigentlich ne recht einfache Sache, sie gehen mit einem Schalter an und aus.
Jetzt möchte ich gerne einen Taster einsetzen mit dem ich die verschiedenen Loops ansteuern kann.

Leider weis ich nicht welchen Befehl ich dafür benutzen kann um aus einer Loop heraus zu kommen und in die nächste springen kann.
Und natürlich wie dann zum Schluss der befehl des ausbleibends kommen kann.

Gruß Glenn

peterfido
22.09.2014, 17:02
Nimm keine Loops, nimm Subs.

PseudoCode:


do
If taster then incr Modus
If Modus > AnzahlModi then Modus=1
select case modus
case 1
Gosub Lichteffekt1
case 2
Gosub Lichteffekt2

end select

loop
end

Lichteffekt1:
...
return

Licheffekt2:
...
return

Bow-Hunter
22.09.2014, 21:43
Das ist jetzt ein bisschen ausführlicher, aber nun zeigt er mir 3 Fehler bezogen auf "Modus" an.



$regfile = "attiny13.dat"
$crystal = 1200000
$hwstack = 0
$swstack = 0
$framesize = 0

Config Portb.1 = Output
Config Portb.2 = Output
Config Portb.3 = Output
Config Portb.4 = Output
Config Pinb.0 = Input



do
If Pinb.0 = 1 Then Incr Modus
If Modus > AnzahlModi then Modus=1
Select Case Modus
Case 1
Gosub Lichteffekt1
Case 2
Gosub Lichteffekt2

end select

loop
end

Lichteffekt1:

Portb.1 = 1
Portb.2 = 0
Portb.3 = 1
Portb.4 = 0
Waitms 100
Portb.3 = 0
Portb.4 = 1
Waitms 100
Portb.3 = 1
Portb.4 = 0
Waitms 100
Portb.1 = 0
Portb.2 = 1
Portb.3 = 0
Portb.4 = 1
Waitms 100
Portb.3 = 1
Portb.4 = 0
Waitms 100
Portb.3 = 0
Portb.4 = 1
Waitms 100

return

Licheffekt2:

Portb.1 = 1
Portb.2 = 1
Portb.3 = 1
Portb.4 = 1
Waitms 100
Portb.1 = 0
Portb.2 = 0
Portb.3 = 0
Portb.4 = 0
Waitms 100

return

Mcgrizzly123
22.09.2014, 22:15
Hi

du musst die Variablen Modus und AnzahlModi auch definieren.:)


$regfile = "attiny13.dat"
$crystal = 1200000
$hwstack = 0
$swstack = 0
$framesize = 0

Config Portb.1 = Output
Config Portb.2 = Output
Config Portb.3 = Output
Config Portb.4 = Output
Config Pinb.0 = Input

Dim Modus As Integer
Dim Anzahlmodi As Integer
Modus = 1
Anzahlmodi = 2

do
If Pinb.0 = 1 Then Incr Modus
If Modus > AnzahlModi then Modus=1
Select Case Modus
Case 1
Gosub Lichteffekt1
Case 2
Gosub Lichteffekt2

end select

loop
end

Lichteffekt1:

Portb.1 = 1
Portb.2 = 0
Portb.3 = 1
Portb.4 = 0
Waitms 100
Portb.3 = 0
Portb.4 = 1
Waitms 100
Portb.3 = 1
Portb.4 = 0
Waitms 100
Portb.1 = 0
Portb.2 = 1
Portb.3 = 0
Portb.4 = 1
Waitms 100
Portb.3 = 1
Portb.4 = 0
Waitms 100
Portb.3 = 0
Portb.4 = 1
Waitms 100

Return

Lichteffekt2:

Portb.1 = 1
Portb.2 = 1
Portb.3 = 1
Portb.4 = 1
Waitms 100
Portb.1 = 0
Portb.2 = 0
Portb.3 = 0
Portb.4 = 0
Waitms 100

Return

Bow-Hunter
22.09.2014, 22:40
Okay, zumindest bekomme ich jetzt das Programm gespeichert. Habs grad mal auf den Tiny übertragen. Es spielt bei Stromzufuhr sofort den ersten Lichteffekt ab und reagiert nicht auf den Taster oder auf den Reset.
Ich probier das ganze morgen nach der Arbeit nochmal.
Schon mal danke bis hier hin...

Peter(TOO)
22.09.2014, 23:44
Hallo,

Okay, zumindest bekomme ich jetzt das Programm gespeichert. Habs grad mal auf den Tiny übertragen. Es spielt bei Stromzufuhr sofort den ersten Lichteffekt ab und reagiert nicht auf den Taster oder auf den Reset.
Ich probier das ganze morgen nach der Arbeit nochmal.

Du drückst die Taste zu lange ;-)


If Pinb.0 = 1 Then Incr Modus

Angenommen dein do-loop benötigt 1ms für einen Durchlauf, dann wird bei jedem Durchlauf Modus inkrementiert!

Du musst also die Flanke erfassen, wenn das Signal der Taste von 0 auf 1 springt und nur dann Modus inkrementieren.


$regfile = "attiny13.dat"
$crystal = 1200000
$hwstack = 0
$swstack = 0
$framesize = 0

Config Portb.1 = Output
Config Portb.2 = Output
Config Portb.3 = Output
Config Portb.4 = Output
Config Pinb.0 = Input

Dim Modus As Integer
Dim Anzahlmodi As Integer
Dim Taste_old As Bit
Dim Taste_new As Bit

Modus = 1
Anzahlmodi = 2
Taste_new = 0


do

Taste_old = Taste_new
Taste_new = Pinb.0
If ((Taste_old XOR Taste_new) AND Taste_new) = 1 Then Incr Modus

If Modus > AnzahlModi then Modus=1
Select Case Modus
Case 1
Gosub Lichteffekt1
Case 2
Gosub Lichteffekt2

end select

loop
end

BASIC ist lange her bei mir, ich hoffe es hat keine Tippfehler.

Hier noch die Erklärung zum Ausdruck ((Taste_old XOR Taste_new) AND Taste_new):
(Taste_old XOR Taste_new)
liefert 1 Wenn sich der Wert von Taste geändert hat, also seit der letzten Abfrage gedrückt oder losgelassen wurde.
Ich gehe davon aus, dass eine gedrückte Taste eine 1 liefert, das hängt jetzt aber von deiner Hardware ab.

Der Ganze Ausdruck liefert nur 1 wenn die Taste gedrückt wurde.

Die Hilfsvariable Taste_new benötigt man, weil sich Pinb.0 zwischen zwei Abfragen ändern könnte.

MfG Peter(TOO)

Bow-Hunter
23.09.2014, 06:17
If ((Taste_old XOR Taste_new) AND Taste_new) = 1 Then Incr Modus
Hier zeigt er mir eine Fehlermeldung an. Daher habe ich diese Zeile mal im Code weggelassen.


$regfile = "attiny13.dat"
$crystal = 1200000
$hwstack = 10
$swstack = 10
$framesize = 10

Config Portb.1 = Output
Config Portb.2 = Output
Config Portb.3 = Output
Config Portb.4 = Output
Config Pinb.0 = Input

Dim Modus As Integer
Dim Anzahlmodi As Integer
Dim Taste_old As Bit
Dim Taste_new As Bit

Modus = 1
Anzahlmodi = 2
Taste_new = 0

Do

Taste_old = Taste_new
Taste_new = Pinb.0
If Pinb.0 = 1 Then Incr Modus


If Modus > Anzahlmodi Then Modus = 1
Select Case Modus
Case 1
Gosub Lichteffekt1
Case 2
Gosub Lichteffekt2

End Select

Loop
End

Lustig:
Solange ich den Taster gedrückt halte laufen alle Lichteffekte nach einander ab.
Jenes Lichteffekt, dass gerade läuft während ich den Taster los lasse, läuft dann nur noch alleine.
Im Grunde ganz witzig aber nicht das was ich zur zeit möchte.

Ist vielleicht nur ein Tippfehler im obigen Code?

Danke Peter
Gruß Glenn

Peter(TOO)
23.09.2014, 06:36
Hallo Glenn,



If ((Taste_old XOR Taste_new) AND Taste_new) = 1 Then Incr Modus
Hier zeigt er mir eine Fehlermeldung an. Daher habe ich diese Zeile mal im Code weggelassen.

TOLL, und welche Meldung ?????


Lustig:
Solange ich den Taster gedrückt halte laufen alle Lichteffekte nach einander ab.
Jenes Lichteffekt, dass gerade läuft während ich den Taster los lasse, läuft dann nur noch alleine.
Im Grunde ganz witzig aber nicht das was ich zur zeit möchte.


Das ist genau das Problem.
Dein Programm erkennt die gedrückte Taste und zählt dann dauernd durch.
Der Rest scheint zu funktionieren.

Ist also nur das Problem mit der Fehlermeldung.

MfG Peter(TOO)

Bow-Hunter
23.09.2014, 07:00
29093
Diese Fehlermeldung, ich hoffe es hilft.

Peter(TOO)
23.09.2014, 07:35
Hallo,
Lösch mal das "= 1" in der fraglichen Zeile.

MfG Peter(TOO)

Bow-Hunter
23.09.2014, 12:56
29098

Ne leider auch nicht.
Und nur ohne "1" ebenfalls nicht.

Peter(TOO)
23.09.2014, 13:18
und mit And statt AND

Ich weiss nicht ob bascom casesensitive ist?

Sauerbruch
23.09.2014, 15:00
Groß- und Kleinschreibung ist bei Bascom glaube ich ziemlich egal.

Was definitiv ein Problem zu sein scheint, sind die Klammern. Bascom meckert nämlich auch schon bei einer einfachen, unverschachtelten AND-Verknüpfung, wenn man sie in Klammern setzt. Da die Klammern ja aber aufgrund der Verschachtelung nötig wären, kann man das Problem lösen, indem man die beiden Verknüpfungen mit einem Hilfs-Bit nacheinander ausführen lässt:



Dim Taste_old As Bit
Dim Taste_new As Bit
Dim X As Bit
Dim Modus As Byte


Do


X = Taste_old Xor Taste_new
X = X And Taste_new


If X = 1 Then Incr Modus


Loop




Dieser Code wird bei mir jedenfalls anstandslos kompiliert.

Und @ Bow-Hunter: Ganz einfach kann man einen Tastendruck erkennen, wenn man den Taster einen Interrupt auslösen lässt, indem der Taster einen Pegelwechsel am Interrupt-Eingangspin bewirkt. Dann braucht man die ganze "Merkerei" mit Taste_old und Taste_new nicht...

Bow-Hunter
23.09.2014, 16:31
So Leute, das ist jetzt die Finale Version von mir. Jetzt funktioniert alles.
Bei Stromzufuhr ist alles aus.
Beim ersten und zweiten schalten blinkt es unterschiedlich.
Beim dritten schalten geht alles wieder aus.
So wollte ich das haben.

Jetzt ein paar Fragen zum Code.
Was bedeutet Dim - As Bit?
und Dim - As Integer?
und Xor?
Diese Begriffe sagen mir noch nichts.

Und wieso muss ich ca. ne halbe Sekunde den Taster drücken bis der Attiny13 reagiert?




$regfile = "attiny13.dat"
$crystal = 1200000
$hwstack = 10
$swstack = 10
$framesize = 10

Config Portb.1 = Output
Config Portb.2 = Output
Config Portb.3 = Output
Config Portb.4 = Output
Config Pinb.0 = Input

Dim Modus As Integer
Dim Anzahlmodi As Integer
Dim Taste_old As Bit
Dim Taste_new As Bit
Dim X As Bit

Modus = 1
Anzahlmodi = 3
Taste_new = 0

Do

Taste_old = Taste_new
Taste_new = Pinb.0

X = Taste_old Xor Taste_new
X = X And Taste_new

If X = 1 Then Incr Modus

If Modus > Anzahlmodi Then Modus = 1
Select Case Modus
Case 1
Gosub Lichteffekt1
Case 2
Gosub Lichteffekt2
Case 3
Gosub Lichteffekt3

End Select

Loop
End

Lichteffekt1:

Portb.1 = 0
Portb.2 = 0
Portb.3 = 0
Portb.4 = 0

Return

Lichteffekt2:

Portb.1 = 1
Portb.2 = 0
Portb.3 = 1
Portb.4 = 0
Waitms 100
Portb.3 = 0
Portb.4 = 1
Waitms 100
Portb.3 = 1
Portb.4 = 0
Waitms 100
Portb.1 = 0
Portb.2 = 1
Portb.3 = 0
Portb.4 = 1
Waitms 100
Portb.3 = 1
Portb.4 = 0
Waitms 100
Portb.3 = 0
Portb.4 = 1
Waitms 100

Return

Lichteffekt3:

Portb.1 = 1
Portb.2 = 1
Portb.3 = 1
Portb.4 = 1
Waitms 100
Portb.1 = 0
Portb.2 = 0
Portb.3 = 0
Portb.4 = 0
Waitms 100
Portb.1 = 1
Portb.2 = 1
Portb.3 = 1
Portb.4 = 1
Waitms 100
Portb.1 = 0
Portb.2 = 0
Portb.3 = 0
Portb.4 = 0
Waitms 100
Portb.1 = 1
Portb.2 = 1
Portb.3 = 1
Portb.4 = 1
Waitms 100
Portb.1 = 0
Portb.2 = 0
Portb.3 = 0
Portb.4 = 0
Waitms 100

Return

HeXPloreR
23.09.2014, 17:29
Hallo Bow-Hunter,

das was du in dem Code jetzt tust nennt sich "pollen" - das bedeutet so viel wie : du fragst den Taster im Hauptprogramm in einem Duchlauf der Hauptschleife ab. Der Grund, warum das jetzt ca 500ms oder etwas genauer sogar ca 600ms dauert, der sollte dir bewußt werden wenn du dir mal überlegst was passiert wenn du eine Unterroutione (gosub) anlegst und dann mit dem Tasterinput dort hin verzweigst? Zeit unempfindlicher wäre ein Interrupt der etwas weiter oben schon vorgeschlagen wurde. Ich empfehle einmal mit dem Cursor auf "Dim" zu gehen und dann F1 zu drücken -> Bascom Hilfe. Zusaätzlich verweise ich mal auf diese Seite (klick mich) (http://halvar.at/elektronik/kleiner_bascom_avr_kurs) - hier findest du unter anderem auch was informatives zum Interrupt.

Viele Grüße
Jörg

Bow-Hunter
23.09.2014, 19:05
Okay, also das mit den 600ms hab ich wohl verstanden. Hätte ich eine Längere Schleife (Loop) so müsste ich halt immer das Ende von ihr abwarten. Bis die Taste Reagiert. Ich werd mich die Tage mal etwas genauer Informieren und versuch dann den Code mal umzubasteln, so das er sofort reagiert.
Danke für die schnellen Antworten.

HeXPloreR
23.09.2014, 20:27
... das mit den 600ms hab ich wohl verstanden. Hätte ich eine Längere Schleife (Loop) so müsste ich halt immer das Ende von ihr abwarten. Bis die Taste Reagiert. ...

Naja, fast - wichtig ist hier zu verstehen und auseinander zuhalten was wo passiert. Deine do-loop ist eine Schleife - Die Hauptschleife. Deine Unterroutinen, die du mit Gosub anwählst sind genau genommen nicht mehr Bestandteil diese Schleife. Der Zeitverlust entsteht in diesem Fall nicht in der Hauptschleife, sondern in der Unterroutine - allein zu sehen an den "6x waitms 100" - und natürlich fehlt der Interrupt. Diese Zeitverzögerung die du bemerkst ist also der Moment in dem sich Dein Programm in einer (langen) Unterroutine befindet. Damit hast du übrigens auch den schlechten Nebeneffekt vom pollen direkt bemerkt.
Manche Programme kann man durchaus damit laufen lassen, wenn es aber mal direkt gehen soll dann ist dieser Weg eher schlecht, weil man je nach dem wie lang eine Unterroutine ist dementsprechend warten - bzw den richtigen Moment der Tasterabfrage erwischen muss. Natürlich ist aber die Zeit die der µC benötigt um einmal die do-loop Schleife abzuarbeiten inklusiver der Unterroutinen die angewählt werden. Da kommt es dann eben noch drauf an was in ihnen passiert.
Beim "Case 1" passiert dir das übrigens auch, nur nicht so extrem auffällig weil keine waits drin sind und der Zeitverzug einfach für "uns" nicht direkt wahrnehmbar ist.

Viele Grüße
Jörg

Searcher
24.09.2014, 18:47
Hallo Bow-Hunter,
ich habe mal versucht bisherige Vorschläge in einem ungetesteten Entwurf für direkte Reaktion auf Tastendruck und Vermeidung von WAITs unterzubringen. Das Debounce Kommando fragt die Taste ab und entprellt auch gleich.

Gruß
Searcher


'### hwstack vergrößern. Wichtig bei Verwendung von Interrupts

$hwstack = 34


'### Alle Variablen können als Byte deklariert werden (spart Speicher im kleinen Tiny13)

'### Der Timer0 wird für die Blink- bzw. Schaltfrequenz konfiguriert

Compare0a = 116 '99,84ms Interruptperiode bei 1,2MHz µC-Takt
Config Timer0 = Timer , Prescale = 1024 , Clear_timer = 1 'Timer0 im Clear Timer on Comparematch

On Compare0a Isr_blink 'ISR wird bei Compare Match A aufgerufen

'### In der Haupschleife steht nur die Tastenabfrage inclusive Tastenentprellung

Do 'Beginn Hauptschleife
Debounce Pinb.0 , 1 , Changemodus , Sub 'Führt Unterprogramm aus, wenn Pinb.0 auf 1 wechselt
Loop 'Ende Hauptschleife



'### Nach Tastendruck wird dieses Unterprogramm ausgeführt, daß den Lichteffekt weiterschaltet und
'### die nötigen Parameter für die Interruptserviceroutine setzt.

Changemodus: 'Unterprogramm setzt Werte für Lichteffekt nach Tastendruck
Disable Compare0a 'Vermeidet Inkonsistenzen in der ISR
If Modus < Anzahlmodi Then Incr Modus Else Modus = 1
Select Case Modus
Case 1 : Anzahlphasen = 0 'Muß Anzahl der Daten in den DATA-Zeilen entsprechen
Case 2 : Anzahlphasen = 5 'Wert von 0 = ein Eintrag, 5 = sechs Einträge bei DATA
Case 3 : Anzahlphasen = 1 '.
End Select
Phase = 0
Enable Compare0a
Return


'### In der Interruptserviceroutine wird alle 100ms das neue Schaltmuster für die LEDs gelesen und
'### die LEDs geschaltet.

Isr_blink: 'wird alle ca. 100ms aufgerufen und schaltet die LEDs
If Phase < Anzahlphasen Then Incr Phase Else Phase = 0 'setzt die nächste Effektphase
Select Case Modus 'entsprechend dem Modus wird das Bitmuster für LEDs geholt
Case 1 : Pattern = Lookup(phase , Lichteffekt1)
Case 2 : Pattern = Lookup(phase , Lichteffekt2)
Case 3 : Pattern = Lookup(phase , Lichteffekt3)
End Select
Portb.1 = Pattern.3 'LED wird geschaltet
Portb.2 = Pattern.2 'LED wird geschaltet
Portb.3 = Pattern.1 'LED wird geschaltet
Portb.4 = Pattern.0 'LED wird geschaltet
Return
End 'end program


'### Hier sind die Schaltmuster abgelegt.

Lichteffekt1:
Data &B0000

Lichteffekt2:
Data &B1010 , &B1001 , &B1010 , &B0101 , &B0110 , &B0101

Lichteffekt3:
Data &B1111 , &B0000

Bow-Hunter
28.09.2014, 14:18
Danke für den Code...


$regfile = "attiny13.dat"
$crystal = 1200000
$hwstack = 34 '### hwstack vergrößern. Wichtig bei Verwendung von Interrupts
$swstack = 10
$framesize = 10

Config Portb.1 = Output
Config Portb.2 = Output
Config Portb.3 = Output
Config Portb.4 = Output
Config Pinb.0 = Input


Dim Anzahlmodi As Integer
Dim Modus As Byte

Modus = 1
Anzahlmodi = 3

'### Alle Variablen können als Byte deklariert werden (spart Speicher im kleinen Tiny13)

'### Der Timer0 wird für die Blink- bzw. Schaltfrequenz konfiguriert

Compare0a = 116 '99,84ms Interruptperiode bei 1,2MHz µC-Takt
Config Timer0 = Timer , Prescale = 1024 , Clear_timer = 1 'Timer0 im Clear Timer on Comparematch

On Compare0a Isr_blink 'ISR wird bei Compare Match A aufgerufen

'### In der Haupschleife steht nur die Tastenabfrage inclusive Tastenentprellung

Do 'Beginn Hauptschleife
Debounce Pinb.0 , 1 , Changemodus , Sub 'Führt Unterprogramm aus, wenn Pinb.0 auf 1 wechselt
Loop 'Ende Hauptschleife

'### Nach Tastendruck wird dieses Unterprogramm ausgeführt, daß den Lichteffekt weiterschaltet und
'### die nötigen Parameter für die Interruptserviceroutine setzt.

Changemodus: 'Unterprogramm setzt Werte für Lichteffekt nach Tastendruck
Disable Compare0a 'Vermeidet Inkonsistenzen in der ISR
If Modus < Anzahlmodi Then Incr Modus Else Modus = 1
Select Case Modus
Case 1 : Anzahlphasen = 0 'Muß Anzahl der Daten in den DATA-Zeilen entsprechen
Case 2 : Anzahlphasen = 5 'Wert von 0 = ein Eintrag, 5 = sechs Einträge bei DATA
Case 3 : Anzahlphasen = 1 '.
End Select
Phase = 0
Enable Compare0a
Return


'### In der Interruptserviceroutine wird alle 100ms das neue Schaltmuster für die LEDs gelesen und
'### die LEDs geschaltet.

Isr_blink: 'wird alle ca. 100ms aufgerufen und schaltet die LEDs
If Phase < Anzahlphasen Then Incr Phase Else Phase = 0 'setzt die nächste Effektphase
Select Case Modus 'entsprechend dem Modus wird das Bitmuster für LEDs geholt
Case 1 : Pattern = Lookup(phase , Lichteffekt1)
Case 2 : Pattern = Lookup(phase , Lichteffekt2)
Case 3 : Pattern = Lookup(phase , Lichteffekt3)
End Select
Portb.1 = Pattern.3 'LED wird geschaltet
Portb.2 = Pattern.2 'LED wird geschaltet
Portb.3 = Pattern.1 'LED wird geschaltet
Portb.4 = Pattern.0 'LED wird geschaltet
Return
End 'end program


'### Hier sind die Schaltmuster abgelegt.

Lichteffekt1:
Data &B0000

Lichteffekt2:
Data &B1010 , &B1001 , &B1010 , &B0101 , &B0110 , &B0101

Lichteffekt3:
Data &B1111 , &B0000


Hab ich da was falsch kopiert? Folgende Fehlermeldung kommt. 29136



Compare0a = 116 '99,84ms Interruptperiode bei 1,2MHz µC-Takt
Config Timer0 = Timer , Prescale = 1024 , Clear_timer = 1 'Timer0 im Clear Timer on Comparematch

On Compare0a Isr_blink 'ISR wird bei Compare Match A aufgerufen

Und könntest du mir diesen Bereich etwas genauer erklären?

Gruß Glenn

Sauerbruch
28.09.2014, 15:02
Das könnte daran liegen, dass Du die Variablen Phase und Anzahlphase nicht dimensioniert hast.

Du kannst eine Variable zwar nennen wie Du willst - aber damit Bascom vernünftig mit den Variablen arbeiten kann muss es wissen, um was für einen Typ von Variable es sich handelt. Das ist die Geschichte mit "Dim XY as Bit (bzw. byte, Integer o.ä.).

Ein Bit ist die kleinste Einheit und kann nur die Werte 1 oder 0 annehmen. Ideal also, um einen Zustand wie "ein/aus" zu speichern.
Ein Byte sind 8 Bits und kann Werte zwischen 0 und 255 darstellen (keine negativen Zahlen!)
Ein Word sind zwei Bytes und kann Werte zwischen 0 und 65535 darstellen (ebenfalls nur positive Zahlen)
Ein Integer sind auch zwei Bytes, diese Variable kann aber Werte zwischen -32768 und +32767 annehmen.

Und dann gibts noch DWord, Single, Double, Long und String, aber die brauchst Du hier erstmal nicht. Wie Searcher ja schon in seinem Codevorschlag auskommentiert hat, kann man für Deine Anwendung alle Variablen als Byte dimensionieren, um Speicherplatz zu sparen.

Der langen Rede kurzer Sinn:

Wenn Du irgendwo in Deinem Programm Variablen einsetzt, musst Du sie vorher dimensioniert haben.
In Deinem Fall fehlen also irgendwo die Zeilen

Dim Phase as Byte
Dim Anzahlphase as Byte

Searcher
28.09.2014, 16:33
Hab ich da was falsch kopiert? Folgende Fehlermeldung kommt.

Hallo Glenn, hat Sauerbruch schon erläutert. Die Deklarationen der Variablen könnte so aussehen (und es könnten immer noch welche fehlen?):


'### Alle Variablen können als Byte deklariert werden (spart Speicher im kleinen Tiny13)
.
.
Dim Anzahlmodi As Byte
Dim Modus As Byte
Dim Anzahlphasen as Byte
Dim Phase as Byte

Modus = 1
Anzahlmodi = 3
.
.






Compare0a = 116 '99,84ms Interruptperiode bei 1,2MHz µC-Takt
Config Timer0 = Timer , Prescale = 1024 , Clear_timer = 1 'Timer0 im Clear Timer on Comparematch

On Compare0a Isr_blink 'ISR wird bei Compare Match A aufgerufen

Und könntest du mir diesen Bereich etwas genauer erklären?

Mit dem Config Timer0 Kommando wird der Timer in den Clear Timer on Compare Match Mode gebracht. Erklärt im RN Wiki http://rn-wissen.de/wiki/index.php/Timer/Counter_%28Avr%29#CTC_Modus_.28Clear_Timer_on_Comp are_Match_mode.29 (und im Datenblatt zum Tiny13 ;) ). Compare0a=116 setzt das OCR0A Register, so daß der Timer0 nach 116 Schritten wieder bei 0 an zu zählen fängt. Der Presacaler 1024 sorgt dafür, das der Timer mit 1/1024stel des Systemtaktes läuft. Er läuft also mit 1200000Hz/1024 = 1171,875Hz, braucht also für einen Schritt 1/1171,875Hz = 0,000853s. Für 116 (OCR0A) Schritte plus 1 = 117 * 0,000853s = 0,099801s.
Der Timer läuft also in knapp 100ms von 0 auf 116 (116Schritte) dann wieder auf 0 (117ter Schritt) und erzeugt jedesmal wenn er auf 116 ist einen ComparematchA Interrupt.
Mit On Compare0a Isr_blink werden also alle ca 100ms die LEDs geschaltet. Der Code ist nicht ganz vollständig. Es fehlt noch "Enable Compare0a" und "Enable Interrupts" direkt nach "On Compare0a .."

Dadurch, daß die ISR (Interrupt Service Routine) immer nur alle 100ms die LEDs schaltet, kann ein Druck auf die Taste erst nach maximal 125ms - aber nicht länger - sichtbar werden. (100ms wg. Interruptfrequenz und 25ms Verzögerung durch die Debounce Routine). Falls da was stört, könnte man sich noch was überlegen...:confused:

Gruß und hoffentlich klappts
Searcher

Bow-Hunter
29.09.2014, 09:02
Hab das "Dim Pattern As Byte" vergessen.
Jetzt funktioniert alles einwandfrei. Vielen Dank für die Tatkräftige Unterstützung.
Hätte das so nie herausgefunden.

Finaler Code:

$regfile = "attiny13.dat"
$crystal = 1200000
$hwstack = 34 '### hwstack vergrößern. Wichtig bei Verwendung von Interrupts
$swstack = 10
$framesize = 10

Config Portb.1 = Output
Config Portb.2 = Output
Config Portb.3 = Output
Config Portb.4 = Output
Config Pinb.0 = Input


Dim Anzahlmodi As Byte
Dim Modus As Byte
Dim Anzahlphasen as Byte
Dim Phase As Byte
Dim Pattern As Byte

Modus = 1
Anzahlmodi = 3

'### Alle Variablen können als Byte deklariert werden (spart Speicher im kleinen Tiny13)

'### Der Timer0 wird für die Blink- bzw. Schaltfrequenz konfiguriert

Compare0a = 116 '99,84ms Interruptperiode bei 1,2MHz µC-Takt
Config Timer0 = Timer , Prescale = 1024 , Clear_timer = 1 'Timer0 im Clear Timer on Comparematch

On Compare0a Isr_blink

Enable Compare0a

Enable Interrupts 'ISR wird bei Compare Match A aufgerufen

'### In der Haupschleife steht nur die Tastenabfrage inclusive Tastenentprellung

Do 'Beginn Hauptschleife
Debounce Pinb.0 , 1 , Changemodus , Sub 'Führt Unterprogramm aus, wenn Pinb.0 auf 1 wechselt
Loop 'Ende Hauptschleife

'### Nach Tastendruck wird dieses Unterprogramm ausgeführt, daß den Lichteffekt weiterschaltet und
'### die nötigen Parameter für die Interruptserviceroutine setzt.

Changemodus: 'Unterprogramm setzt Werte für Lichteffekt nach Tastendruck
Disable Compare0a 'Vermeidet Inkonsistenzen in der ISR
If Modus < Anzahlmodi Then Incr Modus Else Modus = 1
Select Case Modus
Case 1 : Anzahlphasen = 0 'Muß Anzahl der Daten in den DATA-Zeilen entsprechen
Case 2 : Anzahlphasen = 5 'Wert von 0 = ein Eintrag, 5 = sechs Einträge bei DATA
Case 3 : Anzahlphasen = 1 '.
End Select
Phase = 0
Enable Compare0a
Return


'### In der Interruptserviceroutine wird alle 100ms das neue Schaltmuster für die LEDs gelesen und
'### die LEDs geschaltet.

Isr_blink: 'wird alle ca. 100ms aufgerufen und schaltet die LEDs
If Phase < Anzahlphasen Then Incr Phase Else Phase = 0 'setzt die nächste Effektphase
Select Case Modus 'entsprechend dem Modus wird das Bitmuster für LEDs geholt
Case 1 : Pattern = Lookup(phase , Lichteffekt1)
Case 2 : Pattern = Lookup(phase , Lichteffekt2)
Case 3 : Pattern = Lookup(phase , Lichteffekt3)
End Select
Portb.1 = Pattern.3 'LED wird geschaltet
Portb.2 = Pattern.2 'LED wird geschaltet
Portb.3 = Pattern.1 'LED wird geschaltet
Portb.4 = Pattern.0 'LED wird geschaltet
Return
End 'end program


'### Hier sind die Schaltmuster abgelegt.

Lichteffekt1:
Data &B0000

Lichteffekt2:
Data &B1010 , &B1001 , &B1010 , &B0101 , &B0110 , &B0101

Lichteffekt3:
Data &B1111 , &B0000


Hab mal meinen Verwendungszweck gefilmt...


https://www.dropbox.com/s/9huyg7qzqgnbfpz/20140929_094432.mp4?dl=0

So, die eine Baustelle ist fertig, jetzt kommt die Nächste...

https://www.roboternetz.de/community/threads/65691-Kann-ein-ATtiny-%28anstatt-Servo%29-Frequenzen-eines-Empf%C3%A4ngers-umwandeln-%28Strom-An-Aus%29