Poisson-Test-Zählimpulsgenerator

Begonnen von opengeiger.de, 06. Dezember 2023, 10:27

⏪ vorheriges - nächstes ⏩

opengeiger.de

Wenn man Geigerzähler oder Szintillationszähler selbst baut, dann beschleicht einen ja schon mal das Gefühl, das die Auswerteelektronik wertvolle Zählimpulse verschlucken könnte. Das passiert vor allem bei großen Szintillationsdetektoren schnell, wenn diese selbst beim reinen Hintergrund schon Zählraten über 100cps erzeugen. Man kann nun einen Pulsgenerator nehmen und z.B. mit 1kHz auf den Zähleingang gehen und schauen, ob der Mikrocontroller mit seinem Interrupthandling das auch gut abkann und die zu erwartenden 1000cps richtig anzeigt. In Realität kann es aber sein, das reicht immer noch nicht um eine Impulsrate von 1000cps richtig zu messen. Denn die Poisson-Statistik verlangt ja, dass die Abstände der Impulse negativ exponentiell verteilt sein müssen und das bedeutet, dass die Wahrscheinlichkeit für das Auftreten eines Zählimpulses umso größer, ist je geringer der zeitliche Abstand eines Zählimpulses zum Vorgänger ist. Nur im Mittel ergibt sich dann eine gewisse Impulsrate, und genau das ist die gewisse Challenge für die Elektronik, die man unter Umständen besser überprüfen sollte, ob sie das auch kann.

Nun gibt es Pulsgeneratoren wie Sand am Meer mit denen man periodisch auftretende Zählimpulse erzeugen könnte und die man zum Testen der Auswerteelektronik nehmen könnte. Wenn man aber einen Pulsgenerator sucht, der die Zählimpulse mit einer echten Poisson-Statistik erzeugt, so dass eine genau definierte Zählimpulsrate entsteht, aber auch Zählimpulse mit quasi Nullabstand entstehen, der googelt sich die Finger wund und wenn man mit Googeln was finden würde, dann wäre es vermutlich etwas kostspielig, weil das nicht gerade das Bedürfnis von Hinz und Kunz darstellt.

Ich habe aber rausgefunden, dass man das super-einfach auf einem Mikrocontroller wie zum Beispiel einem Arduino hinbekommt. Der folgende Code erzeugt eine saubere Poisson-Statistik auf einem Arduino Uno, zumindest mal bis etwa 500cps. Die maximale Zählrate ist natürlich auch dadurch begrenzt, wie lange ein Loop Durchlauf braucht. Aber diese Lösung soll auch nur beispielhaft sein, man kann sich natürlich einen superschnellen Controller suchen und dann kommt man natürlich auch höher mit der maximalen Zählimpulsrate. Die maximale Zählimpulsrate, die man erreichen kann, kann man ausmessen indem man das delayMicroseconds() statement entfernt. Wie das Ganze funktioniert, ist vermutlich spätestens dann selbsterklärend, wenn man verstanden hat, dass -log(1-rnd)/lambda die inverse Verteilungsfunktion der negativ exponentiellen Abstandsverteilung der Zählimpulse ist.  :D

Wenn man an den Zählimpulsausgang (Pin 5) einen Piezo Beeper anschließt, ggf. mit entsprechender Impulsverlängerung (delayMicroseconds), dann bekommt man als Nebenprodukt auch einen virtuellen Geigerzähler, der auch ganz ohne teuren Detektor mit der richtigen Statistik tickt. Kann das nicht ein nettes, kostengünstiges Weihnachtsgeschenk für Afficionados sein (damit es auch unterm Weihnachtsbaum richtig tickt): Arduino 20Euro, Piezo 1Euro?  :man_in_love:

void setup() {
  Serial.begin(9600);
  pinMode(5,OUTPUT);
  digitalWrite(5,LOW);
}

void loop() {
  double lambda = 0.1;  // in Millisekunden = 100cps
  unsigned long rnl = random(16777216);
  double rnd = rnl/16777215.00;
  int negEx = round(-log(1-rnd)/lambda);
  //Serial.println(negEx);
  delay(negEx);
  digitalWrite(5,HIGH);
  //delayMicroseconds(1000);
  digitalWrite(5,LOW);
}



DL3HRT

Realistisch wird es mit einem Beschleunigungssensor. Wenn man das Gehäuse senkrecht hält,  niedrige Impulsrate. Bewegt man es auf eine Person zu, so steigt die Impulsrate, je mehr man sich der Waagerechten nähert. Damit kann man Leute erschrecken  ;)

Henri

Hallo Bernd,

das ist ja genial!  :yahoo:

Und nur ein paar Zeilen Code...

Jetzt müsste der nur noch nicht nur ein Rechteck-Signal generieren, sondern eines, dass umgekehrt exponentiell wieder abfällt wie die "echten" Zählimpulse. Aber das lässt sich vermutlich am einfachsten in Hardware mit einem kleinen Kondensator lösen.

Tja. Nun habe ich wieder ein neues Bastelprojekt...  :blush:

Viele Grüße!

Henri


PS:

Hatte noch einen Arduino Nano mit Piezo dran in der Bastelkiste und habe den Sketch gerade aufgespielt. Das Ergenis ist wirklich faszinierend!  :yahoo:  :good2:

Henri

Zitat von: DL3HRT am 06. Dezember 2023, 11:12Realistisch wird es mit einem Beschleunigungssensor. Wenn man das Gehäuse senkrecht hält,  niedrige Impulsrate. Bewegt man es auf eine Person zu, so steigt die Impulsrate, je mehr man sich der Waagerechten nähert. Damit kann man Leute erschrecken  ;)

Oder einem Infrarot-Sensor. Die "Strahlenquelle" hat eine Infrarot-LED. Je näher man kommt, desto mehr knackt es  ;D

opengeiger.de

Zitat von: Henri am 06. Dezember 2023, 14:04Jetzt müsste der nur noch nicht nur ein Rechteck-Signal generieren, sondern eines, dass umgekehrt exponentiell wieder abfällt wie die "echten" Zählimpulse. Aber das lässt sich vermutlich am einfachsten in Hardware mit einem kleinen Kondensator lösen.
Mach am besten einen RC-Tiefpass mit einem R in Serie und einem C nach Ground hinter den Arduino Pin, mit nem dicken C alleine überlastest Du vielleicht den Arduino Output Pin. Als R würd ich vielleicht 100Ohm nehmen und dann das C so ausrechnen, dass die Zeitkonstante stimmt. Die Spannung an dem C wird durch den nachfolgenden Eingang natürlich noch belastet, aber typischerweise ist der ja sehr hochohmig.

Xodor

Dafür ist ein ATTiny echt prädestiniert  :)

Henri

So, ich habe jetzt das ultimativ nerdige Weihnachtsgeschenk!  :yahoo:

Einen 10k NTC unten an einen Kaffeebecher geklebt. Den einen Pin an GND, den anderen Pin an einen 10k Festwiderstand und dessen zweites Anschlussbein an +5V. Die Verbindung zwischen NTC und Festwiderstand dann an A7 des Arduino Nano.


Wenn man nun Kaffee in den Becher füllt, klingt das ziemlich "heiß"  :D



Sketch:

/*
* Piezo an D5
*
* 10k NTC  an A7
*
*  GND ---[NTC 10k]-------[R 10k]--- +5V
*                      |
*                      |------------- A7
*
*/


unsigned long aktuelleMillis = 0;
unsigned long letzteMillis = 0;

float TEMP = 0.0000;      // ADC-Wert für die Temperatur


void setup() {
  Serial.begin(9600);
  pinMode(5,OUTPUT);
  digitalWrite(5,LOW);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN,LOW);
}

void loop() {
  aktuelleMillis = millis();
  if(aktuelleMillis - letzteMillis >= 500)        // alle 500 ms Temperatur abfragen
  {
    letzteMillis = aktuelleMillis; 
    TEMP=(1000.000-analogRead(A7))-400;      // AD-Wert ca. 548 bei 20°C       
  }

 
  //double lambda = 0.1;  // in Millisekunden = 100cps
  //double lambda = 0.01;  // in Millisekunden = 10cps
  double lambda = TEMP*TEMP/1000000;
  Serial.print(TEMP);
  Serial.print("    ");
  Serial.println(lambda);
  unsigned long rnl = random(16777216);
  double rnd = rnl/16777215.00;
  int negEx = round(-log(1-rnd)/lambda);
  //Serial.println(negEx);
  delay(negEx);
  digitalWrite(5,HIGH);
  digitalWrite(LED_BUILTIN,HIGH);
  delayMicroseconds(1000);
  digitalWrite(5,LOW);
  digitalWrite(LED_BUILTIN,LOW);
}


Jetzt muss man eigentlich nur noch die Stromversorgung aus einem Peltier basteln  :drinks:

opengeiger.de


Dsl71

Bernd! Super! Ich werd das auf nem ESP32 laufn lassen,hehe

NuclearPhoenix

Super, danke für die großartige Idee! :good2: Und auch noch relativ einfach umgesetzt -- das muss ich mal in meinen Detektor reinjagen und schauen was passiert. Bisher habe ich immer nur den PWM Ausgang benutzt und das ist ja quasi der best case für die Elektronik. Mal sehen wie viel cps ein Raspberry Pi Pico zusammenbringt :)

opengeiger.de

Ich hab jetzt den Poisson-Test-Impulsgenerator mit dem Arduino Uno etwas genauer vermessen. Dazu habe ich folgenden Code für den Poisson-Impulsgenerator verwendet:

void setup() {
  Serial.begin(9600);
  pinMode(5,OUTPUT);
  digitalWrite(5,LOW);
}

void loop() {
  double lambda = 0.001; //delayMicroseconds --> 1000cps
  unsigned long rnl = random(16777216);
  double rnd = rnl/16777215.00;
  int negEx = round(-log(1-rnd)/lambda);
  //Serial.println(negEx);
  //delayMicroseconds(negEx);
  delayMicroseconds(1);
  digitalWrite(5,HIGH);
  //delayMicroseconds(100);
  digitalWrite(5,LOW);
}

Da sind jetzt bewusst einige Zeilen drin kommentiert. Ich habe hier jetzt auch zur Erzeugung des Impulsabstands die Routine delayMicroseconds verwendet, damit die Impuls-Abstandswerte etwas größere Zahlen sind und die Granularität dadurch feiner wird. In genau dieser Code-Variante, wo die Pulse mit einem fixen Impulsabstand von 1usec erzeugt werden, erreicht der Arduino Uno 17000cps. Dieses Limit ist der Dauer eines Schleifendurchlaufs geschuldet. Damit erzeugt er Impulse mit fixem Abstand von 58usec. So lange braucht es eben, bis der betagte 16MHz ATmega328P auf dem Uno Rev3 SMD Board den Code einer Schleife abgearbeitet hat, wenn für den Abstand der Pulse 1us drinsteht und der Abstand zwischen der rising und der falling edge an Pin 5 auskommentiert ist. Das wäre also schon mal ein oberes Limit für die Impulsrate.

Setzt man nun aber die zufällig mit lambda= 0.001 (us) berechneten, negativ exponentiell verteilten Abstandswerte negEx ein und verwendet delayMicrosecond() um den Abstand zu erzeugen, dann kann man mit einem gutem Scope sehen, dass der Minimum Abstand zweier Pulse wegen des zusätzlichen Parameters im Funktionsaufruf jetzt auf 328us hochgeht, was einer theoretisch, maximalen Impulsrate von ,,nur" noch 3049cps entsprechen würde. Wenn aber lambda=0.001us beträgt dann entspricht das ja einer Poisson-verteilten Impulsrate von im Mittel 1000cps. Allerdings mit einem minimalen Abstand zweier Pulse von 328us. Das könnte man mit einem besseren uC noch etwas runterbekommen.

Schließt man einen Piezo ohne Ton-Elektronik an Pin 5 an, dann rauscht es zunächst mal nur ganz leise. Fügt man nun das delayMicroseconds(100) zwischen die Rising und die Falling edge auf Pin 5 ein, dann knackt der Piezo richtig, und dann erzeugt der Poisson-verteilte Test-Impuls-Generator auch ein Geräusch, das einem einen kalten Schauer den Buckel runter jagt. Aber vermutlich empfindet man das nur dann so schauerlich, wenn man weiß, was es denn in etwa bedeuten würde, wenn das Signal von einem echten Gerät mit einem Detektor und einer echten Quelle käme. 1000cps hat man ja nicht so oft, zumindest im Hobby-Bereich. Bei dem schaurigen Gefühl spielen also die unvermeidlichen Assoziationen des Eingeweihten heftig mit. Für andere ists vermutlich nur ein ekelhaftes Rauschen.

Viel mehr als 1000cps bekommt man mit einem Arduino Uno aber nicht mehr hin, da ja dann auch die Granularität der Impuls-Abstandsauflösung schlecht werden würde, weil die Zufallszahlen dann immer kleiner werden. Wenn man noch schneller werden wollte und einen besseren uC nehmen würde, dann bräuchte man, um es wirklich gut zu machen, zusätzlich auch noch eine Routine delayNanoseconds(), was man aber sicher noch selbst aufsetzen könnte.

Ich habe aber auch noch nachgeschaut, ob denn die Statistik des Test-Impuls-Generators stimmt. Dazu habe ich das Serial.println(negEx)-Statement aktiviert und hab mir ein paar hunderttausend Werte ausgeben lassen, hab sie in Matlab eingelesen und dann geschaut, ob das der negativ exponentiellen Verteilung entspricht, was ja die Voraussetzung für die Poisson-Statistik der Impulsrate ist. Und das passt doch erstaunlich genau (siehe Bild negExLambda0p001).

Der nächste Schritt wäre, nun dieses Signal mal auf einen einfachen Impulszähler, der auf einem etwas besseren uC als dem Uno läuft, loszulassen, um zu sehen, ob man diese mittlere Impulsrate von 1000cps auch wirklich genau gezählt bekommt. Ein Arduino Uno kommt nur so etwa auf 100cps, die er dann mit einer Nachkommastelle noch genau misst, bei 500cps, da schwächelt er schon sichtlich, weil er Impulse, die rasch aufeinander kommen einfach verschluckt.

Wer noch nie einen Geigerzähler mit 1000cps hat kreischen hören, ich hab mal ein kleines Video mit Ton als zip angehängt, so zum Vorweihnachtsgruseln ... (Vgeiger1000cps.zip) .  :o

etalon

Zitat von: opengeiger.de am 08. Dezember 2023, 13:59...
Aber vermutlich empfindet man das nur dann so schauerlich, wenn man weiß, was es denn in etwa bedeuten würde, wenn das Signal von einem echten Gerät mit einem Detektor und einer echten Quelle käme. 1000cps hat man ja nicht so oft, zumindest im Hobby-Bereich. Bei dem schaurigen Gefühl spielen also die unvermeidlichen Assoziationen des Eingeweihten heftig mit. Für andere ists vermutlich nur ein ekelhaftes Rauschen.

...

Wer noch nie einen Geigerzähler mit 1000cps hat kreischen hören, ich hab mal ein kleines Video mit Ton als zip angehängt, so zum Vorweihnachtsgruseln ...  :o


Naja, so exklusiv ist das Geräusch von >1000 ips jetzt auch nicht. Selbst mit kleinen Pechblendestücken o. Ä. und nem ollen RDC101 kommt man da bequem hin (siehe Foto). Damit ist auch erst mal die Panik entschärft, sollte das Geräusch durch eine echte Strahlenquelle entstehen.  ;)

Es kommt halt ganz elementar auf die Empfindlichkeit des Sensors an, ob hinter den >1000 ips eine akute Gefährdung zu suchen ist, oder eher nicht. Daher eignet sich solch eine Anzeige auch überhaupt nicht zur Ableitung irgend eines Gefährdungspotentials...  :unknw:

Und ein generiertes Geräusch hat diesbezüglich dann auch keine Aussagekraft. Wenn manche Leute wüssten, von wie vielen Gammaquanten jeder Quadratzentimeter ihres Körpers jede Sekunde durchdrungen wird, wir hätten eine weit höhere Todesrate durch Suizid als durch alle Strahlenbelastungen zusammen...  :D

Sie dürfen in diesem Board keine Dateianhänge sehen.


P.S.: Um Elektronik zu testen, ist das aber sicher sehr hilfreich!

Henri

Das ist echt eine super "Erfindung"! Bin immer noch ganz begeistert! :good2:

Wenn es um hohe Zählraten geht, kommt es ja auch darauf an, ob man einen GM-Zähler oder einen Szintillator simulieren möchte. Beim GM-Zählrohr hat man sowieso eine Totzeit von 30-100µs, und wenn sich der minimale Abstand zwischen zwei Impulsen in diesem Bereich bewegt, ist ja alles genau so, wie es sein soll.

Nur bei Szintillatoren darf es dann gerne etwas schneller gehen.

Ich bin allerdings der Meinung, mal gelesen zu haben, dass es bei den Arduino Makros für micros() ein paar Fallstricke gibt, da es sich ja nicht um eine Echtzeit-Umgebung handelt. Ob man nanoseconds() dann noch hinbekommen würde?


Ich warte noch etwas ab, was hier so an kommen mag, und dann bastel ich mir mal einen kleinen Generator mit einstellbarer Impulsrate, Totzeit und umschaltbarem Tiefpass am Ausgang, um das Verhalten verschiedener GM-Zählrohre und Szintillator-Materialien nachzuahmen. Wieder €35.000,- gespart!  :D

Henri

Zitat von: etalon am 08. Dezember 2023, 14:32Naja, so exklusiv ist das Geräusch von >1000 ips jetzt auch nicht. Selbst mit kleinen Pechblendestücken o. Ä. und nem ollen RDC101 kommt man da bequem hin (siehe Foto).

Oder auch mit auf einem kleinen Blechle abgeschiedenen Radon-Folgeprodukten: https://youtu.be/IT0xugP-9cI?t=730  sind 3.000 cps mit einem Pancake zu erreichen  :o

NuclearPhoenix

Zitat von: Henri am 08. Dezember 2023, 14:32Ich bin allerdings der Meinung, mal gelesen zu haben, dass es bei den Arduino Makros für micros() ein paar Fallstricke gibt, da es sich ja nicht um eine Echtzeit-Umgebung handelt. Ob man nanoseconds() dann noch hinbekommen würde?
Ja, ich glaube gerade am unteren Ende bei einstelligen Zahlenwerten ist es nicht besonders genau. Kommt auch auf die Umsetzung darauf an und welchen Mikrocontroller du benutzt.