Kani-Coaching (C lernen mit Nomis)

Alles klar. Ich nehme erst "Urlaub" (Dirk anschubs)
Habe nach 30min meine ersten Erfolge und die PWM-Funktioniert. Meine Erfolge werde ich hier trotzdem Posten.


CodeBox C
#include <avr/io.h>

int main (void)
{
DDRD = 0b11111111;
PORTD = 0b11111111;

int pwm_counter=0;

while(1)
{

pwm_counter++;

if(pwm_counter <=100)
{
PORTD = 0b00000000;
}
if(pwm_counter >=101)
{
PORTD = 0b11111111;
}

if(pwm_counter == 1500)
{
pwm_counter = 0;
}
}
}

Durch das ändern dieses "if(pwm_counter == 1500)" ändert man die Zeit, in der die LED aus ist. Und so mit auch den "Dimmfaktor"
 
Hallo Kani,

Sieht schon ganz gut aus. Es wird doch was :D

Ein wichtiger Tip:
schreib Kommentare an die Zeilen. Leg deine Gedankengänge, die du beim
programmieren hattest mit in den Quellcode. Das hilft dir später den Quellcode
wieder zu verstehen (z.B. nach ein paar Wochen) und es hilft anderen wenn
sie Dir bei der Fehlersuche helfen wollen deine Gedankengänge nachzuvollziehen.

Mein Quellcode besteht teilweise zur hälfte oder sogar 3/4 nur aus Kommentaren.
Ich habe bei hardwarenahen Programmteilen ganze Bereiche der Datenblätter
als Kommentare mit in den Quellcode übernommen. Meißtens steht bei mir
hinter jeder Zeile nochmal ein Kommentar, was diese Zeile im Programm
eigentlich bewirken soll.

Kannst Dir ja mal Quellcodes von mir ansehen. Auch wenn Du nicht in
Assembler programmieren willst. Einfach mal so als Anregung wie man
Kommentare einfügen kann und wieviel es manchmal werden kann.
Bei meiner 1-Wire-Initialisierung ist das ganze Timing in ASCII drin.

Gruß
Dino
 


CodeBox C
#include <avr/io.h>

int main (void)
{
DDRD = 0b11111111; //PORTD auf Ausgang
PORTD = 0b11111111; //LEDs aus (sonst sonst am Anfang an)

int pwm_counter=0;

while(1)
{

pwm_counter++; //pm_count jeden Schleifendurchlauf +1
//Zeit der "An-Phase"
if(pwm_counter <=10) //Bei Gleich-/weniger als 10 Schleifendurchläufe...
{
PORTD = 0b00000000; //...LED an
}
if(pwm_counter >=11) //Bei Gleich-/mehr als 11 Schleifendurchläufe...
{
PORTD = 0b11111111; //...LED aus bis...
}
//Zeit der "Aus-Phase"
if(pwm_counter == 250) //...250 erreicht.
{
pwm_counter = 0; //Alles von vorne
}
}
}

Ich hab nur das Problem, dass die LED nicht ganz ausgedimmt werden kann. Wenn sie nurnoch schwach leuchten tut sich lange nichts mehr bis die LED an zu blinken/flackern anfängt.
 
Ich hab nur das Problem, dass die LED nicht ganz ausgedimmt werden kann. Wenn sie nurnoch schwach leuchten tut sich lange nichts mehr bis die LED an zu blinken/flackern anfängt.
Das kommt daher, weil du es anscheinend noch so machst wie du es hier beschrieben hast:
Durch das ändern dieses "if(pwm_counter == 1500)" ändert man die Zeit, in der die LED aus ist. Und so mit auch den "Dimmfaktor".
Die "1500" sind nicht der Dimmfaktor, wie du sagst, sondern vielmehr proportional mit der Periodendauer deiner PWM. Der "Dimmfaktor"(Tastverhältniss) wäre bei deinem letzten Programm in Wirklichkeit das Verhältniss zwischen den "250" und den "10" bzw. "11" , das Ändern der "250" alleine wirkt sich also auf die Frequenz viel stärker aus als auf das Tastverhältniss.
 
Hallo Kani,

ich glaube, das kann ich dir erklären ...


CodeBox C
#include <avr/io.h>

int main (void)
{ // Port-Iniitialisierung
DDRD = 0b11111111; //PORTD auf Ausgang (ok)
PORTD = 0b11111111; //LEDs aus (sonst am Anfang an)
// PDx----Widerstand---|<----+5V

int pwm_counter=0; // PWM-Zaehler initialisieren (der Rampenzaehler)

while(1) // Hauptschleife (auf immer und ewig)
{

pwm_counter++; //pm_count jeden Schleifendurchlauf +1

// |___Puls____|----Pause----|_____... Pegel am Ausgang
// 0 <- 10 -> 250 => Wert des Rampenzaehlers
//Zeit der "An-Phase" (Puls) (ok)
if(pwm_counter <=10) //Bei Gleich-/weniger als 10 Schleifendurchläufe...
{
PORTD = 0b00000000; //...LED an (Low da LEDs an +5V) (ok)
}
if(pwm_counter >10) //Bei mehr als 10 Schleifendurchläufe... (mach es so :)
{
PORTD = 0b11111111; //...LED aus bis... (das ist die Pause) (ok)
}

//Zeit der "Aus-Phase" (da ist der Denk-Fehler)
// Das ist deine PWM-Frequenz - also wie hoch die Frequenz
// des PWM-Signals sein soll
if(pwm_counter == 250) //...250 erreicht. (PWM-Rampe neu starten)
{
pwm_counter = 0; //Alles von vorne (Rampe neu beginnen lassen)
}
}
}

Ich hab nur das Problem, dass die LED nicht ganz ausgedimmt werden kann. Wenn sie nurnoch schwach leuchten tut sich lange nichts mehr bis die LED an zu blinken/flackern anfängt.
Das glaube ich gerne. Du änderst ja auch die Frequenz und nicht das
Puls/Pause-Verhältnis. Die LEDs sind also immer 10 Durchläufe an (immer!).
Du änderst dann nur die restliche Zeit die sie nach der An-Phase aus bleiben
sollen. Damit läuft deine Haupschleife schneller von 0 bis zum Endwert und
dadurch wird die gesamte Signal-Frequenz höher.

Frequenz = 1 / Signaldauer

Also 1 durch (Pulszeit + Pausenzeit) ist deine PWM-Frequenz.
Bei Zeit in Sekunden kommt die Frequenz in Hertz bei raus.
Bei Millisekunden sind es Kilohertz und bei Microsekunden Megahertz.

Du mußt lediglich den Wert 10 in beiden Vergleichen durch die selbe
Variable ersetzen. Wenn Du der Variable dann einen Wert zwischen
0 (aus) und 250 (voll) zuweist, dann kannst Du dein Puls/Pause-Verhältnis
verändern und damit die Helligkeit. Die Frequenz bleibt dabei auf 250 Durchläufe.

Das sollte Dir erstmal weiterhelfen.

Gruß
Dino
 
Habs noch ein bissichen einfacher gemacht.
Jetzt muss man nur einen Wert ändern.


CodeBox C

#include <avr/io.h>

int main()
{
DDRD = 0b11111111; //PORTD auf Ausgang
PORTD = 0b00000000; //LEDs aus (sonst sonst am Anfang an)

int pwm_counter=0;

while(1)
{

pwm_counter++; //pm_count jeden Schleifendurchlauf +1
//Zeit der "An-Phase" von 0 an
if(pwm_counter >=30)//Zeit der "Aus-Phase" bis zum Neuanfang der Schleife
{
PORTD = 0b11111111;
}
else
{
PORTD = 0b00000000;
}

if(pwm_counter == 30) //...250 erreicht.
{
pwm_counter = 0; //Alles von vorne
}
}
}
 
Ich frage mich nur, wieso es alle so kompliziert machen?!
 
Ich meine ja nur , weil ich bein Googlen immer auf Programme gestoßen bin, die mindestens 20 Zeilen.

EDIT: So langsam bin ich auch in die Lust gekommen, zu Programmieren. Wenn man es sieht wie es funktioniert, ist das Erfolgserlebnis geiler. :p



CodeBox C


#include <avr/io.h>

int main()
{
DDRD = 0b11111111; //PORTD auf Ausgang
PORTD = 0b00000000; //LEDs aus (sonst sonst am Anfang an)

DDRB = 0b00000000; //Taster auf Eingang
PORTB = 0b00000000; //Int. Pullups deaktivieren (Habe externe)


int test;
int pwm_counter=0;
static unsigned char zustand_taster1;

while(1)
{
if(zustand_taster1 == 0 && !(PINB & (1<<PB0))) //Taster wird gedrueckt (steigende Flanke)
{
zustand_taster1 = 1;

test++;
}
else if (zustand_taster1 == 1 && !(PINB & (1<<PB0))) //Taster wird gehalten
{
zustand_taster1 = 2;
}
else if (zustand_taster1 == 2 && (PINB & (1<<PB0))) //Taster wird losgelassen (fallende Flanke)
{
zustand_taster1 = 3;
}
else if (zustand_taster1 == 3 && (PINB & (1<<PB0))) //Taster losgelassen
{
zustand_taster1 = 0;

}


pwm_counter++; //pm_count jeden Schleifendurchlauf +1
//Zeit der "An-Phase"
if(pwm_counter >=test)
{
PORTD = 0b11111111;
}
else
{
PORTD = 0b00000000;
}
//Zeit der "Aus-Phase"
if(pwm_counter == 30) //...250 erreicht.
{
pwm_counter = 0; //Alles von vorne
}

if(test == 30)
{
test = 0;
}
}
}

Wenn eine aufsteigende Flanke am Taster erkannt wird, wird die LED heller bis sie voll an ist und geht wieder aus.
 
Hi Kani,

Habs noch ein bissichen einfacher gemacht.
Jetzt muss man nur einen Wert ändern.
in der Kürze liegt die Würze :D



CodeBox C

#include <avr/io.h>

int main()
{
DDRD = 0b11111111; //PORTD auf Ausgang
PORTD = 0b00000000; //LEDs aus (sonst sonst am Anfang an)

int leucht=30; // 30 ist 100%
// 15 ist die Hälfte von 30 also 50% Puls/Pause
// Das sind dann 50% Helligkeit
// 7 wären dann ungefähr 25%

int pwm_counter=0;

while(1)
{

pwm_counter++; //pm_count jeden Schleifendurchlauf +1
//Zeit der "An-Phase" von 0 an
if(pwm_counter >= leucht)//Zeit der "Aus-Phase" bis zum Neuanfang der Schleife
{
PORTD = 0b11111111;
}
else
{
PORTD = 0b00000000;
}

if(pwm_counter == 30) //...250 erreicht.
{
pwm_counter = 0; //Alles von vorne
}
}
}

Sieht gut aus. Das was jetzt eingestellt ist, sind 100% an. Ich hab nur mal
den Einstellwert vor die Schleife gezogen.

Hier ein simulierter Durchlauf durch dein Programm ...


CodeBox PWM

---|___Puls___|---Pause---|___Puls___|---Pause---|_.. 0=LEDs an / 1=LEDs aus
|0 <- licht -> 30|0 <- licht -> 30|0 - - - licht (Einstellwert)
| 4 8 12 16 20 24 28 30| 4 8 12 16 20 24 28 30| - - - pwm_counter


Denn mal viel Spaß beim dimmen :D

Gruß
Dino
 
Jap, ich habe die Frequenz auf 255 gestell.

Hendriks Transceiver wertet später die DMX-Adressen so aus:
if(DMXField[0] und dann einfach die Anweisung, also < als Kanalwert 125 dann das machen usw.

Diesen Wert kann man dann doch einfach in eine Variable speichern und bei mir im Programm mit Test ersetzen.
 
Hi Kani,

Jap, ich habe die Frequenz auf 255 gestell.
Dann kann man den Dimmwert jetzt von 0 bis 255 ändern. Also in dem
Sinne ein 8-Bit Software-PWM :D

Hendriks Transceiver wertet später die DMX-Adressen so aus:
if(DMXField[0] und dann einfach die Anweisung, also < als Kanalwert 125 dann das machen usw.

Diesen Wert kann man dann doch einfach in eine Variable speichern und bei mir im Programm mit Test ersetzen.
:confused: Das verstehe ich jetzt nicht genau was du da machen willst :confused:

Also ich versuch mal was.. Eventuell kommen wir dadurch auf einen
gemeinsamen Gedanken-Nenner ;) ...

Also wenn ich das richtig erkannt habe dann ist das, was Henndrick da
zusammengedreht hat ein DMX512-Empfänger. Das heißt also das irgendein
Lichtpult, PC-Software, ... die Lichtanlagen-Steuerdaten auf den DMX-Bus
sendet ...

--InitPuls---Kanal1---Kanal2---Kanal3---....---Kanal511---Kanal512---InitPuls---Kanal1---

Ein Kanal wird dabei durch 8-Bit repräsentiert. Also kann man jeden Kanal
von 0 bis 255 dimmen (Das sind dann am Ausgang 0...100% oder 0..10V).

In dem anderen Thread hatten wir ja gemeinsam vor, den DIP-Switch für
die Start-Kanal-Einstellung des Empfängers durch einen ATmega mit
Up/Down-Tasten und 7-Segment-Multiplex-Anzeige zu ersetzen, weil man
dann nicht im Binär-System rumpopeln muß. Also ein ATmega auf dem
DMX-Board von Hendrick mit der DMX-Empfänger-Software und ein ATmega
auf nem anderen Board mit der UpDown/Anzeige/DIP-Schalter-Simulator -
Software.

Das was du da oben geschrieben hast ...
Also der Kanalwert, das hört sich nach dem Dimm-Wert an. Das wäre in
deinem Programm die Variable "leucht".
DMXField[0] ?? Ist das der Dimmwert im ersten Kanal den der DMX-Empfänger
vom Bus holen soll (also der Kanalwert) oder ist das seine Start-Adresse ?
Hier bin ich verwirrt was du da machen möchtest.

Bei einem DMX-Receiver gibt man die erste Adresse an, die er empfangen
soll. Wenn er zB 4 Kanäle hat und man sagt ihm, das er die Startadresse
235 hat, dann holt er die Kanäle 235,236,237,238 vom Bus und gibt die
Werte der 4 Kanäle (also 0...255) als 0..10V-Signal an seinen Ausgängen
raus. Also 0x00 als 0V und 0xFF als 10V. Mit dem Analog-Signal betreibt
man dann die Dimmerstufen, die das dann in Phasenanschnitt von 230V
umsetzen.

So kenne ich das ...

Erklär einfach noch mal im Detail was du da vorhast. Ich kann deinen
Gedankengängen im Moment nicht ganz folgen...

Kann auch ruhig ein längerer Text mit Skizzen werden. Ein Bild sagt
manchmal mehr als tausend Worte ;)

Gruß
Dino
 
Hi Kani,

EDIT: So langsam bin ich auch in die Lust gekommen, zu Programmieren. Wenn man es sieht wie es funktioniert, ist das Erfolgserlebnis geiler. :p
na sach ich doch, wenn man die Lösung selber gefunden hat und man sieht das
es funktioniert dann freut man sich wie ein Schneekönig :D

Gruß
Dino
 
Deine Annahme war schon ganz richtig. Dem Controller sagt man, was er machen in dem man folgend vorgeht:


CodeBox c
if (DmxField[0]<100)
{
// PA0= HI und PA1= LO
PORTA |= (1<<PA0);
PORTA &= ~(1<<PA1);
}
else if (DmxField[0]>155)
{
// PA0= LO und PA1= HI
PORTA |= (1<<PA1);
PORTA &= ~(1<<PA0);
}
else
{
// PA0= LO und PA1= LO
PORTA &= ~(1<<PA1);
PORTA &= ~(1<<PA0);
}
}

Die Zahl in den [] sagt dem Controller, bei welchem Kanal er das machen soll. Hierbei geht es jetzt um eine Motorsteuerung. Die Zahl hinter < bzw. > ist der Kanalwert.
 
Hallo Kani,

Dann möchtest Du also Änderungen in der DMX-Software machen, damit sie dir die
gewünschten Steueraufgaben bei einem bestimmten Kanalwert erledigt.

Deine Annahme war schon ganz richtig. Dem Controller sagt man, was er machen in dem man folgend vorgeht:


CodeBox c
if (DmxField[0]<100)
{
// PA0= HI und PA1= LO
PORTA |= (1<<PA0);
PORTA &= ~(1<<PA1);
}
else if (DmxField[0]>155)
{
....
...
..

Die Zahl in den [] sagt dem Controller, bei welchem Kanal er das machen soll. Hierbei geht es jetzt um eine Motorsteuerung. Die Zahl hinter < bzw. > ist der Kanalwert.
Das mit dem [ und ] das ist ein Array (ein Datenfeld, eine Liste, ...).
Ich schätze mal das wird in der DMX-Software in etwa ao ablaufen ...
Das Programm liest den Datenstrom auf dem DMX-Bus, bis der Kanal ankommt,
der dem eingestellten Anfangskanal entspricht (z.B. 235). Dieser Kanalwert wird
dann in DMXField[0] übernommen. Wenn er 4 Kanäle empfängt, dann sieht es also
mit dem Start-Kanal 235 folgendermaßen aus ...
Kanal 235 => Kanalwert => DMXField[0]
Kanal 236 => Kanalwert => DMXField[1]
Kanal 237 => Kanalwert => DMXField[2]
Kanal 238 => Kanalwert => DMXField[3]
Das ist bestimmt nicht so programmiert, das der DMX-Receiver alle 512 Kanäle
empfängt. Das würde nämlich dann mit dem RAM im ATmega ziemlich eng werden.
Vor allem in C oder BASCOM. In Assembler könnte man das in Controller mit 1024
Byte reinzwängen (also mindestens ATmega16 oder 32) in nen Mega8515 oder 8535
würde es bei allen Kanälen definitiv nicht reinpassen - die haben nur 512 Byte SRAM
und der Stack braucht ja auch ein wenig ;)

Zur Erklärung eines Arrays, einer Liste, ...

Du hast einen Variablennamen wie jede andere Variable auch und du hast einen
Typ wie bei jeder anderen Variable. Also z.B.

"Hausnummer" vom Typ Integer

Jetzt könnte man der Hausnummer einen Wert zuweisen ..

Hausnummer =12;

Wenn man jetzt eine 2te Hausnummer ablegen möchte dann könnte man eine
weitere Variable mit anderem Namen nehmen. zB ...

Hausnummer2 = 25;

Das ist bei manchen Programmen aber nachher aber sehr umständlich zu verarbeiten.
Darum nimmt man z.B. Arrays oder Listen ...

Hausnummer[0] = 12;
Hausnummer[1] = 25;

Das ist also in diesem Fall einfach eine Liste von Integerwerten, bei der man über die
Zahl in den eckigen Klammern sagen kann, welche Zeile der Liste man bearbeiten
möchte. Die Listen fangen bei manchen Sprachen mit 0 als ersten Wert an und bei
manchen anderen Sprachen mit 1 . Da muß man also etwas aufpassen.

Es gibt auch noch mehrdimensionale Arrays. Ich weiß jetzt nicht, wie die in C
geschrieben werden aber ich mach einfach mal ein Beispiel ...

Farbe[4,6] = 3;
Farbe[5,7] = 2;

Das wäre ein zweidimensionales Array. Als ob man Werte in die Kästchen eines
Karopapiers schreiben würde und dann die Zeilen und Spalten adressiert.

Das kann man natürlich noch erweitern. Man könnte zB auch folgendes schreiben ...

Erbse[3,6,2] = 12;

Das kann man sich wie in einem Würfel vorstellen. Also sozusagen mit Raum-
Koordinaten. Als ob man den Punkt in einem Raum adressieren will (Länge, Breite,
Höhe).

Soviel zu Listen, Arrays, Datenfeldern. ...

Wolln mal sehen ob man da was an der Controllersoftware drehen kann. Besteht die
Möglichkeit, mir die mal im Source zukommen zu lassen? Wenn ich dir dabei helfen
soll oder ist das wegen Copyright von Hendrik nicht möglich ?

Gruß
Dino
 
Hi Kani,

Hi Dino, sehr freundlich von dir.
Ich kenne Arrays schon.
Na denn ... Ich war mir nicht sicher und da hab ich mir gedacht ...
Da es ne Menge Array-Zeugs gibt... (zB assoziative Arrays bei Perl - oder
auch Hash-Tabellen oder Hashes genannt :D )

Hier mal ein ANs von Hendrik:
Interessant ist DMX-Empfang.
Einen Kurs dafür gibt es hier:
http://dmxcontrol.de/wbb2/thread.php?threadid=2237&threadview=0&hilight=&hilightuser=0&page=1

Kurs II:
http://dmxcontrol.de/wbb2/thread.php?threadid=2240

Er darf nur das mit dem PWM nicht verraten weil das bei einer Firma Teil der Patentierung ist oder so.
Ich bau das so auf wie ich denke und dann sehe ich weiter...
Schon mal kurz reingeschaut. Muß ich mir in ner Mußestunde mal ansehen.
Mal sehen wann ich da genug Zeit habe ...

Gruß
Dino
 
LCD-Displays

Hi Kani,

ich wollte mal Fragen, ob ihr irgendwelche guten Einsteigerprojekte kennt?!
Ich finde diese LCDs ganz interessant (http://www.pollin.de/shop/shop.php?cf=produkt.php&ts=0&p=OTg4OTk4).
Eine Uhr baut jeder, obwohl das auch Interesannt wäre.
also den Text nochmal (gerade mit halb fertigem geschreibsel den Tab
dichtgemacht :( Mist!)
Als Anfänger würde ich die Finger von Grafikdisplays lassen. So verlockend
das auch sein mag. Die sind nicht ohne und dann ist man schnell frustriert
wenn es nicht so will wie man möchte.

Nimm erst mal ein Character-Display möglicht mit nem bekannten Kontroller
oder mit einem von dem du das richtige Datenblatt von dem verbauten
Controller-Chip bekommen kannst (Nicht nur ne Anschlußskizze mit
mechanischen Schraubmaßen!)

Ich benutze zur Zeit bei mir eins mit 24Zeichen/8Zeilen mit nem M50530-
Controller und das PC1602 von Pollin mit ST7066U-Controller. Die lassen
sich beide recht gut verwenden. Wobei das PC1602 wegen dem Stecker
nix für Anfänger ist (nur 1mm Pin-Abstand).

Such dir ein Display mit Lötanschlüssen (2,54mm Raster) und Controllern
wie HD44780, M50530.

Ich hätte da folgendes im Auge ...

- LCD-Modul SC1604A (Best.Nr. 120 572) 7,95 EUR => KS0066 Controller
von dem Controller habe ich die Datenblätter hier

- LCD-Modul HLM8070 (Best.Nr. 120 387) 3,95 EUR => M50530 Controller
Den Controller benutze ich selber (mit Assembler)

- LCD-Modul WINTEK WD-C2704M-1HNN (Best.Nr. 120 232) 4,95 EUR
dieses Display hat einer hier im Forum auch schon unter BASCOM laufen
es hat aber 2 Controller. Man muß also einmal für die obere und einmal
für die untere Display-Hälfte initialisieren. Ist sehr groß und die Steuer-
sequenzen sind bei Pollin mit runterzuladen.

Entscheiden mußt du dich aber im Endeffekt selber. Such dir aber kein
zu teures aus, damit der Frust nicht zu groß wird wenn es nicht so
will wie du möchtest.

Denk daran. Du mußt dir das gesamte Timing selber programmieren wenn
es für den Controller in C keine Bibliothek gibt. Wie heißt es so schön ...
Bitgezappel. Also Millisekunden- und Microsendunden-Gewurschtel :D

Gruß
Dino
 
Alles klar, danke Dino. Ich schau dann mal, was es da so gibt.
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)