Forum: Mikrocontroller und Digitale Elektronik TCNT0 % 6 für "Zufallszahl"


von Hannes J. (Firma: eHaJo.de) (joggl) Benutzerseite Flattr this


Lesenswert?

Hallo zusammen, ich habe gerade ein kleines Denkproblem oder 
Programmierproblem oder wie auch immer:
Ich nehme den Timer0 eines Attiny13 und lasse ihn munter im 
Prozessortakt von 0 bis 255 zählen.
Irgendwann dazwischen drücke ich ne Taste und mache
zahl=TCNT0%6
Eigentlich würde ich mir nun erwarten, dass die Variable zahl 
"zufällige" Werte zwischen 0 und 5 beinhalten sollte...
Irgendwie kommt der Wert 1 aber gar nie vor...

Danke schonmal!

von Magnus M. (magnetus) Benutzerseite


Lesenswert?

Dann setz halt den Vorteiler rauf, oder schreib zahl=(TCNT0>>1)%6.

Gruß,
Magnetus

von Dussel (Gast)


Lesenswert?

Interessant.

Oder hast du auch eine Frage ;-)
Theoretisch sollte es so gehen, davon abgesehen, dass die Zahlen 0 bis 3 
eine höhere Wahrscheinlichkeit haben.
Wie oft hast du das denn getestet. Auch wenn die Zahlen etwa gleich 
verteilt sind, kann es lange dauern, bis eine bestimmte Zahl 'gezogen' 
wird.
Wie wird das Ergebnis ausgegeben? Wenn du zum Beispiel je nach Zahl Pins 
einschaltest (LED zum Beispiel), kannst du mal probieren, ob die Ausgabe 
richtig funktioniert oder ob eine LED nicht richtig angeschlossen ist. 
Aus den Informationen fällt mir jetzt nicht ein, woran das sonst liegen 
könnte.

von Hannes J. (Firma: eHaJo.de) (joggl) Benutzerseite Flattr this


Lesenswert?

Ich gebe das auf LEDs aus, ja.
Habe so etwa 60 mal probiert, da sollte die Zahl 1 auf jeden Fall 
vorkommen.
LEDs sind richtig dran. Von Hand kann ich die entsprechenden 
einschalten.
Kanns am Vorteiler liegen?
der Wert 0 kommt ja auch vor, es ist echt nur Wert 1 der nicht vorkommt.

Das mit der Wahrscheinlichkeit, dass 0 bis 3 öfter vorkommen muss ich 
nochmal überdenken ;-)

Edit:
ah ok, wegen 252-255
Also noch nen overflow-compare bei 251 einbauen ;)

von Dussel (Gast)


Lesenswert?

Mit Modulo kommen immer wieder die Zahlen 0,1,2,3,4,5, 0,1,2… Am Ende 
des Zählerregisters ist:
252%6=0
253%6=1
254%6=2
255%6=3

Das heißt, der letzte 'Zahlendurchlauf' wird angefangen, aber die Zahlen 
4 und 5 nicht mehr erreicht. Aber das macht aber nicht viel aus.

Mit 'auf jeden Fall' sollte man bei Zufallswerten vorsichtig sein, das 
gibt es beim Zufall nicht. Aber trotzdem sollte die 1 statistisch 
gesehen zehn mal vorgekommen sein. Das ist doch schon öfter. Kannst du 
vielleicht die Registerwerte direkt irgendwie ausgeben lassen?
Wie geschrieben fällt mir so kein Grund für das Problem ein, außer, dass 
der Zufall dir einfach noch keine 1 geschenkt hat ;-)

von Vlad T. (vlad_tepesch)


Lesenswert?

warum benutzt dui nicht die random funktion?
ums wirklich zufällig zu machen kännte man die beim ersten Tastendruck 
mit der TCNT initialisieren

von Hannes J. (Firma: eHaJo.de) (joggl) Benutzerseite Flattr this


Lesenswert?

ich finds auch ein wenig komisch.
ich lade jetzt auf jeden fall beim Timer-Overflow-INT ne 4 ins 
timer-register, dann sollte das mit der Gleichverteilung ok sein ;-)

Ja, ich finds auch komisch. hab sonst leider keine möglichkeit für ne 
ausgabe, ist ein attiny13.

Ja, doofer Zufall... Wahrscheinlich gewinne ich auch deshalb nie was bei 
Wetten... ;)

von Hannes J. (Firma: eHaJo.de) (joggl) Benutzerseite Flattr this


Lesenswert?

Vlad Tepesch schrieb:
> warum benutzt dui nicht die random funktion?
> ums wirklich zufällig zu machen kännte man die beim ersten Tastendruck
> mit der TCNT initialisieren

Die würde schon etwa 75% vom attiny einnehmen, hatte ich davor mal drin 
:(

von hans (Gast)


Lesenswert?

Zwischen Timer starten und stoppen dürfte eine gerade
Anzahl von Taktzyklen liegen. Dadurch kann die 1 nie erscheinen.

hans

von Dussel (Gast)


Lesenswert?

Er hat nicht geschrieben, dass er den Timer anhält. Und da die 0 
vorkommt, die 1 aber nicht, scheint es auch kein Problem mit dem 
Überlauf zu sein.

Hast du mal versucht, den Modulowert zu ändern, einfach mal bis 2 oder 
sogar nur bis 1 zu zählen?

von Hannes J. (Firma: eHaJo.de) (joggl) Benutzerseite Flattr this


Lesenswert?

Dussel schrieb:
> Er hat nicht geschrieben, dass er den Timer anhält. Und da die 0
> vorkommt, die 1 aber nicht, scheint es auch kein Problem mit dem
> Überlauf zu sein.
>
> Hast du mal versucht, den Modulowert zu ändern, einfach mal bis 2 oder
> sogar nur bis 1 zu zählen?

genau, mein timer wird ganz am anfang gestartet und läuft ununterbrochen 
bis ans ende der zeit :-P

das mit nem anderen modulo versuch ich jetzt mal...

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Das Problem an dem Verfahren ist, dass der Zähler nicht "frei" läuft 
sondern mit dem selben Takt in dem die Befehle ausgeführt werden. Warum 
kann das zu Problemen führen? Einfaches Beispiel: wenn du den 
Zählerstand immer im Raster von 2 Befehlen ausliest, dann wirst du immer 
gerade oder immer ungerade Zahlen bekommen. Lösungsvorschläge: Zähler 
langsamer laufen lassen, Zähler nicht bei 256 sondern bei einer 
möglichst großen Primzahl zurücksetzen (CTC).

von frank (Gast)


Lesenswert?

Andreas Schwarz schrieb:
> Einfaches Beispiel: wenn du den
> Zählerstand immer im Raster von 2 Befehlen ausliest, dann wirst du immer
> gerade oder immer ungerade Zahlen bekommen.

Ich glaube das war den Beteiligten prinzipiell klar.

Hannes Jochriem schrieb:
> Irgendwann dazwischen drücke ich ne Taste und mache
> zahl=TCNT0%6

Die Frage war ja warum drückt er nie bei 1, bzw. könnte das durch etwas 
in seinem Programm verhindert werden. Aber vielleicht postet der TS ja 
mal sein ganzes Programm für die Experten. Damit diese nicht sowas wie 
"hängt evtl. ne Tastenentprellung am Timer0" (als Extrembeispiel) 
abfragen müssen.
frank

von Bully (Gast)


Lesenswert?

frank schrieb:
>> Zählerstand immer im Raster von 2 Befehlen ausliest, dann wirst du immer
>> gerade oder immer ungerade Zahlen bekommen.

Dann dürften aber überhaupt keine ungeraden Werte vorkommen.

Was machst du in der Zeit wo nichts passiert? Sleep oder endlos 
schleife?

von Dussel (Gast)


Lesenswert?

>Dann dürften aber überhaupt keine ungeraden Werte vorkommen.
In dem (einfachen) Beispiel nicht, aber in der Realität gibt es ja auch 
Befehle mit anderen Längen. Die verhindern eine 1 nicht, können aber die 
Wahrscheinlichkeit dafür stark verringern.

von Bully (Gast)


Lesenswert?

Dann währe noch die Frage ob du den Wert in einer In-Routine ausliest 
oder das Taster Input Register nur Pollst (was einiges erklären würde).

von Peter D. (peda)


Lesenswert?

Wenn Du im Main den Taster abfragst, hast Du immer eine bestimmte 
Befehlsfolge die abläuft und da der Timer mit dem gleichen Takt läuft, 
sind bestimmte Timerwerte weniger wahrscheinlich oder können sogar ganz 
entfallen.

Die Lösung ist ganz einfach, Du fragst die Taste nicht im Main ab, 
sondern im Timerinterrupt. Der Timerinterrupt zählt ne Variable 0..5 
rum. Wird die Taste losgelassen, wird diese Variable gespeichert und 
angezeigt.
Dann ist jeder Interrupt (fast) gleichlang und damit jede Zahl gleich 
wahrscheinlich, unabhängig vom Main.

Will man es exakt gleichlang machen, nimmt man einige Takte früher einen 
Compareinterrupt der die CPU idle setzt. Dann hat man keine 
unterschiedliche Interruptlatenz mehr.


Peter

von Rolf Magnus (Gast)


Lesenswert?

Andreas Schwarz schrieb:
> Das Problem an dem Verfahren ist, dass der Zähler nicht "frei" läuft
> sondern mit dem selben Takt in dem die Befehle ausgeführt werden. Warum
> kann das zu Problemen führen? Einfaches Beispiel: wenn du den
> Zählerstand immer im Raster von 2 Befehlen ausliest, dann wirst du immer
> gerade oder immer ungerade Zahlen bekommen.

Er wird aber beim Tastendruck ausgelesen und nicht einfach alle n Takte, 
und dadurch kommt das Zufallselement ins Spiel.

> Zähler nicht bei 256 sondern bei einer möglichst großen Primzahl
> zurücksetzen (CTC).

Dann aber bitte eine, die ein Vielfaches von 6 ist ;-)

von Rolf Magnus (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Wenn Du im Main den Taster abfragst, hast Du immer eine bestimmte
> Befehlsfolge die abläuft und da der Timer mit dem gleichen Takt läuft,
> sind bestimmte Timerwerte weniger wahrscheinlich oder können sogar ganz
> entfallen.

Sprichst du von der Entprellung, oder wo soll da eine Abhängigkeit vom 
Timerwert herkommen?

von Hannes J. (Firma: eHaJo.de) (joggl) Benutzerseite Flattr this


Lesenswert?

Rolf Magnus schrieb:
> Peter Dannegger schrieb:
>> Wenn Du im Main den Taster abfragst, hast Du immer eine bestimmte
>> Befehlsfolge die abläuft und da der Timer mit dem gleichen Takt läuft,
>> sind bestimmte Timerwerte weniger wahrscheinlich oder können sogar ganz
>> entfallen.
>
> Sprichst du von der Entprellung, oder wo soll da eine Abhängigkeit vom
> Timerwert herkommen?

Das könnte natürlich sein, dass das alles von der Entprellung abhängt.
Ich verwende dein debounce-Makro, Peter, und frage es in der Main ab:
while (1)
{
  if(debounce())
  {
    for (i=0; i<20; i++)
    {
      wuerfel(i%6);
      long_delay(100);
    }
    for (i=5; i>0; i--)
    {
      wuerfel(i);
      long_delay(500);
    }
    zahl = TCNT0%6;
    wuerfel(zahl);
    for (i=0; i<3; i++)
    {
      long_delay(350);
      PORTB |= 0b00111100;
      long_delay(350);
      wuerfel(zahl);
    }
  }
}
return 0;
}

Ist glaub ich nicht ganz aktuell mit dem von gestern, hatte Probleme mit 
dem Sync ;)

von Peter D. (peda)


Lesenswert?

Rolf Magnus schrieb:
> Sprichst du von der Entprellung, oder wo soll da eine Abhängigkeit vom
> Timerwert herkommen?

Nein.
Die Mainloop läuft ja nicht in 0 CPU-Takten, sondern benötigt eine 
gewisse Zeit.
Würde sie z.B. 256 Zyklen benötigen, dann liest Du immer den gleichen 
Timerwert. Benötigt sie eine gerade Anzahl, dann kriegst Du auch nur 
gerade Timerwerte.
Je nach Zykluszahl der Mainloop hast Du also ne Abhängigkeit, von Zufall 
kann dann keine Rede mehr sein.
Im Timerinterrupt hast Du dagegen immer die gleiche Zeitdauer pro 
Würfelwert.


Ich würde in diesem speziellen Fall auch garkeine übliche Entprelling 
vorsehen.
Zu Anfang eine Totzeit (~500ms), ehe der Würfel losrollt und nach dem 
Loslassen eine Sperrzeit (~2s) gegen Schummeln.


Peter

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.