PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : LED dimmen (Hilfe bei Valentinstagsgeschenk)



Malte0815
11.02.2008, 10:04
Also ich möchte für meine Freundin ein Herz basteln, welches von hinten mit 3x3 LED´s angestrahlt werden soll (3xrot,3xgrün,3xblau). Die LED´s sollen einfach hell und dunkel dimmen und mit drei Tastern soll man die Farbe wechseln können (Rot, grün, oder Blau).
Da ich noch nicht sehr lange in Basic programmiere weiß ich nicht wie ich das machen soll. Meine Idee ist es nun, die Schaltung mit Kondensatoren aufzubauen. Also LED an bis Kondensator leer und wieder an.
Was haltet ihr davon? Ist die Softwarelösung vielleicht doch gar nicht so schwer? Wie gesagt, ich versuche mich erst ein Paar tage in der Programmierung (ATmega8515, ATtiny13).

Gruß Malte

T.J.
11.02.2008, 10:07
ich würde ein kleinen controller nehmen und das schnell hinproggen

mach erstmal ne Schaltung (3 Inputs für die Taster, 3 Outs für die Farben (an PWM, also Timer) ) und dann fang mit der Software an. Wenn es nicht mehr weiter geht melde dich.

Malte0815
11.02.2008, 10:13
Ist der ATtiny ausreichend?

T.J.
11.02.2008, 10:36
2PWM Ausgänge und 3 Inputs. Wird eng aber könnte gehen. Wir könnten ein PWM out nutzen, müssen dann aber switchen welche der 3 Farben damit betrieben werden soll. Dann haben wir allerdings nur ein Output um 3 Zustände zu schalten...hmmm

(3 Farben sollens aber sein?), weil 2PWM Ausgänge sind ja schon so da, d.h. mit 2 Farben ist es genau passend und recht easy.

Malte0815
11.02.2008, 12:11
Ich habe nun zunächst versucht ohne taster eine led anzusteuern. Ich bekomme 2 Fehlermeldungen: Out of SRAM space (Line 10);
Invalid Parameter for CONFIG parameter or value(Line 7).



$regfile = "ATtiny13.dat"
$crystal = 4000000




Config Timer0 = Pwm , Pwm = 8 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 8

Config Portb.2 = Output
Dim A As Word

do

For A = 0 To 255 Step 1

Pwm1a = A
Waitms 10

Next

For A = 255 To 0 Step -1

Pwm1a = A
Waitms 10

Next
loop
End

Ceos
11.02.2008, 12:22
wenn es "nur" dimmer sein sollen, tut es auch n soft-PWM also per timer-interrupt die pins manuell high und low ziehen, man muss ja nicht den "echten" PWM output benutzen

T.J.
11.02.2008, 13:27
Ich schau zuhause mal in mein code, dann kann ich dir das zeigen. Softpwm hab ich noch nicht gemacht, müsste man mal beispielcode suchen.

Ceos
11.02.2008, 18:02
naja einfach die ISR für OUTPUT_COMPAREn und TIMER_OVERFLOWn und dann das notewndige pinverhalten programmieren wenn die ISR ausgeführt wird ... so schwer isset ja net meine ich mal

T.J.
11.02.2008, 18:34
Grobe Fehler kann ich nicht finden. Ich habe allerdings einmal Clear Down und einmal Clear UP (weiß nicht mehr was das heißt) aber es kann ja nur an deiner Config liegen. Probier mal mit den Einstellungen des PWM rum.

T.J.
12.02.2008, 08:12
Noch nicht weitergekommen? 2 Tage hast du noch :D

ist denn die Hardware schon fertig?

Malte0815
12.02.2008, 10:34
Also meine Herz-Grundplatte ist soweit fertig ;).
Die Schaltung hab ich aufm Steckbrett aufgebaut.
Die PWM mit dem tiny will mir einfach nicht gelingen. Mit meinem mega8515 funktionierts, allerdings mit dem Timer1. Funktioniert denn PWM mit Timer0 überhaupt?
Muss vielleicht in den Fuse-Bits noch was umgestellt werden?

Ceos
12.02.2008, 11:13
das hab ich mittels poti und ADC auf nem ATMega8 bei 8MHz getestet .... bis auf ein paar übergangsflackereien (vermutlich vom poti und beim updaten des OCR register) funktioniert es eigentlich ganz gut, und man könnte theoretisch für jeden port ne neue Duty Variable und StatusVariable einbauen ... zu not kann man auch PIN statt der statusvariable abfragen, aber mir rennt die zeit davon das noch zu testen ...

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/timer.h>
#include <avr/signal.h>
#include <avr/sleep.h>

#define ON 1
#define OFF 0
#define ULONG_MAX 199

volatile unsigned char OFVal;
unsigned char LED1Duty;
unsigned char LED1Stat;




SIGNAL(SIG_OUTPUT_COMPARE2)
{
if (OFVal++ == 200) OFVal = 0;
LED1Duty = (ADC*10)/(1024/10)-1;
if (LED1Stat == OFF && (ULONG_MAX-LED1Duty) == OFVal)
{
PORTB |= BV(PB1);
LED1Stat = ON;
}
if (LED1Stat == ON && ULONG_MAX-(ULONG_MAX-LED1Duty) == OFVal)
{
PORTB &= ~BV(PB1);
LED1Stat = OFF;
}
}

int main(void)
{
cli();
OFVal = 0;
DDRB = BV(PB1)|BV(PB2)|BV(PB3)|BV(PB4);
TIMSK = BV(OCIE2)|BV(TOIE2); //TOIE2 musste ich mit einschalten hat sonst nciht fuinktioniert (komisch ....)
TCNT2 = 0;
OCR2 = 100; //damit kannste die auflösung einstellen 100% sind wegen der ADC formel notwendig
TCCR2 = BV(WGM21)|BV(CS20); //CTC modus, prescaler 1
LED1Duty = 1;
LED1Stat = OFF;
ADCSRA = BV(ADFR) | BV(ADPS2) | BV(ADPS1); // ADC einstellungen
ADMUX = BV(REFS0);
ADCSRA |= BV(ADEN);
ADCSRA |= BV(ADSC);
sei();
while(1) ;
}


da bleiben auch noch ausreichend takte für die while schleife übrig, zur not kannst den prescaler auch noch hochschrauben, dann haste allerdings nen flackernden effekt wenn du es schnell hinundher bewegst

hoffe ich konnte helfen

MfG

Ceos

PS den duty berechne ich im interrupt, ADC 0-1024 mit der formel gibt das 0-100 (0-100%) wenn du ne andere auflösung verwendest brauchst du hier ein duty zwischen 0 - OCR (achtung, OCR bedeutet LED aus, OCR-1 allerdings maximum)

Malte0815
12.02.2008, 11:22
Vielen Dank für deine mühe aber in (ich nehme an) cc hab ich noch gar keinen plan. Hab bis jetzt meine ersten "gehversuche" nur in basic gemacht. Das schien mir für den Anfang etwas einfacher zu sein.

Gruß Malte

T.J.
12.02.2008, 12:54
Das mit dem Timer könnte natürlich ein Problem sein, aber sollte ja gehen. Guck doch mal bitte ins Datenblatt des Tiny, da steht doch genau drin welcher Timer wie PWM macht/kann.

Ceos
12.02.2008, 15:17
link mir mal das datenblatt und beschreib mal was das herz machen soll, vll. kann ich dir dabei helfen (dir ne HEX schustern und erklären wenn du magst), du hast mich da nämlich auf ne idee gebracht und damit könnte ich gleich mal "üben" ^_^

Malte0815
14.02.2008, 00:50
Also ich habe drei farben. Drücke ich nun Taster 1 soll z.B. rot angehen und hell und dunkel faden. Das wars eigentlich schon. Die Farben grün und blau kann man dann (mit noch jeweils einem Taster )nach lust und laune einschalten oder auch nicht. Das sollte selbst ich gebacken kriegen aber wie gesagt, ich bekomme die PWM nicht zum laufen.
Ich mach das Herzchen jetzt soweit fertig da es ja morgen schon soweit ist O:) . Hab es erstmal nur so gemacht das ich die drei farben einfach an und aus machen kann. Ich will es aber später noch nachträglich drauf flashen.

Wäre echt super wenn du mir noch helfen könntest.
Hier ist der link für den tiny13 http://www.atmel.com/dyn/products/product_card.asp?family_id=607&family_name=AVR%AE+8%2DBit+RISC+&part_id=3175

PS.: Bin fast verzweifelt weil ich einen Tag nicht ins forum gekommen bin. War das nur bei mir so?

T.J.
14.02.2008, 09:46
ging mir auch so.

guck mal ob das hilft
https://www.roboternetz.de/phpBB2/viewtopic.php?p=351775#351775

Zum Herz: du wirst sehen sie freut sich ob leuchtend oder fadend, hauptsache es kommt von dir ;)

Ceos
14.02.2008, 12:06
nein ich bin gestern auch net mehr reingekommen sorry, leider muss ich für morgen noch was proggen tut mir unheimlich leid

python_rocks
14.02.2008, 12:38
Ich habe nun zunächst versucht ohne taster eine led anzusteuern. Ich bekomme 2 Fehlermeldungen: Out of SRAM space (Line 10);
Hallo Malte0815!

Der ATtiny13 ist ein sche... Ding. :-( Er hat so wenig SRAM, dass man kaum etwas Vernünftiges damit machen kann. Software-PWM ist damit machbar, aber um Speicherplatz zu sparen würde ich auf jeden Fall Hardware-PWM anstreben.

Dann musst du die Werte für den HW-Stack, den SW-Stack und den Framesize anpassen. Ich habe ein Programm im ATtiny13 laufen und dieses läuft bei mir wenn ich folgende Werte dafür verwende:


$regfile = "attiny13.dat"
$crystal = 9600000
$hwstack = 32
$swstack = 5
$framesize = 20
Leider ist das immer von Programm zu Programm verschieden. Am Besten, du testest das Programm in Bascom und schaust dir im Testprogramm den Karteikartenreiter "uP" an. Es sollte kein Häckchen bei "Frame Overflow" oder "Stack Overflow" auftauchen. Dann sind die Werte OK.

Dazu musst du dein Programm im Simulator laufen lassen und mit "Pause" unterbrechen. Erst dann findest du dort im Karteikartenreiter "uP" sinnvolle Ausgaben.

Interessant zu diesem Thema sind auch diese Links:
- http://avrhelp.mcselec.com/index.html?memory_usage.htm
- https://www.roboternetz.de/wissen/index.php/Bascom_Inside
- http://avrhelp.mcselec.com/index.html?stcheck.htm

Damit dürfte dein Programm laufen. Aber da dein Programm sowiso noch so klein ist, müsste es auch ohne die Anpassung der Stackgrößen arbeiten. Wichtig wird das erst, wenn du noch ein paar mehr Variablen verwendest und evt. sogar in Unterroutinen springst.

Das hier funktioniert zumindest im Simulator:

$regfile = "ATtiny13.dat"
$crystal = 4000000
'$hwstack = 32
'$swstack = 5
'$framesize = 20

Config Timer0 = Pwm , Compare A Pwm = Clear Down , Prescale = 8

Config Portb.2 = Output

Dim A As Byte


Do
For A = 0 To 255 Step 1
Pwm0a = A
Waitms 10
Next

For A = 255 To 0 Step -1
Pwm0a = A
Waitms 10
Next
Loop
End
Vielleicht kannst du damit etwas anfangen. Ich habe es aber nicht real getestet.

mfg
Gerold
:-)


PS: Ist nicht PORTB.0 der PWM-Ausgang?

PS2: Vielleicht kannst du den Prescale des Timers noch nach oben drehen. Experimentier mal ein bischen mit den verschiedenen Werten. Mir kommt 8 ziemlich wenig vor.

.

Ceos
14.02.2008, 13:33
@phyton zu dem prescale 8 kommt hinzu, das der interrupt nur alle 256counts ausgelöst wird, also 8*256 freie zyklen fürs programm, find cih eigentlich ausreichend

python_rocks
14.02.2008, 15:36
Hallo!

Bei 4 Mhz und einem Prescale von 64

Config Timer0 = Pwm , Compare A Pwm = Clear Down , Prescale = 64
wird eine PWM-Frequenz von 122 erreicht.

4000000 (Quarz) / 64 (Prescale) = 62500 (Ticks)
62500 (Ticks) / 256 (Gesamt Pulsweite) = 244,140625 (in eine Richtung)
244,140625 (in eine Richtung) / 2 = 122,0703125 (in beide Richgungen = Hz)

Es wird zuerst von 0 bis 255 hoch gezählt. Stimmt während diesem Hochzählen der Wert PWM0A mit dem Zähler überein, dann wird die LED ausgeschaltet. Kommt der Zähler bei 255 an, dann zählt er nach unten von 255 bis 0. Stimmt während diesem Herunterzählen der Wert PWM0A mit dem Zähler überein, dann wird die LED eingeschaltet. Ein mal Hochzählen und ein mal Herunterzählen ergeben insgesamt einen Impuls. Mit einem Vorteiler von 64 kann somit eine PWM-Frequenz von 122 Hz erreicht werden. Was für das Dimmen von LEDs genügt.

Ich habe das jetzt nachgeprüft. Wenn man im Bascom den TIMERx auf PWM setzt, dann wird rauf und runter gezählt. CLEAR UP oder CLEAR DOWN entscheidet, ob die LED bei einem hohen oder bei einem niedrigen Vergleichswert (PWMxA oder PWMxb) hell oder dunkel ist.

Das war mein erster Versuch mit Hardware-PWM. :-) Scheint gar nicht so schlecht zu funktionieren. :-b

mfg
Gerold
:-)

Malte0815
15.02.2008, 10:53
Das Geschenk war ein voller Erfolg :cheesy:. Vielen dank für eure Hilfe. Das mit dem Dimmen hat zwar wegen Zeitnot noch nicht hingehauen aber ich werde noch dranbleiben. Ich habe wieder eine ganze Menge von euch gelernt . Nächste Woche werd ich den mC nochmal rausnehmen und mich ans programm setzten. Irgenwann muss es ja funktionieren #-o. Es werden also noch ein paar Posts werden.

Gruß Malte

PS.:Tolles Forum, weiter so [-o<

T.J.
15.02.2008, 11:05
Das Geschenk war ein voller Erfolg :cheesy:.

Sag ich doch, Glückwunsch :wink:

Malte0815
24.02.2008, 16:15
Hi hab nun endlich mein Valentinstagsgeschenk fertig gemacht und die PWM funktioniert auch einwandfrei O:) . Ich möchte nun noch per tastendruck alle led eingeschaltet lassen und beim nächsten wieder die Pwm-sequenz. Ich bekomme es irgendwie nicht hin. Vielleicht kann mir nochmal jemand auf die Sprünge helfen.

$regfile = "ATtiny13.dat"
$crystal = 4000000
'$hwstack = 32
'$swstack = 5
'$framesize = 20

Config Timer0 = Pwm , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 8


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

Dim A As Byte




Do


For A = 0 To 255 Step 2
Pwm0a = A
Waitms 15

Next

For A = 255 To 0 Step -1
Pwm0a = A
Waitms 5
Next

For A = 0 To 255 Step 2
Pwm0b = A
Waitms 15

Next

For A = 255 To 0 Step -1
Pwm0b = A
Waitms 5
Next
Loop
End


Gruß Malte

T.J.
24.02.2008, 16:22
Hi,

erstell dir einfach ne subroutine "Stop_pwm:" darin machst du auch einfach ne loop mit der du nur per tastendruck "return" machst.

In deinen Forschleifen musst du nun den Taster abfragen und "Gosub Stop_pwm" aufrufen wenn er gedrückt wurde. Dann werden die PWM werte nicht mehr geändert und du bist in stop_pwm solange du ihn wieder drückst. Dann gehts genau da weiter wo du aufgehört hast.

Bitwait PinX.X , Reset ist übrigends ne nette Funktion ;)

pmaler
24.02.2008, 16:31
Hab den Thread jetzt erst gesehen... Du hast also sowas wie ich gebastelt.

Ein Womanicer, Heartopener

Hab heute gerade Bilder hier von meiner Variante reingestellt:


https://www.roboternetz.de/phpBB2/viewtopic.php?p=354574#354574

Malte0815
25.02.2008, 12:50
Hab jetzt vieles Probiert aber ich komm beim nächsten Tastendruck aus der Sub-routine nicht mehr raus?

$regfile = "ATtiny13.dat"
$crystal = 4000000
'$hwstack = 32
'$swstack = 5
'$framesize = 20

Config Timer0 = Pwm , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 8


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

Portb.2 = 1
Portb.4 = 1

Dim A As Byte

Declare Sub Stop_pwm


Do


For A = 0 To 255 Step 2
Pwm0a = A
Waitms 15

If Pinb.3 = 0 Then
Gosub Stop_pwm
End If

Next

For A = 255 To 0 Step -1
Pwm0a = A
Waitms 5

If Pinb.3 = 0 Then
Gosub Stop_pwm
End If

Next

For A = 0 To 255 Step 2
Pwm0b = A
Waitms 15

If Pinb.3 = 0 Then
Gosub Stop_pwm
End If

Next

For A = 255 To 0 Step -1
Pwm0b = A
Waitms 5

If Pinb.3 = 0 Then
Gosub Stop_pwm
End If

Next
Loop
End

Stop_pwm:
Do
Loop
Return

Noch ne blöde Frage? Wollte mein "Kunstwerk" mal präsentieren, weiß aber nicht wie ich ein Bild hochladen kann?[/img]

T.J.
25.02.2008, 13:17
Hab jetzt vieles Probiert aber ich komm beim nächsten Tastendruck aus der Sub-routine nicht mehr raus?

Noch ne blöde Frage? Wollte mein "Kunstwerk" mal präsentieren, weiß aber nicht wie ich ein Bild hochladen kann?[/img]

Wenn dein Taster gedrückt wird ist Pinb.3 eher = 1 oder?

ich meinte eher sowas:


$regfile = "ATtiny13.dat"
$crystal = 4000000
'$hwstack = 32
'$swstack = 5
'$framesize = 20

Config Timer0 = Pwm , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 8


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

Portb.2 = 1
Portb.4 = 1

Dim A As Byte

Declare Sub Stop_pwm


Do


For A = 0 To 255 Step 2
Pwm0a = A
Waitms 15

If Pinb.3 = 1 Then
bitwait Pinb.3, reset
Gosub Stop_pwm
End If

Next

For A = 255 To 0 Step -1
Pwm0a = A
Waitms 5

If Pinb.3 = 1 Then
bitwait Pinb.3, reset
Gosub Stop_pwm
End If

Next

For A = 0 To 255 Step 2
Pwm0b = A
Waitms 15

If Pinb.3 = 1 Then
bitwait Pinb.3, reset
Gosub Stop_pwm
End If

Next

For A = 255 To 0 Step -1
Pwm0b = A
Waitms 5

If Pinb.3 = 1 Then
bitwait Pinb.3, reset
Gosub Stop_pwm
End If

Next
Loop
End

Stop_pwm:
Do
If Pinb.3 = 1 then
bitwait Pinb.3, reset ' warten bis er losgelassen wird,
Return 'sonst geht er oben gleich wieder in Stop_pwm
End if
Loop


bei dem bitwait muss man gucken wo es am sinnvollsten ist, ich hab es dir einfach mal so reingesetzt
Bild hochladen: Attachment hinzufügen

Malte0815
26.02.2008, 12:09
So, endlich ist es fertig.
@ T.J. ich hab deinen Code nochn bisschen umgeändert. Jetzt wird das Faden der Lichter bei Tastendruck gestoppt und beim nächsten einfach Fortgesetzt (Vielen Dank für deine Hilfe). Ich hab noch eine "Pause-Led" mit eingebaut da der Lichtwechsel ziemlich langsam verläuft. So kann man sehen ob die Pause-Funktion aktiviert ist. Hier ein paar Bilder.

T.J.
26.02.2008, 12:48
Super, freut mich dass es klappt!