Forum: Projekte & Code Sensirion SHT11 Code


von (prx) A. K. (prx)


Angehängte Dateien:

Lesenswert?

Es gibt hier zwar schon Code dafür, aber für meinen Geschmack ist der 
recht eigentümlich programmiert. Hier geht es ausserdem ohne 
Fliesskommarechnung ab.

von Joachim B. (jojo84)


Lesenswert?

Cool, danke!
Ich versuche mich grad mit verschiedenen Codes an zu freunden, da kann 
etwas Inspiration nicht schaden.
Aber weil ich fast schon den Überblick verloren habe bei 546 Pointern 
und dauernd irgendwelche "errors" war ich fast schon so weit einen 
eigenen Code zu schreiben... *seuz'

von Ron (Gast)


Lesenswert?

Mist! Wieder nur in C. Hat denn keiner mal was in Assembler?

von (prx) A. K. (prx)


Lesenswert?

Kurzanleitung:

Die Leitung SDA benötigt einen externen Pullup-Widerstand.

In config.h müssen die Zeilen SHT11_xxx an die verwendeten Portpins 
angepasst werden. SHT11_LOWRES bestimmt den Messmodus, genau (0) oder 
schnell (1).

In der allgemeinen Initialisierung, also ungefähr am Anfang von main() 
die Funktion sht11_init() aufrufen.

Grundsätzlicher Ablauf einer Messung, gibt Feuchte in hundertstel 
Prozent, oder Fehlercode -32xxx, siehe dazu sht11.h:
1
int16_t 
2
feuchte_messen(void)
3
{
4
    sht11_start_humid(void);
5
    while (!sht11_ready())
6
        ;
7
    return sht11_result_humid();
8
}

Es ist sicher nicht verkehrt, dies so zu erweitern, dass man ggf. 
irgendwann mit Timeout rausfliegt, wenn sich ewig nichts rührt.

von (prx) A. K. (prx)


Lesenswert?

Cut-and-paste Fehler.
1
int16_t 
2
feuchte_messen(void)
3
{
4
    sht11_start_humid();
5
    while (!sht11_ready())
6
        ;
7
    return sht11_result_humid();
8
}

von Harald S. (cornyhunter)


Lesenswert?

Danke,

werde es weier probieren.

Grüsse
Harald

von Johannes S. (demofreak)


Lesenswert?

Klappt einwandfrei, danke.

/Hannes

von Gerd (Gast)


Lesenswert?

Hallo,

ich hab eine Ansteuerung für die SHT-Sensoren in Ethersex integriert. 
Details sind hier zu finden:

http://www.ethersex.de/index.php/SHT

Den Code selbst (unter GPL3+) gibt es hier:

http://github.com/ethersex/ethersex/tree/master/hardware/sht/

Ich habe nicht den Code von A.K. verwendet, sondern was eigenes 
entwickelt. Features:
- Abfragefrequenz einstellbar (gut für lange Leitungen)
- Nur Festkommaberechnungen
- Berechnung der Temperaturkompensation

Viel Spaß damit!

Gerd

von Thorsten (Gast)


Lesenswert?

Hi,

ich nutze diese Lib, habe nur das Problem wenn ich im File config auf 
die höhere Auflösung umschalte stimmt das Ergebnis in der Temperatur, 
ansonsten habe ich statt 25Grad nur 17Grad auf dem Display (wir haben 
hier gerad rund 25Grad). Auf die Luftfeuchte hat es scheinbar keinen 
feststellbaren Einfluss.

Bitte um Rücknmeldung.

Gruß,
Thorsten

von Thorsten S. (whitejack)


Angehängte Dateien:

Lesenswert?

Hallo,

so, nun ist der Code um die Temperaturkompensierung erweitert und 
getestet. Um die Einzelmessungen aus obigem Code ist eine Statemashine 
gestrickt, die die gesamte Messung steuert.
Zum ablauf
1)Es wird eine Messung angestoßen
2)Es wird Temperatur und Feuchte gemessen.
3)Es wird abgefragt ob messung feritg ist
4)Es können die Werte entnommen und weiterverwertet werden.
//generell
1)es werden keine Interrupts benutzt und keine spezielle 
Prozessorhardware
2)Portpins können im config Header frei gewählt werden.
3)Momentan kann man den code nur für einen Sensor nutzen
4)Messung mit High und Low resolution möglich
5)Alles ohne floatrechung, sehr speichersparend

//Berechnungen
Es wurde alle Anaben aus dem Datenblatt verwertet
1)Tempberechnung (Berücksichtigung der Spannung möglich)
2)Feuchteberechnung (Berücksichtigung der Temp abhängigkeit gegeben)

Die Berechnungen wurden in beiden Bereichen mit einem Exel Test 
verglichen, auch im Zip enthalten.

Der Fehler beträgt +/-0.01 im schlechtesten Fall.

Gruß,
Thosrten

von Infoboter (Gast)


Lesenswert?

Danke für den Code! Hier ein Test:
1
char buffer[64];
2
sht11_init();
3
for(;;){
4
  sht11_start_measure();
5
  _delay_ms( 1000 );
6
  while( !sht11_measure_finish() );
7
  sprintf( buffer, "%i.%i °C  %i.%i %%\n", sht11_get_tmp()/100,  sht11_get_tmp()%100, sht11_get_hum()/100, sht11_get_hum()%100 );
8
  uputs0( buffer );
9
}

http://de.wikipedia.org/wiki/Gradzeichen

von Denny (Gast)


Lesenswert?

Hallo,

ich verwende den Code von Thorsten S.
Meine Kabellänge zwischen Atmel und einem SHT11 Sensor beträgt ungefähr 
10 cm.
In dieser Beschaltung lässt sich der Sensor wunderbar verwenden und 
auslesen.

Da ich ihn gern als Außensensor verwenden möchte, habe ich versucht 
mittels hochwertigen CAT.6 Netzwerkkabel das ganze auf 5 Meter 
auszuweiten, aber leider bekomme ich keine Daten ausgelesen.

Jetzt habe ich vermehrt gelesen, das man die Taktrate runtersetzen 
sollte,
und genau da besteht auch schon meine Frage, welche Teile im Code müßte 
ich dafür ändern ?!

Gruß

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

Die Initialisierungssequenz vom IIC-Bus.

von Andy (Gast)


Lesenswert?

Hallo,
leider komme ich gerade nicht weiter, habe die sht_11_whitejackV3 und 
die Testabfrage von Infoboter ausprobiert, doch leider kommt als 
Ergebniss nur <00> zurück.

Wie sehe ich, ob der I²C Bus überhaupt funktioniert? Habe einen SHT15 
und einen Atmega 328p.

von (prx) A. K. (prx)


Lesenswert?

Andy schrieb:

> Wie sehe ich, ob der I²C Bus überhaupt funktioniert?

Es ist kein I2C-Bus. Nur ähnlich.

von Owen S. (senmeis)


Lesenswert?

Servus,

in dieser Lib sind folgende Zeile zu sehen:
1
static void  sda_hi(void)    { clrBits(DDR(SHT11_PORT), SHT11_SDA); }
2
static void  sda_lo(void)    { setBits(DDR(SHT11_PORT), SHT11_SDA); }

Damit wird die Leitung entweder als Input oder Output konfiguriert. Hat 
das aber mit dem Pegel zu tun?

Gruss
Owen

von (prx) A. K. (prx)


Lesenswert?

Owen Senmeis schrieb:

> Damit wird die Leitung entweder als Input oder Output konfiguriert. Hat
> das aber mit dem Pegel zu tun?

Die bidirektionale SDA-Leitung arbeitet so als Open-Drain. Als Ausgang 
mit Wert 0 konfiguriert zieht der Controller aktiv runter. Als Eingang 
konfiguriert zieht der externe Widerstand hoch.

von Owen S. (senmeis)


Lesenswert?

Meinst Du diese Zeile:
1
clrBits(PORT(SHT11_PORT), SHT11_SCL | SHT11_SDA);  // SCK output low, SDA input/high

Damit wird die SDA Leitung nach Low gezogen wenn diese als Output 
konfiguriert. Falscher Kommentar?

Gruss
Owen

von (prx) A. K. (prx)


Lesenswert?

Der Kommentar bezieht sich auf diese 3 Zeilen zusammen:
1
    clrBits(PORT(SHT11_PORT), SHT11_SCL | SHT11_SDA);  // SCK output low, SDA input/high
2
    setBits(DDR(SHT11_PORT),  SHT11_SCL);
3
    clrBits(DDR(SHT11_PORT),  SHT11_SDA);
Für das "high" in "input/high" sorgt der externe Pullup.

Und nein, diesen Teil meinte ich oben nicht, der ist nur die 
Voraussetzung dafür. Der Zustand der Datenleitung wird im 
Kommunikationsprotokoll absichtlich über das Richtungsregister 
gesteuert, nicht über das unverändert auf 0 bleibende Bit im 
Datenregister.

von Vorn N. (lufthackn)


Lesenswert?

hallo,


ich habe den Code von A K erfolgreich an einem Atmega mit SHT11 zum 
laufen gebracht. in einem andren thread fragte dubhorn nach der 
möglichkeit mehrere SHT einzubinden.

Timo DIttmar schrieb:
> Hallo
>
> @ A. Dubhorn
>
> also um mehrere SHT Sensoren an verschiedenen Datenpin anzusteuern würde
> ich das statische Makro umändern.
> So etwas in der Art:
> #define SET_SHT_DATA(SHT_DATA_PIN) SHT_DATA_PORT |= ( 1 <<
> ((SHT_DATA_PIN)))
>
> die #define SHT_DATA_PIN PD6 Anweisung rausschmeißen und die Funktionen
> so anpassen das man den Pin übergeben kann  z.B. so:
> unsigned char sht_write_statusreg(unsigned char *p_sht_value, unsigned
> char pin)
>
> natürlich müssen die anderen Makros die auf den Datenpin zugreifen und
> jeder Aufruf der Makros in den Funktionen angepasst werden. sollte aber
> möglich sein.
> Poste den Code doch mal wenn du fertig bist.
>
> @ Turbocity
>
> Nicht das ich wüste.  Man könnte überprüfen ob der Stromverbrauch
> innerhalb der Specs liegt, allerdings ist das nur ein sehr indirekter
> Hinweis.
>
> Grüße Timo


hat das hier schon jemand gelöst und für mehrere SHT umgeschrieben?
ich komm irgendwie nich drauf...


gruß lufthackn

von (prx) A. K. (prx)


Angehängte Dateien:

Lesenswert?

Na wenns denn sein muss... Anbei die Originalversion für 2 SHTs, SCL 
gemeinsam, SDA getrennt aber am gleichen Port. Ist etwas älter als die 
oben, ohne Lowres-Support. Und ohne Thorstens Kompensation.

Macht aus der Konstanten SHT_SDA eine Variable, in der die Bitmaske der 
zu verwendeten Portleitung vom SDA Signal drinsteht. Das ist alles.

von MaWin (Gast)


Lesenswert?

> Hier geht es ausserdem ohne Fliesskommarechnung ab.

Natürlich nicht,
const int32_t C2 = (int32_t)(0.648  100  (1L<<24));
ist eine satte Fliesskommaberechnung.

> hat das hier schon jemand gelöst und für mehrere SHT umgeschrieben?

Schon, bloss für einen anderen Prozessor:
1
unsigned char channel=0;
2
void data(int i) { if(channel) DATA1=i; else DATA0=i; wait1(); }
3
int datain(void) { if(channel) return DATA1; return DATA0; }
4
void clk(int i) { if(channel) SCK1=i; else SCK0=i; wait1(); }
5
void clk0(void) { clk(0); }
6
void clk1(void) { clk(1); }
7
void datadir(int i) { if(channel) DATADIR1=i; else DATADIR0=i; wait1(); }
8
void datadir0(void) { datadir(0); }
9
void datadir1(void) { datadir(1); }
10
void clkdir(int i) { if(channel) SCKDIR1=i; else SCKDIR0=i; wait1(); }
11
void clkdir0(void) { clkdir(0); }
12
void clkdir1(void) { clkdir(1); }
13
14
void sbus_reset(void)
15
// communication reset: 
16
// DATA-line=1 and at least 9 SCK cycles followed by transmission start signal
17
//       _____________________________________________________         ________
18
// DATA:                                                      |_______|
19
//          _    _    _    _    _    _    _    _    _        ___     ___
20
// SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______|   |___|   |______
21
{  
22
  unsigned char i; 
23
24
  data(1);                         // DATA high
25
  datadir(1);                         // DATA als Ausgang
26
  clkdir(1);                         // SCK  als Ausgang  
27
  clk0();                           // Initial state
28
  for ( i=0; i<10; i++ )               // 9 SCK cycles
29
  { 
30
    clk1();
31
    clk0();
32
  }
33
  clk1();
34
  data(0);
35
  clk0();  
36
  clk1();
37
  data(1);       
38
  clk0();       
39
}
40
41
unsigned char sbus_send(unsigned char value)
42
// writes a byte on the Sensibus and checks the acknowledge 
43
{ 
44
  unsigned char i;
45
46
  datadir(1);                        // DATA als Ausgang zum Schreiben
47
  for ( i=0x80; i; i>>=1 )           // shift bit for masking
48
  { 
49
    if(i&value) data(1); else data(0);
50
    clk1();                         // clk for SENSI-BUS
51
    clk0();
52
  }
53
  clk1();                       // clk #9 for ack 
54
  datadir(0);                        // DATA als Eingang zum Lesen
55
  i = datain();                       // check ack (DATA will be pulled down by SHT11)
56
  clk0();        
57
  return i;                       // error=1 in case of no acknowledge
58
}
59
60
unsigned char sbus_read(unsigned char ack,unsigned char reverse)
61
// reads a byte form the Sensibus and gives an acknowledge in case of "ack=1" 
62
{ 
63
  unsigned char i, val;
64
65
  val=0;
66
  datadir(0);                        // DATA als Eingang zum Lesen
67
  i=(reverse?0x01:0x80);           // shift bit for masking
68
  while(i)
69
  { 
70
    clk1();                        // clk for SENSI-BUS
71
    if(datain()) val|=i;       // read bit  
72
    clk0();            
73
    if(reverse) i<<=1; else i>>=1; 
74
  }
75
  datadir(1);                        // DATA als Ausgang
76
  data(!ack);                     // in case of "ack==1" pull down DATA-Line
77
  clk1();                     // clk #9 for ack
78
  clk0();                
79
  datadir(0);                        // DATA als Eingang zum Lesen
80
  return val;
81
}
82
83
unsigned char lut[] = 
84
{
85
  0, 49, 98, 83, 196, 245, 166, 151, 185, 136, 219,
86
  234, 125, 76, 31, 46, 67, 114, 33, 16, 135,
87
  182, 229, 212, 250, 203, 152, 169, 62, 15,
88
  92, 109, 134, 183, 228, 213, 66, 115, 32,
89
  17, 63, 14, 93,108, 251, 202, 153, 168,
90
  197, 244, 167, 150, 1, 48, 99, 82, 124, 77,
91
  30, 47, 184, 137, 218, 235, 61, 12, 95,
92
  110, 249, 200, 155, 170, 132, 181, 230,
93
  215, 64, 113, 34, 19, 126, 79, 28, 45, 186,
94
  139, 216, 233, 199, 246, 165, 148, 3, 50,
95
  97, 80, 187, 138, 217, 232, 127, 78, 29,
96
  44, 2, 51, 96, 81, 198, 247, 164, 149, 248,
97
  201, 154, 171, 60, 13, 94, 111, 65, 112,
98
  35, 18, 133, 180, 231, 214, 122, 75, 24,
99
  41, 190, 143, 220, 237, 195, 242, 161, 144,
100
  7, 54, 101, 84, 57, 8, 91, 106, 253, 204,
101
  159, 174, 128, 177, 226, 211, 68, 117, 38,
102
  23, 252, 205, 158, 175, 56, 9, 90, 107, 69,
103
  116, 39, 22, 129, 176, 227, 210, 191, 142,
104
  221, 236, 123, 74, 25, 40, 6, 55, 100, 85,
105
  194, 243, 160, 145, 71, 118, 37, 20, 131,
106
  178, 225, 208, 254, 207, 156, 173, 58, 11,
107
  88, 105, 4, 53, 102, 87, 192, 241, 162,
108
  147, 189, 140, 223, 238, 121, 72, 27, 42,
109
  193, 240, 163, 146, 5, 52, 103, 86, 120,
110
  73, 26, 43, 188, 141, 222, 239, 130, 179,
111
  224, 209, 70, 119, 36, 21, 59, 10, 89, 104,
112
  255, 206, 157, 172
113
};
114
115
int sbus_measure(unsigned char command)
116
{
117
  int i,msb,lsb;
118
  unsigned char crc;
119
  
120
    if(sbus_send(command)) return -1;
121
  for ( i=0; i<655; i++ ) if ( !datain() ) break; // wait until sensor has finished the measurement
122
  if (datain()) return -1; // or timeout is reached
123
  msb = sbus_read(ACK,0); // read the first byte (MSB)
124
  lsb = sbus_read(ACK,0); // read the second byte (LSB)
125
  crc = sbus_read(noACK,1); // read checksum
126
  // 4 status register bits go into sent crc, but they are 0 if sensor is as we want it
127
  if(crc!=lut[lut[lut[command]^msb]^lsb]) return -1;  // crc check fails
128
  return (msb<<8)|lsb;
129
}
130
131
double pow10(double x)
132
{
133
  return exp(x*2.30258509299404568402);
134
}
135
136
void main(void)
137
{
138
    double t,h,dew,feuchte,m,k;
139
    int temp,humi,c;
140
141
    channel=0;  
142
    while(1)
143
    {
144
        sbus_reset();
145
        temp=sbus_measure(MEASURE_TEMP);
146
        if(temp!=-1)
147
        {
148
            t = temp*0.01-40.1; // calc. temperature from ticks to [°C] for 5V supply
149
            sbus_reset(); // nur ein start reicht nicht, es muss ein reset sein
150
            humi=sbus_measure(MEASURE_HUMI);
151
            if(humi!=-1)
152
            {
153
                h = 0.0367*humi-0.0000015955*humi*humi-2.0468; // calc. humidity from ticks to [%RH]
154
                h = (t-25) * (0.01+0.00008*humi) + h;     // calc. temperature compensated humidity [%RH]
155
                if(h>100.0) h=100.0;           // cut if the value is outside of
156
                else if(h<0.1) h=0.1;           // the physical possible range
157
                if(t<0.0) // über Eis
158
                {
159
                    m=22.46;
160
                    k=243.12;
161
                }
162
                else
163
                {
164
                    m=17.62;
165
                    k=272.62;
166
                }
167
                dew = log(h/100.0) + ((m*t)/(k+t));
168
                dew = k*dew/(m-dew);
169
                // Berechnungen http://www.wetterochs.de/wetter/feuchte.html
170
                feuchte = 216.687 * (h/100.0)*(6.1078*pow10(7.5*t/(237.3+t))) / (t+273.15);
171
            }
172
        }
173
        channel=!channel;
174
    }
175
}

von (prx) A. K. (prx)


Lesenswert?

MaWin schrieb:

> const int32_t C2 = (int32_t)(0.648  100  (1L<<24));
> ist eine satte Fliesskommaberechnung.

Ach herrje. Ja, das ist formal gesehen eine Fliesskommarechnung. Die 
aber bereits der Compiler durchführt und durch eine ganzzahlige 
Konstante ersetzt. Ich hätte das auch den Taschenrechner machen lassen 
und als magische Konstante reinschreiben können.

Also für Haarspalter: "Hier geht es ausserdem zur Laufzeit ohne 
Fliesskommarechnung ab."

von Vorn N. (lufthackn)


Lesenswert?

es läuft, abweichung zwischen 2 SHT11 Sensoren;
0,3°C und 0,5% rLf

Da will ich jetzt auch keine Haare spalten wa? LOL

trotz sehr schlechter lagerung über monate hinweg sind die dinger noch 
ziemlich genau. ich freu mich!

gruß Lufthackn

von Ralf (Gast)


Lesenswert?

Gibt es irgendwo einen simplen Beispielcode für den Arduino mit zwei 
Sensoren und der entsprechenden Bibliothek?
Ich bekomme das irgendwie nicht hin;(

Freundliche Grüße
Ralf

von Jürgen S. (jurs)


Lesenswert?

Ralf schrieb:
> Gibt es irgendwo einen simplen Beispielcode für den Arduino mit zwei
> Sensoren und der entsprechenden Bibliothek?
> Ich bekomme das irgendwie nicht hin;(

Du kannst am I2C-Bus zwar verschiedene Sensoren gleichzeitig betreiben, 
aber nur "verschiedene" Sensoren, die alle eine unterschiedliche 7-Bit 
Gerätenummer haben müssen. Ich kenne keine Möglichkeit, zwei gleiche 
I2C-Sensoren gleichzeitig an einem Arduino zu betreiben, es sei denn, Du 
schaltest immer den gerade nicht benötigten Sensor "mit der doppelten 
Gerätenummer" jeweils vom Bus ab.

1-Wire Sensoren können dagegen über eine pro Sensor eindeutige 64-Bit 
Nummer addressiert werden, davon kannst Du viele gleichzeitig an einen 
Arduino dranhängen und sie trotzdem einzeln adressieren und abfragen:

http://www.arduino.cc/playground/Learning/OneWire

von egberto (Gast)


Lesenswert?

Also bei mir ist die Temp viel zu hoch, die Feuchte viel zu niedrig -> 
irgendwelche Ideen (SHT11 funktioniert prinzipiell, wenn ich auf den 
Sensor hauche, springt die Feuchte nach oben, die Temperatur steigt ein 
wenig).
Ob HIRES oder LOWRES ist egal....

Der SHT wird jede Sekunde abgefragt (also geschaut, ob fertig, Werte 
geholt und dann die Messung neu gestartet). Erwärmt der sich selbst beim 
Messen? Sollte ich nur alle 10 Min abfragen?

Hat jemand eine Idee?

Viele Grüße,

egberto

von (prx) A. K. (prx)


Lesenswert?

egberto schrieb:
> Erwärmt der sich selbst beim Messen?

Im Prinzip ja, aber 1/s ist gemäss Datasheet kein Problem.

von Egberto (Gast)


Lesenswert?

nächste Idee - eventuell wird die eingebaute Heizung ja irgendwie 
(irrtümlich) eingeschaltet? Vom Verhalten her würde das ja passen ???

von (prx) A. K. (prx)


Lesenswert?

Tja, das musst du schon selber rausfinden.

von Egberto (Gast)


Lesenswert?

also ich schreibe das nicht in das Config-Register....gibt es da im Code 
eine Option für ? Ich habe so auf die Schnelle erst mal nix gefunden...

Viele Grüße,

egberto

von Egberto (Gast)


Lesenswert?

Es scheint an den Sensoren zu liegen....die lagen ein paar Jahre hier 
rum....
Wenn ich die ein paar Stunden mit Heizung betreibe, nähern sich die 
gemessenen Werte der Realität an - für ein Raumthermometer ok.

Frohes Fest,

Egberto

von (prx) A. K. (prx)


Lesenswert?

Im Datasheet steht was zu Rekonditionierung drin.

von Egberto (Gast)


Lesenswert?

Die Klimakammer dafür hatte ich grad nicht zur Hand ;-)

Ich wollte eigentlich auch nur zum Ausdruck bringen, das der Code 
einwandfrei ist und das Problem eher bei den Sensoren zu suchen ist.

Frohes Fest,

Egberto

von Steffen H. (avrsteffen)


Angehängte Dateien:

Lesenswert?

Ron schrieb:
> Mist! Wieder nur in C. Hat denn keiner mal was in Assembler?

Hab das Ganze jetzt mal in Assembler umgesetzt. Ausgabe der Temperatur 
und relativen Feuchte über UART und LCD.

Port-Pins sind alle einzeln frei wählbar, auch für das LCD (4-bit). 
D4-D7 müssen also nicht auf einem Port zusammenhängen. Die 
Sensibus-CLK-Frequenz kann in Grenzen eingestellt werden. F_SBUS max ist 
F_CPU/32. Es wird bei überschreiten der Grenzen eine ERROR-Meldung 
erzeugt.

Pinbelegung:
SDA,SCL,F_SBUS,SHT_RESOLUTION sowie SHT_VOLTAGE in der senserion.inc
RW,RS,E und D4..D7 in der lcd_routines_4bit.inc

Die Daten stehen dann im SRAM zur freien Verfühgung als ASCII mit 
Einheit bereit.

Das alles passt in einen ATtiny2313, der mit ca. 87% gefüllt wird.


Gruß Steffen

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.