mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Problem mit Zufallscode


Autor: Jackson02 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Abend zusammen!

Ich hätte hier meiner Meinung nach eine "schöne" und einfache Idee einen 
fast einwandfreien Zufallsgenerator für eigentlich jede Anwendung. Die 
Idee dazu ist eigentlich recht gut.
Nur leider gibts einen Hacken - Da ich noch nicht so lange in der 
µC-Branche bin, kann es sein, dass sich ein Fehler (wahrscheinlich mit 
dem Interrupt) eingeschlichten hat.
- Controller ist zu Testzwecken nur ein Attiny13 (Soll später über 
Matrixdisplay eine Zahl ausgegeben werden mit einem Atmega8 oder 
Attiny2313)
- Der Interrupt-Pin ist der PB0 (Pin5)
- Ausgänge sind (wie man sieht) PB2 (Pin7) und PB1 (Pin6)

Die Idee ist, einen Zufälligen "RND"-Wert durch ständiges Wiederholen 
dauernd zu ändern und in die Variable A zu schreiben. Durch den 
Interrupt soll dann der in A gespeicherte Wert verarbeitet und 
ausgegeben werden.

Hier nun einmal der Code:
(Ich habe hier bewusst Rnd(50) statt die normalerweise benötigten Rnd(2) 
für meine 2 Zustände bzw. Ausgänge genommen, da sich so mehrere Ausgänge 
oder die "Wahrscheinlichkeit" leicht ändern lässt)
$regfile = "attiny13.dat"
$crystal = 1200000
$hwstack = 22

Config Pinb.0 = Input
Config Portb.1 = Output
Config Portb.2 = Output
Pinb.0 = 1

On Int0 On_int0
Config Int0 = Falling
Enable Int0
Enable Interrupts

Dim A As Word
A = 0

Do
A = Rnd(50)
Waitms 10
End
Loop

On_int0:
If A < 25 Then
Portb.1 = 0
Portb.2 = 1
Else
Portb.1 = 1
Portb.2 = 0
End If
Wait 1
Portb.1 = 0
Portb.2 = 0
Return

Ich hoffe, dass mir jemand weiterhilft :)

Mit den besten Grüßen

Manuel

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit Zufallszahlen muss man vorsichtig sein.
So manche vermeintlich clevere Idee dazu ist ein Schuss in den Ofen.

Deine gehört dazu.
Wenn die Laufzeiten der einzelnen Programmteile ein ganzzahliges 
Vielfaches zueinander haben, kann es sein, dass einzelne Zahlen deines 
Wertebereiches niemals erzeugt werden. Oder aber noch schlimmer: 
Einzelne Zahlen werden durch das Verhältnis der Laufzeiten zueinander 
extrem bevorzugt.

Daher ist es am besten:
Benötigt man eine Zufallszahl, dann ruft man die RND auf. Und ansonsten 
lässt man das Zeugs in Ruhe. Die Formel die hinter RND steckt, ist so 
ausgeklügelt worden, dass sich automatisch die gewünschte Verteilung der 
Zufallszahlen ergibt (meistens eine Gleichverteilung). Greift man da an, 
macht man die Dinge nie besser sondern maximal bleibt die Charakteristik 
der Zahlen erhalten. Meistens verschlimmert man aber die Situation und 
die generierten Zahlen weisen alles andere als eine vernünftige 
Zufallsverteilung auf.

Viele Zufallszahlengeneratoren kann man seeden. Das heist man gibt ihnen 
den ersten Wert vor, von dem an dann der Generator die weiteren Zahlen 
bestimmt. Dieses seeden kann man zb durch Zeitmessung bis zum ersten 
Tastendruck machen. Aber danach ist man mit der Devise: Hände weg vom 
Generator besser bedient.

In deinem konkreten Beispiel könntest du zb eine Steuerung einbauen, 
dass dein ständiges RND generieren abgebrochen wird, sobald der erste 
externe Interrupt kommt. Ab dann verwendet die Interrupt Routine nur 
noch RND um jeweils die nächste Zahl zu erzeugen, die laufende 
Generierung in der Hauptschleife sollte dann besser aufhören.
Damit hast du erreicht was du erreichen wolltest: Die Startbedingungen 
für die erzeugten Zufallszahlen hängen von der Zeitdauer bis zum ersten 
Interrupt ab und danach hast du eine saubere Zufallszahhlenverteilung, 
wie sie RND implementiert hat.

Autor: Manuel B. (jackson02)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was bedeutet das nun im Bezug auf meinen Code?

Achja, ich vergaß zu erwähnen. Das Problem ist, dass sie bei einem 
Drücken des Interrupt-Tasters nichts tut. Also die Ausgänge werden nicht 
gesetzt und führen ständig 0-Signal.

Grüßle

Autor: Grübler (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Manuel B.
>Was bedeutet das nun im Bezug auf meinen Code?

Wenn ich K.H.B. richtig verstanden habe,
ist dein Code für den A... ;-)


>Achja, ich vergaß zu....... führen ständig 0-Signal.

Siehe oben

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Nur mal so: Wolltest du mit

>Pinb.0 = 1

den Pull-Up einschalten? Wenn ja sollte es wohl besser

Portb.0 = 1 heissen.

MfG Spess

Autor: Manuel B. (jackson02)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also nach K.H.B. soll ich ja "nur" den RND verwenden wenns nicht anders 
geht. In diesem Fall ruf ich ihn ja schließlich auch nur auf, weil ich 
eben seine Funktion brauche - die Zeit mit der 1ms soll ja ledeglich den 
RND-Wert alle paar Millisekunden verändern.
Ich bezweifle nicht, dass das nicht passiert.
Jedoch fällt mir kein Fehler an dem Code auf, welchen ich aber gerne 
Wissen würde. Schließlich lernt man ja aus seinen Fehlern ;)


Grüßle

Autor: Manuel B. (jackson02)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ahh..
@spess53

Danke.. fiel mir gar nicht auf.

Ich stells gleich mal um.
Danke nochmals.

Allerdings besteht das Problemchen nun leider immer noch :(

Grüßle

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> So manche vermeintlich clevere Idee dazu ist ein Schuss in den Ofen.

Man kann eigentlich generell sagen: echte Zufallszahlen (also
solche, die selbst dann nicht vorhersagbar sind, wenn man den Code
kennt, der sie erzeugt) lassen sich nur durch physikalische
Effekte erzeugen, die bedingt durch ihre Physik eine garantiert
zufällige Verteilung haben.

Autor: GerK (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Dreh mal "End und Loop" um.

MfG
GerK

Autor: MaWin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Die Idee ist, einen Zufälligen "RND"-Wert durch ständiges Wiederholen
> dauernd zu ändern und in die Variable A zu schreiben. Durch den
> Interrupt soll dann der in A gespeicherte Wert verarbeitet und
> ausgegeben werden.

Der Interrupt ist also ein Tastendruck,
und gezählt wird so schnell, daß der Zähler dauernd komplett rumzählt,
wie lang die Zeit zwischen dem vorherigen und diesem Tastendruck ist, 
wobei nur die niederwertigen Stellen benutzt werden.

Das Verfahren ist alt, uralt,
bei ausreichend schnellem Zähler reicht es gar, die Länge des 
Tastendrucks (in Millisekunden, wobei nur der Mikrosekundenanteil als 
Zufallszahl gilt) abzustoppen.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ob das geht, dazu müßte man erstmal wissen, wie die rnd()-Funktion 
implementiert ist.
Wenn sie z.B. nicht immer exakt gleiche Berechnungszeit benötigt, ist 
das Ergebnis nicht mehr zufällig.
Wenn sie einen Timer benutzt, auch nicht.

Warum nimmst Du ein Word (16Bit) für ne Variable, die nur max 50 sein 
kann?
Und wenn sie >255 werden könnte, hast Du eh noch das Atomicity-Problem.


Peter

Autor: Jackson02 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Abend,
Werde eure Ratschläge mal befolgen und so den Code morgen Vormittag mal 
umbauen.
Ich hoffe dass dann keine Leichtsinnsfehler mehr drinnen sind und ich 
das Programm zuverlässig gestalten kann.
Werde den Code natürlich dann mal posten.

Die besten Grüße

Manuel

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.