Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 15 of 15

Thread: Best Teensy 3.1 Random Number Generator?

  1. #1

    Best Teensy 3.1 Random Number Generator?

    I'm about to port a project from Arduino Uno to Teensy 3.1 that relies on unpredictable random numbers. On the Uno I use this bit of awesome code called Probably Random:

    https://gist.github.com/endolith/2568571

    As you can see, it uses the AVR Watchdog Interrupt for entropy, so I assume it won't compile on Teensy. Is there another method I can use on Teensy 3.1 to return "truly" random numbers? Or at least an entropy method that makes the Arduino Random() function usable? Thanks for the help!

  2. #2
    Senior Member
    Join Date
    Jun 2013
    Location
    So. Calif
    Posts
    2,828
    read A/D that whose input pin is floating and yielding noisy numbers?
    sum as unsigned all bytes in RAM?
    else have to build some hardware like reversed biased diode hooked to A/D.

    These are just once, to seed the standard PNG library code.

  3. #3
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    19,914
    Some time ago I looked into porting this library, but using the LPTMR from the 1 kHz slow clock source rather than the watchdog.

  4. #4
    Quote Originally Posted by PaulStoffregen View Post
    Some time ago I looked into porting this library, but using the LPTMR from the 1 kHz slow clock source rather than the watchdog.
    Cool! Mark me down as one who would use such a thing. Or any drop-in function that returns a unique byte every time the Teensy boots (with no clock).

  5. #5
    Senior Member
    Join Date
    Mar 2013
    Location
    Austin TX
    Posts
    415
    You could use a random source, such as the least-significant bits of a 16-bit ADC reading, to seed an LFSR (see the wiki article here: http://en.wikipedia.org/wiki/Linear_...shift_register).

    LFSRs can be arranged to be maximal length, in that they don't repeat values until having output all other values. To get the seed for say a 16-bit LFSR, take 4 16-bit ADC readings, and take the 4 LSBs off each (eg. the "noise") and concatenate into a 16-bit seed. Perhaps then have the LFSR generate a random number of readings prior to outputting useful values.

  6. #6
    Senior Member Jp3141's Avatar
    Join Date
    Nov 2012
    Posts
    458
    Quote Originally Posted by nox771 View Post
    You could use a random source, such as the least-significant bits of a 16-bit ADC reading, to seed an LFSR (see the wiki article here: http://en.wikipedia.org/wiki/Linear_...shift_register).

    LFSRs can be arranged to be maximal length, in that they don't repeat values until having output all other values. To get the seed for say a 16-bit LFSR, take 4 16-bit ADC readings, and take the 4 LSBs off each (eg. the "noise") and concatenate into a 16-bit seed. Perhaps then have the LFSR generate a random number of readings prior to outputting useful values.
    You could also XOR with the individual Teensy's MAC address -- they are unique.

    Here's some code (modified from: http://forum.pjrc.com/threads/91-teensy-3-MAC-address)

    Code:
    #include <stdlib.h>
    
    // http://forum.pjrc.com/threads/91-teensy-3-MAC-address
    
    #define LEDpin   13
    
    void setup() {
      uint8_t m[6];
      char MAC[] = "X11:22:33:44:55:66";
        
      // Setup Serial connection
      Serial.begin(9600);   
      pinMode(LEDpin, OUTPUT); digitalWrite(LEDpin, HIGH); 
      while (!Serial) {digitalWrite(LEDpin, HIGH); delay(10); digitalWrite(LEDpin, LOW); delay(80); }
    
            FTFL_FCCOB0 = 0x41;             // Selects the READONCE command
            FTFL_FCCOB1 = 0x0E;             // read the given word of read once area
                                            // -- this is one half of the mac addr.
            FTFL_FSTAT = FTFL_FSTAT_CCIF;   // Launch command sequence
            while(!(FTFL_FSTAT & FTFL_FSTAT_CCIF)) {}
                                        // Skip FTFL_FCCOB4 as it's always 0.
            *(m+0) = FTFL_FCCOB5;       // collect only the top three bytes,
            *(m+1) = FTFL_FCCOB6;       // in the right orientation (big endian).
            *(m+2) = FTFL_FCCOB7;       
    
            FTFL_FCCOB1 = 0x0F;             // read the given word of read once area
            FTFL_FSTAT = FTFL_FSTAT_CCIF;   // Launch command sequence
            while(!(FTFL_FSTAT & FTFL_FSTAT_CCIF)) {}
                                        // Skip FTFL_FCCOB4 as it's always 0.
            *(m+3) = FTFL_FCCOB5;       // collect only the top three bytes,
            *(m+4) = FTFL_FCCOB6;       // in the right orientation (big endian).
            *(m+5) = FTFL_FCCOB7;       
     
    for (int i=0; i < 6; i++) {Serial.write(itoa(m[i]+0x100, MAC, 16)+1); Serial.write(i < 5 ? ':' : '\n');} 
    }
    
    void loop() {} // dummy
    Last edited by Jp3141; 03-17-2014 at 10:37 PM.

  7. #7
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    19,914
    Here's a copy of the Entropy library ported to Teensy3.

    You'll need to create an empty wdt.h file in hardware/teensy/cores/teensy3/avr. Or just comment out the line #include line in Entropy.h.

    Please let me know how this works for you?
    Attached Files Attached Files

  8. #8
    Quote Originally Posted by PaulStoffregen View Post
    Please let me know how this works for you?
    Brilliant! Works perfectly. Thank you so much.

  9. #9
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    19,914
    Walter Anderson has updated the official Entropy library with Teensy 3.x support.

    http://code.google.com/p/avr-hardwar...WikiAVRentropy

  10. #10
    Senior Member+ manitou's Avatar
    Join Date
    Jan 2013
    Posts
    1,914
    I just unzipped the latest Entropy lib. Example DICE compiles for UNO and teensy ++ 2, but for teensy 3 I get compiles errors

    Code:
    sketchbook/libraries/Entropy/Entropy.cpp: In member function 'uint32_t EntropyClass::random()':
    sketchbook/libraries/Entropy/Entropy.cpp:92:16: error: 'ATOMIC_RESTORESTATE' was not declared in this scope
    sketchbook/libraries/Entropy/Entropy.cpp:92:35: error: 'ATOMIC_BLOCK' was not declared in this scope
    sketchbook/libraries/Entropy/Entropy.cpp:93:3: error: expected ';' before '{' token
    OK, i added #include <util/atomic.h> to Entropy.cpp. that seemed to fix it.
    still worked for UNO, for DUE the include needs to be inside #ifndef ARDUINO_SAM_DUE
    Paul can you let Walter Anderson know?
    Last edited by manitou; 05-08-2014 at 09:48 PM. Reason: hacked a fix

  11. #11
    Junior Member
    Join Date
    May 2014
    Posts
    3
    I checked the Teensy core, and found that Paul has provided equivalents for the Atomic functions. So I modified the header file to inlcude the util/atomic.h file if TEENSYDUINO is defined. I have uploaded the corrected Entropy.h file to the google code page as well as prepare a new zip file Entriopy-v1.0.1.zip which includes the bug fix. The correct fix (utils/atomic.h should NOT be included for the #ifndef ARDUINO_SAM_DUE is:


    // Separate the ARM Due headers we use
    #ifdef ARDUINO_SAM_DUE
    #include <sam.h>
    #include <sam3xa/include/component/component_trng.h>
    #endif

    // Teensy required headers
    #ifdef TEENSYDUINO
    #include <util/atomic.h>
    #endif

    // Separate AVR headers from ARM headers
    #ifdef __AVR__
    #include <avr/interrupt.h>
    #include <avr/wdt.h>
    #include <util/atomic.h>
    #endif

  12. #12
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    19,914
    Looks like this is fixed in version 1.0.1. I'm updating the copy on the PJRC website and in the upcoming Teensyduino 1.19...

  13. #13
    Junior Member
    Join Date
    May 2014
    Posts
    3
    Cool! Thanks!

  14. #14
    Senior Member xxxajk's Avatar
    Join Date
    Nov 2013
    Location
    Buffalo, NY USA
    Posts
    521
    Nice library implementation.
    Is there any way to use this to just get an initial seed, and then turn off the ISR so that it does not interrupt any more?
    I'm thinking that an end or stop method would be a nice and handy addition. The idea is I could grab an initial seed value, and then use the IRQ/watchdog for something else.

  15. #15
    Junior Member
    Join Date
    May 2014
    Posts
    3
    Quote Originally Posted by xxxajk View Post
    Nice library implementation.
    Is there any way to use this to just get an initial seed, and then turn off the ISR so that it does not interrupt any more?
    I'm thinking that an end or stop method would be a nice and handy addition. The idea is I could grab an initial seed value, and then use the IRQ/watchdog for something else.
    On this site, Arduino random seed I have an example sketch on how to use the same basic approach on an AVR to just seed the pseudo-random number generator. If you look at the source code for the entropy library, it should be easy to modify that example for whichever teensy you want.

    Now for the downside, while the example sketch uses fewer resources than the library, and the interrupt is turned off after the seed is generated, it is still attached to the interrupt vector. You'll need to find an example of how (if possible) to reassign the interrupt vector to a different handler.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •