Forum: Mikrocontroller und Digitale Elektronik AVR + Schrittmotor + Bascom verständnisproblem


von Nico R. (lordnicon)


Angehängte Dateien:

Lesenswert?

Hallo Liebe Forengemeinde

Da hier schon sehr sehr oft über das Thema Schrittmotoren usw. 
Lamentiert wurde möchte ich euch garnicht lange mit einem Roman belasten 
und schmeisse meine Frage einfach mal in den raum ...


Ich Zerbreche mir seit Tagen den Kopf wie es doch Teschnisch am besten 
umzusetzen wäre einen ATMEGA32 oder 644 über Serielle Schnittstelle 
vernünftig zu steuern...

Was ich bereits habe und mit welchem Aufbau ich Arbeite.

Ich habe eine voll Funktionsfähige 3D-Step Schrittmotor Steuerkarte mit 
L297 + L298 IC's in Betrieb und eine selbstgebaute ATMEGA Testplatine..

Jetzt habe ich durch ein sehr Simples Bascom Programm ( SIEHE ANHANG ) 
die momentan 2 Schrittmotoren mit ca 1 Khz auf Tastendruch angesteuert 
... ist ja soweit keine hexerei ...

Mein Verständnisproblem ist nun aber folgendes ...

Wie geht man bei einem Atmega am besten her wenn ich ihm über die 
Serielle schnittstelle eie befehlskette übergeben möchte um ihm 
Geschwindigkeit und Steps der achsten mitzuteilen.

Und daraufhin müsste er ja jeden Motor Separat anlaufen lassen ( 
beschleunigungskurve ) und ihn nach "X" steps wieder Bremsen .

Wie macht man sowas Programmierteschnisch ? da der AVR ja nur einen 
Thread hat indem er alles abarbeiten muss ... Das geht irgendwie nicht 
in meine Birne, da er Ja wenn er den einen Motor z.B. Grade beschleunigt 
und den anderen Bremsen soll einen der beiden Arbeiten unterbrechen 
müsste ...

Ich weiss das hört sich echt wirr an .. Aber vieleicht greift ihr mir ja 
etwas unter die Arme oder gebt mir den richtigen Denkanstoß ...

Vielen Dank an euch ....

PS: Ihr müsst mir keinen Quellcode vorkauen ( wenn ihr wollt werde ich 
aber nicht Schlagen ;-)  ) aber für ein paar Logische erklärungen wäre 
ich euch sehr Dankbar ....

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

An und für sich ist es einfach: zwischen zwei Takten für den einen Motor 
hat der Prozessor nichts zu tun. Und in der Zeit bearbeitet er die 
anderen und macht die Kommunikation.
Wenn z.B. eine Schrittfrequenz von 1kHz an einer Achse eingestellt ist, 
dann macht der Prozessor für diese Achse bei z.B. 1 Million 
Operationen/sec jede Millisekunde (1/1kHz) vielleicht 200 Operationen, 
das sind dann 200us. Und damit hat diese eine Achse gerade mal 20% der 
Rechenleistung verbraucht. Die 2. und 3.Achse dann auch noch jeweils 
20%, sind in der Summe 60% der Rechenleistung für die 3 Achsen. Bleiben 
noch 40% übrig für die Kommunikation.

Sodele.
In Assember und C ist das klar: Timer loslaufen lassen. Dann 3 
Capture-Register mit zugehörigem Interrupt einrichten und (fast) fertig. 
Dann noch die serielle Schnitte mit Interrupt bedienen und ein wenig 
drumherum.
Und weil aktuelle uCs noch wesentlich schneller rennen als mit 1 Mops 
bleibt da ausreichend Luft.
Jetzt hast du 1 kleines Problem: wie geht das mit Bascom?
Aber du wolltest ja nur die Idee ;-)

von uwe (Gast)


Lesenswert?

Hallo Nico,

also ich wuerde da folgendermassen rangehen:

Timer 0 toggelt Portc.1
Timer 2 toggelt portc.4
beide timer prescale=1024
dimensioniere: speed-c1 als byte, speed-c4 als byte, gaspedal-c1 und 
gaspedal-c4 als byte

der timer Toggelt den Port immer bei Ueberlauf, also dem entsprechenden 
Timer Interrupt. der Timer muss gucken ob speed=0 ist und dann den timer 
wieder auf 0 setzen ohne zu toggeln.
ist speed nicht null (0 < speed*) dann soll er toggeln und den Timer auf 
den Wert "speed*" setzen.

Zweck ist das die Timer immer gleichmaessig den Pin wackeln lassen (bei 
0 aber nicht) und speed* sagt wie lange es dauert bis der timer wieder 
neu ausloest, also der naechste schritt kommt. ist speed*=50 laeuft der 
Timer dann bei 50 los und toggelt wieder bei dem naechsten ueberlauf.

speed kann man entweder mit dem gleichen timer hoch- oder runterzaehlen 
(die Rampe), das waere dann z.b. (gaspedal=0 ist bremsen, 1 kein gas, 2 
gas geben)
select case gaspedal
    case = 0: if speed<>0 then
              decr(speed)
              endif
    case = 1:  'nix machen
    case = 2: if speed<240 then (!)
              incr(speed)
              endif
    else
end select
(Steilere Rampe bekommst du durch addition bzw subtraktion von 2, 3 oder 
mehr, aber aufpassen das speed* nicht ueberlaeuft) ein geringerer wert 
ist sicherlich erstmal anschaulicher.

240 als maximalwert fuer den timer heisst, er muss mindesten 15 schritte 
machen (bis 255) um enen neuen schritt auszuloesen (entspricht dann 
ungefaehr deinen 1000Hz)
(18MHz  prescaler 1024  mind.15 schritte) das bedeutet er laeuft mit 
mindestens 68Hz (255 Timerschritte) oder ist aus, wenn es eben nicht 
toggelt.

Damit gibst du nur vor ob der bei jedem schritt schneller werden soll, 
oder nicht. du kannst den wert fuer speed auch direkt vorgeben und kein 
gas geben (gaspedal* = 1), dann hast du halt keine rampe.

Oder du zaehlst die Rampe mit dem Timer1. (wuerde ich jetzt nicht 
machen)

Jedenfalls kann dein Hauptprogramm nun in ruhe gucken in welche richtung 
er drehen soll, dazu vielleicht zuerst bremsen, die pins umsetzen, und 
wieder gas geben und die serielle und das LCD bearbeiten. der 
eigentliche takt kommt immer vom timer, abhaengig davon ob Gaspedal 0, 1 
oder 2 ist.
alle werte werden vom hauptprogramm an globale variablen uebergeben die 
die Timer dann benutzen.

in der Hoffnung das das so funktioniert ;o))) ich hab mir das bis genau 
dahin ueberlegt, hier bastle ich gerade (d.h. das buegeleisen wird 
gerade warm ;o))

bye uwe

von Peter Diener (Gast)


Lesenswert?

Hallo,

ich würde einen Timer einrichten, der mit einigen kHz einen Interrupt 
auslöst. In diesem würde ich dann entscheiden, ob ein Motor einen Step 
erhält oder nicht. Nach wievielen Interrupts der Motor gesteppt wird 
hängt dann von der gewünschten Geschwindigkeit ab. Dafür könnte man in 
arrays definierte Rampen fahren, wobei man vorher berechnen muss, wann 
die "down-Rampe" startet, dass bei der Zielposition gestoppt wird.

Die Kommunikation würde ich asynchron über interrupts lösen, so dass 
eine Verfahranforderung (absolute Sollposition aller Achsen) global zur 
Verfügung gestellt wird.
Sollposition - Istposition ist dann der gewünschte Verfahrweg. Wenn er 
lang genug ist, beschleunigt man die "up-Rampe" bis zur maximalen 
Geschwindigkeit und rechnet aus, wann die Bremsrampe starten muss 
(Zielposition - n Ticks). Ist der Verfharweg kurz, darf eben nicht voll 
beschleunigt werden, man muss vorher beginnen zu bremsen. Bei 
geschickter Programmierung geht das ohne Fallunterschwidung.

Grüße,

Peter

von Nico R. (lordnicon)


Lesenswert?

Hey Super

Finde ich klasse das ich heute morgen direkt 3 gute Antworten bekommen 
habe, das hat mir den weg über die Timer aufgezeigt ...

Ich danke euch drei bis hier her erstmal für eure mühe mir bei meinem 
Problem zu helfen ...

Ich werde heute Nachmittag zuhause mal versuchen die lösung von UWE 
umzusetzten da mir dieser beitrag in meiner momentanen situation am 
besten weiter hilft ...

Ich werde dann heute Abend oder morgen berichten wie es gelaufen ist ...

PS: Aber bitte lasst euch nicht abhalten wenn ihr noch ein paar ideen 
habt immer her damit. Bekanntlich denken kommen die Besten Ideen immer 
in der Summe zusammen ... Ich werde regelmäßig hier rein schauen ..

Vielen Dank nochmal an euch drei .... bis Später !

von eProfi (Gast)


Lesenswert?

Also, ich würde das so lösen:

der Timer "gehört" dem Motor, der momentan am schnellsten dreht, d.h. 
der insgesamt am meisten Schritte machen muss.

Die langsameren werden über eine DDS = Bresenham's Linienalgo gesteppt.

z.B. Motor0: 10 Schritte, Motor1: 5 Schritte, Motor2: 4 Schritte
M0 M1 M2  m0sum   m1sum   m2sum
 0            0       0       0
 1        32768 s 16384   13107
 2  1     32768 s 32768 s 26214
 3     1  32768 s 16384   39321 s -> 6553
 4  2     32768 s 32768 s 19660
 5     2  32768 s 16384   32767
 6  3     32768 s 32768 s 45874 s -> 13106
 7        32768 s 16384   26213
 8  4  3  32768 s 32768 s 39320 s -> 6552
 9        32768 s 16384   19659
10  5  4  32768 s 32768 s 32766 //m2-Schritt wird wg. Abrunden geskippt

Wenn Du es optimal machen willst (auch nicht sooo schwer, aber 
eigentlich unnötig), muss M2 "sich den Timer kurz ausleihen", um genau 
zwischen den M0-Schritten 2 und 3 seinen M2-Schritt 1 reinzulegen.

Wie funktioniert's?
Du brauchst 3 16bit-Zählvariablen, auf diese addierst Du bei jedem 
Schritt des schnellsten Motors eine (FixedPoint)-Variable:
in C würde das so aussehen:
uint16_t m0, m1, m2;
uint16_t m0steps, m1steps, m2steps;
uint16_t m1sum=0, m2sum=0;


Wobei hier noch eine "Umleitung" stattfindet:
m0 ist nicht zwangsweise Motor0, sondern die Bitmaske des Pins des 
momentan schnellsten MotorX.
m0=1;//Bitmaske des schnellsten Motors
m1=2;//Bitmaske eines anderen Motors
m2=4;//Bitmaske eines anderen Motors
m0steps=10; m1steps=5; m2steps=4;//Beispiel


//folgende 2 Zeilen müssen 32bit-Berechnungen sein:
int16_t m1add=(32768L * m1steps) / m0steps;//=16384
int16_t m2add=(32768L * m2steps) / m0steps;//=13107,2


void timerISR(void){
  do1step(m0);//schnellster Motor steppt auf jeden Fall
  if((m1sum+=m1add)>=32768){m1sum-=32768;do1step(m1);}
  if((m2sum+=m2add)>=32768){m2sum-=32768;do1step(m2);}
  }

die Routine do1step sieht also folgendermassen aus:
void do1step(char mx){ //könnte man natürlich auch inlinen
  motorport &= ~mx; //betreffendes Pin low (mache Schritt)
  delay(1);
  motorport |=  mx; //betreffendes Pin wieder hoch
  }


Wg. des Abrundens (13107,2 -> 13107) muss man noch eine Lösung finden 
(--> Bresenham).

von Nico R. (lordnicon)


Lesenswert?

Hallo eProfi

Das sieht schon ganzschön heftig aus was du da gepostet hast .. hört 
sich in jedem fall plausibel an, nur tue ich mich momentan bisschen 
schwer mit der Umsetzung der hier gegebenen Tips ...

Bei der versuchten umsetzung von Uwe's Idee habe ich im moment noch das 
Problemm das meine Motoren so vor sich hin surren mit ca 60 Hz aber ich 
kann sie einfach nicht beschleunigen ... Irgendwie mache ich da was 
falsch bei der umsetzung mit den Timern

@ Uwe
Hast du schon den Code in Bascon umsetzen können ? hat sich so angehört 
alsob du auch an sowas arbeitest ...

@eProfi
Ich nehme an du hältst nicht so viel von Bascon bsw. Basic oder. Das du 
mir das vieleicht in Basic erklären könntest ?

PS: Zwischenfrage
Da ich ja nach möglichkeit keine SChritte verlieren möchte muss ich ja 
gewährleisten das alle Takte an die Motoren übergeben werden... Meine 
Frage ist jetzt folgende, was passiert eigentlich wenn z.B. 2 Timer 
gleichzeitig einen interupt auslösen ! Werden dann beide Sprungroutinen 
nacheinander abgearbeitet oder wird eine der beiden Routinen garnicht 
abgearbeitet ???

von Gast (Gast)


Lesenswert?

>Da ich ja nach möglichkeit keine SChritte verlieren möchte muss ich ja
>gewährleisten das alle Takte an die Motoren übergeben werden... Meine
>Frage ist jetzt folgende, was passiert eigentlich wenn z.B. 2 Timer
>gleichzeitig einen interupt auslösen ! Werden dann beide Sprungroutinen
>nacheinander abgearbeitet oder wird eine der beiden Routinen garnicht
>abgearbeitet ???

Nacheinander.
In meiner Schrittmotorsteuerung mit ATMega2560 laufen die 4 16bit Timer 
mit Interrupt. Mit jedem Timerinterrupt wird 1 Motor angesteuert, also 4 
insgesamt. Zusätzlich läuft ein 8bit-Timer mit Interrupt im 10ms Abstand 
als Systemtimer und zur Tastenentprellung, sowie der UART-Interrupt für 
die Kommunikation mit 115200Baud. Das funktioniert ganz gut. Alle 4 
Motoren können gleichzeitig laufen ohne dass es merklich unrunden Lauf 
gibt. Die Interruptroutinen sind zwar Codemäßig sehr lang, aber effektiv 
hält der µC sich nur sehr kurz in den einzelnen Interrupts auf, da immer 
nur ein Teil des Codes ausgeführt wird (verschiedene Motor-Stati). Die 
Rampen berechne ich übrigens zur Laufzeit im Timer-Interrupt. Lediglich 
vor dem Losfahren werden diverse Grundparameter für die Rampen 
vorberechnet. Der Rest halt on the fly.

von Nico R. (lordnicon)


Lesenswert?

Kannst du mir denn behilflich sein zumindest einen motor vernünftig zum 
laufen zu bekommen ? mit Beschleunigung usw.

Ich weiss das man sowas nicht gerne macht, schließlich steckt da meist 
ne menge Gehirnschmalz drin ... Ich würde nur mein Projekt gerne vorran 
treiben und stecke aber Arbeitstechnisch momentan so tief in Arbeit das 
ich mich auf mein Hobby nicht voll Konzentrieren kann ...

Wir könnten das auch Via E-Mail klären wenn du nicht möchtest das der 
Code Public wird...

Mein Projekt welches ich vorhabe ist weder Komerzieller Natur noch 
irgendein Auftrag o.ä. sondern schlicht und einfach mein eigener 
Basteltrieb!
Es soll erstmal ein ganz simpler Stiftplotter werden der über mein 
selbst geschriebenes Programm via koordinaten geführt werden soll ....


Mfg: Nico

von Gast (Gast)


Lesenswert?

Code kann ich nicht rausgeben, weil ich dann Ärger mit meinem Boss 
kriegen könnte.

Ich habe mich bei den Rampen im Wesentlichen an diese Beschreibung 
gehalten.

http://www.embedded.com/columns/technicalinsights/56800129?_requestid=309459

Das gleiche ist auch nochmal in der Applikation-Note 446 von Atmel 
erklärt.

http://www.atmel.com/dyn/resources/prod_documents/doc8017.pdf

Vom Prinzip her sieht das so aus:
- Befehl kommt rein (Zielpunkt, Beschleunigung, Verzögerung, 
Maximalgeschw.)
- In einer Start-Routine werden nun die Grundparameter für die Rampen 
ausgerechnet (wann erreicht der Motor die Maximalgeschw., wann muß ich 
anfangen zu bremsen, erreiche ich vieleicht garnicht die Vmax?)
- In dieser Routine wird dann auch der erste Timer-Wert berechnet und 
der Timer gestartet.
- Wenn der Timer-Interrupt kommt, wird das Clock-Signal für den Motor 
erzeugt und der nächste Timer-Wert berechnet, anschließend der Interrupt 
wieder verlassen.

Im Interrupt selbst gibt es verschiedene Stati.
1- Motor STOP -> Hier wird der Timer gestoppt und ggf. der Motor 
komplett Stromlos gemacht.
2- Beschleunigen -> hier wird immer der nächste Timer-Wert berechnet und 
überprüft, ob Vmax erreicht ist oder ggf. schon wieder gebremst werden 
muß.
3- Fahren -> nur einen Impuls generieren und prüfen ob gebremst werden 
soll.
4- Bremsen -> hier wird immer der nächste Timer-Wert für die Verzögerung 
berechnet.

Bei mir sind im Interrupt noch einige weiter Stati, weil ich noch eine 
Referenzfahrt (Endschalter) und einen Manuellen Modus mit drinhabe.

Das Geheimnis ist nun, dass im Interrupt immer nur der Codeteil 
ausgeführt wird, dessen Status gerade aktiv ist. Dadurch ist der 
Interrupt relativ kurz.

Sachen die ich immer im Timer-Interrupt mache sind:
- Prüfen ob ein Endschalter ausgelöst ist, dann den Schritt nichtmehr 
machen.
- Den Schritt erzeugen.

Man kann die Rampen auch über eine Tabelle erzeugen, oder linear, das 
ist aber nicht so schön (von der Optik her) wie über den Algorithmus der 
in den obigen Quellen beschrieben ist.

von uwe (Gast)


Lesenswert?

Hallo nico,

du scheinst da ja recht fix zu sein, ich habe genau garkeinen handschlag 
gemacht ;o)

evtl hast du vergessen das der timer, wenn er ausgeloest hat, am ende 
der interruptroutiene natuerlich als aktuellen timerwert die variable 
speed zugewiesen bekommen muss. also, letzte zeile im interrupt:

timer0=speed_c1

sonst laeuft der timer immer wieder bei null los, er soll ja aber z.b. 
bei 150 loslaufen und nach 105 zaehlschritten (105xprescaler) und dann 
das pin toggeln, bzw beim naechsten mal eben nur 104 schritte 
undsoweiter.

HTH, bye uwe

Die Zeit die vergeht waehrend ein interrupt den anderen blockiert ist 
nich schlimm, 1024 takte vergehen bei einem zaehlschritt, da kann der uC 
einiges machen. viele zaehlschritte sind ein motor step. Ein verrueckter 
tick verzoegert den timer so das die sich beim naechsten mal nicht 
wieder treffen, ausser die anzahl der schritte aendert sich 
unterschiedlich (du verstehen? ;o))

von Nico R. (lordnicon)


Angehängte Dateien:

Lesenswert?

Hallo Euch Allen

Also nachdem ich mir hier nochmal Alle vorschläge durchgelesen habe und 
mir paar Kaffee gegönnt habe hat es endlich klick gemacht und ich habe 
ein kleines Prog Geschrieben ( Siehe Anhang )... Und siehe da er macht 
genau das was ich möchte !!

Es ist zwar noch die Grobe Lineare Art der beschleunigung aber man fängt 
ja bekanntlich klein an nichtwahr ... :-D


Kurze erklärung

Beim senden von paar Zahlen über UART passiert folgendes

1 (49) = Beschleunigen
2 (50) = Bremsen, danach setzt er automatosch Gas_x auf 0 bzw. 48 um zu 
togglen
3 (51) = Bremsen

So Die nächsten Kannen Kaffe werden dabei drauf gehen das Ding Bisschen 
Inteligent zu machen und irgendwie vernünftige Rampen zu Programmieren 
...

PS: Die UART behandle ich mit Absicht ohne Interrupt, der pollt dann 
zwar wie ein Irrer aber dadurch bekomme ich wenigstens keine weiteren 
Unterbrechungen. Weiss nicht ob die Idee jetzt so der knaller ist aber 
es fühlt sich nicht grade falsch an ...

Mfg: Nico

von eProfi (Gast)


Lesenswert?

Gut, hier meine Überlegungen:

Du hast physikalisch gesehen folgende Größen:

Zeit, Weg (Count), Geschwindigkeit (Frequ), Beschleunigung (Accel).

Weg ist die Anzahl der Schritte, dafür würde ich mal eine 
32bit-Zählervariable reservieren.
Geschwindigkeit ist die Frequenz, also Xtal  prescaler  Timer.

Beschleunigung ist die Änderung der Frequenz.

in C läßt sich das recht kurz und bündig schreiben:

Count+=Frequ+=Accel;

oder aufgeröselt (ich weiß: es ist nicht 100% das selbe wg. Reihenfolge)
Count=Count+Frequ;
Frequ=Frequ+Accel;

Wenn der Motor stillsteht und Du loslegen willst, setzt Du einfach Accel 
auf einen (positiven=eine Drehrichtung oder negativen=andere 
Drehrichtung) Wert.
Dann wird jedes mal die Frequenz erhöht, solange bis die gewünschte 
Geschwindigkeit erreicht ist (oder Du schon wieder abbremsen (=Accel auf 
einen negativen Wert setzen) musst).

Zum Stehenbleiben setzen wir bei (Frequ == etwa 0)   Accel auf 0.

Das Richtungssignal ist das Vorzeichen der Frequenz.

So, jetzt kommt das größte Problem:
diese 2 Berechnungen müssten theoretisch in immer gleichen Zeitabständen 
durchgeführt werden.
Viel günstiger wäre es jedoch, wenn die Berechnung zu jedem Schritt 
stattfinden würde (zumindest bei hohen Frequenzen).

Dazu wenden wir einen genialen Trick an:
je öfter diese Berechnung wg. sich erhöhenden Frequenz ausgeführt wird, 
desto weniger addieren wir jedes mal:
Count=Count+Frequ/Frequ; //also um 1
Frequ=Frequ+Accel/Frequ;
Timer=Fxtal/Presc/Frequ;  //Fxtal/Presc ist eine Konstante

Vorteil: die Beschleunigung ist absolut konstant  und die 
Frequenzänderung absolut linear.

Um nun richtig in FixedPointarithmetik rechnen zu können, muss man sich 
davon lösen, dass der Wert in Frequ  die echte Frequenz in Hertz ist.
Es ist ein zur echten Hertz-Zahl proportionaler Wert, sowas wie 
milli-Hertz.

Jetzt hast Du was zum Knobeln.... (hoffentlich reicht der Kaffee)

von Nico R. (lordnicon)


Lesenswert?

Hallo eProfi und natürlich der rest auch
So langsam bekomme ich nen durchblick durch die ganze sache, ich werde 
mich am wochenende mal auf den Hintern setzen und versuchen alle ideen 
unter einen Hut zu bekommen. Ich bin mal gespannt ob ich eine anständige 
lösung auf die Beine bekommen kann !!!


Aber wie gesagt immer her mit neuen Ideen und Gedanken ! Man kann nie 
genug davon haben :-D ...

Mfg: Nico

von Nico R. (lordnicon)


Lesenswert?

Guten Morgen euch allen hier

Statusbericht:

Ich habe es am wochenede endlich hin bekommen meine Beschleunigungs und 
Bremsrampen machen genau das was sie sollen ...

Ich lasse sie Linear via Bresenham Algo. berechnen, nachdem die 
beschleunigungskurve nicht das problem war bin ich bald verückt geworden 
die Bremsrampe berechnen zu lassen wegen formelumstellung ... Naja wie 
so oft war die Lösung so simpel das man sich selber oft für doof hält 
;-) ...

Aber manchmal sieht man halt den Wald vor Bäumen nichtmehr ....


So momentan fighte ich da dran die Steuerung intelligent zu machen, 
sprich wann soll wie weit beschleunigt usw ......


Werde hier regelmäßig reinschauen um zu sehen ob es neues gibt !

Mfg: Nico

von Christian R. (cradi)


Lesenswert?

Hallo Nico,

ich habe diesen Thread gefunden, und versuche nun selbst diese Rampen zu 
programmieren. Ich habe alles gut durchgelesen, komme aber nicht weiter, 
bzw. finde nicht mal einen Anfang.

Kannst Du Deinen Lösungsweg beschreiben?

Gruß
Christian

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.