mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Zufallszahlen mit Atmega8


Autor: David (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,
ich versuche jetzt seit geraumer Zeit Zufallszahlen mit meinem Atmega8 
zu generieren doch irgendwie funktioniert das nicht so richtig. Also 
probieren wollte ich es mit einem linear rückgekoppelten 
Schieberegister(http://de.wikipedia.org/wiki/Linear_r%C3%BCckgekop...)
um das umzusetzen nutze ich folgenden Code:
.include  "avr.h"
;------------------------------------------------------------------------
;Reset and Interrupt vector             ;VNr.  Beschreibung
  rjmp  main  ;1   POWER ON RESET
  reti    ;2   Int0-Interrupt
  reti    ;3   Int1-Interrupt
  reti    ;4   TC2 Compare Match
  reti    ;5   TC2 Overflow
  reti    ;6   TC1 Capture
  reti    ;7   TC1 Compare Match A
  reti    ;8   TC1 Compare Match B
  reti    ;9   TC1 Overflow
  reti    ;10  TC0 Overflow
  reti    ;11  SPI, STC Serial Transfer Complete
  reti    ;12  UART Rx Complete
  reti    ;13  UART Data Register Empty
  reti    ;14  UART Tx Complete
  reti    ;15  ADC Conversion Complete
  reti    ;16  EEPROM Ready
  reti    ;17  Analog Comparator
  reti    ;18  TWI (I²C) Serial Interface
  reti    ;19  Store Program Memory Ready
;------------------------------------------------------------------------
;Start, Power ON, Reset
main:  ldi  r16,lo8(RAMEND)
  out  SPL,r16
  ldi  r16,hi8(RAMEND)
  out  SPH,r16  ;init Stack

  ldi  r16,0xFF  ; PORTB als Ausgabe
  out  DDRB,r16
  
  ldi  r16,0b00101001  ;Startwert laden
  out  PORTB,r16

;------------------------------------------------------------------------
mainloop:
  mov  r17,r16  ;Register 16 nach Register 17 kopieren
  lsr  r17  ;Register 17 3 mal nach rechts schieben
  lsr  r17
  lsr  r17
  eor  r17,r16  ;Register 17 und 16 exclusiv oder verknüpfen
  lsr  r16  ;Register 16 nach rechts schieben
  sbrc  r17,0  ;wenn Bit 0 von Register 17 nicht gesetzt ist
  sbr  r16,5  ;dann soll Bit 5 von Register 16 nicht gesetzt werden
  out  PORTB,r16  ;Register 16 ausgeben
  rcall  delay  ;Verzögern
  rcall  delay
  rcall  delay
  rcall  delay
  rcall  delay
  rcall  delay
  rjmp  mainloop  ;und wieder von vorn

delay:
  ldi  r20,0x00
loop1:
  ldi  r19,0x00
loop2:
  nop
  nop
  inc  r19
  cpi  r19,0b11111111
  brne  loop2

  nop
  nop
  inc  r20
  cpi  r20,0b11111111
  brne  loop1
  ret
;------------------------------------------------------------------------

Bevor sich jemand beschwert: Ich weiß, dass die Verzögerung nicht 
optimal gelöst ist und dass man das eigentlich mit einem Timer macht, 
aber darum gings mir erstmal nicht.
Das Problem ist das er nach ein paar Schritten bei dem Wert 0b00111111 
stehen bleibt und ich verstehe nicht warum, denn eigentlich müsste dass 
quasi eine Endlosschleife sein bei der sich ständig die Werte ändern. 
Könnte mir bitte jemand einen Tip geben? Danke schon mal vornweg.
David

Autor: Domschl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Deinen Gedankengang mit der eor-Verknüpfung verstehe ich zwar nicht ganz 
(bin schon müde), aber ich habe erst vor kurzem das selbe Programm auf 
eine 8051 in asm und c geschrieben. Ich erkläre mal, wie ich es gelöst 
habe (hat funktioniert):
Wenn man von einem 8-Bit Schieberegister ausgeht:
Du musst die Bits 0,4,5,6 eor-Verknüpfen und an den Eingang des 
Schieberegisters legen. Meine Methode:
Du legts eine Kopie des Registers an. Danach schiebst du nach einander 
jedes der 4 relevanten Bits in das Carry-Bit und summierst mit dem 
Befehl ADC die einzelnen Bits auf. Am ende überprüfst du das LSB dieser 
Zahl und wenn es gesetzt ist dann: Das Register mit der Zufallszahl 
einmal nach rechts schieben und das MSB setzen. Sonst nur einmal 
schieben und nichts setzen.

Ich hoffe ich konnte dir helfen. Vielleicht schreib ich das Beispiel 
noch schnell. Wenn ja, poste ich es.

Autor: David (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke erstmal für den Tip.
Naja wie der Alogithmus funktioniert steht ja in dem Link, da ist auch 
das mit der EOR Verknüpfung erklärt. Ich mache das halt so dass ich eine 
Kopie der Zahl anlege, dann die Kopie 3 mal nach rechts schiebe damit 
quasi das Bit 0 mit Bit 3 EOR verküpft wird.
Ich benutze zwar (erstmal) nur 6 Bit, aber ich denke dass ich dein 
Verfahren trotzdem anwenden kann. Schau'n mer ma'.

Autor: Domschl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier das Beispiel:
.def pzz=r16
.def temp=r17
.def summe=r18
.def null=r19

initialisierungen....
.
.
.
ldi pzz, 1  ;Muss mit 1 vorgeladen werden
.
.

zufall:
mov temp, pzz
clr summe
clr null
lsr temp

adc summe, null
lsr temp
lsr temp
lsr temp
lsr temp
adc summe,null
lsr temp
adc summe,null
lsr temp
adc summe,null

lsr pzz
sbrc summe, 0
sbr pzz,128
out portb,pzz

ret


Habs schnell simuliert und es sieht alles richtig aus. Nach 255 
durchläufen kommt wieder die 1. Ich hoffe ich konnte dir damit helfen.

Autor: Knut Ballhause (Firma: TravelRec.) (travelrec) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Meine Lösung sieht so aus:
;generates 16 bit random value (16Bit SR with feedback on Bit 0, 2, 11, 15)
RANDOM:
 mov  Temp, RandomL    ;exor feedback outputs for SR input
 andi  Temp, 0b00000001
 lsl  Temp
 lsl  Temp
 eor  Temp, RandomL
 andi  Temp, 0b00000100
 swap   Temp
 lsl  Temp
 mov  TempH, RandomH
 andi  TempH, 0b00001000
 swap  TempH
 eor  TempH, RandomH
 andi  TempH, 0b10000000
 eor  TempH, Temp
 rol  TempH    
 rol  RandomL
 rol  RandomH
 ret

RandomL und RandomH müssen zu Initialisierung mit einem Wert |= 0 
geladen werden. Die Routine wird 1x pro Main-Durchlauf aufgerufen, wenn 
Zufallszahlen gebraucht werden, liest man einfach RandomL und/oder 
RandomH aus.

Autor: Winfried (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mal so kleiner Tipp, was Dokumentation von Code angeht: Die Kommentare 
sollen nicht beschreiben, was der Befehl macht, sondern Info darüber 
geben, warum man etwas macht. Sonst hat man keinen Informationsgewinn. 
Man schreibt z.B. nicht "Port B Pin 1 setzen" sondern "LED einschalten".

Autor: Winfried (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@TravelRec: Schön kompakter Code, gefällt mir...

Autor: David (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So danke an alle für die Tipps, hat super funktioniert. Nun muss ich nur 
noch ein paar schlechte Angewohnheiten (Verzögerung) ausbessern und dann 
gefällts mir richtig gut.

Autor: Jan Zodiax (Firma: ujbxp) (zodiax)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Meine Idee: ich arbeite gerne mit unbeschalteten (offenen) ADC Port
und nehme das "Spannungsrauschen" auf. Das ergibt wirklich 100% Random 
;-)

.include"m32def.inc" ; hier mega 32 -müßte auch mit atmega8 
funktionieren


.def adlow     = r20  ; ADC Register
.def adhigh    = r21  ; ADC Register
.def cr_tmp    = r16  ; random zahl
.def temp1     = r17

  ldi     temp1, (1<<REFS0)      ; konfiguriere ADC
 out     ADMUX, temp1
 ldi     temp1, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
 out     ADCSRA, temp1



;ADC-Wert einlesen

sample_adc:
    sbi     ADCSRA, ADSC        ; den ADC starten

wait_adc:
    sbic    ADCSRA, ADSC
    rjmp    wait_adc
     in      adlow, ADCL         ; LOW Byte lesen
     in      adhigh, ADCH        ; High Byte lesen

     mov cr_tmp,adlow
    add cr_tmp, adhigh


random_10: ; konvertiere zufallszahl zwischen 0 und 9
           subi  cr_tmp, 10        ; 10 abziehen
           brcc  random_10     ; ist dadurch ein Unterlauf enstanden?
           subi  cr_tmp, -9  ; ja, dann 9 dazu

end: rjmp end

;Die Zufallszahl steht in cr_temp!


cheers
Zodiax

Autor: ArthurDent (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe seit geraumer Zeit den hier im Einsatz. Der Link ist allerdings 
tot :-(


/* This code is listed in
 * http://remus.rutgers.edu/~rhoads/Code/code.html
 *
 * in file
 * http://remus.rutgers.edu/~rhoads/Code/random2.c
 *
 * with the following description:
 *
 * Concatenation of two 16-bit Multiply with carry generators.
 * Has a list of recommended parameters. Good and even faster than the 
above.
 * Perhaps the fastest of any generator that passes the Diehard tests.
 */

/* concatenation of following two 16-bit multiply with carry generators 
*/
/* x(n)=a*x(n-1)+carry mod 2^16 and y(n)=b*y(n-1)+carry mod 2^16, */
/* number and carry packed within the same 32 bit integer.        */
/******************************************************************/

#ifndef _RRAND_H_
#define _RRAND_H_

/* return a random float >= 0 and < 1 */
#define rand_float          ((double)rrand() / 4294967296.0)

static unsigned int SEED_X = 521288629;
static unsigned int SEED_Y = 362436069;


static inline unsigned int rrand ()
   {
/* Use any pair of non-equal numbers from this list for "a" and "b"
    18000 18030 18273 18513 18879 19074 19098 19164 19215 19584
    19599 19950 20088 20508 20544 20664 20814 20970 21153 21243
    21423 21723 21954 22125 22188 22293 22860 22938 22965 22974
    23109 23124 23163 23208 23508 23520 23553 23658 23865 24114
    24219 24660 24699 24864 24948 25023 25308 25443 26004 26088
    26154 26550 26679 26838 27183 27258 27753 27795 27810 27834
    27960 28320 28380 28689 28710 28794 28854 28959 28980 29013
    29379 29889 30135 30345 30459 30714 30903 30963 31059 31083
*/
   static unsigned int a = 18000, b = 30903;

   SEED_X = a*(SEED_X&65535) + (SEED_X>>16);
   SEED_Y = b*(SEED_Y&65535) + (SEED_Y>>16);

   return ((SEED_X<<16) + (SEED_Y&65535));
   }


static inline void rrand_seed( unsigned int seed1, unsigned int seed2 )
   {
   if (seed1) SEED_X = seed1;   /* use default seeds if parameter is 0 
*/
   if (seed2) SEED_Y = seed2;
   }

#endif /* _RRAND_H_ */

Autor: ArthurDent (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Jan Zodiax (Firma ujbxp)

Gibt das wirklich 100% Random ?

Hat man bei so einer Hardwareloesung nicht immer die Gefahr, das 
irgendwelche Dreckeffekte einem doch irgendwelche Periodizitaeten oder 
anderes Einstrahlen?

Als Seed wuerde ich auch etwas "richtig" Zufaelliges waehlen, jedoch 
ansonsten sind Pseudo Noise Folgen erste Wahl.

Autor: Jan Zodiax (Firma: ujbxp) (zodiax)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ArthurDent wrote:
> @Jan Zodiax (Firma ujbxp)
>
> Gibt das wirklich 100% Random ?
>
> Hat man bei so einer Hardwareloesung nicht immer die Gefahr, das
> irgendwelche Dreckeffekte einem doch irgendwelche Periodizitaeten oder
> anderes Einstrahlen?
>
> Als Seed wuerde ich auch etwas "richtig" Zufaelliges waehlen, jedoch
> ansonsten sind Pseudo Noise Folgen erste Wahl.

Hallo ArthurDent,

Periodizitaet habe ich bisher nicht feststellen können; ich verwende
diesen Randomgenerator häufig in Spielen.
Für ein gutes Ergebnis brauchst Du nur ein Stück Draht vom ADC Messpin 
(in diesem Fall Pin 40= A0)herauszuführen, 2-3 cm reichen vollkommen.
Der Controller empfängt dann soviel Rauschen und Datenmüll von Aussen 
(Handy\TV\Radio-strahlen etc..). Kein Mensch dann kann vorhersagen 
welche Zahl als nächstes kommt,und das ist meiner Meinung nach ein gutes 
Zufallsergebnis.
Probiers einfach mal aus, schreib die Zufallsdaten zurück ins RAM
und sende sie per serieller Schnittstelle zurück zum PC.

Gruß
Zodiax

Autor: Knut Ballhause (Firma: TravelRec.) (travelrec) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich denke, der offene ADC-Pin wird in der Hauptsache 50Hz der 
allgegenwärtigen Netzleitung messen, was keinesfalls zufällig ist. 
Versuche Deinen ADC-Zufallsgenerator mal in einem abgeschiedenen Gebiet 
ohne Stromnetz zu betreiben, ich vermute mal, die Ergebnisse werden ganz 
anders aussehen.

Autor: Hagen Re (hagen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn man beweisbar guten Zufall haben möchte dann sollte man einen 
Pseudo Zufallsgenerator benutzen.

Ich mache es immer so:

- zwei LFSRs mit hinreichend großer Periode und unterschiedlichen 
Polynomen
- ein Startwert=Seed steht im EEPROM
- beim RESET wird Startwert aus EEPROM geladen in beide PRNGs
- der eine PRNG wird nun dazu benutzt den nächsten Seed zu berechnen, 
dieser Wert wird gespeichert im EEPROM
- der zweite PRNG dient dann in der Anwendung als Zufallsgenerator und 
läuft mit dem so berechneten Seed

Somit erzeugt man nach jedem RESET einen anderen Seed. Diese Erzeugung 
ist abhängig von dem einen PRNG. Nach dem ersten flashen der Anwendung 
startet das System (jede AVR Kopie) mit exakt den gleichen Bedingungen. 
Somit kann man auch eventuelle Fehler exakt reproduzieren und 
simulieren, da man die Anfangsbedingungen der PRNGs eben reproduzieren 
kann. Nichts ist schlimmer als eine Fehlersuche in einem Program das 
echten Zufall in dessen Programablauf benutzt.

Der dazu nötige Code beträgt 31 Opcodes.
Der Code in Main() zur Berechnung der Seeds sieht dann so aus (aus 
meinem Glühwürmchen Projekt in der Codelib)
  // init PRNG, load last seed from EEPROM, calculate next seed and store back to EEPROM, use another polynom as in lfsr()
    eeprom_read_block((uint8_t *)&seed, (uint8_t *)(0), 4);
    lfsr_poly(32, 0x8140C9D5);
    eeprom_write_block((uint8_t *)&seed, (uint8_t *)(0), 4);

Gruß Hagen

Autor: Hagen Re (hagen)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
source

Autor: Knut Ballhause (Firma: TravelRec.) (travelrec) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Den Trick mit der wechselnden Seed im EEPROM wenden wir auch an ;-)

Autor: Hagen Re (hagen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Er ist sicher und sparrt den enormen Aufwand wenn man versucht sein möge 
den aktuellen Seed beim Wegfallen der Spannung speichern zu wollen ;)

Wichtig erachte ich aber den Fakt das man so wirklich eine 
Reproduzierbarkeit der Ergebnisse des Programmes bekommt. Und 
Programmieren bedeutet als Erstes für den Programmierer eine 
Reproduzierbarkeit zu erreichen.

Für die spätere Serialization des Programmes, also so das jede AVR Kopie 
einen anderen Zufall erzeugt, kann man ja die EEPROM Zellen für jede AVR 
Kopie serialisieren = individuell initialisieren.

Allgemein halte ich nicht viel von den vorgeschlagenen HW-Lösungen. Der 
so erzeugte "Zufall" ist in erster Linie mal nur abhängig von den 
physikalischen Eigenschaften der Bauteile. Erst in vierter/fünfter Linie 
ist er abhängig vom thermischen Zufalls-Rauschen auf Grund der 
Hintergrundstrahlungen des Universums, und nur das wäre eine gute Quelle 
für echten Zufall. Die Konstrukteure der Bauteile versuchen ja gerade 
all diese unerwünschten Abhängigkeiten zu minimieren, sprich 
Temperaturstabilitäten zu verbessern, Einflüsse durch EMV zu minimieren 
usw. Das Rauschen des ADCs im AVR ist also erstmal systembedingt und 
nicht so stark zufällig wie man annehmen würde.

Davon abgesehen entsteht für den Entwickler immer eine 
Argumentations-Falle. Denn beweise mir das der so erzeugte Zufall auch 
wirklich echt zufällig sein muß ! Das kann man aber nicht da man nicht 
alle Parameter des Systemes kennen kann. Im Umkehrschluß kann ich also 
mit Recht behaupten das das das System "ADC + Antenne" eben keinen 
Zufall erzeugt, sondern nur hochkomplexe und von vielen Unbekannten 
abhängige Bits sammelt.

Gruß Hagen

Autor: Knut Ballhause (Firma: TravelRec.) (travelrec) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Genauso kann der ADC-Pin durch Spannungeeinstreuung hochlaufen und an 
der Spannungsoberkante kleben bleiben und somit für einen längeren 
Zeitraum sauber 0x3FF (1023) ausgeben. Nicht wirklich Zufall.

Autor: Hagen Re (hagen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gibt also zwei Wege:

1.) man erzeugt "Zufall" mit mathematischen Verfahren. Die Komplexität 
dieses Verfahrens und der verwendeten Zahlengrößen bestimmt die 
Vorhersagbarkeit durch Dritte und die statistischen Eigenschaften des 
Zufalls. Je nach Verfahren und Komplexität kann man diesen "Zufall" dann 
nur reproduzieren wenn man die Anfangsbedignungen kennt, sprich das 
Seed. Schützt man dieses so wird defakto für einen Dritten der erzeugte 
Zufallsstrom wie echter icht vorhersagbarer Zufall erscheinen. Somit 
kann man Beide Vorteile als Entwickler nutzniesen, die evtl. nötige 
Reproduzierbarkeit der Ergebnisse in der Entwicklungsphase und die 
beweisbare Nicht-Reproduzierbarkeit des Zufallsstromes für Dritte die 
keinen Zugriff auf das Seed haben.

2.) man misst "Zufall". Dann benutzt man Hardware, mit ihr kann man 
keinen Zufall erzeugen sondern nur Zufallseregnisse messen. Dabei ist es 
aber dann auch wirklich wichtig das man sauber misst, also scharf 
abgrenzen kann zwischen der zu messenden Zufallsquelle und den 
physiaklsichen Störparametern der Bauteile und der Umwelt, und eben eine 
gute Quelle der physikalischen Zufallsereignisse benutzt. In letzter 
Konsequenz kann man eigentlich nur die Hintergrundstrahlung des 
Universums als solch eine Quelle als gut bezeichnen. Oft benutzt man 
radioaktive Zerfallsprozesse als Quelle. Auch diese sind als gut zu 
bewerten da sie in letzter Konsequenz mit dem zeitlichen Verlauf des 
Universums korrelieren, ergo Hintergrundstrahlung. Aber nur dann wenn 
man sie von anderen absichtlichen radioaktiven Störquellen auch 
messtechnisch unterscheiden kann.


Gruß Hagen

Autor: Hagen Re (hagen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Genauso kann der ADC-Pin durch Spannungeeinstreuung hochlaufen und an
>der Spannungsoberkante kleben bleiben und somit für einen längeren
>Zeitraum sauber 0x3FF (1023) ausgeben. Nicht wirklich Zufall.

Und viel schlimmer ist dabei der Fakt das man dieses Eregnis eben nicht 
reproduzieren noch vorhersagen kann. Man wird dann als Entwickler 
bestimmte mathematische Verfahren nachschalten müssen, also zb. die 
Entropie verdichten zb. durch Hashalgorithmen, oder statistische 
Verfahren um den so erzeugten "Zufall" zu bewerten. In letzter 
Konsequenz hat man einen enormen zusätzlichen Aufwand betrieben der mehr 
kostet als gleich einen guten beweisbaren PRNG zu benutzen.

Für den Entwickler bedeutet dies also:
Man verlässt sich in seiner Entwicklung, im Nachweis der 
Funktionstüchtigkeit des eigenen Programmes auf Unvorhersagbarkeiten. 
Das ist ein Widerspruch in der Arbeitsweise des Entwicklers.

Gruß Hagen

Autor: Jürgen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Schützt man dieses so wird defakto für einen Dritten der erzeugte
> Zufallsstrom wie echter icht vorhersagbarer Zufall erscheinen.

Das gilt nur bei kryptografisch sicheren Zufallszahlengeneratoren.
Deine LFSRs gehören nicht dazu.

Jürgen

Autor: Hagen Re (hagen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jo ich weiß habe auch nichts anderes behauptet ;) Es ging ja in dieser 
Aussage im Allgemeinen um die machbaren Vorteile der PRNG im Vergleich 
zu HW-RNGs.

Gruß Hagen

PS: übrigens sind es nicht meine LFSRs, ich habe sie nur in AVR Source 
umgesetzt ;)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.