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
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).
> 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?
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!
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.
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.
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.
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?
> 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).
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.
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.
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.
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.
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.
> 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.
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.
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.
=> http://www.nongnu.org/avr-libc/user-manual/ unter "supported devices" steht der kleinste, mit c programmierbare AVR ist der ATtiny13.
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...
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?
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.
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
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..
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...
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.
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.