Forum: Mikrocontroller und Digitale Elektronik Zufallszahlen erzeugen


von Ingo L. (grobian)


Lesenswert?

Ich will eine Zufallszahl erzeugen und die auf dem Port darstellen.
Was im DEV c++ noch funktionier (natürlich habe ich die Ausgabe auf dem 
Bildschirm) macht im AVR Studio Probleme. Irgendwie will die Funktion 
srand (time(NULL)) nicht so richtig folgende Fehler treten auf:
../PERSONALFILZER.c:16: warning: implicit declaration of function 
'srand'
../PERSONALFILZER.c:16: warning: implicit declaration of function 'time'
../PERSONALFILZER.c:16: error: 'NULL' undeclared (first use in this 
function)
...usw
Was mag hie nicht stimmen??

define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <lcd.h>
#include <lcd.c>
#include <avr/pgmspace.h>
#include <math.h>


int main(void)
{
int a,b;

DDRA = 0xff;
srand (time(NULL));

   while(1)
    {
      b = rand()%10;
      PORTA = b;
    _delay_ms(5000);
    }
}


Gruß Ingo

von Michael G. (linuxgeek) Benutzerseite


Lesenswert?

Was haeltste davon dass es die Funktion time() nicht gibt?

von Ingo L. (grobian)


Lesenswert?

bringt mich jetzt nicht so richtig weiter???

von Johannes M. (johnny-m)


Lesenswert?

> #include <lcd.c>
Und das hat da mit Sicherheit nichts zu suchen! .c-Dateien werden nicht 
mit #include eingebunden.

von Marian (Gast)


Lesenswert?

Dir fehlt die richtige Library, versuchs mal mit der <stdlib.h>.

von Johannes M. (johnny-m)


Lesenswert?

Ingo Laabs wrote:
> bringt mich jetzt nicht so richtig weiter???
Du kannst nunmal keine Funktion benutzen, die es nicht gibt bzw. die der 
Compiler nicht kennt. Du musst sie also entweder selber schreiben oder 
eine existente Funktion des Namens finden und sie dem Compiler bekannt 
machen.

von ... .. (docean) Benutzerseite


Lesenswert?

bitte schön...

http://www.roboternetz.de/wissen/index.php/Zufallszahlen_mit_avr-gcc

PS:
NULL kennt ein reiner C-Compiler auch nicht...

von Ingo L. (grobian)


Lesenswert?

nun ja im Dev C++ hat alles so funktioniert

#include <cstdlib>
#include <iostream>
#include <math.h>
using namespace std;

int main(void)
    {
              int a,b;
              cout <<("Zuffallsfaktor......");
              cin >> a;
              srand (time(NULL));
       {
              while(1)
              {
                  b = rand()%a;

                  cout << b << endl << endl;
                  if (b==0)
                   cout <<("................Treffer................")<< 
endl << endl;

                  system("PAUSE");
                  cout << endl << endl;
              }
       }

return EXIT_SUCCESS;

}

und da meckert der compiler nicht über NULL

@johannes
die lcd dateien befinden sich da weil ich die Zahlen später auf dem 
display brauche

von chris (Gast)


Lesenswert?

Weisst du überhaupt was du tust ?

Nicht beleidigend gemeint, aber man hat den Eindruck als würdest du nach 
der Copy-and-Paste Methode mit vorhandennen Quelltexten arbeiten.

von Johannes M. (johnny-m)


Lesenswert?

Ingo Laabs wrote:
> nun ja im Dev C++ hat alles so funktioniert
> und da meckert der compiler nicht über NULL
Nun ist (wie der Name schon sagt) der devc++ ein C++-Compiler und der 
WINAVR (den Du ja vermutlich mit AVRStudio zusammen benutzt) ein 
C-Compiler. C und C++ haben zwar eine gewisse Schnittmenge, sind aber im 
Großen und Ganzen zwei ziemlich unterschiedliche Dinge! Wie wäre es, 
wenn Du Dich über die Programmiersprache, in der Du arbeiten willst, und 
die Plattform, auf der das ganze laufen soll, informierst, bevor Du 
damit anfängst?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ingo Laabs wrote:

> und da meckert der compiler nicht über NULL

Ja, und?

Es sagt ja niemand, das falsch geschriebener Code einen Fehler
erzeugen muss, aber er kann es eben.

NULL wird nur von <stdio.h> und <stddef.h> garantierterweise (gemäß
Standard) bereit gestellt.  Allerdings ist es natürlich anderen
Headerdateien nicht verboten, diese Konstante auch bereit zu stellen.
Allerdings kannst du natürlich statt NULL auch gleich 0 schreiben.

Aber zurück zum Problem: woher bitte soll dein Microcontroller ohne
Betriebssystem denn eine Kennung der aktuellen Uhrzeit besitzen?
Nichts anderes ist doch der Aufruf der Funktion time().

Um auf dem Controller ein random seed zu gewinnen, musst du dir schon
etwas mehr Mühe geben, und das Ganze hängt insbesondere davon ab,
über welche Art von Zufällen der Kram verfügt, der um deinen Controller
ringsum gruppiert ist.

von ... .. (docean) Benutzerseite


Lesenswert?

Ingo Laabs wrote:
> die lcd dateien befinden sich da weil ich die Zahlen später auf dem
> display brauche

Die kannst du gerne tuen.... nur dann #include bitte nur die .h und 
NICHT die .c...

Das ist Vergewaltigung des Präprozessors...

von Michael G. (linuxgeek) Benutzerseite


Lesenswert?

Jörg Wunsch wrote:

> Aber zurück zum Problem: woher bitte soll dein Microcontroller ohne
> Betriebssystem denn eine Kennung der aktuellen Uhrzeit besitzen?
> Nichts anderes ist doch der Aufruf der Funktion time().

Ich glaube dem Ingo ist nicht bewusst dass er hier keinen PC sondern 
eine vollkommen andere Plattform ohne OS programmieren will?

Als seed eignet sich z.B. (wenn man es einfach machen will) ein 
Timerregister. Je nachdem, wann man es dann ausliest ist der Wert auch 
pseudozufaellig. Das duerfte sogar noch um einiges besser sein als der 
Aufruf von time(), der ja sehr definiert voraussagbar und nicht hoch 
aufgeloest ist.
Und klar ist auch, dass sich so gewonnener Zufall natuerlich nicht fuer 
irgendwelche kryptographischen Anwendungen eignet, aber darum wird's 
hier sicher sowieso nicht gehen.

Michael

von Ingo L. (grobian)


Lesenswert?

@chris
nee noch probiere ich und ich denke mal ALLE hier sind in irgendeiner 
Form durch anfängliches probieren zum Ziel gekommen..sicher auch DU

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Michael G. wrote:

> Als seed eignet sich z.B. (wenn man es einfach machen will) ein
> Timerregister.

Unter Umständen.  Wenn der Timer aber synchron mit dem CPU-Takt läuft,
ist die Chance (falls keine anderen physikalischen Effekte mit im
Spiel sind) gut, dass der Timer an der gleichen Stelle im Programmfluss
auch stets den gleichen Wert hat.

Ingo Laabs wrote:

> ...und ich denke mal ALLE hier sind in irgendeiner
> Form durch anfängliches probieren zum Ziel gekommen.

Naja, aber ein wenig drüber nachdenken, was da eigentlich gerade
passieren soll, darf man schon auch.  Eigentlich kannst du ja froh
sein, dass deine Bibliothek keine Funktion time() hat, so hat dich
wenigstens der Compiler mit der Nase drauf gestoßen, dass dein
copy&paste hier gar keine sinnvollen Ergebnisse bringen kann (weil
es die entsprechende Umgebung eben nicht hergibt).

von Michael G. (linuxgeek) Benutzerseite


Lesenswert?

Was Du unter "Probieren" verstehst verstehe ich unter Planlosigkeit ;) 
Und PC-Code zu kopieren und damit nen AVR programmieren zu wollen ist 
definitiv planlos, sorry.

von Ingo L. (grobian)


Lesenswert?

das sind Dinge, die muss mann aber erstmal wissen, gell

von chris (Gast)


Lesenswert?

Stimmt schon.

Da ist es jetzt an der Zeit die Beiträge zu lesen und zu verstehen, 
warum das nicht funktionieren kann. So lernt man :)

von Michael G. (linuxgeek) Benutzerseite


Lesenswert?

Jörg Wunsch wrote:
> Michael G. wrote:

> Unter Umständen.  Wenn der Timer aber synchron mit dem CPU-Takt läuft,
> ist die Chance (falls keine anderen physikalischen Effekte mit im
> Spiel sind) gut, dass der Timer an der gleichen Stelle im Programmfluss
> auch stets den gleichen Wert hat.

Sobald zumindest ein paar Funktionsaufrufe mit vom input abhaengiger 
Laufzeit und Interrupts auftreten duerfte das nicht mehr passieren. 
Ansonsten kann man  natuerlich z.B. mit dem Grundrauschen des ADC einen 
seed produzieren, das waere sogar ziemlich gut. Kommt sicher auf die 
Anwendung an fuer einfaches halte ich ersten Ansatz fuer OK.

von Ingo L. (grobian)


Lesenswert?

@Michael

Columbus wollte auch nach Indien und ist in Amerika gelandet..und er 
hatte geplant.

von Michael G. (linuxgeek) Benutzerseite


Lesenswert?

Ich frag mich langsam ob dieser Beitrag hier ernst gemeint war oder ob 
das nur getrolle ist...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Michael G. wrote:

> Sobald zumindest ein paar Funktionsaufrufe mit vom input abhaengiger
> Laufzeit und Interrupts auftreten duerfte das nicht mehr passieren.

Ja, man braucht halt irgendwelche physikalischen Effekte dafür.  Wenn
man den 32-kHz-Oszillator benutzt, kann man dessen Anschwingverhalten
auch ausnutzen, das hat auch eine gewissen Zufälligkeit.  Bei neueren
AVRs kann man auch den 128-kHz-RC-Oszillator ,,anzapfen'' (bspw. über
einen watchdog-Interrupt), der ist auch komplett asynchron.

Man muss sich eben Gedanken machen, was dafür wirklich in Frage kommt.

von xyz (Gast)


Lesenswert?

>Columbus wollte auch nach Indien und ist in Amerika gelandet..und er
>hatte geplant.

Ach verstehe ...
du machst den Zufallszahlenquatsch in der Hoffnung, dass was cooles bei 
rumkommt? Vielleicht nen Webserver oder so ?

Viel Glück

;P

von Ingo L. (grobian)


Lesenswert?

neee ich brauche einfach nur ne zufällige zahl(en) zwischen 1 und 8.
Habe es dann am PC probiert und die og lösung gefunden.
Das es so nicht auf den AVR übertragbar ist war mir schon klar. Ich 
wusste nicht das es die RANDOM-FUNKTION so in der Form nicht im AVR 
anwendbar ist. ´Deshal die Frage die hier für eiige Leute für ein wenig 
wirbel sorgt. Bin halt was C betrifft noch am Anfang..so wie wir es hier 
alle mal waren...ok??

so gleich Fußball, Bier kühlen  und dann Daumen drücken und das wird 
kein Zufall...wir gewinnen..

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Die random()-Funktion funktioniert in der avr-libc praktisch genauso
wie auf einem PC: sie erzeugt eine Pseudo-Zufallszahlenfolge (allerdings
eines kleineren Wertebereichs durch den kleineren Datentyp "int").

srand(time(0)) ist übrigens auch auf einem PC mehr eine Krücke denn
eine richtige Lösung.  Wenn man bessere Entropiequellen hat (und auf
heutigen PCs hat man die praktisch immer), tut man gut daran, diese
zu nutzen statt der Systemzeit.

von Michael G. (linuxgeek) Benutzerseite


Lesenswert?

Jörg Wunsch wrote:

> srand(time(0)) ist übrigens auch auf einem PC mehr eine Krücke denn
> eine richtige Lösung.

Ja, untauglich vor allem fuer ernsthafte Anwendungen. Wenn's aber nur 
fuer nen Spiel oder sowas is isses i.d.R. OK.

von Andreas W. (Gast)


Lesenswert?

Entropiequellen sind zufällige nicht vorhersagbare Zustände. Weiß er 
sicher nicht.

Ein µC hat keine Zufälle. Die muss man sich immer irgendwo anders 
herholen. zum Beipsiel einen extra RC-Schwingkreis der läuft nicht so 
stabiel wie ein Quarz. Oder einen extra Rauschgenerator der termisches 
Rauschen für einen µC "auswertbar" macht. sowas in der Art halt.

Wenn du eine Zufallszahl per Knopfdruck machen möchtest. Dann kannst du 
auch das Knopfdrücken auswerten, also wie lange drückt einer, aber bitte 
das Prellen berücksichtigen, sonst wertest du nur das letzte Prellen 
aus, das liegt immer im ähnlichen Bereich.

von Andreas W. (Gast)


Lesenswert?

Achso das "includen" der ".c" ist nicht wirklich gut. normalerweise 
werden code-dateien ".c" einzeln vom compiler übersezt und vom linker 
dann eingebunden. das solltest du auch machen. ich weiß jetzt nicht wie 
das bei AVR-Studio geht, aber ich schätze die lcd.c einfach ins projekt 
aufnehmen.
Die headerdatei (.h) lässt du included, dann sind in deiner Code-datei 
(.c) die lcd-funktionen bekannt.

von Simon K. (simon) Benutzerseite


Lesenswert?

Hat sich mal jemand den Link vom Roboternetz angeguckt? Die haben imho 
ne ziemlich gute Idee einen Seed zu produzieren. Und vor allem sehr 
einfach.

http://www.roboternetz.de/wissen/index.php/Zufallszahlen_mit_avr-gcc

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Simon K. wrote:

> Hat sich mal jemand den Link vom Roboternetz angeguckt? Die haben imho
> ne ziemlich gute Idee einen Seed zu produzieren. Und vor allem sehr
> einfach.

Naja, das Einschaltmuster eines SRAMs ist exemplarabhängig relativ
stabil.  Es ist physikalisch (geometrisch) bedingt, in welche
Richtung die Flip-Flops vorzugsweise kippen, wenn die Betriebsspannung
angelegt wird.

Wenn es natürlich nur darauf ankommt, für verschiedene Geräte jeweils
verschiedene Startwerte zu erhalten, es dagegen nicht stört, wenn das
gleiche Gerät bei jedem Einschalten mit guter Wahrscheinlichkeit mit
der gleichen Folge startet, dann mag das gehen.  Ich würde allerdings
die Variante bevorzugen, den gesamten Speicher (vor der Initialisierung)
aufzusummieren, nicht nur ein Byte zu betrachten.

von 3356 (Gast)


Lesenswert?

Was spricht denn gegen ein rueckgekoppeltes schieberegister ? Ein 
solches LFSR hat eine definierte Periode. Wenn man die genuegend Gross 
waehlt ... Ein 32 bit schieberegister hat eine Periode von 4 milliarden 
Samples. Das ist in den meisten Faellen brauchbar. Sonst kann man zu 
noch groesseren Laengen gehen. Application note 210 von Xilinx hat die 
Koeffizienten bis zu einer laenge von 168 bit gelistet. Dessen Periode 
ist 2^168, was fuer normale Anwendungen genuegend sein sollte.

von Andreas W. (Gast)


Lesenswert?

Trotz komischen Start ist der thread echt interesant geworden.

Wo holt ihr den Startwert einer Zufallszahl auf einen µC her? oder wie 
macht ihr so sonst Zufallszahlen?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

3356 wrote:

> Was spricht denn gegen ein rueckgekoppeltes schieberegister ?

Was meinst du, was hinter rand() und random() dahinter steckt?

Genau: ein LFSR.

von P.J. (Gast)


Lesenswert?

Nimm die Funktion hier... ;-)

public int getRandomNumber()
{
    return 4;    // chosen by fair dice roll
                 // guaranteed to be random
}

von Timmo H. (masterfx)


Lesenswert?

Wie wärs für den Startwert mit Summe aus ein paar Bytes aus dem Stack, 
davon das Komplement, geteilt durch den Wert eines floatenden ports vom 
ADC, plus den Wert eines floatenden ports vom ADC. :-)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Timmo H. wrote:
> Wie wärs mit Summe aus ein paar Bytes aus dem Stack, davon das
> Komplement, geteilt durch den Wert eines floatenden ports vom ADC, plus
> den Wert eines floatenden ports vom ADC. :-)

Hast du's probiert?

Stack: wenn der Codepfad bis zur Initialisierung synchron war, steht
dort immer das gleiche drauf.

Floatender ADC-Port: dürfte eine Tendenz haben, auf einer der beiden
Endlagen zu liegen, je nachdem, wer dort als letztes Ladung
eingespeist hat.  Du müsstest eine kapazitive Einkopplung eines
50-Hz-Brumm oder so haben, damit du dort wirklich etwas anderes
lesen kannst.

Wie schon geschrieben, machen kann man viel, aber das hängt von der
ganz konkreten Umgebung ab, welche Zufallsquellen man heran ziehen
kann, um das LFSR zu initialisieren.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Jörg Wunsch wrote:
> Simon K. wrote:
>
>> Hat sich mal jemand den Link vom Roboternetz angeguckt? Die haben imho
>> ne ziemlich gute Idee einen Seed zu produzieren. Und vor allem sehr
>> einfach.
>
> Naja, das Einschaltmuster eines SRAMs ist exemplarabhängig relativ
> stabil.  Es ist physikalisch (geometrisch) bedingt, in welche
> Richtung die Flip-Flops vorzugsweise kippen, wenn die Betriebsspannung
> angelegt wird.
>
> Wenn es natürlich nur darauf ankommt, für verschiedene Geräte jeweils
> verschiedene Startwerte zu erhalten, es dagegen nicht stört, wenn das
> gleiche Gerät bei jedem Einschalten mit guter Wahrscheinlichkeit mit
> der gleichen Folge startet, dann mag das gehen.  Ich würde allerdings
> die Variante bevorzugen, den gesamten Speicher (vor der Initialisierung)
> aufzusummieren, nicht nur ein Byte zu betrachten.

Den nicht-initialisierten RAM per XOR als seed zu nehmen schien mir 
damals am einfachsten, aber wie gesagt ist zu erwarten, dass der Wert 
eines Bits nicht unabhängig von der Bit-Nummer/Adresse/Nibble ist. 
Deshalb wäre eine pfiffigerer Operator als XOR eine Option.

Bei meinem AVR (ATtiny25) geht's aber ganz zuverlässig: Ich hab mal ne 
Uhr gebaut, wie als Wecker ein Klangspiel anstösst. Nun könnte man 
meinen, das Klangspiel würde recht zufällig bimmeln und streuen wie 
Lottozahlen. Aber das ist leider nicht so. Das Klangspiel bimmelte immer 
in ziemlich der gleichen Sequenz und irgendwann kennt man die auswendig.

Weil ich die Uhr nicht umprogrammieren wollte (8051 in asm **örgx**) hab 
ich die 2 Strippen genommen und ne Ansteuerplatine mit dem ATtiny25 
gemacht. Die Platine bekommt von der Uhr 1 Mintte lang Saft und das 
war's. Daher kann ich mir im Tiny25 keinen Zustand merken und hab die 
besagte seed und die Multiplikation in GF(2^n) implementiert (wenn man 
sich die Multiplikation in GF(2^n) anschaut wird man erkennen, dass LFSR 
kaum was anderes sind. In GF hat man allerding noch ein irreduzibles 
Erzeugerpolynom. Meine mathematische Intuition sagt mir aber, dass LFSR 
am besten funzt, wenn die dort verwendeten Polynome ebenfalls 
irreduzibel sind.)

rhabarberrhabarberrhabarber... Jedenfalls werd ich jetzt jeden Morgen 
von anderen Sphärenklängen vom Reich der Träume in die schnöde Realität 
befördert :-)

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.