Forum: Mikrocontroller und Digitale Elektronik Knobelei: Zufallsgenerator


von Alex (Gast)


Lesenswert?

Hallo zusammen,
ich plane eine kleine Einrichtung, die folgendes Element enthalten muss:

Einen "Zufallsgenerator", der zufällig aber mit festem Mittelwert (und 
der soll einstellbar 10 min oder 1 stunde betragen) anspringt. Ich 
brauche also lediglich ein digitales signal, das für kurze zeit um den 
festen mittelwert zufällig auftritt.

Wie ich das Signal generiere ist eigentlich an keine Bedingungen 
geknüpft, nur an folgen(schwere)de: die gesamte Elektronik muss 
möglichst klein sein und sollte minimalen stromverbrauch haben, da sie 
wie eine uhr über viele tage mit batterie funktionieren soll.

Was würdet ihr vorschlagen? Gibt es andere sinnvolle Ansätze als über 
einen µC? Wenn einen µC nehmen - welchen (kleinen) AVR? Ich kann nicht 
Assembler programmieren - wenn es ein kleiner AVR werden würde, wie 
schwer wäre die umsetzung in assembler für einen laien?



Beste Grüße

Alex

von Alex (Gast)


Lesenswert?

achja, bevor der kommentar auftritt, dass echter zufall mit dem µC 
ohnehin nicht möglich ist: Es muss kein echter sein, er muss nur echt 
wirken (also bei längerer beobachtung nicht eindeutig ein muster 
aufweisen).

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


Lesenswert?

> Einen "Zufallsgenerator", der zufällig aber mit festem Mittelwert (und
> der soll einstellbar 10 min oder 1 stunde betragen) anspringt.
Dann mußt du ja nur das Doppelte des Mittelwerts als Obergrenze in einen 
Zufallsgenerator einspeisen und dann die ermittelte Zeit abwarten.

> Gibt es andere sinnvolle Ansätze als über einen µC?
Eher nein. Die Zufallskomponente könntest du zwar als LFSR auch mit 
diskreten Komponenten aufbauen, aber dann bekommst du damit ein Problem:
> die gesamte Elektronik muss möglichst klein sein
Diese Aufgabe schreit laut nach einem 6 oder 8 Pin uC.

> wie schwer wäre die umsetzung in assembler für einen laien?
Das ist nicht trivial, denn du mußt mit Sleep-Modes usw. herumkämpfen...
Ich würde da wenn du ganz von vorn beginnst, mit einem Zeitaufwand von 
ca. 1 Monat rechnen.

>  Ich kann nicht Assembler programmieren
Kannst du C?

von Alex (Gast)


Lesenswert?

c++ gut,
c ausreichend für bisherige µC projekte allerdings noch exkl interrupts 
und timer (ja was bleibt da schon übrig =D )

Ich hab den Attiny 13 herumliegen... aber ein monat ist mir zu lang!

von Lukas K. (carrotindustries)


Lesenswert?

Du kannst ja mit dem ADC des AVRs etwas rauschendes, z.B. eine Z-Diode 
vermessen. Per Portpin kannst du diese zwecks Stromverbrauch abschaltbar 
machen.

von MoritzS (Gast)


Lesenswert?

Ein externer Rauschgenerator wie z.B.

http://www.ve6aqo.com/images/Leo_Rauschgenerator/Rauschgen_m..jpg

wird vom AD-Wandler des AVR abgetastet. Die so ermittelten Werte können 
als  Initialisierungsvektor oder als Muster zur Art der Rückkopplung für 
ein LRSR

http://de.wikipedia.org/wiki/Linear_r%C3%BCckgekoppeltes_Schieberegister

dienen.

Dies sollte dir eine konstante Zufallsverteilung geben, deren Mittelwert 
die Hälfte des maximal erreichbaren Wertes ergibt.

Wenn das Aufbauen des Rauschgenerators zu aufwändig oder zu 
stromintensiv ist, reicht vielleicht (je nach Umgebung) auch das Samplen 
eines digitalen Eingangspins. Der darf dann natürlich keine 
Pull-Up/Pull-Down-Widerstände haben.

von Karl H. (kbuchegg)


Lesenswert?

Ich denke das Generieren der Zufallszahl ist nicht das große Problem an 
sich. Für viele Zwecke ist rand() gut genug.

Den Teil den man lernen muss ist: wie wartet man möglichst Stromsparend 
eine gewisse Zeit lang ab.

von Alex (Gast)


Lesenswert?

danke für die antworten soweit!
Das ganze soll (mit knopfzelle) auf die größe einer uhr gebracht werden 
- ist dein Ansatz (@MoritzS) da realisierbar?

Was ist nur durch programmiertechnik maximal auf der bereits vorandenen 
hardwareebene eines avrs möglich, den ich nehmen könnte?
Bzw immernoch das problem der größe - die AtMega 16 die ich 
programmieren kann sind ja ein bisschen zu groß ;)
Was ist der kleinste AVR, der sich in C programmieren lässt?

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


Lesenswert?

> Was ist der kleinste AVR, der sich in C programmieren lässt?
Nimm irgendwas in der Liga um den Attiny45 mit 8 Pins dann hast du 
genügend Luft. Wenns dann in Serie gehen soll und du zigtausende Geräte 
brauchst kannst du immer noch optimieren....

BTW: vergiss diese Pseudo-Zufallszahlen mit AD-Wandler und 
Rauschgenerator, bis die wirklich zufällige Zahlen liefern hast du 
schon lange das Ding mit rand() ausreichend zufällig am laufen (du 
brauchst ja nur 1 neue Zufallszahl alle 10 Minuten bis 1h).

von Alex (Gast)


Lesenswert?

danke.
ich habe die funktion rand() lange nicht mehr benutzt - und erinnere 
mich (hoffentlich richtig?) daran, dass ich eine zahl vorgebe, die dann 
die obere grenze der generierten zufallszahl gilt.
Wenn ich nun als obere grenze das doppelte der zahl nehme ist mein 
mittelwert die zahl selbst?

Das wäre dann vielleicht schon eine ausreichende lösung.

von Karl H. (kbuchegg)


Lesenswert?

Alex schrieb:
> danke.
> ich habe die funktion rand() lange nicht mehr benutzt - und erinnere
> mich (hoffentlich richtig?) daran, dass ich eine zahl vorgebe, die dann
> die obere grenze der generierten zufallszahl gilt.

falsch.
rand() liefert eine Zahl zwischen 0 und RAND_MAX

Was du dann mit dieser Zahl weiter machst, obliegt ganz dir. Du kannst 
sie zb durch eine Bereichsgröße modulo nehmen(ja ich weiß, ist nicht 
optimal) und eine Untergrenze dazuzählen. Was auch immer du willst.

> Wenn ich nun als obere grenze das doppelte der zahl nehme ist mein
> mittelwert die zahl selbst?

Yep.

von Detlev T. (detlevt)


Lesenswert?

ATTiny13A wäre auch mein Tipp.

Algorithmen für Zufallszahlengeneratoren dürften nicht schwer zu finden 
sein. Du musst halt den passenden finden, der die Verteilung hat, die du 
anstrebst bzw. wie man die Werte von rand() so umrechnet, dass diese 
Verteilung herauskommt. Problematisch ist da natürlich immer noch, den 
Startwert zu finden. Man könnte aber immer den neusten Wert als seed ins 
EEPROM schreiben.

Tja, und du musst dich halt mit dem Sleep-Modus auseinander setzen.

von Karl H. (kbuchegg)


Lesenswert?

Alex schrieb:

> Das wäre dann vielleicht schon eine ausreichende lösung.

Für ein Casin0 wirds nicht reichen, aber für den Hausgebrauch ist rand() 
eine ausreichend gute Lösung.

von Alex (Gast)


Lesenswert?

merci beaucoup, ich werds mal ausprobieren!

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


Lesenswert?

Wie soll denn dein digitales Signal überhaupt ausgegeben werden?
Wie viele Bits sollen (pseudo-)zufällig werden?  So ganz ist mir
die Aufgabe noch nicht klar.

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


Lesenswert?

> Wie viele Bits sollen (pseudo-)zufällig werden?
So wie ich das verstanden habe, soll die Zeit zwischen 2 Ipulsen 
zufällig sein, aber im langjährigen Mittel um die 10 Minuten (also 
brauche ich eine zufallszeit von 0 bis 20 Minuten). Oder 1 Stunde, oder 
irgendwas einstellbares dazwischen.

von Mark B. (markbrandis)


Lesenswert?

Lothar Miller schrieb:
> im langjährigen Mittel um die 10 Minuten

Naja, dann kann ich aber auch einen Fall haben in dem ich 59 mal nur 
eine Sekunde warte, und einmal 599 min 1 sek - das macht im Schnitt auch 
10 Minuten ;-)

Alleine den Mittelwert vorgeben reicht mMn nicht, es bräuchte auch eine 
Angabe wie stark die Zufallswerte denn um dieses Mittel streuen 
sollen/dürfen.

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


Lesenswert?

Quick hack, als Diskussionsbasis.  (Nicht getestet, keine Garantie,
nicht auf lebende Menschen oder Tiere anwenden oder in der Luft- und
Raumfahrt benutzen usw. usf.  ;-)
1
#include <stdbool.h>
2
#include <stdlib.h>
3
#include <stdint.h>
4
5
#include <avr/io.h>
6
#include <avr/interrupt.h>
7
#include <avr/power.h>
8
#include <avr/sleep.h>
9
10
#define F_CPU 9.6E6
11
#include <util/delay.h>
12
13
#define CLOCK_PRESCALER 256
14
#define TIMER_PRESCALER 1024
15
16
#define TIMER_PERIOD (256 / (F_CPU / CLOCK_PRESCALER / TIMER_PRESCALER))
17
18
#define MEDIAN (10 * 60)  /* 10 minutes */
19
20
static uint16_t countdown;
21
static volatile bool timer_expired;
22
23
ISR(TIM0_OVF_vect)
24
{
25
  if (--countdown == 0) {
26
    TCCR0B = 0;  /* turn off timer */
27
    timer_expired = true;
28
    clock_prescale_set(clock_div_1);
29
  }
30
}
31
32
static void
33
starttimer(uint16_t timeout)
34
{
35
  countdown = timeout;
36
  TCNT0 = 0;
37
  timer_expired = false;
38
  clock_prescale_set(clock_div_256);
39
  TCCR0B = _BV(CS02) | _BV(CS00);  /* start timer with prescaler 1024 */
40
}
41
42
static void
43
ioinit(void)
44
{
45
  TIMSK0 = _BV(TOIE0);
46
  sei();
47
  DDRB = _BV(4);  /* connection for LED or something else */
48
}
49
50
static void
51
signal_event(void)
52
{
53
  PORTB |= _BV(4);
54
  _delay_ms(500);
55
  PORTB &= ~_BV(4);
56
}
57
58
int
59
main(void)
60
{
61
  ioinit();
62
63
  for (;;) {
64
    int r = rand();
65
    uint16_t timeout = (unsigned)r % (unsigned)(2 * MEDIAN / TIMER_PERIOD) + 1;
66
67
    starttimer(timeout);
68
    do
69
    {
70
      sleep_mode();
71
    }
72
    while (!timer_expired);
73
    signal_event();
74
  }
75
}

Ich war vor allem mal neugierig, ob das in einen ATtiny13 überhaupt
reinpassen würde, schließlich werden ja Divisionen/Modulo-Operationen
benötigt.  Keine Angst, der Gleitkommakram wird komplett vom Compiler
aufgedröselt, schreibt sich so halt nur einfacher hin. ;-)

Immerhin, ist derzeit nur zu 75 % ausgelastet, ich hatte schlimmeres
befürchtet.

Das sollte unserem Kandidaten vielleicht erstmal als Basis für
eigene Experimente genügen.

Die Ruhestromaufnahme sollte bei einigen 10 µA liegen.  Weniger würde
nur noch gehen mit Controllern, deren Timer man im Schlaf mit einem
32-kHz-Quarz takten lassen kann, damit man den Haupttakt ausschalten
kann.

von MoritzS (Gast)


Lesenswert?

=> http://www.nongnu.org/avr-libc/user-manual/   unter "supported 
devices" steht der kleinste, mit c programmierbare AVR ist der ATtiny13.

von Alex (Gast)


Lesenswert?

zu oben (spezifizierung der zufalls/mittelgeschichten):
Bei der Einstellung 10 min soll im Mittel alle 10 minuten ein high 
Impuls (und so gesehen ein Bit) (der länge 1-3s) ausgegeben werden, der 
einen transistor ansteuert. Das "Mittel" ist so gemeint, dass nach dem 
Einschalten beispielsweise nach 7 minuten der erste Impuls, dann nach 
13, dann nach 16, dann nach 4 [...] ein Impuls kommt. Obergrenze 
zwischen den Impulsen sollte 20-40 minuten nicht überschreiten.

@Jörg
Herzlichen Dank für das Codebeispiel! Das hilft mir sehr weiter, denke 
ich.
Ich bin eher hobby- und gelegenheitsprogrammierer deshalb meine Fragen, 
die sich höchstwahrsch. schon aus dem code beantworten lassen...:
-Du nutzt den internen Oszillator des AtTiny13?
- Mit AVRStudio (AVRGCC) und einem isp adapter ist der code so auf den 
tiny13 flashbar?

@Mark
Gaußverteilt wäre nicht verkehrt ;) aber so wichtig ist das nicht, 
zweiseitig exponentialverteilt ginge auch etc... es geht dabei in erster 
linie um eine sinnvolle verteilung, was hier bedeutet dass ich 
vielleicht zu 80-90% innerhalb von 15 minuten den nächsten Impuls 
bekomme...

von Karl H. (kbuchegg)


Lesenswert?

Alex schrieb:
> zu oben (spezifizierung der zufalls/mittelgeschichten):
> Bei der Einstellung 10 min soll im Mittel alle 10 minuten ein high
> Impuls (und so gesehen ein Bit) (der länge 1-3s) ausgegeben werden, der
> einen transistor ansteuert. Das "Mittel" ist so gemeint, dass nach dem
> Einschalten beispielsweise nach 7 minuten der erste Impuls, dann nach
> 13, dann nach 16, dann nach 4 [...] ein Impuls kommt. Obergrenze
> zwischen den Impulsen sollte 20-40 minuten nicht überschreiten.

Einige dich mit dir selber welches die kürzeste Zeit sein soll nach der 
der nächste Puls kommt und welches die längste.

      rand() % ( max - min ) + min

das ist die Zeit, die du als nächstes warten willst.

> vielleicht zu 80-90% innerhalb von 15 minuten den nächsten Impuls
> bekomme...

was solls denn eigentlich werden?

von Alex (Gast)


Lesenswert?

Die genaue Beschreibung macht hier nicht so viel sinn aber es wird eine 
Armbanduhr, die nicht die Zeit anzeigt sondern (einstellbar) als 
Erinnerer funktioniert.
Da das ganze als Konditionierung funktionieren soll, die später nicht 
von dem Signal selber sondern von der Erwartung des Signals abhängt 
(damit die Uhr irgendwann weggelassen werden kann) ist die zufälligkeit 
nötig.
Die Erinnerung funktioniert über eine kurze vibration.

Dafür bin ich übrigens immernoch bei der Suche nach einem 
(online)Anbieter in Deutschland, der möglichst kleine Vibrationsmotoren 
in scheibenform verkauft. Falls hier also einer bekannt sein sollte bin 
ich für Links wie immer dankbar.

von fz (Gast)


Lesenswert?

Zum Thema kleine Vibrationsmotoren, wenn du ein altes Handy hast das du 
nicht mehr benötigst kannst du es ausschlachten. Dort sollte sich ein 
kleiner Motor befinden

von Alex (Gast)


Lesenswert?

danke, habe ich auch schon dran gedacht aber ich hab keins =D
zudem sind in einigen alten handies die motoren stabförmig, ich brauche 
aber DISK..

von Daniel F. (danielosna)


Lesenswert?

Disc könnte schwierig werden denke ich... selbst in relativ aktuellen 
Handy sind die in Stabform drin... Bauhöhe so 3-4 mm würde ich tippen...

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


Lesenswert?

Alex schrieb:

> Herzlichen Dank für das Codebeispiel! Das hilft mir sehr weiter,
> denke ich.

Ja, wenn du schon mal C programmiert hast, solltest du dich in so ein
"Gerippe" schneller reinfinden können, als es von null auf selbst zu
zimmern.

> - Du nutzt den internen Oszillator des AtTiny13?

Ich nutze gar nichts. ;-) Ja, ich habe es auf den internen 9,6-
MHz-Oszillator des ATtiny13 ausgelegt, der standardmäßig aktiv ist.

> - Mit AVRStudio (AVRGCC) und einem isp adapter ist der code so auf
> den tiny13 flashbar?

Weiß ich nicht, hab' kein AVR Studio. :)  Ich würde allerdings davon
ausgehen, dass man das machen kann.

Der Prozessortakt von 9,6 MHz wird nur während der aktiven Phase
benutzt, danach wird er runtergeteilt durch 256 (über den clock
prescaler), das sind also einige 10 kHz.  Dieser Takt wird dann
nochmals durch 1024 geteilt für den Timer, der nach 256 Schritten
überläuft.  Das entspricht ziemlich genau 7 s pro Überlauf, und nach
jedem Überlauf wacht der Prozessor auf.  Diese 7 s sind dann auch die
Granularität der Ereignisse.

> Gaußverteilt wäre nicht verkehrt ;)

Naja, da müsstest du wohl mehr Aufwand reinstecken, und ich fürchte,
dass dann der ATtiny13 auch nicht mehr ausreicht.  rand() ist einfach
nur gleichverteilt.

von Alex (Gast)


Lesenswert?

Hallo,
die diskussion hier ist einige zeit her und ich laufe seit ebenfalls 
einiger zeit mit meinem prototypen in der tasche herum, der nach deinem 
(jörg) code so super läuft. nun habe ich allerdings noch das problem, 
dass die gesamte schaltung, die in einem fach einer micro AAA zelle 
platz finden muss (und bislang auch tut) ein/ausschaltbar sein muss.
da ich keine mechanischen schalter der größe und form finde, wie ich sie 
brauche, dachte ich daran, die schaltung über einen taster in und aus 
dem sleep mode zu holen.

nun hat sich mein grundverständnis bzgl dem obigen code zwar verbessert, 
er reicht aber noch nicht aus, um das einfache folgende zu 
implementieren:

einfacher tasterdruck -> µC geht in den sleep mode
erneuter tastendruck -> µC geht aus dem sleep mode und führt die 
mainschleife aus.

ich bin auch nicht sicher, ob das noch auf den tiny passt bzw wie man es 
coden müsste, damit das auch noch draufpasst?

ich denke die frage ist für die meisten hier lächerlich einfach, für 
mich aber aufgrund der leidigen interrupt/sleepmode einarbeitung noch 
nicht ganz trivial.
kann mir da jemand helfen oder ein codebeispiel geben?

Viele Grüße

Alex

von Michael R. (mexman) Benutzerseite


Lesenswert?

Halo Alex,

wenn Du statt eines AVR einen PIC nehemn koenntes, koennte ich Dir das 
schicken.

Der Zufallsgenerator sind 7 Zeilen Assemblercode, die skalierung nochmal 
drei und das meiste ist die Initialisierung des Chips.

Echte Peanuts.


Gruss

Michael

von Alex (Gast)


Lesenswert?

hallo michael,
uuh mit PICs (genauso wie assembler) habe ich so GAR keine erfahrung! :( 
dafür bin ich wohl noch nicht genug in der materie ... wie programmiere 
ich die denn (hardwaremäßig)?
ich glaube dafür müsste ich mein bisheriges projekt zu sehr 
umkrempeln...

herzlichen dank für das angebot!

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.