Hallo Jungs hab mal wieder eine kleine Frage ( Der nicht fragt bleibt
dumm..)
Wie bereits bekannt sein sollte bastele mit RGBs herum und dazu hätte
ich mal folgende Frage.
Ich erzeuge hardware PWM Signale mit Bascom die meine RGBs steuern,
soweit so gut.
Ich habe festgestellt wenn der AVR die Do Loop schleife wieder holt,
gibt es einen kleine "aussetzter bzw dunkel Phase"
Bsp:
Do
Rot erhöhen
Grün erhöhen
Blau erhöhen
Blau verringern
Grün verringern
Loop
Nun wenn der erster durchlauf beendet wird, geht Rot kurz aus. Frage
warum ?
Zweite Frage wäre wie kann ich es am besten machen, dass keine Dunkle
Momente enstehen ? Hoofe habe mich verständlich ausgedrückt.
Danke im Voraus
Hallo Bastler,
Poste mal den ganzen Code, denn an der Do-Loop Schleife allein, liegt es
nicht.
Evtl. Überlaufen des Compare Registers der roten LED o.ä.
Bastler schrieb:> Klaus aus der Kasse schrieb:>> Fehler in Zeile 42>> Danke für den eindeutigen Hinweis
Da hat er leider recht, ohne den ganzen Code kann man nicht sagen wo der
Controller Zeit verbummelt oder welche Variablen überlaufen ... die 42
bezieht sich auf "Per Anhalter durch die Galaxis" wo die Antwort auf das
Leben, das Universum und alles eben als 42 angegeben ist.
ist ironisch gemeint :)
Bastler schrieb:> Nun wenn der erster durchlauf beendet wird, geht Rot kurz aus. Frage> warum ?
µC bootet neu, weil Return ohne Gosub ausgeführt wird -> Stackunterlauf
Bastler schrieb:> Enable Timer1> Enable Timer2
Nimm das raus, Du hast keine ISRs definiert.
Nach meinem Verständnis habe den Code so erstellt:
( lasse mich gerne belehren und nehme gerne Beispiele an )
Nun wenn an Int0 Eingang eine Veränderung eintritt also der Schalter
wird umgelegt (Hi-Low) wird das Programm sofort unterbrochen und springt
zu "sub" und dort wird so lange Do-Loop ausgeführt bis der Schalter
wieder umgelegt wird. Also auf dem Steckbrett funzt auch soweit. Mit
dieser Variante habe ich erreicht, im Gegensatz zu if Then Gosub..daß
der Programmwechsel sofort erfolgt.
Wo fehlt jetzt der Gosub ?
aua ... Endlosschleife in ISR, LCD-Ausgabe in ISR ... Getadc in ISR ...
schöner Programmierstil ist das leider nicht ... das gehört alles in
eine Mainloop und die Tastenabfrage kannst DU dort auch locker per
debounce machen
Dein Programmkonzept ist recht "merkwürdig"... Du hast keine
Hauptschleife. Dein µC läuft direkt in die erste ISR rein, verschluckt
sich am Return und läuft Amok. Das Programmkonzept solltest du nochmal
überdenken. Ich würde das in etwa so machen (Pseudocode):
1
Timer1 konfigurieren
2
3
Timer1 an
4
Interrupts an
5
6
'Keine Tasteninterrupts definieren!!!
7
8
Do
9
If Taste1 gedrückt Then
10
Set ModusFlag
11
EndIf
12
If Taste2 gedrückt Then
13
Clear ModusFlag
14
EndIf
15
Loop
16
17
Timer1ISR:
18
'HIER DÜRFEN KEINE (LANGEN / ENDLOS-)SCHLEIFEN VORKOMMEN!!! SONST LÄUFT DEIN µC AMOK!!!
19
If ModusFlag = 1 Then
20
Mache einen(!) Schritt von Modus1
21
Else
22
Mache einen(!) Schritt von Modus2
23
EndIf
24
Return
Ganz wichtig: Jeder Code braucht eine Endlosschleife (Hauptschleife), in
die er direkt nach dem Start läuft und in der das Hauptprogramm steht!!!
Gruß
Jonathan
Meine aller erste Variante war auch so "etwa" das Problem was ich hatte,
wenn sehr langsam gefadet wurde, reagierte das programm nicht sofort auf
Mode wechsel..
Du hast eine mood: und eine return Anweisung, aber keinen Einsprung in
die Mood-Subroutine, was sie nämlich sein muss, da sonst der Return
nicht funktioniert. Return springt aus einer Subroutine raus, die zuvor
aufgerufen wurde, nur wohin soll er zurück springen wenn er garnicht
gesprungen ist??
Das führ unweigerlich dazu dass irgendwann ein Reset ausgeführt wird.
Wenn überhaupt, dann ist der mood-Teil Deine Mainloop, die dann einfach
mit do .... loop in sich geschlossen wird, nicht mit return.
Du kannst aber auch eine Mainloop voranstellen ,
die dann einfach
do
gosub mood
loop
ist.
wesentlich besser wirds dann noch wenn Du
do
if taster = irgendwas then gosub mood
if taster = nicht_irgendwas then gosub beleuchtung
loop
in der "beleuchtung dann einfach die endlosschleife raus und den
interrupt auf den müll und gut ist.
Dann hast Du da was missverstanden. ISR müssen so schnell wie möglich
abgearbeitet werden. Also bei jedem ISR-Aufruf nur einen Fading-Schritt
machen. Also etwa so:
was den direkten modewechsel angeht, da kannst du einfach in jeder der
loops in "mood" nen exit loop reinhängen, der per if taste=gedrückt
ausgelöst wird ... dann rasselt das programm einfach durch die loops
nahc unten durch bei gedrückter taste.
Do
If Taste1 gedrückt Then
Set ModusFlag
EndIf
If Taste2 gedrückt Then
Clear ModusFlag
EndIf
Loop
-------------------------------------------------
Möchte mit einem "umschalter" machen
würde so gehen : ?
do
If Mode=1 then
gosub Mod
end if
If Mode=0 then
gosub Fade
end if
loop
Mod
adc abfragen
Select Case
Return
Fade
Fading routine
Return
Ob es in der Fading routine sauber drinn bleibt bezweifele ich..hmmm
Nein, so wird das nichts. Wenn das Programm erstmal in einer Routine
drinn ist, reagiert es nicht mehr auf einen Tastendruck. Mach es mal so,
wie in meinen zwei Beispielcodes :)
Gruß
Jonathan
Habe folgendes,
so verstanden :
Wenn Der Taster O ist dann geht in den SUB Beleuchtung dort je nach Poti
leuchtet etwas..
Wenn der Taster ist 1 also auf High, wird festgestellt in der Isr dann
macht die Fading bis Fadingschritt 0 ist dann wird so lange wiederholt
bis Modus auf 1 ist sonst geht er raus bzw in den SUB Beleuchtung
Bastler schrieb:> Habe folgendes,>> so verstanden :
Dein Grundkonzept sieht jetzt gut aus.
Aber ehe du da jetzt weiter künstelst, bring das jetzt erst mal zum
Laufen und teste es!
Die beiden schlimmsten Fehler, die man speziell am Anfang machen kann
* zu viel Code auf einmal schreiben, der nicht getestet ist
* an einmal geschriebenem Code sklavisch festhalten und nur ja keine
Änderung zulassen
wird da nichts faden. Wenn du dich an den Overflow vom Timer 0 hängst,
dann musst du auch den Timer 0 aktivieren.
Und die Timereinstellungen für Timer 1 und Timer 2, die dann die PWM für
die LED machen, fehlen auch noch.
Fhutdhb Ufzjjuz schrieb:> die 42> bezieht sich auf "Per Anhalter durch die Galaxis" wo die Antwort auf das> Leben, das Universum und alles eben als 42 angegeben ist.
Im übrigen auch 7 bit binär: 0101010
Hatte noch beim Timer Config was übersehen :
trotzdem wird weder gefadet noch Farben verändert wenn Pind.1 high oder
low ist. Was habe ich übersehen oder falsch verstanden ?
'***********************************************************************
********
' Schalter an PD.! High = "Mood-Modus" Low = "Beleuchtungs-Modus"
' 10k-Poti an PC.0
' LED Rot an PB.1
' LED Grün an PB.2
' LED Blau an PB.3
'***********************************************************************
********
$regfile = "m8def.dat"
$crystal = 16000000
$hwstack = 100
$swstack = 100
$framesize = 100
'Taster Modus
Config Pind.1 = Input
Portd.1 = 1
Modus Alias Pind.1
Config Portb.1 = Output 'LED Rot
Config Portb.2 = Output 'LED Gruen
Config Portb.3 = Output 'LED Blau
Config Timer0 = Timer , Prescale = 64
On Timer0 Timer0_isr
Enable Interrupts
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Dim Pause As Word
Dim Speed As Word
Dim Adc0 As Word
Dim Fadingschritt As Byte
R Alias Compare1a
G Alias Compare1b
B Alias Ocr2
Do
If Modus = 0 Then
Gosub Beleuchtung
End If
'Hier kommt dann LCD Ausgabe rein
Loop
Timer0_isr:
'Das hier wird regelmäßig aufgerufen
If Modus = 1 Then
If FadingSchritt = 0 Then
Incr R
If R = 255 Then Incr FadingSchritt
ElseIf FadingSchritt = 1 Then
Incr G
If G = 255 Then Incr FadingSchritt
ElseIf FadingSchritt = 2 Then
Incr B
If B = 255 Then Incr FadingSchritt
ElseIf FadingSchritt = 3 Then
Decr R
If R = 0 Then Incr FadingSchritt
ElseIf FadingSchritt = 4 Then
Decr G
If G = 0 Then Incr FadingSchritt
ElseIf FadingSchritt = 5 Then
Decr B
If B = 0 Then FadingSchritt = 0
EndIf
Else
Gosub Beleuchtung
EndIf
Return
Beleuchtung:
Adc0 = Getadc(0)
Select Case Adc0
Case 1 To 50 'Rot 100
R = 255
G = 0
B = 0
Case 60 To 100 : 'Rot 100
Grün 50
R = 255
G = 125
B = 0
Case 110 To 200 : 'Rot 100
Grün 100
R = 255
G = 255
B = 0
Case 210 To 300 : 'Rot 100
Grün 100 Blau 125
R = 255
G = 255
B = 125
Case 310 To 400: 'Rot 100
Grün 100 Blau 100
R = 255
G = 255
B = 255
Case 510 To 600: 'Rot 50 Grün
100 Blau 100
R = 125
G = 255
B = 255
Case 610 To 700: 'Rot 0 Grün
100 Blau 100
R = 0
G = 255
B = 255
Case 710 To 800: 'Rot 0 Grün
50 Blau 100
R = 0
G = 125
B = 255
Case 810 To 950: 'Rot 0 Grün
0 Blau 100
R = 0
G = 0
B = 255
End Select
Return
solltest Du weglassen. Das wird doch schon im Timer erledigt! Außerdem
solltest Du den Timer und die Interrupts noch aktivieren ("Enable ***").
Und den Prescaler solltest Du höher wählen.
Gruß
Jonathan
Ups zwieschendurch habe Leute schon gepostet.
Naja ich muss in den Keller Laufen, wo die Werkstatt ist um etwas zum
testen.
Der Timer ist nun "denke ich" korrekt konfiguriert, den Vorteiler habe
ich grösser gemacht, damit schneller läuft, aber läuft momenten nichts.
'***********************************************************************
********
' Schalter an PD.! High = "Mood-Modus" Low = "Beleuchtungs-Modus"
' 10k-Poti an PC.0
' LED Rot an PB.1
' LED Grün an PB.2
' LED Blau an PB.3
'***********************************************************************
********
$regfile = "m8def.dat"
$crystal = 16000000
$hwstack = 100
$swstack = 100
$framesize = 100
'Taster Modus
Config Pind.1 = Input
Portd.1 = 1
Modus Alias Pind.1
Config Portb.1 = Output 'LED Rot
Config Portb.2 = Output 'LED Gruen
Config Portb.3 = Output 'LED Blau
Config Timer0 = Timer , Prescale = 64
On Timer0 Timer0_isr
Enable Interrupts
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Dim Pause As Word
Dim Speed As Word
Dim Adc0 As Word
Dim Fadingschritt As Byte
R Alias Compare1a
G Alias Compare1b
B Alias Ocr2
Do
''If Modus = 0 Then
'Gosub Beleuchtung
'End If
'Hier kommt dann LCD Ausgabe rein
Loop
Timer0_isr:
'Das hier wird regelmäßig aufgerufen
If Modus = 1 Then
If FadingSchritt = 0 Then
Incr R
If R = 255 Then Incr FadingSchritt
ElseIf FadingSchritt = 1 Then
Incr G
If G = 255 Then Incr FadingSchritt
ElseIf FadingSchritt = 2 Then
Incr B
If B = 255 Then Incr FadingSchritt
ElseIf FadingSchritt = 3 Then
Decr R
If R = 0 Then Incr FadingSchritt
ElseIf FadingSchritt = 4 Then
Decr G
If G = 0 Then Incr FadingSchritt
ElseIf FadingSchritt = 5 Then
Decr B
If B = 0 Then FadingSchritt = 0
EndIf
Else
Gosub Beleuchtung
EndIf
Return
Beleuchtung:
Adc0 = Getadc(0)
Select Case Adc0
Case 1 To 50 'Rot 100
R = 255
G = 0
B = 0
Case 60 To 100 : 'Rot 100
Grün 50
R = 255
G = 125
B = 0
Case 110 To 200 : 'Rot 100
Grün 100
R = 255
G = 255
B = 0
Case 210 To 300 : 'Rot 100
Grün 100 Blau 125
R = 255
G = 255
B = 125
Case 310 To 400: 'Rot 100
Grün 100 Blau 100
R = 255
G = 255
B = 255
Case 510 To 600: 'Rot 50 Grün
100 Blau 100
R = 125
G = 255
B = 255
Case 610 To 700: 'Rot 0 Grün
100 Blau 100
R = 0
G = 255
B = 255
Case 710 To 800: 'Rot 0 Grün
50 Blau 100
R = 0
G = 125
B = 255
Case 810 To 950: 'Rot 0 Grün
0 Blau 100
R = 0
G = 0
B = 255
End Select
Return
Bastler schrieb:> Der Timer ist nun "denke ich" korrekt konfiguriert, den Vorteiler habe> ich grösser gemacht, damit schneller läuft
du meinst langsamer.
Je höher der Teiler, desto langsamer
> , aber läuft momenten nichts.
Du hast ja auch die Timer noch nicht aktiviert, die die PWM erzeugen.
Bis jetzt hast du mit dem Timer0 nur die Zeitsteuerung, die sich um das
Weiterschalten der Steuerwerte für die PWM kümmert. Aber du hast noch
keine PWM.
Bin Ein Säckel....
PWM Timer...
aber tortzdem tut sich nicht viel
'***********************************************************************
********
' Schalter an PD.! High = "Mood-Modus" Low = "Beleuchtungs-Modus"
' 10k-Poti an PC.0
' LED Rot an PB.1
' LED Grün an PB.2
' LED Blau an PB.3
'***********************************************************************
********
$regfile = "m8def.dat"
$crystal = 16000000
$hwstack = 100
$swstack = 100
$framesize = 100
'Taster Modus
Config Pind.1 = Input
Portd.1 = 1
Modus Alias Pind.1
Config Portb.1 = Output 'LED Rot
Config Portb.2 = Output 'LED Gruen
Config Portb.3 = Output 'LED Blau
Config Timer0 = Timer , Prescale = 64
On Timer0 Timer0_isr
Enable Interrupts
Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Up , Compare B Pwm
= Clear Up , Prescale = 1
Config Timer2 = Pwm , Pwm = On , Compare Pwm = Clear Down , Prescale = 1
Enable Timer1
Enable Timer2
Start Timer1
Start Timer2
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Dim Pause As Word
Dim Speed As Word
Dim Adc0 As Word
Dim Fadingschritt As Byte
R Alias Compare1a
G Alias Compare1b
B Alias Ocr2
Do
''If Modus = 0 Then
'Gosub Beleuchtung
'End If
'Hier kommt dann LCD Ausgabe rein
Loop
Timer0_isr:
'Das hier wird regelmäßig aufgerufen
If Modus = 1 Then
If FadingSchritt = 0 Then
Incr R
If R = 255 Then Incr FadingSchritt
ElseIf FadingSchritt = 1 Then
Incr G
If G = 255 Then Incr FadingSchritt
ElseIf FadingSchritt = 2 Then
Incr B
If B = 255 Then Incr FadingSchritt
ElseIf FadingSchritt = 3 Then
Decr R
If R = 0 Then Incr FadingSchritt
ElseIf FadingSchritt = 4 Then
Decr G
If G = 0 Then Incr FadingSchritt
ElseIf FadingSchritt = 5 Then
Decr B
If B = 0 Then FadingSchritt = 0
EndIf
Else
Gosub Beleuchtung
EndIf
Return
Beleuchtung:
Adc0 = Getadc(0)
Select Case Adc0
Case 1 To 50 'Rot 100
R = 255
G = 0
B = 0
Case 60 To 100 : 'Rot 100
Grün 50
R = 255
G = 125
B = 0
Case 110 To 200 : 'Rot 100
Grün 100
R = 255
G = 255
B = 0
Case 210 To 300 : 'Rot 100
Grün 100 Blau 125
R = 255
G = 255
B = 125
Case 310 To 400: 'Rot 100
Grün 100 Blau 100
R = 255
G = 255
B = 255
Case 510 To 600: 'Rot 50 Grün
100 Blau 100
R = 125
G = 255
B = 255
Case 610 To 700: 'Rot 0 Grün
100 Blau 100
R = 0
G = 255
B = 255
Case 710 To 800: 'Rot 0 Grün
50 Blau 100
R = 0
G = 125
B = 255
Case 810 To 950: 'Rot 0 Grün
0 Blau 100
R = 0
G = 0
B = 255
End Select
Return
alles ist dunkel egal ob Pin 3 high oder Low ist ond egal ob ich am Poti
drehe..
ich habe kurz noch das "schlechte" Programm kurz reingeladen, das geht,
also muss noch im Code was faul sein..Schaltung ist OK.
PS: Möchte mich trotzdem für Eure Mühe und hilfsbereitsschaft bedanken !
Die Hilfe drückt sich da leider etwas unverständlich aus...
Das "Start TimerX" kannst du auch weglassen. Beim Enable werden die
Timer automatisch gestartet. Und da fehlt noch ein "Enable Timer0"...
Den Vorteiler von Timer0 solltest du auf 1024 stellen, sonst siehst du
vom Fading nicht viel...
Außerdem solltest du dir mal angewöhnen, Einrückungen zu benutzen. Das
macht den Code viel lesbarer.
Jonathan Strobl schrieb:> Den Vorteiler von Timer0 solltest du auf 1024 stellen, sonst siehst du> vom Fading nicht viel...
Hab ich auch gedacht, bis ich es nachgerechnet habe.
Bei seinen 16 Mhz sollte zb Rot den Farbverlauf in ca. 4 Sekunden von
dunkel nach Hell bei einem Vorteiler von 64 durchlaufen.
Jonathan Strobl schrieb:> Ich komme da nicht auf 4 Sekunden, sondern auf 1/4 Sekunde... Da kommen> Hertz raus :)>> 16000000Hz : 256 : 64 : 256 = ca. 4Hz
:-)
Mir fällt es wie Schuppen von den Haaren. Du hast recht. Weiß auch
nicht, wie ich von den 4 am Taschenrechner auf 4 Sekunden gekommen bin
und nicht auf 4 Hz.
Können wir uns auf 4Hz sind auf den LED als hektisches auf und Abblinken
bemerkbar einigen? :-)
Hmmm...Grübel....
Die einzige Veränderung, daß alle 3 Leds voll an sind. fedar fading noch
Mood Modus..
'***********************************************************************
********
' Schalter an PD.1 High = "Mood-Modus" Low = "Beleuchtungs-Modus"
' 10k-Poti an PC.0
' LED Rot an PB.1
' LED Grün an PB.2
' LED Blau an PB.3
'***********************************************************************
********
$regfile = "m8def.dat"
$crystal = 16000000
$hwstack = 100
$swstack = 100
$framesize = 100
'Taster Modus
Config Pind.1 = Input
Portd.1 = 1
Modus Alias Pind.1
Config Portb.1 = Output 'LED Rot
Config Portb.2 = Output 'LED Gruen
Config Portb.3 = Output 'LED Blau
Config Timer0 = Timer , Prescale = 64
On Timer0 Timer0_isr
Enable Interrupts
Config Timer1 = Pwm , Pwm = 8 , Compare A = Clear , Compare B = Clear ,
Prescale = 1
Config Timer2 = Pwm, Compare = Clear, Prescale = 256
Enable Timer1
Enable Timer2
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Dim Pause As Word
Dim Speed As Word
Dim Adc0 As Word
Dim Fadingschritt As Byte
R Alias Compare1a
G Alias Compare1b
B Alias Ocr2
Do
''If Modus = 0 Then
'Gosub Beleuchtung
'End If
'Hier kommt dann LCD Ausgabe rein
Loop
Timer0_isr:
'Das hier wird regelmäßig aufgerufen
If Modus = 1 Then
If FadingSchritt = 0 Then
Incr R
If R = 255 Then Incr FadingSchritt
ElseIf FadingSchritt = 1 Then
Incr G
If G = 255 Then Incr FadingSchritt
ElseIf FadingSchritt = 2 Then
Incr B
If B = 255 Then Incr FadingSchritt
ElseIf FadingSchritt = 3 Then
Decr R
If R = 0 Then Incr FadingSchritt
ElseIf FadingSchritt = 4 Then
Decr G
If G = 0 Then Incr FadingSchritt
ElseIf FadingSchritt = 5 Then
Decr B
If B = 0 Then FadingSchritt = 0
EndIf
Else
Gosub Beleuchtung
EndIf
Return
Beleuchtung:
Adc0 = Getadc(0)
Select Case Adc0
Case 1 To 50 'Rot 100
R = 255
G = 0
B = 0
Case 60 To 100 : 'Rot 100
Grün 50
R = 255
G = 125
B = 0
Case 110 To 200 : 'Rot 100
Grün 100
R = 255
G = 255
B = 0
Case 210 To 300 : 'Rot 100
Grün 100 Blau 125
R = 255
G = 255
B = 125
Case 310 To 400: 'Rot 100
Grün 100 Blau 100
R = 255
G = 255
B = 255
Case 510 To 600: 'Rot 50 Grün
100 Blau 100
R = 125
G = 255
B = 255
Case 610 To 700: 'Rot 0 Grün
100 Blau 100
R = 0
G = 255
B = 255
Case 710 To 800: 'Rot 0 Grün
50 Blau 100
R = 0
G = 125
B = 255
Case 810 To 950: 'Rot 0 Grün
0 Blau 100
R = 0
G = 0
B = 255
End Select
Return
Und nur um das klarzustellen
Du brauchst beides. Du musst den Timer0 enabeln UND du musst
selbstverständlich auch die Interrupts freigeben.
Enable Interrupts hat so gesehen an und für sich nichts mit dem Timer an
sich zu tun. Es gibt global die Bearbeitung von Interrups frei. Wo die
herkommen ist egal. Das kann der Timer 0 sein, das kann aber auch die
UART sein oder ....
Die übliche Vorgehensweise ist es, erst mal die ganze Hardware zu
initialisieren und einzustellen und dann, wenn das alles erledigt ist,
kommt vor die zentrale Do-Loop das Enable Interrupts
Ihr seid einfach KLASSE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
und wie man sagt, ständig unterbezahlt !!!!
jetzt gehts. Ich werde mich um die Finetuning kümmern.
Do Loop ausbauen...
Die Geschwindigkeiten kann ich dann mit Poti regeln, in dem ich
Temp=adc0/4
waitms=Temp
mache...............
Bastler schrieb:> Die Geschwindigkeiten kann ich dann mit Poti regeln, in dem ich>> Temp=adc0/4>> waitms=Temp
Nein, das wird nichts. Dein Timer läuft dann doch immernoch so schnell.
Ab einer bestimmten Wartezeit läuft dann aber dein Controller Amok, da
er den Interrupts nicht mehr hinterherkommt. Du hast zwei Möglichkeiten,
eine Frequenzeinstellung zu machen: Entweder du veränderst den
(Software-)Vorteiler (einfach), oder du benutzt den CTC-Modus (schwer).
Mach das besser so:
'Nur alle <Geschwindigkeit> Timerinterrupts deine Fading-Routine ausführen
8
Incr Swprescaler
9
If Swprescaler = Geschwindigkeit
10
Swprescaler = 0
11
12
... 'Dein Fading-Algorithmus
13
EndIf
14
Return
Je größer "Geschwindigkeit", desto größer der Vorteiler. Bei einem
ADC-Wert von 1023 gibt das dann eine Fading-Frequenz von:
16000000Hz : 256 [Maximaler Timer-Wert] : 1 [Vorteiler] : (1023 * 16
[Software-Vorteiler]) : 256 [Fading-Stufen] = 0,015Hz
Gruß
Jonathan
Jonathan muss ich langsam ein Bier ausgeben !!
Werde deine Variante auch einbauen, bzw genauer anschauen.
Bin gerade in der Do - Loop
mit der LCD noch beschöftigt ( Balkenanzeige )
Was du auf jeden Fall aus dem Thread mitnehmen solltest:
Es gibt ein paar Ausnahmen, aber meistens ist waitms das falsche
Werkzeug. Du möchtest waitms meiden wie der Teufel das Weihwasser, weil
es dich so gut wie immer auf die falsche Fährte führt. waitms ist das
Äquivalent zu: Du bleibst neben der Waschmaschine stehen und wartest bis
sie fertig ist, anstatt dass du in der Zwischenzeit den Rest deiner
Hausarbeit machst und ab und zu nachsiehst ob die Maschine fertig ist.
Das "Ab und zu, allerdings regelmässig" erledigst du mit einem Timer und
einer Timer-Interrupt-Funktion, die eben vom Timer "ab und zu und
regelmässig" aufgerufen wird. Dazu brauchst du nur deine Arbeitsweise
umstrukturieren zu: "Jetzt ist ein bischen Zeit vergangen, was genau
gibt es jetzt, genau zu diesem Zeitpunkt zu tun". Deine jetzige
Fading-Funktion zeigt sehr schön, wie sowas ausshen kann.
Ja sieht schon besser aus , einiges habe auf jedenfall zugelernt !!!
Aber...dies verstehe ich nicht ganz :
Dim Anzeige As String * 16
Dim Geschwindigkeit As Byte
Dim Adc0 As Word
Dim Fadingschritt As Byte
Dim W As Word , Perc As Word , Channel As Byte , I As Byte , Cols As
Byte
Dim Swprescaler As Byte
----------------------
Timer0_isr:
Geschwindigkeit = Getadc(0)
Shift Geschwindigkeit, Left, 4 'Mit 16 multiplizieren
'Nur alle <Geschwindigkeit> Timerinterrupts deine Fading-Routine
ausführen
Incr Swprescaler
If Swprescaler = Geschwindigkeit
Swprescaler = 0
kriege Compiler fehler
Assigment error [Wprescaler:0 Geschwindigkeit:2]
Hmm..irgendwo ist noch ein Gedankenfehler...
Egal wie ich am Poti drehe, pulst in einer Geschwindigkeit
Config Timer0 = Timer , Prescale = 1
On Timer0 Timer0_isr
Enable Timer0
Enable Interrupts
Timer0_isr:
Geschwindigkeit = Getadc(0)
Shift Geschwindigkeit, Left, 4 'Mit 16 multiplizieren
'Nur alle <Geschwindigkeit> Timerinterrupts deine Fading-Routine
ausführen
Incr Swprescaler
If Swprescaler = Geschwindigkeit Then
Swprescaler = 0
End If
If Modus = 1 Then
Anzeige = "Fader Modus"
If Fadingschritt = 0 Then
Incr R
If R = 255 Then Incr Fadingschritt
Elseif Fadingschritt = 1 Then
Incr G
If G = 255 Then Incr Fadingschritt
Eine Frage an Johnathan (der offensichtlich in BASCOM gut drauf ist).
Ist der BASCOM Compiler wirklich so schwach, dass man das hier
Shift Geschwindigkeit, Left, 4 'Mit 16 multiplizieren
dem doch einprägsameren und leichter verständlichen
Geschwindigkeit = 16 * Geschwindigkeit
vorziehen sollte?
Du hast den Sinn dahinter
Incr Swprescaler
If Swprescaler = Geschwindigkeit Then
Swprescaler = 0
noch nicht verstanden.
Der Sinn besteht darin, dass man nur dann, wenn Swprescaler auf 0
zurückgesetzt wird, die Arbeit in der ISR macht.
Anders ausgedrückt:
Der Sekundenzeiger deiner Uhr tickt jede Sekunde einmal. Jetzt kannst du
natürlich bei jedem Tick 1 weiterzählen und bei 5 deine Zählung wieder
auf 0 zurücksetzen. Aber ein echtes "mach nur alle 5 Sekunden, also 12
mal in der Minute" wird daraus nur dann, wenn du das was du zu tun hast
auch an diese 5 Sekunden Zählung koppelst. Wenn du weiterhin jede
Sekunde deine Arbeit machst, dann wird das deswegen nicht langsamer bzw.
weniger oft in der Minute ausgeführt.
Also nicht
Incr Swprescaler
If Swprescaler = Geschwindigkeit Then
Swprescaler = 0
End If
... mache die Arbeit
sondern
Incr Swprescaler
If Swprescaler = Geschwindigkeit Then
Swprescaler = 0
... mache die Arbeit
End If
beachte, wo genau das "mache die Arbeit" steht und überlege, wie sich da
jetzt das Hochzählen von Swprescaler auf die Aufrufhäufigkeit von "mache
die Arbeit" auswirkt.
Du solltest die Zeile "Shift Geschwindigkeit, left, 4" wieder rausnehmen
und den Vorteiler von Timer0 auf 64 stellen, ich hatte nämlich nicht
bedacht, dass sich der Controller bei ganz hoher Geschwindigkeit
aufhängen würde... Und wie Karl Heinz Buchegger schon geschrieben hat,
musst du die Fading-Routine in das If-Konstrukt packen.
Gruß
Jonathan
Stehe echt auf dem Schlauch...Laute Bäume....
Wenn ich am Poti drehe ist nur ein wildes geblinke..
'***********************************************************************
********
' Schalter an PD.1 High = "Mood-Modus" Low = "Beleuchtungs-Modus"
' 10k-Poti an PC.0
' LED Rot an PB.1
' LED Grün an PB.2
' LED Blau an PB.3
'***********************************************************************
********
$regfile = "m8def.dat"
$crystal = 16000000
$hwstack = 100
$swstack = 100
$framesize = 100
'Taster Modus
Config Pind.1 = Input
Portd.1 = 1
Modus Alias Pind.1
Config Portb.1 = Output 'LED Rot
Config Portb.2 = Output 'LED Gruen
Config Portb.3 = Output 'LED Blau
Config Timer0 = Timer , Prescale = 1
On Timer0 Timer0_isr
Enable Timer0
Enable Interrupts
Config Timer1 = Pwm , Pwm = 8 , Compare A = Clear , Compare B = Clear ,
Prescale = 1
Config Timer2 = Pwm , Compare = Clear , Prescale = 256
Enable Timer1
Enable Timer2
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Dim Anzeige As String * 16
Dim Geschwindigkeit As Word
Dim Adc0 As Word
Dim Fadingschritt As Byte
Dim Swprescaler As Byte
R Alias Compare1a
G Alias Compare1b
B Alias Ocr2
Config Lcdpin = Pin , Db7 = Portb.0 , Db6 = Portd.7 , Db5 = Portd.6 , _
Db4 = Portd.5 , E = Portc.4 , Rs = Portc.5
Config Lcd = 16 * 2
Cls
Cursor Off
Do
'LCD Ausgabe
Loop
Timer0_isr:
Geschwindigkeit = Getadc(0)
Shift Geschwindigkeit, Left, 4 'Mit 16 multiplizieren
'Nur alle <Geschwindigkeit> Timerinterrupts deine Fading-Routine
ausführen
Incr Swprescaler
If Swprescaler = Geschwindigkeit Then
Swprescaler = 0
If Modus = 1 Then
If Fadingschritt = 0 Then
Incr R
If R = 255 Then Incr Fadingschritt
Elseif Fadingschritt = 1 Then
Incr G
If G = 255 Then Incr Fadingschritt
Elseif Fadingschritt = 2 Then
Incr B
If B = 255 Then Incr Fadingschritt
Elseif Fadingschritt = 3 Then
Decr R
If R = 0 Then Incr Fadingschritt
Elseif Fadingschritt = 4 Then
Decr G
If G = 0 Then Incr Fadingschritt
Elseif Fadingschritt = 5 Then
Decr B
If B = 0 Then Fadingschritt = 0
End If
End If
Else
Gosub Beleuchtung
End If
Return
Beleuchtung:
Adc0 = Getadc(0)
Select Case Adc0
Case 1 To 50 'Rot 100
R = 255
G = 0
B = 0
Case 60 To 100 : 'Rot 100
Grün 50
R = 255
G = 125
B = 0
Case 110 To 200 : 'Rot 100
Grün 100
R = 255
G = 255
B = 0
Case 210 To 300 : 'Rot 100
Grün 100 Blau 125
R = 255
G = 255
B = 125
Case 310 To 400: 'Rot 100
Grün 100 Blau 100
R = 255
G = 255
B = 255
Case 510 To 600: 'Rot 50 Grün
100 Blau 100
R = 125
G = 255
B = 255
Case 610 To 700: 'Rot 0 Grün
100 Blau 100
R = 0
G = 255
B = 255
Case 710 To 800: 'Rot 0 Grün
50 Blau 100
R = 0
G = 125
B = 255
Case 810 To 950: 'Rot 0 Grün
0 Blau 100
R = 0
G = 0
B = 255
End Select
Return
Karl Heinz Buchegger schrieb:
>Eine Frage an Johnathan (der offensichtlich in BASCOM gut drauf ist).>>Ist der BASCOM Compiler wirklich so schwach, dass man das hier>> Shift Geschwindigkeit, Left, 4 'Mit 16 multiplizieren>>dem doch einprägsameren und leichter verständlichen>> Geschwindigkeit = 16 * Geschwindigkeit>>>vorziehen sollte?
Ja, tatsächlich... Ich hatte es eben nochmal getestet...
Gruß
Jonathan
Hmmm..Scheibenkleister...Es wird schlimmer wie vorher..Wenn ich am Poti
drehen hat mit Fading nichts mehr zu tun..Wirres geblinke..
'***********************************************************************
********
' Schalter an PD.1 High = "Mood-Modus" Low = "Beleuchtungs-Modus"
' 10k-Poti an PC.0
' LED Rot an PB.1
' LED Grün an PB.2
' LED Blau an PB.3
'***********************************************************************
********
$regfile = "m8def.dat"
$crystal = 16000000
$hwstack = 100
$swstack = 100
$framesize = 100
'Taster Modus
Config Pind.1 = Input
Portd.1 = 1
Modus Alias Pind.1
Config Portb.1 = Output 'LED Rot
Config Portb.2 = Output 'LED Gruen
Config Portb.3 = Output 'LED Blau
Config Timer0 = Timer , Prescale = 64
On Timer0 Timer0_isr
Enable Timer0
Enable Interrupts
Config Timer1 = Pwm , Pwm = 8 , Compare A = Clear , Compare B = Clear ,
Prescale = 1
Config Timer2 = Pwm , Compare = Clear , Prescale = 256
Enable Timer1
Enable Timer2
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Dim Anzeige As String * 16
Dim Geschwindigkeit As Word
Dim Adc0 As Word
Dim Fadingschritt As Byte
Dim Swprescaler As Byte
R Alias Compare1a
G Alias Compare1b
B Alias Ocr2
Config Lcdpin = Pin , Db7 = Portb.0 , Db6 = Portd.7 , Db5 = Portd.6 , _
Db4 = Portd.5 , E = Portc.4 , Rs = Portc.5
Config Lcd = 16 * 2
Cls
Cursor Off
Do
'LCD Ausgabe
Loop
Timer0_isr:
Geschwindigkeit = Getadc(0)
Incr Swprescaler
If Swprescaler = Geschwindigkeit Then
Swprescaler = 0
If Modus = 1 Then
If Fadingschritt = 0 Then
Incr R
If R = 255 Then Incr Fadingschritt
Elseif Fadingschritt = 1 Then
Incr G
If G = 255 Then Incr Fadingschritt
Elseif Fadingschritt = 2 Then
Incr B
If B = 255 Then Incr Fadingschritt
Elseif Fadingschritt = 3 Then
Decr R
If R = 0 Then Incr Fadingschritt
Elseif Fadingschritt = 4 Then
Decr G
If G = 0 Then Incr Fadingschritt
Elseif Fadingschritt = 5 Then
Decr B
If B = 0 Then Fadingschritt = 0
End If
End If
Else
Gosub Beleuchtung
End If
Return
Beleuchtung:
Adc0 = Getadc(0)
Select Case Adc0
Case 1 To 50 'Rot 100
R = 255
G = 0
B = 0
Case 60 To 100 : 'Rot 100
Grün 50
R = 255
G = 125
B = 0
Case 110 To 200 : 'Rot 100
Grün 100
R = 255
G = 255
B = 0
Case 210 To 300 : 'Rot 100
Grün 100 Blau 125
R = 255
G = 255
B = 125
Case 310 To 400: 'Rot 100
Grün 100 Blau 100
R = 255
G = 255
B = 255
Case 510 To 600: 'Rot 50 Grün
100 Blau 100
R = 125
G = 255
B = 255
Case 610 To 700: 'Rot 0 Grün
100 Blau 100
R = 0
G = 255
B = 255
Case 710 To 800: 'Rot 0 Grün
50 Blau 100
R = 0
G = 125
B = 255
Case 810 To 950: 'Rot 0 Grün
0 Blau 100
R = 0
G = 0
B = 255
End Select
Return
Jonathan Strobl schrieb:> Du solltest die Zeile "Shift Geschwindigkeit, left, 4" wieder rausnehmen> und den Vorteiler von Timer0 auf 64 stellen, ich hatte nämlich nicht> bedacht, dass sich der Controller bei ganz hoher Geschwindigkeit> aufhängen würde...
Ich würde das Auslesen das ADC überhaupt in die Hauptschleife verlagern.
Es gibt keinen Grund warum das in der ISR sein muss.
>Ich würde das Auslesen das ADC überhaupt in die Hauptschleife verlagern.>Es gibt keinen Grund warum das in der ISR sein muss.
Stimmt. Oder den ADC im Freerunning-Modus betreiben.
Gruß
Jonathan
Bastler schrieb:> Hmmm..Scheibenkleister...Es wird schlimmer wie vorher..Wenn ich am
An diese Stelle zeigt sich die Wichtigkeit von richtigem Einrücken.
Schau dir deinen Code nochmal genau an und überlege welches End if bzw.
noch wichtiger welches else zu welchem if gehört!
Sauberes Code Einrücken ist kein Selbstzweck sondern hilft
Schachtelungs-Fehler zu vermeiden. Also tu es! Jetzt!
Sory Das Ergebnis wie gerade beschrieben, bloss Copy Paste war falsch.
'***********************************************************************
********
' Schalter an PD.1 High = "Mood-Modus" Low = "Beleuchtungs-Modus"
' 10k-Poti an PC.0
' LED Rot an PB.1
' LED Grün an PB.2
' LED Blau an PB.3
'***********************************************************************
********
$regfile = "m8def.dat"
$crystal = 16000000
$hwstack = 100
$swstack = 100
$framesize = 100
'Taster Modus
Config Pind.1 = Input
Portd.1 = 1
Modus Alias Pind.1
Config Portb.1 = Output 'LED Rot
Config Portb.2 = Output 'LED Gruen
Config Portb.3 = Output 'LED Blau
Config Timer0 = Timer , Prescale = 64
On Timer0 Timer0_isr
Enable Timer0
Enable Interrupts
Config Timer1 = Pwm , Pwm = 8 , Compare A = Clear , Compare B = Clear ,
Prescale = 1
Config Timer2 = Pwm , Compare = Clear , Prescale = 256
Enable Timer1
Enable Timer2
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Dim Anzeige As String * 16
Dim Geschwindigkeit As Word
Dim Adc0 As Word
Dim Fadingschritt As Byte
Dim Swprescaler As Byte
R Alias Compare1a
G Alias Compare1b
B Alias Ocr2
Config Lcdpin = Pin , Db7 = Portb.0 , Db6 = Portd.7 , Db5 = Portd.6 , _
Db4 = Portd.5 , E = Portc.4 , Rs = Portc.5
Config Lcd = 16 * 2
Cls
Cursor Off
Do
'LCD Ausgabe
Loop
Timer0_isr:
Geschwindigkeit = Getadc(0)
Incr Swprescaler
If Swprescaler = Geschwindigkeit Then
Swprescaler = 0
If Modus = 1 Then
If Fadingschritt = 0 Then
Incr R
If R = 255 Then Incr Fadingschritt
Elseif Fadingschritt = 1 Then
Incr G
If G = 255 Then Incr Fadingschritt
Elseif Fadingschritt = 2 Then
Incr B
If B = 255 Then Incr Fadingschritt
Elseif Fadingschritt = 3 Then
Decr R
If R = 0 Then Incr Fadingschritt
Elseif Fadingschritt = 4 Then
Decr G
If G = 0 Then Incr Fadingschritt
Elseif Fadingschritt = 5 Then
Decr B
If B = 0 Then Fadingschritt = 0
End If
End If
Else
Gosub Beleuchtung
End If
Return
Beleuchtung:
Adc0 = Getadc(0)
Select Case Adc0
Case 1 To 50 'Rot 100
R = 255
G = 0
B = 0
Case 60 To 100 : 'Rot 100
Grün 50
R = 255
G = 125
B = 0
Case 110 To 200 : 'Rot 100
Grün 100
R = 255
G = 255
B = 0
Case 210 To 300 : 'Rot 100
Grün 100 Blau 125
R = 255
G = 255
B = 125
Case 310 To 400: 'Rot 100
Grün 100 Blau 100
R = 255
G = 255
B = 255
Case 510 To 600: 'Rot 50 Grün
100 Blau 100
R = 125
G = 255
B = 255
Case 610 To 700: 'Rot 0 Grün
100 Blau 100
R = 0
G = 255
B = 255
Case 710 To 800: 'Rot 0 Grün
50 Blau 100
R = 0
G = 125
B = 255
Case 810 To 950: 'Rot 0 Grün
0 Blau 100
R = 0
G = 0
B = 255
End Select
Return
Ich wiederhole mich, weil es möglicherweise untergeht:
Sauberes Code Einrücken ist kein Selbstzweck sondern hilft
Schachtelungs-Fehler zu vermeiden. Also tu es! Jetzt!
Und ich unterstreiche das ... 2 mal und in Rot!
Es sind immer diejenigen, die keine konsequente Einrückstruktur haben,
die über ihre eigenen Füsse stolpern und Code produzieren, der wegen
lächerlicher Schachtelungsfehler nicht funktioniert. Jede Codezeile am
linken Rand anfangen zu lassen hat nun mal nichts mit vernünftiger
Codeformatierung zu tun.
Ups....
Timer0_isr:
Geschwindigkeit = Getadc(0)
Incr Swprescaler
If Swprescaler = Geschwindigkeit Then
Swprescaler = 0
If Modus = 1 Then
If Fadingschritt = 0 Then
Incr R
If R = 255 Then Incr Fadingschritt
Elseif Fadingschritt = 1 Then
Incr G
If G = 255 Then Incr Fadingschritt
Elseif Fadingschritt = 2 Then
Incr B
If B = 255 Then Incr Fadingschritt
Elseif Fadingschritt = 3 Then
Decr R
If R = 0 Then Incr Fadingschritt
Elseif Fadingschritt = 4 Then
Decr G
If G = 0 Then Incr Fadingschritt
Elseif Fadingschritt = 5 Then
Decr B
If B = 0 Then Fadingschritt = 0
End If
End If
Else
Gosub Beleuchtung
End If
Return
Bitte nicht schlagen !!!!
Karl Heinz Buchegger schrieb:> Ich wiederhole mich, weil es möglicherweise untergeht:>> Sauberes Code Einrücken ist kein Selbstzweck sondern hilft> Schachtelungs-Fehler zu vermeiden. Also tu es! Jetzt!>> Und ich unterstreiche das ... 2 mal und in Rot!
Und ich markiere es nochmal mit grünem Neon-Marker! Einrücken ist
wirklich wichtig! Sonst wäre ich im 2500-Zeilen-Quälcode meiner
Spielekonsole (mit nem Mega1284P @ 20MHz und Bytecode-Interpreter xD)
längst untergegangen!
Wenn du das dann eingerückt hast, wirst du deinen Fehler wahrscheinlich
sofort finden...
Gruß
Jonathan
Bastler schrieb:> Bitte nicht schlagen !!!!
Ähm... Ok, ich halte mich mal zurück xD
Also... Grundkurs: Wie rückt man ein?
Einrückungen sind äußerst wichtig, damit man bereits beim ersten Blick
erkennen kann, welcher Befehl welchem untergeordnet ist. Die
übergeordneten Befehle, die unabhängig sind, schreibt man weiter links,
als die untergeordneten Befehle.
Beispiel:
1
If V1 = 1 Then
2
TuWas
3
EndIf
Beispiel 2:
1
If V1 = 1 Then
2
TuWas
3
ElseIf V1 = 2 Then
4
TuWasAnderes
5
Else
6
TuIrgendwasAlternatives
7
EndIf
If...EndIf, If...Else...EndIf und If...ElseIf...Else...EndIf sind die
übergeordneten Konstrukte, da von ihnen die Ausführung der
eingeschlossenen Befehle abhängt. Deshalb stehen sie weiter links.
Ebenso sind "Do...Loop", "Select...Case...EndSelect" und Routinen mit
abschließendem Return übergeodnete Konstrukte.
Beispiel:
1
Do
2
TuWasImmerWieder
3
Loop
Wann immer ein Befehl von einem anderen Befehlskonstrukt abhängig ist,
wird er eingerückt.
Gruß
Jonathan
Es ist keine Bestechung oder sonstwas was ich sagen möchte, aber
Jonathna hat echt viel Geduld als Dankeschön, wenn das Proggi so funzt
wie ich mir vorgestellt habe möchte ich Dir 6 Blaue 7 Segmentanzeigen
schneken, falls brauchst ist kein Witz !!!
PS: habe schon versucht so einzurücken wie ich gedacht habe, siehe
oben,,aber hilft nicht wirklich weiter...Mehr praxis ...mehr praxis..
Ach, keine Ursache :). Ich helfe dir doch gerne!
Les' dir aber mal meinen "Grundkurs: Einrücken" durch und mach' die
Einrückungen dann nochmal wie beschrieben.
Gruß
Jonathan
(Hmmm, 7-Segment-Anzeigen könnte ich durchaus gebrauchen... Ich überleg'
mal :) )
So :
Timer0_isr:
Geschwindigkeit = Getadc(0)
Incr Swprescaler
If Swprescaler = Geschwindigkeit Then
Swprescaler = 0
If Modus = 1 Then
If Fadingschritt = 0 Then
Incr R
If R = 255 Then Incr Fadingschritt
Elseif Fadingschritt = 1 Then
Incr G
If G = 255 Then Incr Fadingschritt
Elseif Fadingschritt = 2 Then
Incr B
If B = 255 Then Incr Fadingschritt
Elseif Fadingschritt = 3 Then
Decr R
If R = 0 Then Incr Fadingschritt
Elseif Fadingschritt = 4 Then
Decr G
If G = 0 Then Incr Fadingschritt
Elseif Fadingschritt = 5 Then
Decr B
If B = 0 Then Fadingschritt = 0
End If
End If
Else
Gosub Beleuchtung
End If
Return
Besser ?
PS: Ich wollte mit der Anzeige nur sagen, daß ich Deine Mühe unheimlich
schätze und ich war/bin nie geizig gewesen !
Nixie ? VDF Röhren ?
Möchte aber vom Kernproblem jetzt nicht wegommen !!
Bastler schrieb:> PS: Ich wollte mit der Anzeige nur sagen, daß ich Deine Mühe unheimlich> schätze und ich war/bin nie geizig gewesen !
Wie gesagt, keine Ursache. Die 7-Segment-Displays brauchst du mir aber
nicht zu schicken :)
Gruß
Jonathan
Das kann schon mal so nicht stimmen. Gehen wirs durch
Timer0_isr:
Geschwindigkeit = Getadc(0)
Incr Swprescaler
If Swprescaler = Geschwindigkeit Then
Wieso steht das Incr in der Zeile darüber am linken Rand und das if
nicht? Dazwischen war nichts, was eine Einrückung vom if verursachen
würde. Das if steht auf derselben logischen Ebene wie das incr
Nach diesem then hast du die davon abhängige Anweisung in die nächste
Zeile geschrieben. Gut so!
Swprescaler = 0
hier ist sie
If Modus = 1 Then
Huch. Wieso steht dieses if schon wieder am linken Rand? Das
vorhergehende if wurde noch nicht mit einem end if abgeschlossen, also
hänbgt diese Anweisung von diesem if ab und wird natürlich genauso
eingerückt, wie alle Anweisungen die von diesem vorherge4henden if
abhängen.
Die Idee hinter der Einrückung ist es, dass ALLE Anweisungen, die von zb
einem IF abhängen auf derselben Einrückungsstufe stehen.ö
If Fadingschritt = 0 Then
Incr R
If R = 255 Then Incr Fadingschritt
bei allen vorhergehenden if war es so, dass die vom if abhängige
Anweisung (also die im then Zweig) auf einer neuen Zeile eingterückt
war. Hier ist es nicht so! Warum? Mach die Dinge immer gleich!
Nächster Versuch :
Geschwindigkeit = Getadc(0)
Incr Swprescaler
If Swprescaler = Geschwindigkeit Then
Swprescaler = 0
If Modus = 1 Then
If Fadingschritt = 0 Then
Incr R
If R = 255 Then
Incr Fadingschritt
Elseif Fadingschritt = 1 Then
Incr G
If G = 255 Then
Incr Fadingschritt
Elseif Fadingschritt = 2 Then
Incr B
If B = 255 Then
Incr Fadingschritt
Elseif Fadingschritt = 3 Then
Decr R
If R = 0 Then
Incr Fadingschritt
Elseif Fadingschritt = 4 Then
Decr G
If G = 0 Then
Incr Fadingschritt
Elseif Fadingschritt = 5 Then
Decr B
If B = 0 Then Fadingschritt = 0
End If
End If
Else
Gosub Beleuchtung
End If
Return
kurz essen, dann gehts weiter ..smile !!
Jonathan Strobl schrieb:> Die 7-Segment-Displays brauchst du mir aber> nicht zu schicken :)
Warum nicht ?
Ich tu es gerne !! Du hilfst mir, dafür mächte mich auf dieser Weise
mich auch bedanken !!
Ach nein, die brauchst du mir nicht zu schicken... Ich helfe dir doch
gerne :)
So, und jetzt zurück zum Thema. Dein jetziger Versuch ist schon besser,
aber immernoch nicht so gut. Übung macht den Meister :)
Hier noch ein kleines Beispiel:
1
Incr V1 'Logische Ebene 0
2
If V1 = 16 Then 'Hier beginnt die logische Ebene 1
3
4
If V2 = 10 Then 'Hier beginnt die logische Ebene 2
5
TuWas
6
V2 = 0
7
Else 'Dies hier ist nicht untergeordnet, da es zum If-Konstrukt gehört!
8
TuWasAnderes
9
EndIf 'Hier ist die logische Ebene 2 zu Ende!
10
11
TuNochwas
12
V1 = 0
13
14
Else 'Dies hier ist nicht untergeordnet (If-Konstrukt)!
15
16
TuNochwasAnderes
17
18
EndIf 'Hier ist die logische Ebene 1 zu Ende!
19
20
Lcd V1
Ich hoffe, jetzt ist es verständlicher :)
Gruß
Jonathan
hm....
[_code]
Timer0_isr:
Geschwindigkeit = Getadc(0)
Incr Swprescaler 'Ebene 1
If Swprescaler = Geschwindigkeit Then
Swprescaler = 0
If Modus = 1 Then
If Fadingschritt = 0 Then 'Ebene 2
Incr R
If R = 255 Then
Incr Fadingschritt
Elseif Fadingschritt = 1 Then
Incr G
If G = 255 Then
Incr Fadingschritt
Elseif Fadingschritt = 2 Then
Incr B
If B = 255 Then
Incr Fadingschritt
Elseif Fadingschritt = 3 Then
Decr R
If R = 0 Then
Incr Fadingschritt
Elseif Fadingschritt = 4 Then
Decr G
If G = 0 Then
Incr Fadingschritt
Elseif Fadingschritt = 5 Then
Decr B
If B = 0 Then Fadingschritt = 0
End If 'Ende Ebene
2
End If
Else
Gosub Beleuchtung
End If
Return
[_/code]
heißen (und bei den anderen auch). Sonst funktioniert es nicht richtig.
Schau dir mein Beispiel noch mal genau an.
Gruß
Jonathan
P.S.: Codetags schreibt man ohne das "_", das habe ich nur dazugemacht,
damit das nicht als Codetag interpretiert wird.
Der einziger Unterschied ist :
Wenn der Schalter High ist dann läuchten alle lege ich auf LOW geht Rot
aus
wenn ich am Poti drehe ändert sich nicht..Nicht so prickelnd..((
Bei dem ersten "Case" im "Select-Käse-EndSelect" fehlt noch ein
Doppelpunkt... Das "Config LCDPin, ..." solltest du in einer Zeile
schreiben...
grübelnicht-weiß-was-da-los-ist
Gruß
Jonathan
Sift habe ich raus..
Also Schalter auf Low , ADC0 klein.
Rot aus Grün blau an...drehe am Poti nichts...
Schalter High. AdcO klein
Alle 3 Farben an, drehe am Poti tut sich nichts..
So - ich hole jetzt mein Steckbrett, einen ATMega8 und ein bisschen
Kleinkram und teste, was da nicht geht... Das will ich jetzt einfach mal
wissen. Es kann doch nicht sein, dass so ein kleines Progrämmchen nicht
geht...
Gruß
Jonathan
Die Version, die ich eben geposted habe, MUSS gehen. Ich habe den Fehler
nämlich gefunden ("Swprescaler" würde "Geschwindigkeit" nie
erreichen)... Geht es?
Gruß
Jonathan
Also zu Deinem Code...
Entweder extrem langsam..( AdcO ist ca 0 ) oder weiss nicht
Im Colour modus läuft nicht so "rund" wei meine, ca in der Mitte (adc
500 ) ist ein Loch..alle aus..
Hast mal meine angeguckt ?
, wenn die LEDs gegen VCC geschaltet sind. Dass da kein "Loch" ist,
liegt wahrscheinlich an den Fehlern in deinem Programm... Bei der
Fading-Geschwindigkeit sind mir 2 Fehler unterlaufen. Bitte ersetze die
Zeile
@ Jonathan: du musst deine Timer Konfiguration so machen wie es
"Bastler" macht.
Du Schreibst immer: Compare A = Clear, Compare B = Clear....
Richtig ist aber: Compare A PWM = Clear UP oder Down , Compare B PWM =
Clear Up oder Down...
Nein, Compare A = Clear ist richtig. Die Bascom-Hilfe drückt sich da
etwas komisch aus. Compare X setzt/löscht/trennt den OCnX-Pin, während
Compare X Pwm die Aktion beim erreichen des maximalen Zählerstandes
angibt.
Gruß
Jonathan
Jonathan Strobl schrieb:> Nein, Compare A = Clear ist richtig. Die Bascom-Hilfe drückt sich da> etwas komisch aus.
Falsch. Bascom erlaubt jedoch beide Schreibarten und verwendet sie in
etwa gleichwertig. "In etwa" deshalb, weil ein Clear UP ein Setzen des
Pins beim einem Compare Match beim Hochzählen entspricht, während es
beim Clear DOWN genau umgekehrt ist. Das sollte ein Bug in Bascom sein.
> Compare X setzt/löscht/trennt den OCnX-Pin, während Compare X Pwm die> Aktion beim erreichen des maximalen Zählerstandes angibt.
Das hat mit dem maximalen Zählerstand gar nix zu tun, Set/Clear oder
Clear UP/Clear DOWN bezieht sich allein auf den Vorgang des Compare
Match.
Der Grund für die unterschiedliche Syntax bei der Verwendung
Timer/Clear/Set versus PWM/Clear UP/Clear DOWN ergibt sich aus dem
Datenblatt, dort wird beim Timermode von Clear/Set gesprochen, während
es beim Phase Correct PWM Mode Clear UP/Clear Down heißt.
Bascom verwendet für PWM immer den Phase Correct Mode.
Jonathan Strobl schrieb:> Enable Timer1> Enable Timer2
Es ist keine ISR für Timer1 oder Timer2 im Code enthalten, darum gibt's
auch keine Notwendigkeit diese Interrupts zu erlauben. Nimm den Unsinn
raus.
Abgesehen davon ist sowohl der Originalcode als auch Dein Code
schlichtweg grauselig. Das würde man am Besten mit einem
Zustandsautomat, auch "State Machine" genannt machen, in der Timer0-ISR
würde man lediglich ein Flag, z.B. ein ms_Tic setzen und das dann in der
State Machine auswerten und zurücksetzen.
In dieser State Machine wäre auch problemlos jegliche Schalterabfrage zu
erledigen, dafür braucht man keinen eigenen Interrupt.
Sollte der Begriff State Machine nicht bekannt sein, das Internet und
ich denke auch MC.net sollte erschöpfend Auskunft geben können.
Ich weiß, dass man das besser mit Flags gemacht hätte. Aber ich wollte
"Bastler" nicht noch durch Flags verwirren... Bei dem "Enable Timern"
hatte ich mich schlichtweg vertan. Danke, dass du mich da aufgeklärt
hast :)
Gruß
Jonathan
Hallo Jonathan, also habe Deine Version geflasht :
Spannend, glaubst nicht !
Also die feste Farben Modus geht soweit,ohne "loch" ich muss auch sagen,
war ich mit der Aussage nicht ganz einverstanden.
Du hast gesagt :
R=255
G=225
B=255
würde nicht gehen, weil gegen +5 geschaltet wird.
Warum gehen dann die andere Kombinationen ?
R=255
G=0
B=255 ?
Nun zum Code habe also geflasht egal wie der Poti steht fadet nicht.
Blau Grün an. Nochmal der Code :
Ich habe langsam überhaupt keine Erklärung, warum diese ISR Variante
nicht geht und meine alte Int0 "besser" geht....Rätsel ( Also an der
Schaltung bzw Hardware, AVR kann es nicht liegen )
bezüglich ADC :
Diese Variante hatte ich schon benutzt :
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc
Mit dieser Variante ist die geplante ISR Variante auch nicht sauber
gelaufen.
Nun hat Johannes folgendes Vorgeschlagen :
Config Adc = Free , Prescaler = 4 , Reference = Avcc
Start Adc
>Ich habe langsam überhaupt keine Erklärung, warum diese ISR Variante
nicht geht....
Deine Timer0_Isr wird alle 1024 µS oder ca. 1 mS aufgerufen. Überlege
mal was du da alles in die Interrupt Routine packst...?!?
Allein die ADC Wandlung nimmt schon etwa >= 260µS in anspruch, rund ein
viertel deiner verfügbaren Zeit...
Ich würde die Lücken im Case schließen:
>Case 1 To 50 : 'Rot 100>Case 60 To 100 : 'Rot 100 Grün>Case 110 To 200 :
Case 1 To 50 : 'Rot 100
Case 51 To 100 : 'Rot 100
Grün Case 101 To 200 :
Oder Du rechnest den 10Bit ADC-Wert in einen 8Bit um.
Kann es wirklich sein, das das ganze Programm Konstrukt von Jonathan
doch nicht für die Anwendung passt ?
Gerhard : Ja das Poti funktioniert nicht in der Fading ( okay faden tut
allgemein nicht ) aber in der Select Case Anwendung Ja
Ich würde erst mal identifizieren, ob es der ADC oder die PWM ist, die
da Probleme macht.
Dazu würde ich den ADC erst mal stilllegen.
zb so
anstelle von
1
Timer0_isr:
2
3
Geschwindigkeit = Getadc(0)
4
5
'Nur alle <Geschwindigkeit> Timerinterrupts deine Fading-Routine ausführen
6
Incr Swprescaler
würde ich den ADC Wert mal als fixe Konstante vorgeben
1
Timer0_isr:
2
3
'Geschwindigkeit = Getadc(0)
4
Geschwindigkeit = 0
5
6
'Nur alle <Geschwindigkeit> Timerinterrupts deine Fading-Routine ausführen
7
Incr Swprescaler
Wenn jetzt immer noch nichts fadet, dann liegt das Problem irgendwo in
den PWM bzw. den Timer Konfigurationen.
Wenn es aber fadet, dann habe ich eine Theorie. Und die hängt damit
zusammen, welchen Wertebereich das ADC Ergebnis hat. Da können Werte von
0 bis 1023 auftreten. Und 1023 mal den Fadingschritt auslassen bis dann
endlich mal um 1 hochgesetzt wird, das kann schon dauern.
Aber erst mal: nachsehen ob das Fading an sich funktioniert! Dazu den
ADC stilllegen und mit einem bekannten konstanten Wert operieren.
Hallo Jonathan,
schlechte Nachrichten ...
Also faden..tut sich nichts..
habe meine Version nochmal in den gleichen AVR geflascht, tut ohne
Probleme.
verstehe ich nicht.
Jonathan Strobl schrieb:> $crystal = 16000000> Config Adc = Free , Prescaler = 4 , Reference = Avcc
Ein ADC-Clock von 4MHz ist jenseits von Gut und Böse. Ist auch völlig
unnötig, denn wenn der ADC mit "Free" konfiguriert wird, so wartet
Bascom bei GetADC() nicht bis zum Ende einer neuen Wandlung, sondern
holt nur das aktuelle Ergebnis aus ADCL/ADCH ab.
Der ADC kann damit also so langsam wie möglich eingestellt werden, bzw.
auf AUTO gesetzt werden.
Der ADC schwankt immer ein wenig und somit ist es recht wahrscheinlich
daß der ADC-Wert sich ändert und ein Vergleich per "=" nicht zutrifft.
Dann dauert es mehr als eine Minute, bis Swprescaler übergelaufen ist
und sich wieder im Bereich < 1024 befindet.
Testen kann man auch, indem man Geschwindigkeit fest setzt und nicht per
ADC zuweist.
Also Jungs ich weiss nicht, was da los ist,
Ich denke so langsam ich bleibe bei meiner Variante, irgendwie funzt
alles nicht mal annähernd so wie mein schlechtes Programm...
Meine ADC Config habe ich schon bestimt 5 mal in andere Schaltungen
verwendet
Diese stammt Ursprünglich von Halvar ( Habe am Anfang ausfühlich die
Seite studiert)und einige Beispiele mit ADC habe ich im Forum Ledstyles
bzw. Roboternetz auch gesehen. Ich meine jetzt nicht von komplexen
Anwendungen, sondern so ganz einfache wie meine.
Hallo zusammen,
ich habe die Schaltung mal schnell selber auf einem Steckbrett gebaut.
Ich habe nur Atmega 168 bei mir umliegen aber das ist im Prinzip kein
groér unterschied...
Jonathan's Code funktioniert soweit ich habe nur die Konfiguration des
Timer1 und timer2 angepasst....
Leute ... das ganze Gerümpel in eine ISR zu packen ist nix und bleibt
nix, sow wie modellierter Mist eben Mist bleibt, nur schöner ...
fangt nochmal von vorne an, erst die Timers configurieren, dann den ADC,
dann Tastenabfrage, dann eine Mainloop bauen mit nem Flag und die
Subroutinen die je nach Schalterstellung angesprungen werden.
Schritt für Schritt ...
Habe ich auch schon überlegt, daß es so nicht wird.
Interresant finde ich was wirklich in meiner Lösung ( Schalter löst
interrupt aus ) wirklich schlecht ist ?
Was macht wirklich einen Sinn "millionen mal " im Code hin un her zu
springen ?
ja, macht es, wenn Du z.B. den Schalter auf nem Interrupt lässt und nen
Timer für Timings verwendest, die auch wieder interrupt basieren, dann
sperrt der Taster-Int den Timer-Int und umgekehrt. Wenn das programm nun
endlos in einem Int hängt gehen keine anderen mehr.
Außerdem kann es noch Probleme mit Highlevelbefehlen von Bascom geben,
hab da vor langer Zeit mal die Beobachtung gemacht, da das Subroutinen
sind die aus dem Int angesprungen werden und wieder zurück in die
Interruptroutine. Keine Ahnung ob die Probleme mittlerweile behoben
sind, aber in früheren Versionen konnte es passieren, dass in der
Interruptroutine die Ints wieder aktiviert wurden, wodurch ein Int im
Int im Int usw. usw. ausgelöst werden konnte ... gabe sehr merkwürdige
Programmabläufe ... wie gesagt, kann, muss nicht und möglicherweise auch
schon gefixt.
Das hin und her springen ist dem Controller wurst, kost keinen Cent
extra, gibt aber sauberen Code.
Fhutdhb Ufzjjuz schrieb:> Leute ... das ganze Gerümpel in eine ISR zu packen ist nix und bleibt> nix, sow wie modellierter Mist eben Mist bleibt, nur schöner ...
'Ne Schönheit find' ich den Code auch nicht. Dennoch spricht nix
dagegen, daß es funktioniert. Obwohl die ISR etwas "länglich" aussieht,
so benötigt sie nicht mehr als 500 Takte, bei einer Aufrufrate der ISR
von 976/s sind das gerade mal 3% der verfügbaren Rechenleistung.
Es ist auch unwichtig, ob die ISR optisch lang aussieht, wesentlich sind
die Schritte, in der sie durch ist. Vor allem ob sie glatt durchläuft,
ob irgendwelche Loops drin sind oder sonstwas blockierend wirkt, wie
z.B. GetADC(), das auf das Ende der Wandlung wartet. Ist aber hier alles
nicht der Fall.
Was in den beiden letzten Codes nicht passt, ist Config Lcdbus = 4, das
hat dort nix zu suchen.
Mal den nachfolgenden, modifizierter Code von Jonathan ausprobieren, da
ist die ADC-Geschichte anders gelöst.
'Nur alle <Geschwindigkeit> Timerinterrupts deine Fading-Routine ausführen
76
Incr Swprescaler
77
If Modus = 1 Then
78
If Swprescaler > Geschwindigkeit Then
79
Swprescaler = 0
80
If Fadingschritt = 0 Then
81
Incr R_fading
82
If R_fading = 255 Then Incr Fadingschritt
83
84
Elseif Fadingschritt = 1 Then
85
Incr G_fading
86
If G_fading = 255 Then Incr Fadingschritt
87
88
Elseif Fadingschritt = 2 Then
89
Incr B_fading
90
If B_fading = 255 Then Incr Fadingschritt
91
92
Elseif Fadingschritt = 3 Then
93
Decr R_fading
94
If R_fading = 0 Then Incr Fadingschritt
95
96
Elseif Fadingschritt = 4 Then
97
Decr G_fading
98
If G_fading = 0 Then Incr Fadingschritt
99
100
Elseif Fadingschritt = 5 Then
101
Decr B_fading
102
If B_fading = 0 Then Fadingschritt = 0
103
End If
104
105
R = R_fading
106
G = G_fading
107
B = B_fading
108
End If
109
Else
110
Gosub Beleuchtung
111
End If
112
Return
113
114
115
Beleuchtung:
116
117
Adc0 = ADC
118
119
Select Case Adc0
120
121
122
Case 1 To 59 : 'Rot 100
123
R = 255
124
G = 0
125
B = 0
126
Case 60 To 109 : 'Rot 100 Grün 50
127
R = 255
128
G = 125
129
B = 0
130
Case 110 To 209 : 'Rot 100 Grün 100
131
R = 255
132
G = 255
133
B = 0
134
Case 210 To 309 : 'Rot 100 Grün 100 Blau 125
135
R = 255
136
G = 255
137
B = 125
138
Case 310 To 409: 'Rot 100 Grün 100 Blau 100
139
R = 255
140
G = 255
141
B = 255
142
Case 410 To 509: 'Rot 50 Grün 100 Blau 100
143
R = 125
144
G = 255
145
B = 255
146
147
Case 510 To 609: 'Rot 0 Grün 100 Blau 100
148
R = 0
149
G = 255
150
B = 255
151
152
Case 610 To 709: 'Rot 0 Grün 50 Blau 100
153
R = 0
154
G = 125
155
B = 255
156
157
Case 710 To 809: 'Rot 0 Grün 0 Blau 100
158
R = 0
159
G = 0
160
B = 255
161
162
Case 810 To 909:
163
R = 168
164
G = 128
165
B = 128
166
167
Case 910 To 1023:
168
R = 0
169
G = 0
170
B = 0
171
172
End Select
173
174
175
Return
Fhutdhb Ufzjjuz schrieb:> Keine Ahnung ob die Probleme mittlerweile behoben> sind, aber in früheren Versionen konnte es passieren, dass in der> Interruptroutine die Ints wieder aktiviert wurden, wodurch ein Int im> Int im Int usw. usw. ausgelöst werden konnte ...
Das fällt jetzt unter Mythen und Märchen.
> Fhutdhb Ufzjjuz schrieb:>> Keine Ahnung ob die Probleme mittlerweile behoben>> sind, aber in früheren Versionen konnte es passieren, dass in der>> Interruptroutine die Ints wieder aktiviert wurden, wodurch ein Int im>> Int im Int usw. usw. ausgelöst werden konnte ...>> Das fällt jetzt unter Mythen und Märchen.
Ich gäbe Dir Recht, hätte ich selbst derlei Effekte nicht schon
beobachtet, leider, das Suchen des Fehler gestaltete sich auch äußerst
mühsam und erst die Begutachtung des Hex im AVR-Studio lieferte damals,
wie gesagt schon ne Weile her, Aufschluss.