The Smell of Molten Projects in the Morning

Ed Nisley's Blog: Shop notes, electronics, firmware, machinery, 3D printing, laser cuttery, and curiosities. Contents: 100% human thinking, 0% AI slop.

The New Hotness

  • Random LED Dots: Radioactive Noise

    In need of a quick-and-easy way to generate interesting data that would make an LED array do something and, what with radioactivity being the canonical source for random numbers, an ancient Aware Electronics RM-60 (*) emerged from the heap. The manual will get you up to speed on radiation detection, if you can read past the DOS-era program description.

    It produces a 100 µs (-ish) pulse for each detection:

    Aware RM-60 Geiger Pulse
    Aware RM-60 Geiger Pulse

    The minimum period seems to be around 500 µs, but I lack a sufficiently fierce radioactive source to verify that in any finite amount of time.

    Seeing as how all we need is a little randomness, measuring the time when a pulse occurs will suffice; we’re not talking hardcore crypto.

    With the pulse arriving on the Arduino D2 input, define an interrupt handler that sets a flag, bumps a counter, and records the current time in microseconds:

    void GeigerHandler(void) {
    	if (!GeigerTicked) {				// stop recording until loop() extracts the data
    		GeigerTicked = true;
    		GeigerTicks++;
    		GeigerTime = micros();
    	}
    }	
    

    Define D2 as an input, turn on the pullup, and trigger that handler on the falling edge of the pulse:

    pinMode(PIN_GEIGER,INPUT_PULLUP);	// RM-60 has its own pullup, but add this one, too
    
    attachInterrupt((PIN_GEIGER - 2),GeigerHandler,FALLING);	
    

    Because an absolute timestamp of each event will produce an obviously non-random sequence of monotonically increasing numbers, I ran each four byte timestamp through a simple hash function to whiten the noise:

    //------------------
    // Jenkins one-at-a-time hash
    // From http://en.wikipedia.org/wiki/Jenkins_hash_function
    
    uint32_t jenkins_one_at_a_time_hash(char *key, size_t len)
    {
        uint32_t hash, i;
        for(hash = i = 0; i < len; ++i)
        {
            hash += key[i];
            hash += (hash << 10);
            hash ^= (hash >> 6);
        }
        hash += (hash << 3);
        hash ^= (hash >> 11);
        hash += (hash << 15);
        return hash;
    }
    

    Then the only thing left to do is spin around the loop() while waiting for a particle to arrive:

    	if (GeigerTicked) {
    		digitalWrite(PIN_HEARTBEAT,HIGH);				// show a blip
    		analogWrite(PIN_DIMMING,LEDS_OFF);				// turn off LED array to prevent bright glitch
    
    		Hash = jenkins_one_at_a_time_hash((char *)&GeigerTime,4);	// whiten the noise
    		
    		GeigerTicked = false;							// flag interrupt handler to resume recording
    //			printf("%9ld %08lx %08lx ",GeigerTicks,GeigerTime,Hash);
    		SetLED(Hash);
    	}
    

    The Heartbeat LED gets turned off every 25 ms.

    In the spirit of “video or it didn’t happen”: there’s a movie about that.

    (*) Circuit Cellar readers of long memory will recognize the RM-60 as the McGuffin for the Radioactive Randoms column in 1990 that explained features of interrupt-driven code in a Micromint BASIC-52 board. Decades later, the hardware & software served as Prior Art in a patent suit that forced me to write some Rules of Engagement. Selah.