mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik MSP430 Binäre Zufallszahl generieren und darauf LEDs aufleuchten lassen


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Andriy V. (derandrey)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Hallo liebe Forenmitglieder,

ist es möglich in C eine zufällige Dualzahl zu erzeugen in vorgegebener 
größe, also zum Beispiel eine 12 Bit Dualzahl wie 001010010001?
Ich habe schon Google durchforstet, jedoch nichts hilfreiches dazu 
gefunden. Ich möchte nämlich ein Spiel programmieren, dass 3 
Schwierigkeitsstufen hat. Für die 1. Schwierigkeitsstufe brauche ich 
eine 4 Bit, für die 2 Stufe eine 8 Bit und für die 3 Stufe eine 12 Bit 
binäre Zufallszahl. Das Spiel soll so aussehen, für jede 0 soll die rote 
LED aufleuchten, für jede 1 die grüne LED, gestartet wird beim LSB. 
Danach soll man die entsprechenden Tasten am Mikrocontroller drücken 
(rechts für rote LED, links Grüne LED) um diese Farbkombination zu 
wiederholen. Nun hänge ich jedoch schon allein beim erstellen der 
Zufallszahl :/

Die einzige Möglichkeit die ich hier sehe wäre eine zufällige 
Dezimalzahl zu erzeugen und diese dann in eine Binärzahl umzuwandeln, 
jedoch bin ich mir nicht sicher ob das genau so geht wie ich mir das 
vorstelle, weil ich ja genau die größe/länge brauche, also wenn bei der 
3. Stufe (12Bit) eine Zahl, z. B. eine "4" generiert wird, sollen davor 
noch 8 Nullen sein (0000 0000 0100), hoffe ihr versteht was ich mein. 
Was mir noch einfallen würde, wäre eine Zufallszahl zwischen 0 und 1 zu 
generieren und diese dann in einem Array der entsprechenden Bitlänge zu 
speichern.

Habe erst jetzt mit der C Programmierung angefangen, deswegen weiß ich 
nicht genau wie ich das realisieren kann.

Danke schon mal für eure Hilfe :)

: Bearbeitet durch User
Autor: Lötlackl *. (pappnase) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Falls eine Pseudozufallszahl genügt, dann ist vielleicht so etwas 
interessant.
https://de.wikipedia.org/wiki/Linear_r%C3%BCckgekoppeltes_Schieberegister

Autor: Karl M. (Gast)
Datum:

Bewertung
-9 lesenswert
nicht lesenswert
Hallo Andriy V. schrieb:
> zufällige Dezimalzahl zu erzeugen

Das ist doch schon ein Widerspruch in sich - das geht nicht!

Eine Zufallszahl kann man nicht vorhersagen nur die statistische 
Verteilung!

Autor: Erik (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Echte Zufallszahlen gehen nicht ohne spezielle Hardware, die 
physikalische Eigenschaften ausnutzt. Hat ein Standard MSP430 aber 
nicht.

Pseudo Random Generator ist dein Freund für die Suche.

zB sowas:

unsigned short lfsr = 0xACE1u;
unsigned bit;

unsigned rand(){
  bit  = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5) ) & 1;
  return lfsr =  (lfsr >> 1) | (bit << 15);
}

Autor: Karl M. (Gast)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
Hallo,

Dezimalzahl sind doch Binärzahl und auch nur Zahlen.

^------Basis 10       ^-----Basis 2

Also wo ist das Problem?

Autor: Bernd B. (microwave-designer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Andriy,

sollte die Zufallszahl mit

   int rand(void)

in Deiner Entwicklungsumgebung nicht funktionieren, kann man über die 
zuvor beschriebene Pseudozufallszahl das Problem lösen.

Notfalls eine 16-bit Pseudozufallszahl generieren und die überschüssigen 
Stellen ausblenden. -> bitweise AND

Evtl. wäre es günstig beim Ausblenden die neue Zahl mit der vorherigen 
zu vergleichen, da es manchmal vorkommt, dass die neue Zahl nach der 
Bit-Operation der vorhergehenden gleicht. Dann einfach die nächste Zahl 
erstellen.

Ich habe das für den MSP430 einmal in Assembler programmiert. Das geht 
gut!

Gruß

Bernd

Autor: Schlumpf (Gast)
Datum:

Bewertung
3 lesenswert
nicht lesenswert
Da es sich eh um ein Spiel mit Tasten und LEDs handelt, und du 
vermutlich auch eine weitere Taste für "neues Spiel" haben wirst, kannst 
du auch den Mensch als "Zufallsgenerator" verwenden.
Das wäre eine Alternative zu "rand()"

Einfach einen Zähler sehr schnell inkrementieren, solange die Taste 
"neues Spiel" gedrückt ist und beim Loslassen der Taste bleibt der 
aktuelle Wert stehen.


Ähnlich, wie früher eim "elektronischen Würfel"

Das Menschliche Auge und Reaktionszeit ist so langsam, dass das Ergebnis 
zufällig ist.

Autor: Erik (Gast)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
Bernd B. schrieb:
> Evtl. wäre es günstig beim Ausblenden die neue Zahl mit der vorherigen
> zu vergleichen, da es manchmal vorkommt, dass die neue Zahl nach der
> Bit-Operation der vorhergehenden gleicht. Dann einfach die nächste Zahl
> erstellen.

Rein aus Neugier, warum?

Darf ein zufällige Zahl nicht der vorigen zufällig gleichen?

Gerade bei Verkleinerung des Zahlenraumes erhöht sich die 
Wahrscheinlichkeit jeder einzelne Zahl.

Autor: Andriy V. (derandrey)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die schnellen Antworten. Tut mir leid für die Verwirrung, ich 
meinte eine pseudo-Zufallszahl die z.B über die Systemzeit erzeugt wird, 
also sowas wie rand(). Das ich keine echte Zufallszahl erzeugen kann ist 
mir bewusst aber Danke. Mir geht es eher darum wie ich eine binäre 
pseudo-Zufallszahl in einer bestimmten länge generieren kann, falls dies 
möglich ist. Der Ansatz von Bernd B. scheint mir gut aber leider bin ich 
noch zu unerfahren um zu wissen wie ich da umsetzen kann.

Autor: Erik (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Andriy V. schrieb:
> Mir geht es eher darum wie ich eine binäre
> pseudo-Zufallszahl in einer bestimmten länge generieren kann

Generiere die Zahl entweder mittels rand() aus einer Library oder 
mittels lfsr (siehe oben).

Danach einfach:

1) Auf die entsprechenden Stellen zurechtschneiden (& 0x3 -> 2 Bits). 
Dies ist möglich da jede einzelne Bitstelle der Zufallszahl ebenso 
zufällig ist (ist wie oben bereits geschrieben nur eine andere 
Zahlendarstellung).

2) Modulo % benutzen, falls es keine Zweierpotenz sein soll

Autor: StefG (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die meisten Zufallsgeneratoren liefern eine float Zahl zwischen 0 und 1.
Diese Zahl dann mit 16 (für 4 bit) multiplizieren, 0.5 dazuzählen, dann 
Nachkommastellen abschneiden.
Gibt integer Zahl zwischen 0 und 16.

Autor: Bernd B. (microwave-designer)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Hallo Andriy,

hier ein Stück Code:


;-------------------------------------------------------------------------------
Prng        ; pseudo random number generator 16 bit
;-------------------------------------------------------------------------------
            cmp.w   #0x0, &lfsr16
            jnz     Prng16_1
            mov.w   #0x53a1, &lfsr16        ; set seed if start value was zero
Prng16_1    bit.w   #0x8000, &lfsr16
            push.w  SR                      ; take relevant bit from status reg.
            bit.w   #0x2000, &lfsr16
            xor.w   SR, 0(SP)
            bit.w   #0x1000, &lfsr16
            xor.w   SR, 0(SP)
            bit.w   #0x0400, &lfsr16
            xor.w   SR, 0(SP)
            rrc.w   0(SP)
            rlc.w   &lfsr16                 ; shift carry to LSB
            incd.w  SP
            reta                            ;




Ich habe das so gemacht, dass in der Variable "&lfsr16" ein Startwert 
oder der letzte Wert aus dem letzten Aufruf liegt. Diese Variabel muss 
während der gesamten Laufzeit vefügbar sein und darf nur an dieser 
Stelle verändert werden.

Bei mir habe ich am Bildschirm der Applikation sogenannte Softkeys. Über 
Pseudozufallszahlen lege ich Symbole an die Keys und bitte den Nutzer 
diese Tasten zu drücken. Das dient einer Bestätigung, das Gerät komplett 
stromlos zu schalten. Damit gehen in meiner Applikation auch alle 
Speicherwerte verloren. Mit dem Vergleich und der erneuten Berechnung 
stelle ich sicher, dass jeder neue Vorschlag vom vorhergehenden sich 
unterscheidet. Das ist bei Dir wahrscheinlich nicht notwendig, so dass 
Du wahrscheinlich genau diesen Code verwenden kannst.

Mit der Anweisung "push SR" erzeuge ich mir Platz für eine Variable. Mit 
dem "incd.w" justiere ich den Stack wieder. Die Prozedur ist eine 1 zu 1 
Umsetzung der vielen Erklärungen von Wikipedia.

Der Code stammt vom 23.04.2008, d. h. ich möchte meine Beiträge an 
dieser Stelle abschließen, Dich bitten, Dich mit dem Code selbst 
auseinander zu setzen und NUR wenn es wirklich nicht anders geht noch 
einmal zu rufen.

Danke und happy coding

Bernd

Autor: Kaj (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Ein LFSR ist nur ein mittelmaessig guter Zufallszahlengenerator, da sich 
die Periode, je nach gewaehlten Rueckkopplungskoeffizienten, sehr 
schnell wiederholen kann.

Beispiel:
Ein LFSR vom Grad m = 4 mit dem Rueckkopplungskoeffizienten
x^4 + x + 1 hat eine Periode von 15 (maximale Folgenlaenge).

Ein LFSR vom Grad m = 4 mit dem Rueckkopplungskoeffizienten
x^4 + x^3 + x^2 + x + 1 hat nur eine Folgenlaenge von 5.

Um die maximale Folgenlaenge zu erreichen brauchst du ein primitives 
Polynom, ein Spezialfall der irreduzieblen Polynome.


Wenn du eine 12 Bit Zahl (also im Bereich [0 - 4095]) brauchst, dann 
mach doch einfach:
uint16_t number = rand() % 4096;
http://www.cplusplus.com/reference/cstdlib/rand/

Erik schrieb:
> Echte Zufallszahlen gehen nicht ohne spezielle Hardware, die
> physikalische Eigenschaften ausnutzt.
Wenn Lavalampen als "spezial Hardware" gelten...
http://www.gizmodo.co.uk/2017/11/one-of-the-secrets-guarding-the-secure-internet-is-a-wall-of-lava-lamps

Autor: Peter D. (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andriy V. schrieb:
> ist es möglich in C eine zufällige Dualzahl zu erzeugen

Ja.
Siehe rand() und srand() in <stdlib.h>

https://www.microchip.com/webdoc/AVRLibcReferenceManual/group__avr__stdlib.html

Autor: Andriy V. (derandrey)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Tut mir leid ich bin etwas verwirrt, weil ich hier viele verschiedene 
Lösungsansätze bekomme, manche eher kompliziert (also meines Empfindens) 
andere simpel wie zum Beispiel einfach nur die rand() Methode zu 
verwenden, jedoch weiß ich nicht wie das gehen soll, denn rand() bekomme 
ich nur eine Dezimalzahl wie z.B "8" und keine Dualzahl wie z.B "1000" 
ausgegeben, also soweit ich weiß. Oder liege ich da falsch?

Autor: Erik (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Andriy V. schrieb:
> nur eine Dezimalzahl wie z.B "8" und keine Dualzahl wie z.B "1000"

https://de.wikipedia.org/wiki/Dualsystem

oder Freitagstroll?

Kaj schrieb:
> Wenn Lavalampen als "spezial Hardware" gelten...

Ich bezeichne die Lavalampen + Kamera schon als Spezialhardware.
Oder gibs die Kombination mittlerweile integriert in uCs ?

Autor: Andriy V. (derandrey)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Ich meinte ich brauche die Darstellung der pseudo-Zufallszahl im 
Dualsystem und ob es dafür schon eine Standardmethode gibt wie rand()?

Autor: Bernd B. (microwave-designer)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Hallo Andriy,

ich komme doch noch einmal durch: Wie programmierst Du den MSP430?

Gruß

Bernd

Autor: Superschlumpf (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Zu Zeiten wo Mann noch den Urlader haendisch per Binaertastatur
in die Ferritkerne schrieb, wusste jeder halbwegs was er tat.

Heute scheint dagegen die voellige Dummheit ausgebrochen zu sein.

Autor: Andriy V. (derandrey)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Hallo Bernd,

was genau meinst du wie ich den MSP430 programmiere? Möchtest du den 
Ablauf wissen oder welche Ports, Tasten, LEDs ich benutze? Welches 
Programm ich nutze?



Superschlumpf schrieb:
> Zu Zeiten wo Mann noch den Urlader haendisch per Binaertastatur
> in die Ferritkerne schrieb, wusste jeder halbwegs was er tat.
>
> Heute scheint dagegen die voellige Dummheit ausgebrochen zu sein.

Danke für deinen hilfreichen Beitag!

Autor: Bernd B. (microwave-designer)
Datum:

Bewertung
-2 lesenswert
nicht lesenswert
Hallo Andriy,

ein Problem liegt in den unqualifizierten Kommentaren, z. B. dem 
Foristen, den Du ebenfalls angesprochen hast. Egal, jetzt zum 
Lösungsansatz:

In einem persönlichen Gespräch und vis a vis fällt es mir immer leichter 
mein Gegenüber einzuschätzen. Handelt es sich um einen Studenten, einen 
Abiturienten, einen Praktikanten, einen gestandenen Ingenieur 
(vielleicht aus einem andere Fachbereich), einem Kaufmann mit Affinität 
zur Elektrotechnik, einem Röhrenbastler mit ersten 
Mikroprozessor-Kontakten, usw. Mit meiner Frage nach Deiner 
Entwicklungsumgebung habe ich versucht herauszufinden, wer du bist und 
welche Erfahrungen bei Dir vorhanden sind.

Das ist immer der Nachteil in einem Forum zu kommunizieren. Bereits in 
Deiner Anfrage ganz oben hast Du signalisiert, dass Du in der Bedeutung 
der unterschiedlichen Zahlensysteme nicht so ganz fit bist. Deine 
Dezimalzahl möchtest Du in eine Binärzahl umwandeln. Der Unterschied in 
den Zahlendarstellungen ist bei Dir vielleicht nicht so ganz geläufig. 
Stelle Dir einfach ein Lineal mit cm-Skala als das Dezimalsystem vor. 
Wenn Du jetzt ein Maßband mit Zollteilung daneben legst (1 Zoll entspr 
2,54 cm), erkennst Du den Zusammenhang zwischen den unterschiedlichen 
Darstellungen. Beim Dezimalsystem erweitert sich die Zahl um eine 
weitere Stelle, sobald die Darstellung über die 9 rollt. (8, 9, 10, 
11,... - Potenz zur Basis 10). Bei der Binärdarstellung erweitern sich 
die Stellen, sobald die Zahl über die Potenz zur Basis 2 rollt (0, 1, 
10, 11, 100, 101, ...). Also ist es wurscht, in welchem Zahlensystem Du 
rechnest. Wir Menschen rechnen historisch bedingt im Dezimalsystem - 
Dank sei den Arabern! Die Mikroprozessoren fühlen sich aber nur im 
Binärsystem wohl, da sie nur die Bedingungen Strom / kein Strom kennen. 
Da sich der Mensch anpasst, rechnen die Programmierer ebenfalls im 
Binärsystem oder im Hexadezimalsystem (hier rollt die Stelle bei 16 
(okay von 15 auf 0), usw. Das Hex-System ist besonders praktisch, da man 
mit 2 Stellen 256 Zustände beschreiben kann oder mit 4 Stellen die 16 
Bit (das ist binär) oder eben 65536 als Dezimalzahl.

Sofern Du einen Debugger benutzt, schreibe doch einmal in eine 
Speicherzelle eine Zahl mit der von Dir gewählten Zahlenbasis und sieh 
Dir die Darstellung im Debug-Fenster mit einem Dump des Speichers an. 
Beim MSP430 bietet sich ein Register, z. B. Register R8 an. Das Register 
wird in den Beispielprogrammen mehr oder weniger benutzt. Lass den 
Prozessor nicht laufen, nur gucken.

Jetzt wirst Du feststellen, dass Deine Dezimalzahl bei der Eingabe 
automatisch in eine Hexzahl umgewandelt wird. du kannst auch die 
Darstellung bei der Ausgabe ändern. ... usw.

Okay, vielleicht ist das alles kalter Kaffee, aber ich kann schwer 
einschätzen, auf welchem technisch Level ich Dir weiterhelfen kann. Wenn 
es bis jetzt doch interessant war, dann nimm bitte mit, dass es echt 
egal ist, welches Zahlensystem Du verwendest, da Compiler und Debugger 
alle Zahlen automatisch in die jeweiligen Zahlensysteme umrechnen. Nimm 
Dir eine Zahl mit Deiner gewünschten Bit-Anzahl  und wandle sie in 
Binär, also Bitdarstellung um. Versuche zu verstehen, was mit den AND- 
und OR-Funktionen passiert.

Dann noch eine Anmerkung: Eine Pseudozufallszahl ist keine echte 
Zufallszahl. Spannt Dein Algorithmus einen Zahlenraum von 5 Bit 
(beispielsweise) auf, werden nach allen 32 Berechnungen alle Zahlen 
einmal errechnet. Und das geschieht nach einer vorbestimmten 
Reihenfolge. Das heißt auch, dass nach den 32 Aufrufen genau die gleich 
Abfolge wiederkehrt. Es gibt Möglichkeiten diese Einschränkungen oder 
Gegebenheiten zu verbessern. Das spielt aber bei 8-bit oder 12-bit keine 
Rolle, wenn nach 256 Aufrufen oder 4096 Aufrufen die Zahlenfolge 
wiederkehrt. Wenn Du echte Zufallszahlen erstellen willst, musst Du wohl 
ein mit radioaktiven Zerfall und einem Zählrohr arbeiten.

So, langer Text - viel Erfolg!

Bernd

Autor: Werner S. (wernertrp)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Benutzer soll sich die Zufallszahl selbst erzeugen mit einem 
Reaktionstest. Er soll eine Taste drücken wenn eine LED aufleuchtet.
Die letzten Stellen eines us Counters werden dann als Zufallszahl 
genommen.

Autor: Chris K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auch ein beliebter Trick. Z-Diode an den adc anschließen. Sampeln lassen 
und das lsb als einzelnes bit in eine variable schrieben, dann wieder 
Sampeln und das bit an die nächste Stelle der Variablen schrieben und so 
weiter und so weiter. Dabei ist es egal, ob 8, 10, 16 oder 32 bit. Alles 
was man tut ist adc Sampeln lassen und lsb in die Variable shiften. 
Durch die z-Diode hat man ordentlich thermisches rauschen auf dem adc 
und das lsb ist somit fast zufällig.

Autor: Route 6. (route_66)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Bernd B. schrieb:
> Okay, vielleicht ist das alles kalter Kaffee,

Richtig!
Der TE hat ja nicht das Problem,eine Zufallszahl zu erzeugen. Er sucht 
eine zufällige Zeichenkette (String) aus Nullen und Einsen mit 
vorgegebener Länge.
Da ist sein Ansatz mit einem Array schon der richtige Weg.
Statt "0" und "1" (0x30 bzw. 0x31) kann er auch "R" und "G" für seine 
Farbenzuordnung ins Array schreiben.

Autor: Peter D. (peda)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Bernd B. schrieb:
> Das heißt auch, dass nach den 32 Aufrufen genau die gleich
> Abfolge wiederkehrt.

Nein.
Die Lib-Funktionen benutzen in der Regel ein 32Bit Schieberegister und 
das legt die Wiederholung fest, d.h. erst alle 4294967295 mal wiederholt 
sich die Folge (2^32 - 1).
Daher ist es egal, ob Du von jedem Aufruf nur 5 Bits oder 1 Bit 
verwendest.

Autor: Andre R. (ltisystem)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Route 6. schrieb:
> Bernd B. schrieb:
>> Okay, vielleicht ist das alles kalter Kaffee,
>
> Richtig!
> Der TE hat ja nicht das Problem,eine Zufallszahl zu erzeugen. Er sucht
> eine zufällige Zeichenkette (String) aus Nullen und Einsen mit
> vorgegebener Länge.
> Da ist sein Ansatz mit einem Array schon der richtige Weg.
> Statt "0" und "1" (0x30 bzw. 0x31) kann er auch "R" und "G" für seine
> Farbenzuordnung ins Array schreiben.

Ich würds auch mit einem Array machen: für deine acht Stellen würde ich 
mir für jede einzelne ne rand() holen und wenn das Ergebnis größer als 
0.5 ist, dann kommt eine 1 an die Stelle und kleiner eine 0:
int led[8] = {0};
int temp = 0;

for(i=0; i++; i>7){
  temp = rand();
  if(temp > 0.5){
    led[i] = 1;
  }else{
    led[i] = 0;
  }
}

Der Vorteil vom Array ist auch, dass du dann besser drauf zugreifen 
kannst. Denke es ist besser zu verstehen, jede einzelne Array Stelle 
anzusprechen, als mit BIT-Operationen und Shiftings rumzudoktoren, damit 
wäre es zwar vielleicht effizienter was den Code angeht. Würde aber 
sagen, für das Projekt reicht's.

Liebe Grüße

: Bearbeitet durch User
Autor: Bernd B. (microwave-designer)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Leute, das hier in dem Forum ist echt anstrengend!

1. Problem taucht bei der Erzeugung von Pseudozufallszahlen auf.
2. MSP430-Prozessor, wisst Ihr, ob er die Mathe-Lib verwendet? Von 
welchen Hersteller ist die Software? Wie ist die implementiert? Welchen 
C-Dialekt verwendet er? In welcher Entwicklungsumgebung programmiert er? 
Welchen Prozessor verwendet er? Hat der Prozessor einen Mathe-Kern? Ich 
programmiere seit über 20 Jahren mit dem MSP430 und habe bis heute nicht 
die Mathe-Lib verwendet, weil man sie anfangs für teures Geld kaufen 
musste und ich sie bislang bei meinen Projekten mit diesem Prozessortyp 
nicht benötige. Vor allem passt die vom Microchip nicht.
3. Auf eine rand()-Funktion greift er nicht zu.
4. "Vielleicht lautet die Aufgabenstellung verwenden Sie einen 
Pseudozufallszahlengenerator." Wenn das eine vorgegebene 
Aufgabenstellung ist, nützt es nichts zu diskutieren. Da geht dann keine 
Zenerdiode, kein ADC mit Rauschen, kein Timer, usw.
5. Pseudozufallszahlen sind keine echten Zufallszahlen. Die 
Pseudozufallszahlen lassen sich berechnen. Es gibt einen Nachfolger, der 
sich aus einer mathematischen Beziehung herleitet. Ist der Zahlenraum 
z.B. auf 32 Zahlen begrenzt (das sind 2 hoch 5 Zahlen), wird jede Zahl 
genau einmal aufgerufen, wenn man 32 Berechnungen durchläuft. Da gibt es 
auch mit 32-Bit nix zu diskutieren. Das ist das Angenehme (bzw. die 
Definition) von Pseudozufallszahlen: Innerhalb des festgelegten 
Zahlenraums besitzt jede Zahl die gleiche Auftrittswahrscheinlichkeit, 
und die Summe aller ist gleich eins. Kenne ich eine Pseudozufallszahl 
und die Berechnungsvorschrift, kann ich die nächste ermitteln. Die 
Anwendungen, die solche Zahlen verwenden sind z.B. Modulationsverfahren 
bei Mobiltelefonen oder beim GPS, allerdings nicht beim Roulette!
...
Auf jeden Fall drücke ich die Andriy die Daumen, doch noch irgendwo 
Hilfe zu bekommen!

Gruß ins Forum

Bernd

Autor: Andriy V. (derandrey)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

Andre R. schrieb:
> Ich würds auch mit einem Array machen: für deine acht Stellen würde ich
> mir für jede einzelne ne rand() holen und wenn das Ergebnis größer als
> 0.5 ist, dann kommt eine 1 an die Stelle und kleiner eine 0:

Ja genau, sowas hab ich mir auch vorgestellt. Mir war nur nicht klar, 
wie genau ich das machen kann.

Bernd B. schrieb:
> 2. MSP430-Prozessor, wisst Ihr, ob er die Mathe-Lib verwendet? Von
> welchen Hersteller ist die Software? Wie ist die implementiert? Welchen
> C-Dialekt verwendet er? In welcher Entwicklungsumgebung programmiert er?
> Welchen Prozessor verwendet er? Hat der Prozessor einen Mathe-Kern?

Also ich verwende das MSP430F5529 LaunchPad (Texas Instruments), die 
Mathe-Lib nutze ich jetzt gerade nicht (wäre aber möglich), meine 
Entwicklungsumgebung ist die IAR Embedded Workbench IDE.

Was ich brauche ist einfach eine zufällige Abfolge von Nullen und 
Einsen, einmal in der länge 4 Bit, 8 Bit und 12 Bit. Egal ob mit einem 
Pseudozufallszahlengenerator oder anders, kann auch die rand()-Funktion 
nutzen. Hab mir das jetzt auch so überlegt gehabt, dass ich eine 
pseudozufallszahl im gewünschten Bereich z.B 4 Bit, also eine Zahl 
zwischen 0-15 erzeuge, diese ins Binärsystem umwandele und in einem 
Array abspeichere. Dann durchlaufe ich das Array und bei jeder 0 und 1 
wird die bestimmte Lampe aufleuchten.

: Bearbeitet durch User
Autor: Bernd B. (microwave-designer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Andriy,

wie steuert Du die LED an?

Evtl. brauchst Du kein Array.

Gruß

Bernd

Autor: Andriy V. (derandrey)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Bernd,

ich dachte einfach über die Port-Pins,
hab mich aber damit noch nicht wirklich auseinandergesetzt, weil ich ja 
schon bei der Erzeugung der zufälligen Abfolge von nullen und einsen 
Probleme habe.
Bin wie gesagt ganz neu auf dem Gebiet mit C- Porgrammierung und 
Mikrocontrollern. Ich kenne mich ganz gut mit Java aus und da hätte ich 
sowas eben mit einem Array gelöst.

Gruß

Autor: Bernd B. (microwave-designer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andriy,

handelt es sich hier um eine private Bastelei oder um eine Schul- oder 
Semesterarbeit?

Gruß

Bernd

Autor: Schlumpf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andriy V. schrieb:
> also eine Zahl
> zwischen 0-15 erzeuge, diese ins Binärsystem umwandele und in einem
> Array abspeichere.

Du brauchst diese Zahl nicht ins Binräsystem wandeln, da sie bereits im 
Binärsystem vorliegt. Dein Controller KANN Daten nur binär verarbeiten.
Ich glaube, hier liegt dein gedankliches "Problem".

Wenn du einer Variable i den Wert 5 zuweist, dann steht im Controller an 
der ensprechenden Speicherstelle "0000 0101". Ganz automatisch und ohne 
Wandlung.

Und wenn du dann z.B. in C schreibst:

i << 1, dann wird "0000 0101" um eine Stelle nach links geschoben und es 
steht folgendes in deiner Speicherstelle: "0000 1010".
Deine Variable i hat dann also den dezimalen Wert 10.

Das ist jetzt nur ein Beispiel, um zu verdeutlichen, was ich meine.

Analog dazu kannst du einfach einen dezimalen Wert in das Register für 
einen 8 Bit-Port schreiben und der Wert erscheint dann binär auf den 8 
Pins.

Autor: Bernd B. (microwave-designer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
... nochne Frage:

Sprechen wir hier von 2 LED gesamt oder von 24 LED gesamt bei maximaler 
Ausbaustufe?

Bernd

Autor: Andre R. (ltisystem)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andriy V. schrieb:
> hab mich aber damit noch nicht wirklich auseinandergesetzt, weil ich ja
> schon bei der Erzeugung der zufälligen Abfolge von nullen und einsen
> Probleme habe.

Warum machste das nicht mit dem Array?

Da kannst du dir auch beliebig große "Zahlen/Arrays" erzeugen. Ist 
einfach, tut was es soll, der Programmcode zum erzeugen der Arrays steht 
da und du kannst dich jetzt um die LED Sache kümmern.

int rand_zeroone_4[4] = {0};
int rand_zeroone_8[8] = {0};
int rand_zeroone_12[12] = {0};
int temp = 0;
for(i=0; i++; i>3){
  temp = rand();
  if(temp > 0.5){
    rand_zeroone_4[i] = 1;
  }else{
    rand_zeroone_4[i] = 0;
  }
}

for(i=0; i++; i>7){
  temp = rand();
  if(temp > 0.5){
    rand_zeroone_8[i] = 1;
  }else{
    rand_zeroone_8[i] = 0;
  }
}

for(i=0; i++; i>11){
  temp = rand();
  if(temp > 0.5){
    rand_zeroone_12[i] = 1;
  }else{
    rand_zeroone_12[i] = 0;
  }
}

wenn du das ausführst hast du in rand_zeroone_x jeweils eine 
pseudozufällige Abfolge von Einsen und Nullen drin stehen. Für echte 
Zufallszahlen (im Artikel als nichtdeterministisch beschrieben) lies dir 
den Artikel mal durch

https://de.wikipedia.org/wiki/Zufallszahlengenerator#Nichtdeterministische_Zufallszahlengeneratoren

Autor: Bernd B. (microwave-designer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Andriy,

... die Frage nach der Art des Projekts liefert die Art der Antworten:
- Semesterarbeit -> ich helfe Dir mit Verweisen, wo Du Deine 
Informationen herholst

- Hobbyprojekt -> wie Semesterarbeit, jedoch auch mehr Hinweise zur 
Lösung

Die Frage nach den verwendeten Ausgabe LED bestimmt die Datenstruktur in 
Deinem Code.

Du hast Dir mit dem F5529 einen sehr mächtigen Prozessor ausgesucht. Und 
das Evaluationsboard ist ebenfalls sehr umfangreich ausgestattet. Hier 
hast Du bereits 2 LED und 2 Taster.

Gruß

Bernd

Autor: Andriy V. (derandrey)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andre R. schrieb:
> der Programmcode zum erzeugen der Arrays steht
> da und du kannst dich jetzt um die LED Sache kümmern.

Danke dir für deine Hilfe. Ich hätte da noch eine Frage zu dem Code:

Andre R. schrieb:
> int rand_zeroone_4[4] = {0};
Was genau bewirkt bei dieser Zeile dieses = {0} ?

Bernd B. schrieb:
> Sprechen wir hier von 2 LED gesamt oder von 24 LED gesamt bei maximaler
> Ausbaustufe?

Von insgesamt 2 LEDs. Und es handelt sich hierbei um ein Projekt.

Autor: Random (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Andre R. schrieb:
> Warum machste das nicht mit dem Array?

Weil die Bit-Kombinationen auf einen Port gehen. Was soll dann das 
Rumgeeiere und die Speicherverschwendung?
Läuft doch kein Java auf dem kleinen Knecht.

Autor: Max M. (maxmicr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andre R. schrieb:
> int rand_zeroone_4[4] = {0};
> int rand_zeroone_8[8] = {0};
> int rand_zeroone_12[12] = {0};
> int temp = 0;for(i=0; i++; i>3){
>   temp = rand();
>   if(temp > 0.5){
>     rand_zeroone_4[i] = 1;
>   }else{
>     rand_zeroone_4[i] = 0;
>   }
> }

temp ist eine Ganzzahl, du vergleichst eine Ganzzahl mit einem 
Fließkomma-Wert. Wenn rand() eine Fließkommazahl zwischen 0 und 1 
liefert müsste in temp meistens der Wert 0 drinn stehen, oder nicht? Wie 
kann das funktionieren?

Autor: Peter D. (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andriy V. schrieb:
> Was ich brauche ist einfach eine zufällige Abfolge von Nullen und
> Einsen, einmal in der länge 4 Bit, 8 Bit und 12 Bit.

rand() liefert einen int von mindestens 15 Bit:

https://www.tutorialspoint.com/c_standard_library/c_function_rand.htm
The C library function int rand(void) returns a pseudo-random number in the range of 0 to RAND_MAX.

RAND_MAX is a constant whose default value may vary between implementations but it is granted to be at least 32767.

Du mußt nur noch die gewünschte Bitzahl ausmaskieren:
int rand4, rand8, rand12;

rand4 = rand() & 0xF;
rand8 = rand() & 0xFF;
rand12 = rand() & 0xFFF;

Autor: Andre R. (ltisystem)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Max M. schrieb:
> Andre R. schrieb:
>> int rand_zeroone_4[4] = {0};
>> int rand_zeroone_8[8] = {0};
>> int rand_zeroone_12[12] = {0};
>> int temp = 0;for(i=0; i++; i>3){
>>   temp = rand();
>>   if(temp > 0.5){
>>     rand_zeroone_4[i] = 1;
>>   }else{
>>     rand_zeroone_4[i] = 0;
>>   }
>> }
>
> temp ist eine Ganzzahl, du vergleichst eine Ganzzahl mit einem
> Fließkomma-Wert. Wenn rand() eine Fließkommazahl zwischen 0 und 1
> liefert müsste in temp meistens der Wert 0 drinn stehen, oder nicht? Wie
> kann das funktionieren?

du hast völlig recht!!! peinlich!!! man ersetze int temp durch float 
temp und könnte aus den int rand_zeroone_x ein byte rand_zeroone_x 
machen...

Random schrieb:
> Andre R. schrieb:
>> Warum machste das nicht mit dem Array?
>
> Weil die Bit-Kombinationen auf einen Port gehen. Was soll dann das
> Rumgeeiere und die Speicherverschwendung?
> Läuft doch kein Java auf dem kleinen Knecht.

Ja stimmt schon, wenn das so läuft wie beim Arduino und mit PortC = 
B10010101 die Pins PC7, PC4, PC2 und PC0 auf High gestellt werden, dann 
ist das mit einem 4-8-12 Bit integer schon ein bisschen 
kuhler/eleganter. Allerdings auch anfangs etwas schwerer zu verstehen.


Peter D. schrieb:
> Du mußt nur noch die gewünschte Bitzahl ausmaskieren:int rand4, rand8,
> rand12;
>
> rand4 = rand() & 0xF;
> rand8 = rand() & 0xFF;
> rand12 = rand() & 0xFFF;

Schon elegant, rein von der Erzeugung der Zahlen. Allerdings muss man es 
gar nicht maskieren, weil das eh alles 16Bit Integers sind und man 
händisch nur bis zum 4-8-12 Bit begrenzen muss, da man z.B. nicht drauf 
gucken kann ab wann das Array 0 ist da 0 bei diesem Projekt ja iene 
Bedeutung hat. Bissceh verwirrt beschrieben, versteht man es trotzdem 
halbwegs? Musst jetzt halt auch beachten, dass rand4 trotzdem 16 bits 
lang ist und dich aber nur die letzten 4 lsb's interessieren. Da gehts 
mit dem Array schon etwas einfacher: Das Array kannst du mit ner 
for-Schleife einfach durch gehen und jede Stelle dem Port zuweisen. Man 
will ja keine 4-8-12 LEDs gleichzeitig aufleuchten lassen sondern 
entweder eine rote oder eine grüne, oder hab ich das falsch verstanden? 
Dann müsste man noch mit der jeweilige Stelle maskieren um an jedes 
einzelne Bit ran zu kommen.

Autor: Peter D. (peda)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Andre R. schrieb:
> Allerdings muss man es
> gar nicht maskieren

Ich wollte damit nur das Prinzip verdeutlichen.
Natürlich reicht es, wenn man einfach die Ausgabeschleife nur bis 4, 8 
oder 12 zählen läßt.

Autor: Bernd B. (microwave-designer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Andriy,

ich komme wegen eigener Projekte erst jetzt wieder dazu etwas 
beizusteuern. Zwischenzeitlich hast Du ja eine Menge Vorschläge 
erhalten, wie man vorgehen könnte.

Die Frage nach der Anzahl der Ausgabe-Bit führte über Deine Antwort auf 
meiner Seite zu einer recht übersichtlichen Lösung.

Deine Zufallszahl liegt z. B. im Register R8. Im Register R9 liegt ein 
Bitmuster, das die zu verarbeitenden Bits enthält. R9 wird entweder mit 
0x000f, mit 0x00ff oder mit 0x0fff geladen, sobald Du die

Zufallszahl erstellt hast.

Zum Programmstart hast du ja bereits die Ausgaben (LED) auf die richtige 
Portausgabe und auf "leere" Werte gesetzt. Außerdem ist der Jumper auf 
Deinem Board gesteckt. Folgender Code dient zur

Initialisierung der Ports:
;------------------------------------------------------------------------------
; port bits for user LED init
;------------------------------------------------------------------------------
            bic.b      #0x01, &P1OUT    ; clr bit for red
            bis.b      #0x01, &P1DIR    ; output

            bic.b      #0x08, &P4OUT    ; clr bit for green
            bis.b      #0x08, &P4DIR    ; output

Ich habe mich an Fig. 41 vom Dokument 
http://www.ti.com/lit/ug/slau533d/slau533d.pdf orientiert. Dieses 
Dokument sollte Dir ebenfalls vorliegen.

Jetzt benötigst Du 2 Prozeduren, um die LED entsprechend zu setzten. Da 
immer nur eine LED leuchten soll, sollten in den Prozeduren 
Verriegelungen implementiert sein.
;------------------------------------------------------------------------------
set_green
;------------------------------------------------------------------------------
            bic.b      #0x01, &P1OUT    ; clr bit for red
            bis.b      #0x08, &P4OUT    ; set bit for green
            ret

;------------------------------------------------------------------------------
set_red
;------------------------------------------------------------------------------
            bis.b      #0x01, &P1OUT    ; set bit for red
            bic.b      #0x08, &P4OUT    ; clr bit for green
            ret

So, jetzt kommt die Geschichte mit den Registern R8 und R9. Nehmen wir 
an, Du möchtest eine 4-bit breite (Zufalls-)zahl verarbeiten oder 
ausgeben. Dabei kannst Du folgendermaßen vorgehen.
;------------------------------------------------------------------------------
show_next_bit
;------------------------------------------------------------------------------
            clrc.w      ; clear carry
            rrc.w     R9      ; move bit from pattern to carry
            jnc       snb_9    ; nothing to show
            ; continue to show during pattern
            rrc.w     R8    ; move output bit to carry
            jc        snb_1     ; jump if bit is set
            call      #set_green
            jmp       snb_9
snb_1       call      #set_red
            ;
snb_9
            ret

Damit schiebst Du Deine zufällige Bitfolge durch das Register R8 und 
entscheidest, welche Farbe angezeigt werden soll. Gleichzeitig steuert 
das Pattern in R9, wie oft Du diese Prozedur durchführen

musst.

Außerhalb läuft eine Schleife:
;------------------------------------------------------------------------------
; show random bit-pattern sequentially
;------------------------------------------------------------------------------
            mov.w   R9, 0x000f    ; load pattern of 4 bit number
            call    #Prng    ; call to get new number
            mov.w   &lfsr16, R8    ; load pseudo random number
srbps_1
            cal     #show_next_bit
            ; ... some more code
            bit.w   #0x0001, R9    ; test for rmore bits to show
            jnz     srbps_1
            ; ... done

Mit diesen paar Bytes Code erzeugst Du Dir eine zufällige Bitfolge und 
legst sie in R8 ab. Das Pattern, ob 4-bit, usw. definierst Du in R9. Die 
Bitfolge schiebst Du durch R8 und das Carry-Bit. Anhand

des Carry-bits entscheidest Du, welche Farbe. Die Schnittstelle zu den 
LED erfolgt über Interface-Routinen. Beide LED sind auf dem EVM an zwei 
verschiedenen Ports.

Der oben geschriebene Code ist nicht durch einen Compiler oder Assembler 
gelaufen. Fehler mögen drin sein :) Sie zu finden ist Transferleistung. 
Auch ist die Übersetzung in C eine Transferleistung. Das meinte ich mit 
"ich liefere Dir nicht die Lösung, sondern zeige Dir, wo Du suchen oder 
vorgehen musst.

Versuche diesen Ablauf auf Deiner Workbench (IAR) im Einzelschritt-Modus 
anzusehen. Beobachte die Register. Beobachte das Carry-Bit. Am besten 
startest Du, in dem Du in der Workbench die Register setzt, um die LED 
ein- und auszuschalten.

Vielleicht fragst du Dich, warum man in einer Hochsprache programmiert 
und warum man so viele hundert Kilobyte FLASH benötigt. Für dieses 
Projekt lautet die Antwort: "Ich weiß es nicht!" Die kleinen Prozessoren 
von TI sind einfach super gut und super gut zu programmieren... auch 
ohne Java.

Ziehe Dir die Dokument http://www.ti.com/lit/ug/slau144j/slau144j.pdf ab 
Abschnitt 3.4.6 rein. Sieh Dir die Nutzung der Register in 
http://www.ti.com/lit/ds/symlink/msp430f5529.pdf ab Seite 69 an. Es gibt 
auch zu allen Prozessoren Code-Beispiele in ASM und C.

Lesen, lesen, lesen, ...

Happy coding

Bernd

Autor: Andriy V. (derandrey)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, danke nochmal für eure Hilfen.
Ich habe die Erzeugung der Zufallszahl nun mit Hilfe des Analog/Digital 
Converters gelöst:

void initialize_ADC(void)               // Set bits in configuration 
registers
{
  {
  P6SEL |= 0x01;                            // Enable A/D channel A0
  REFCTL0 &= ~REFMSTR;                      // Reset REFMSTR to hand 
over control to
                                            // ADC12_A ref control 
registers
  ADC12CTL0 = ADC12ON+ADC12SHT02+ADC12REFON+ADC12REF2_5V; // Turn on 
ADC12
                                            // Set sampling time, set 
reference
                                            // generator on and set it 
to 2,5V
  ADC12CTL1 = ADC12SHP;                     // Use sampling timer
  ADC12MCTL0 = ADC12SREF_1;                 // Vr+=Vref+ and Vr-=AVss

  for ( i=0; i<0x30; i++);                  // Delay for reference 
start-up

  }


void adc_nBitZahl(int bitLaenge){

  while (1)                                 // Main loop
  {
    rand = 0;                               // Clear variable rand
    for (i = 0; i<bitLaenge; i++){
      ADC12CTL0 |= ADC12SC;                 // Start single 
A/D-Conversion
      while (!(ADC12IFG & BIT0));           // Wait until converions is 
finished
      LSBit = ADC12MEM0 & 0x01;             // Grab LSB of conversion
      LSBit = LSBit << i;                   // Shift LSB (only one Bit) 
to Bit i
      rand = rand | LSBit;                  // Insert it at the right 
place
    }
    __no_operation();                       // SET BREAKPOINT HERE
  }

void main(void)
{
  WDTCTL = WDTPW+WDTHOLD;
  initialize_ADC();
  adc_nBitZahl(4);
  adc_nBitZahl(8);
  adc_nBitZahl(12);

}

Nun mache ich mich dran die LEDs aufleuchten zu lassen, hab mir gedacht 
dies mache ich mittels shiften.
Bernd danke dir für deinen ausführlichen Ansatz und das du so viel Zeit 
investierst mir zu helfen, leider muss ich gestehen, dass ich das mit 
dem Carry nicht so ganz verstehe. Vielleicht liegt es auch daran das ich 
nichts mit diesem Code in Assembler-Sprache (weil ich diese nie gelernt 
habe) anfangen kann und absolut keine Ahnung habe wie ich diese 
übersetzen kann, geschweige den verstehe was du da hingeschrieben hast, 
tut mir leid.

: Bearbeitet durch User
Autor: Andre R. (ltisystem)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kuhl, kannst ja mal Update geben. Viel Erfolg!

Autor: Andriy V. (derandrey)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Hallo

vielleicht ist das eine blöde Frage, aber so wie es jetzt ist wird die 
random zahl in "rand" gespeichert, wenn ich diese ausgebe, wird mir nur 
eine Dezimalzahl angezeigt, wie greife ich nun auf das Register zu wo 
die Zahl im Binärsystem gespeichert ist? Und wie spreche ich dann davon 
immer das erste Bit an?

Autor: Andre R. (ltisystem)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
Moin,

also nochmal zum Verständnis: Jede Zahl im Rechner ist dort binär 
hinterlegt, da ein digitales Gerät hauptsächlich mit Nullen und Einsen 
arbeitet. Wie willst du sonst mit Schaltungen Zustände speichern? Du 
kannst ja einem analogen Bauteil (was anderes ist ja ein Computer nicht, 
der besteht nämlich aus ganz vielen Transistoren, Widerständen, 
Condensatoren, Verstärkern, Mosfets etc) nicht sagen "hey das ist ne 
12". Sondern du musst analoge Bauteile so verschalten dass sie mehrere 
Stellen von Nullen und Einsen speichern können und kodierst somit deine 
Informationen ins binärsystem. Eine einzelen Stelle, also eine Stelle wo 
entweder eine 0 oder eine 1 drins teht nennt man ein Bit. Acht Bits sind 
ein Byte. 1024 Byte sind ein Kilobyte, 1024 Kilobyte sind ein Megabyte 
usw.

Hast du jetzt also eine Variable bspw.
int var = 12;

so steht irgendwo in deinem Speicher die Zahl 0000000000001100, da:

1. ein Integer meist 16 Bits lang ist
2. eine 1 an dritter Steller vom LSB (last significant bit) eine 4 
darstellt (falls du das nicht verstehst, guck mal bitte bei Wiki nach 
Binärsystem) und eine 1 an vierter Stelle eine 8 --> 4+8 sind 12

Also wenn du im Hinterkopf hast, dass alles was im Rechner passiert, 
jedes Bild jeder Ton und auch jede Zahl nur eine Abfolge von Nullen und 
Einsen ist dann weißt du dass deine gewünschte Zahl sowieso schon binär 
vorliegt, du musst nur noch ran kommen (sorry das ich mich wiederhole, 
aber ich war vor Jahren überwältigt als ich begriffen hab dass so viele 
Nullen und Einsen gebraucht werden um z.b. ein Bild darzustellen).

Jedenfalls liegt deine 12 aka 0000000000001100 jetzt irgendwo rum und du 
kannst sie mit dem Aufruf der Variable var greifen. Nun gibt es sowas 
wie Logik, also eine Konvention die sagt, was passiert wenn man zwei 
Bits (siehe oben was ein Bit ist) mit einander vergleicht, was auch 
ziemlich logisch ist: die gängigsten sind UND, ODER.

UND, wir d als & geschrieben (wird 1 wenn das eine Bit UND das andere 
Bit 1 sind):
0 & 0 = 0 (Null und Null sind Null)
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1 

ODER, wird als | geschrieben (wird 1 wenn das eine Bit ODER das andere 
Bit 1 ist):
0 | 0 = 0 (Null oder Null ist Null)
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1

Was soll das ganze? Damit kommst du an deine Stellen ran:

Du hast deine Zahl var = 12 = 0000000000001100 und willst jetzt 
meinetwegen wissen, was das niederste Bit ist. Also verknüpfst oder 
tastest du die Zahl mit einer so genannten Maske ab:
var      0000000000001100
                &        
Maske    0000000000000001
-------------------------
Ergebnis 0000000000000000

Heißt du weißt, das var an der Stellte ganz rechts eine 0 stehen hat, 
weil die UND-Verknüpfung mit der Maske eine 0 Ergibt. Das Gleiche würde 
beim nächsten Bit passieren. Jetzt aber zum von rechts aus gesehen 
dritten Bit:
var      0000000000001100
                &        
Maske    0000000000000100
-------------------------
Ergebnis 0000000000000100

Im Ergebnis steht eine eine 4, du weißt also dass die Zahl var an 
dritter Bitstelle eine 1 hat.

So gehst du jetzt auch mit deinem Problem vor:


Peter D. schrieb:
> rand4 = rand() & 0xF;
> rand8 = rand() & 0xFF;
> rand12 = rand() & 0xFFF;

Das ist genau das was du wolltest. 0xF sind zahlen im Hexadezimalsytem, 
also es gibt nicht nur 2 Zustände wie beim Binärsystem, nicht nur 10 
Zustände wie beim Dezimalsystem sondern 16 Zustäden (nach 0-9 kommen 
noch A-F, also ist eine dezimale 11 im Hexadezimalsystem ein B). Also 
steht da, was Peter geschrieben hat:
rand4 = rand() & 0000000000001111

rand4 ist dein Ergebnis, rand() ist deine Pseudozufallszahl (also irgend 
eine Abfolge von 0 und 1) und 0xF ist deine Maske:
rand() 0110110001110101
              &
0xF    0000000000001111
-----------------------
rand4  0000000000000101

Somit hast du jezt die hintersten 4 Bit von deiner Zufallszahl 
abgetastet. Gibst du sie jetzt auf deinem Rechner aus so wird rand4 den 
Wert 5 ausspucken also weißt du "ok von meiner 4 Bit Zahl ist das ganz 
rechte Bit eine 1 und das dritte Bit eine 1".

So gehst du auch mit 8 und 12 Stellen vor
rand() 0110110001110101
              &
0xFF   0000000011111111
-----------------------
rand8  0000000001110101

Und so weiter.

Hoffe das hilft fürs Verständnis.

Grüße

Autor: Andriy V. (derandrey)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andre R. schrieb:
> Moin,
>
> also nochmal zum Verständnis: Jede Zahl im Rechner ist dort binär
> hinterlegt, da ein digitales Gerät hauptsächlich mit Nullen und Einsen
> arbeitet.

Danke aber mir ist das schon bewusst, ich möchte nur wissen wie ich auf 
die Binär hinterlegte Zahl zugreifen kann. Das mit der Zufallszahl in 
der gewünschten Bitlänge habe ich ja schon hinbekommen, mit dem oben 
geposteten Code. Nur weiß ich jetzt nicht genau wie ich auf den 
hinterlegten Binärcode für die Zufallszahl zugreife und den BinärCode so 
durchlaufe, dass bei jeder 1 die rote und bei jeder 0 die grüne LED 
aufleuchtet. Wenn ich mit dem Debugger das Programm durchlaufe, wird mir 
angezeigt, dass zum Beispiel die generierte 4 Bit Zufallszahl, sagen wir 
mal "8", bei der Locaion: Memory:0x2400 hinterlegt ist. Ich nehme mal an 
(wenn ich es richtig Verstanden habe), dass diese bei der genannten 
Location im Binärsystem gespeichert ist. Falls ja wie greife ich nun 
darauf zu und wie schaffe ich es die LED auf der entsprechenden Zahl (0 
oder 1) aufleuchten zu lassen?

Beitrag #5444981 wurde vom Autor gelöscht.
Autor: Random (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh man, da haben wir den shit! Mit dem Array Krams haben sie dich völlig 
ausder kKurve gekippt.

Uint16_t myvar = Rand();

For(int i = 0;i < 16;i++)
  Ledxyz = (myvar >> i) & 0x0001;

Autor: Anonym (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schon selbstständig eine Lösung gefunden oder gibt es noch Hilfebedarf? 
Wenn ja, schreib mal konkret, was du noch nicht verstehst / nicht 
umsetzen kannst. Dein Projekt scheint etwas umfangreicher zu sein, als 
nur die Bits vom ADC auszulesen und entsprechend die LED's zum Leuchten 
zu bringen.

Autor: Andriy V. (derandrey)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, ja es gibt noch Hilfebedarf. Habe bisher noch keine Lösung, für 
das Problem, die einzelnen Bits vom ADC auszulesen gefunden. Ja mein 
Projekt ist etwas umfangreicher ich möchte das Spiel "Simon says", falls 
dir das was sagt auf dem Microkontroller programmieren.

Autor: Theor (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andriy V. schrieb:
> Hallo, ja es gibt noch Hilfebedarf. Habe bisher noch keine Lösung, für
> das Problem, die einzelnen Bits vom ADC auszulesen gefunden. [...]

Andre hat Dir in seinem Beitrag oben eigentlich alle nötigen 
gedanklichen Schritte erklärt. Paradoxerweise verwendest Du die auch in 
der Funktion, die aus den ADC-Werten eine Zufallszahl macht.
Du müsstest es eigentlich sehen, falls Du grundsätzlich die Fähigkeiten 
hast zu begreifen, was Du siehst.
Das Problem ist nämlich nun schon so weit herunter gebrochen worden, 
dass man, eigentlich nur noch die Lösung hinschreiben kann. Einfacher 
geht es schlicht nicht mehr. Bildlich gesprochen, stehst Du vorm Baum 
und berührst ihn mit der Nasenspitze und fragst uns, wo er denn nun ist, 
der Baum.

Also: Schau Dir den ADC-Code nochmal Schritt für Schritt an. Denk drüber 
nach. Schau Dir Andres Beitrag nochmal Schritt für Schritt an. Denk auch 
darüber nach. Lies auch im C-Buch über die Operatoren.

Falls dann immer noch etwas unklar ist, dann erschöpfe Dich nicht in: 
"Ich weiß nicht". Vielmehr versuche eine Lösung und schildere das 
Problem dabei bzw. falls Du keine Lösung zustande bekommst, erkläre 
ausführlich woran es denn scheitert - und zwar in den Begriffen die Dir 
hier erklärt worden sind und aufgrund der Tatsachen, die Du nun kennst. 
Es sollte erkennbar sein, dass Du die drei Empfehlungen oben auch 
befolgt hast. Sonst kommst Du nämlich nicht weiter.


Eine Bemerkung noch: Fehler, auch dumme Fehler sind nicht schlimm und es 
wird Dich in der Regel auch niemand dafür herabsetzen. falls Du Dir 
darüber Sorgen machst. Was aber im Allgemeinen kritisch gesehen wird, 
ist, selbst gar keine Anstrengungen zu unternehmen.

Autor: Bernd B. (microwave-designer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Andriy,

gerade der Kommentar von 15:05h sollte Dich ermutigen!

Nachdem Du die Katze aus dem Sack gelassen hast, habe ich ein bisschen 
gegoogelt. Und siehe da, es gibt sogar fertigen Code in C.

https://github.com/seanliu93/MSP430_simonsays

Ich weiß allerdings nicht, ob Dir der Code helfen wird. Du verwendest 
einen Prozessor der oberen Leistungsklasse mit allem Pipapo. Aus meiner 
Sicht würde bereits ein MSP430F201x ausreichen oder ein MSP430G2xx 
device, entspr. mit dem LaunchPad.

Falls die ganze Programmiererei bei Dir nicht klappt, versuche es ruhig 
in einer anderen Programmierumgebung.

Andriy V. schrieb:
> Ich kenne mich ganz gut mit Java aus und da hätte ich
> sowas eben mit einem Array gelöst.

Ich bin sicher nicht der einzige, der Deine Aussage irgendwie nicht 
zusammen bekommt.

Happy coding

Bernd

Autor: Peter D. (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andriy V. schrieb:
> Habe bisher noch keine Lösung, für
> das Problem, die einzelnen Bits vom ADC auszulesen gefunden.

Vergiß den ADC, damit eine Zufallsfolge zu erzeugen, ist alles andere 
als einfach. Es kann leicht passieren, daß durch Schaltungsfehler die 
Folge nicht gleichverteilt ist.
Du brauchst eine Rauschquelle am Eingang, z.B. eine Rauschdiode oder 
eine hohe Verstärkung. Und die AD-Wandlung darf nicht durch Störungen 
auf der VCC beeinflußt werden.
Du hast auch nicht den vollen ADC-Bereich, sondern nur wenige Bits 
Rauschen. In der Regel nimmt man nur das unterste Bit und ruft 
entsprechend oft eine Wandlung auf.
Ansonsten ist es schnurz, ob ADC oder rand(), beide liefern Bits.

Die rand() Funktion ist garantiert gleichverteilt und erfordert keine 
zusätzliche Hardware.

Autor: Andriy V. (derandrey)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich habe es jetzt versucht so zu lösen:
void setRedLED(void){
  P1OUT |= 0x01;          // LED rot an
  P4OUT &= ~0x80;         // LED grün aus 
}

void setGreenLED(void){
  P1OUT &= ~0x01;  //LED rot aus
  P4OUT |= 0x80;  //LED grün an
 
}

void main(void)
{
  WDTCTL = WDTPW+WDTHOLD;
  initialize_ADC(); 
  rand4 = adc_nBitZahl(4); 
  rand8 = adc_nBitZahl(8);
  rand12 = adc_nBitZahl(12);
  
   if ((rand4&=0x01)==1){
     setGreenLED();
   }
   else{
     setRedLED();
   }


if ((rand4&=0x02)==1){
     setGreenLED();
   }
   else{
     setRedLED();
   }


if ((rand4&=0x03)==1){
     setGreenLED();
   }
   else{
     setRedLED();
   }


if ((rand4&=0x04)==1){
     setGreenLED();
   }
   else{
     setRedLED();
   }
}

Wenn ich es im Debbug-Modus durchlaufen lassen funktioniert das auch, 
jedoch finde ich, wenn ich das für jede 
Schwierigkeitsstufe(4Bit,8Bit,12Bit) so viele if- Anweisungen hab sieht 
das nicht wirklich übersichtlich aus... wie könnt ich das verkleinern.
Bisher leuchtet z.b die rote LED auch die ganze Zeit wenn im Byte zwei 
oder mehr nullen hintereinander kommen, eigentlich soll die Dauer des 
Aufleuchtens sowie die Dauer dazwischen jeweils etwa 0.5 Sekunden 
betragen. Wie kann ich das realisieren?

Autor: Thomas E. (picalic)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andriy V. schrieb:
> if ((rand4&=0x02)==1){

Sorry, aber wenn das in Deinem Debugger funktioniert, ist wohl Dein 
Debugger kaputt!

Du solltest wirklich den Ratschlägen folgen und Dir erstmal fundierte 
Programmierkenntnisse aneignen. Ohne Wissen, was Operatoren wie "&=" 
machen oder welchen Wert ein Ausdruck in Klammern am Ende hat, kommst Du 
nicht weiter. Die oben zitierte if-Bedingung kann z.B. niemals war 
werden!

Autor: Andriy V. (derandrey)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja danke für den Hinweis das stimmt, hab ich jetzt auch bemerkt, war 
wohl Zufall das es beim ersten Probieren gestimmt hat.

Jedoch ist diese Zeile immer richtig:
if ((rand4&0x01)==1){
     setGreenLED();
   }
   else{
     setRedLED();
   }

Hier prüfe ich immer ob der LSB eine 1 ist oder nicht.

Bei den restlichen if anweisungen war ich gedanklich wohl ziemlich 
falsch,
weil ich dachte mit 0x02 kann ich den zweiten bit überprüfen und mit 
0x03 den dritten usw...

Hab das jetzt anders gemacht, hoffe ich hab jetzt nicht wieder einen 
Gedankenfehler drin, aber so hat hat es bis jetzt immer richtig 
aufgeleuchtet als ich es getestet habe.

for(i=0;i<4;i++){
    
    if((rand4&0x01)==1){
      
     setGreenLED();
   }
   else{
     setRedLED();
   }
   
    rand4=rand4>>1;
}

: Bearbeitet durch User
Autor: stiller Leser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich würde es so machen:
for(i=0;i<4;i++){
   if(rand4&(1<<i)){
     setGreenLED();
   }else{
     setRedLED();
   }
}

dann werden Binärzahlen vielleicht verständlicher
Andriy V. schrieb:
> weil ich dachte mit 0x02 kann ich den zweiten bit überprüfen und mit
> 0x03 den dritten usw

Autor: Andre R. (ltisystem)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja es könnte schon eklig mit if's und else's werden. Kann man wenn man 
sich gut auskennt auch elegant lösen aber für den Anfang...

Die Zahlen mit den 'x' sind im Hexadezimalsystem
Hexadezimal   Binär    Dezimal
0x01          0001     1
0x02          0010     2
--> bis hier geht das noch, weil deine Maske (siehe Binär) EINE 1 an der Stelle hat, die du möchtest, aber ...
0x03          0011     3
--> hier würdest du dann nach zei Bits maskieren.

Im MSP430 hab ich gelesen kann man eine Verzögerung mit delay_cycles(x) 
erzeugen. X ist dabei der Clockcycle...betreibst du deinen µC 
(Mikrocontroller) also bspw. mit 1MHz (glaub das is default) arbeitest 
und delay_cycles(1000) schreibst, dann hält der µC den Code für 
1000*(1/1MHz) an.

Damit kannst du deine LEDs toggeln:
void setRedLEDxsec(void){
  P1OUT |= 0x01;          // LED rot an
  delay_cycles(x);
  P1OUT = 0;              // insofern auf P1OUT nix anderes mehr läuft
}

void setGreenLEDxsec(void){
  P4OUT |= 0x80;  //LED grün an
  delay_cycles(x);
  P4OUT = 0;
}

Autor: Eric B. (beric)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andriy V. schrieb:
> Ich kenne mich ganz gut mit Java aus und da hätte ich
> sowas eben mit einem Array gelöst.

Dann programmier das Spiel doch erstmal in Java und versuche erst danach 
es auf den uC in C hin zu bekommen.

Autor: Andriy V. (derandrey)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eric B. schrieb:
> Dann programmier das Spiel doch erstmal in Java und versuche erst danach
> es auf den uC in C hin zu bekommen.

Was würde das mir bringen? Für mich ist C nicht das Problem, das ist ja 
ähnlich wie Java sondern eher der Mikrocontroller und wie ich die 
einzelnen Sachen wie Register usw. davon anspreche.

Autor: Theor (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich denke, Du hast durchaus noch Probleme in C und in Java.

Es scheint nämlich so, als wenn Dir die Bedeutung von Operatoren wie 
"&", "|" etc. nicht klar sind. Die sind nämlich in C und in Java gleich. 
Das selbe gilt für die Operatoren "&=" und "|=", die eine Zuweisung 
enthalten, und eine Reihe weiterer, wie die Schiebeoperationen "<<" und 
">>", die in Verbindung mit einer Nummerierung der Bits, einen durchaus 
nützlichen Sinn haben.

Ebenso ist Dir anscheinend die Umrechnung von verschiedenen 
Zahlendarstellungen nicht klar oder zumindest nicht geläufig.
Du solltest - auf dem Papier - zumindest mal die Umrechnungen zwischen 
Binärer, dezimalen und Hexadezimalen Zahlen üben.
Ebenso wichtig ist, wie diese Zahlen aufgebaut sind.

Praktisch brauchst Du das nicht immer gedanklich im Einzelnen 
nachzuvollziehen, wenn Du programmierst aber Du solltest wissen, wie es 
geht.
Mit der Zeit aber hat man so ein paar wichtige Werte bzw. Folgen im 
Kopf. Etwa 1, 2, 4, 8, 16 etc. - also die Zweierpotenzen. Das ist nur 
ein Problem der Übung und des Auswendiglernens, wenn man sich mal eine 
Tabelle neben die Tastatur legt oder auf den Bildschirm holt und einfach 
nachschaut. Aber auch das muss man mal machen.

Aber es ist wichtig, dass anhand einfacher Beispiele nachzuvollziehen 
bevor man zu komplexeren Programmen kommt.
Auf Deine Weise, scheint das nur ein Nebenproblem zu sein. In 
Wirklichkeit aber musst Du Dir bildlich gesprochen, jedes Mal, bevor Du 
Dich aufmachst, die Welt zu erobern, die Schnürsenkel von jemandem 
zubinden lassen.

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.