Forum: Mikrocontroller und Digitale Elektronik Random Zahl generieren


von Sebastian (Gast)


Lesenswert?

Hallo liebe Community...


mitlerweile hab ich das mit dem PWM in den Griff bekommen aber habe noch 
ein anderes Problem:


Wie kann ich einen Random Wert, also eine Zufällige Zahl in einem 
Festgelegten bereich, z.B. 155 generieren?

Hab hier im Forum leider nichts brauchbares Gefunden.


Grüße
Sebastian

von Sebastian (Gast)


Lesenswert?

Achja ich programmiere in AVR-GCC

von uwegw (Gast)


Lesenswert?

<stdlib.h>
rand()

von Sebastian (Gast)


Lesenswert?

hm

hab mal folgenden code gebastelt:
1
#include <avr/io.h>
2
3
int x=0;
4
 
5
unsigned short get_seed()
6
{
7
   unsigned short seed = 0;
8
   unsigned short *p = (unsigned short*) (RAMEND+1);
9
   extern unsigned short __heap_start;
10
    
11
   while (p >= &__heap_start + 1)
12
      seed ^= * (--p);
13
    
14
   return seed;
15
}
16
17
int main (void)
18
{
19
   srand(get_seed());
20
   x = (rand() %11); // Begrenzung von 0 - 10
21
}

Funktioniert das ganze?

von Martin (Gast)


Lesenswert?

Probieren geht über studieren.

von Vaterssohn (Gast)


Lesenswert?

google mal nach "lineare Kongruenzmethode". Nach dieser Formel arbeiten 
viele Zufallsgeneratoren.

von Sebastian (Gast)


Lesenswert?

Ich werd erstmal heut abend mein Programm Testen und euch dann 
berichten.


Grüße
Sebastian

von Hagen R. (hagen)


Lesenswert?

@sebastian, filtere mal alle Addressen aus die durch dein Program als 
globale Variablen schon belegt sind, also den Seed des RNGs selber auch. 
Dann wirst du feststellen das ein RESET eines schon unter Strom 
stehenden Controllers immer den gleichen Wert liefert.

Ich mache es immer so:

- ich benutze ein 32Bit LFSR als RNG
- diesem LSFR Code kann man die Polynome vorgeben
- ich benutz 2 unterschiedliche Polynome A und B
- beim Powerup der MCU lade ich aus dem EEPROM ein 32 Bit Wert als Seed
- diesen schicke ins LFSR mit Polynom A und speicher das Resultat zurück 
in den EEPROM an gleicher Stelle
- dieser Seed wird als akuelles Register des LFSR benutzt
- zur Laufzeit benutze ich das LFSR mit Polynom B

Somit laufen 2 LFSR in parallel. Das eine wird immer nur beim RESET 
aktualisert und dessen Seed steht im EEPROM. Das andere LFSR wird damit 
initialisiert. Beide LFSR benutzen andere Polynome.

Das ist zwar nicht echt zufällig, aber eben beweisbar immer 
pseudozufällig im Gegensatz zu deiner Methode.
Bei einem RESET wird nämlich der SRAM nicht ständig mit Zufallsdaten 
gefüllt, bzw. ist es garnicht gesagt das der SRAM ohne Strom nach 
Einschalten ein zufällig Inhalt aufweisen muß.
Gleiches gilte für Methoden wie mit dem ADC und Rauschen. Das Rauschen 
des ADCs muß nicht echt zufällig sein sondern systembedingt.

Gruß Hagen

PS: in der Codelib nach "Glühwürmchen" suchen, dort findest die meinen 
LFSR Source für WinAVR GCC und auch in main() oben besprochene 
Initialisierung.

von Sebastian (Gast)


Lesenswert?

okay danke für deinen Tipp

ich werd heut abend dann mal Test und Programmierstunden einrichten ;)

von Hagen R. (hagen)


Lesenswert?

falls du andere Polynome brauchst (müssen von spezieller Form sein damit 
die maximale Periode von 2^32-1 erreicht wird) dann sag es.

Gruß Hagen

von Sebastian (Gast)


Lesenswert?

okay mach ich sobald ich es testen konnte :)

von Andy (Gast)


Lesenswert?

Hallo,
Sorry, dass ich den alten Thread hochhole, aber ich habe auch eine Frage 
bzgl. dieses Themas.
Ich habe mehrere µC, die das komplett gleiche Programm laufen haben. Nun 
muss ich eine Random-Zahl generieren, die bei allen aber unterschiedlich 
sein muss. Zur Zeit mach ich das mit der Rand()-Funktion, aber die 
Zahlen sind alle gleich!
Jemand deine Idee? Besten Dank!

mfg
Andy

von Nils S. (kruemeltee) Benutzerseite


Lesenswert?

du brauchst nen passenden seed. Ich würde als platzsparenden 
Zufallsgenerator einen nach Park-Miller-Carta basteln, hier einige 
funktionierende Codebeispiele:
http://www.firstpr.com.au/dsp/rand31/

Als seed kannst du die Zeit nehmen. Sprich du bastelst dir entweder 
irgendwie die aktuelle Uhrzeit rein oder, was viel besser wär, eine 
"Systemuhr". Einen Timer (frequenz nahezu egal), der eine globale 
Variable hochzählt.

Das höchste der Gefühle wär natürlich wenn du dir daraus die Unix 
Systemzeit errechnen lässt und das dann als seed nimmst.

von Frank (Gast)


Lesenswert?

Was ist mit Hardware?

Das Rauschen einer Z-Diode, Trigger, Zähler - sollte echte Zufallszahlen 
hervorbringen und gibts bestimmt auch als fertigen Chip, oder?

Frank

von Andy (Gast)


Lesenswert?

OK, danke erstmal für eure Hinweise.
Was ich mir gedacht habe: Wie wärs, wenn ich von Anfang an einen Timer 
laufen lasse und wenn ich die Zahl brauche, mach ich Rand()*TCNT2/255. 
Ich glaube, ein bisschen unterschiedlich werden die Timer auf 2 Atmels 
schon laufen, oder glaubt ihr, dass die immer die gleichen Werte haben 
werden??

von Nils S. (kruemeltee) Benutzerseite


Lesenswert?

Die haben IMMER die gleichen Werte, allerdings nicht zur selben Zeit ;)

von Barny F. (barny)


Lesenswert?

Was spricht denn gegen die Methode den Ram vor dem 1. Schreibzugriff 
auszulesen und alle Werte mit XOR zu verodern?
Der Startzustand des Ram's müsste eigentlich jedes mal anders sein.

von Maxxie (Gast)


Lesenswert?

Ist er aber nicht. Die Speicherzellen haben recht hohe Tendenzen beim 
einschalten sehr oft den gleichen Zustand einzunehmen 
(Fertigungstoleranzen die einen Zustand bevorzugen lassen) Man kann mit 
der Methode gar recht sicher feststellen, ob man der sram gewechselt 
worden ist (für systeme in denen das möglich ist)

Man kann aber recht volatile Meßwerte mit hernehmen. Ein floating ADC 
ist zwar auch nicht ganz zufällig, aber nett :-p

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


Lesenswert?

Maxxie schrieb:
> Ist er aber nicht. Die Speicherzellen haben recht hohe Tendenzen beim
> einschalten sehr oft den gleichen Zustand einzunehmen

Wobei ich mir vosrtellen kann, dass ein XOR über alle nicht
benutzten RAM-Zellen (so es genügend viele sind) in der Tat
gar keinen so schlechten Zufallswert ergeben könnte.  Das müsste
man einfach mal mit hinreichend vielen Versuchen erfassen und
dann als Plot darstellen.

von Andy (Gast)


Lesenswert?

Hallo,
Wie gesagt, ich habs nun über den TCNT2 gelöst - meint ihr, ist das ein 
zuverlässiger Zufallszahlengenerator?
Was mir noch in den Sinn gekommen ist: Gibt es eine Art Seriennummer im 
Atmel, die ich auslesen und für die Zufallszahlenberechnung heranziehen 
könnte??
THX

Andy

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


Lesenswert?

>> Zur Zeit mach ich das mit der Rand()-Funktion ...
> Wie gesagt, ich habs nun über den TCNT2 gelöst - meint ihr, ist das ein
> zuverlässiger Zufallszahlengenerator?
Es geht doch gar nicht um den Generator, sondern nur um den Anfangswert 
(seed = die Saat). Ich glaube nicht, dass der Timer immer anders 
losläuft und du damit zuverlässig jedesmal einen anderen Startwert hast.

Sehr schön zum Erzeugen eines Saatwertes sind Benutzeraktionen oder 
extern angeschlossene Hardware (Endschalter, Taster, Zeichen über 
SIO...). Wenn ein Timer schnell hochläuft und der Zählerwert bei einem 
Pegelwechsel als Seed verwendet wird, kann ein Benutzer oder Ventil 
ziemlich sicher nicht denselben Startwert zweimal erzeugen. srand() muß 
ja nicht in der Nähe von rand() stehen, und es kann auch öfter 
aufgerufen werden.

von Andy (Gast)


Lesenswert?

Deshalb hab ich ja den Timer genommen. Nur ist die Frage, ob 2 µC die 
zugleich eingeschalten werden und die zugleich einen Zufallswert 
ausspucken sollen, denselben Wert ausgeben werden, oder ob die 2 Timer 
ein bisschen auseinanderlaufen werden.
Hätte ich eine Art Seriennummer, die einzigartig ist, könnte ich ja 
diese zum Seed-Wert nehmen und ich hätte 2 verschieden laufenden 
Timer...

von Andy (Gast)


Lesenswert?

BTW: Was ist srand()??

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


Lesenswert?

Andy schrieb:
> BTW: Was ist srand()??
Ja, wie bitte?
Du hängst dich an einen Thread und hast den nicht mal durchgelesen?
Beitrag "Re: Random Zahl generieren"
Das ist hart, meine Herren  :-/

Mit srand() wird der Startwert für den Zufallszahlengenerator 
festgelegt.
Als Stichworte für Guugel: srand() und rand(). Damit werden 
Zufallszahlen erzeugt.

von Andy (Gast)


Lesenswert?

sorry, hab ich grade gelesen.... :-)

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.