Teensy 3.2 as randomized external sync

LuHi

New member
Hello people!

I am new here, so I hope with this post I will do everything correct and be within the guidelines for the forum.

I would need a little bit of guidance for my project I guess. I am trying to synchronize four systems truly randomized (at least fairly, as requirement) all using interrupts. The code was first written and used for Arduino so there might be still also some things that need to be changed, as for example a random register that helps with the entropy of the randomness.

What I am stuck with, is the stability. Sometimes the output just freezes for a few seconds. Also I am trying to implement a watchdog which I don't really touch yet before the rest is not in an acceptable state.

The code looks like this:

Code:
// Random seed includes
#define randomSeed(s) srandom(s)
volatile uint32_t seed;  // These two variables can be reused in your program after the
volatile int8_t nrot;    // function CreateTrulyRandomSeed()executes in the setup() function

// define output pins
// The LED_BUILTIN pin is helpful as an indicator that the program is running
#define N_PINS 3
const int pins[N_PINS] = { 13, 14, LED_BUILTIN };

// define baud rate
int bd = 9600;

// define interrupt timer
IntervalTimer dogTimer;
IntervalTimer onTimer;
IntervalTimer randomOffTimer;
IntervalTimer projectionTimer;
volatile int randomDelay = 0;
int tElapsed = 0;

//define pulse parameters
#define INTERVAL_MIN 1000   //define minimum interval length [ms]
#define INTERVAL_MAX 1000   //define maximum interval length [ms]
#define PULSE_LEN 1000      //define the pulse length [ms]
volatile bool LEDstate = 0;
volatile int counter = 0;

void CreateTrulyRandomSeed() {
  seed = 0;
  nrot = 32;  // Must be at least 4, but more increased the uniformity of the produced
              // seeds entropy.

  while (nrot > 0)
    ;  // wait here until seed is created
}

void kickDog() {
  noInterrupts();
  WDOG_REFRESH = 0xA602;
  WDOG_REFRESH = 0xB480;
  interrupts();

  // Serial.println("KICK");
}

void on() {
  tElapsed = elapsedMillis();
  //switch LED to HIGH
  LEDstate = 1;
  //change the signal to on (high, 3.3V)
  for (int i = 0; i < N_PINS; i++) {
    digitalWrite(pins[i], LEDstate);  //turn the pins on (high, 3.3V)
  }

  //finding random delay for LED LOW
  randomDelay = random(INTERVAL_MIN, INTERVAL_MAX);
  tElapsed = elapsedMillis() - tElapsed;
  randomOffTimer.begin(randomOff, PULSE_LEN * 1000 - tElapsed);
  onTimer.begin(on, (PULSE_LEN + randomDelay) * 1000 - tElapsed);

  // Serial.println("ON");
}

void randomOff() {
  //switch LED to LOW
  LEDstate = 0;
  //change the signal to off (low, 0V)
  for (int i = 0; i < N_PINS; i++) {
    digitalWrite(pins[i], LOW);  //turn the pins off (low, 0V)
  }

  // Serial.println("OFF");
}

//function called by the interrupt sending the signal through USB port
void sendSerial60() {
  if (nrot < 0) {
    counter++;

    noInterrupts();
    if (LEDstate)
      Serial.print("1");
    else
      Serial.print("0");
    Serial.print("#");
    interrupts();

    Serial.println(counter);
  }

  nrot--;
  seed = seed << 8;
  // seed = seed ^ TCNT1L; #############################################################################################################################
}

void setup() {
  //start Serial connection
  Serial.begin(bd);
  //define interrupt function to refesh the watchdog
  dogTimer.begin(kickDog, (INTERVAL_MAX + PULSE_LEN + 1) * 1000);
  dogTimer.priority(70);
  //define interrupt function and interrupt timing for the pulse length
  onTimer.begin(on, PULSE_LEN * 1000);
  onTimer.priority(100);
  //define random interrupt function and interrupt timing for the interval pulse length
  // randomOffTimer.begin(randomOff, PULSE_LEN * 1000);
  randomOffTimer.priority(100);  //setting timer priority higher than average priority and higher than projectionTimer
  //define projection interrupt function and interrupt timing 59Hz -> 16949.15254us (projectors @59Hz, but listener on other side sampling at 60Hz -> 16666.66667)
  projectionTimer.begin(sendSerial60, 16666.66667);  //59.81: 16719.61211, 60: 166666.6667, 120: 8333.3333333
  projectionTimer.priority(128);                     //setting timer priority to mid level 0-255, lower priorty than randomTimer

  for (int i = 0; i < N_PINS; i++) {
    pinMode(pins[i], OUTPUT);
    digitalWrite(pins[i], LOW);
  }

  // WDOG_UNLOCK = WDOG_UNLOCK_SEQ1;
  // WDOG_UNLOCK = WDOG_UNLOCK_SEQ2;
  // // delayMicroseconds(1);
  // WDOG_STCTRLH |= WDOG_STCTRLH_WAITEN | WDOG_STCTRLH_STOPEN | WDOG_STCTRLH_ALLOWUPDATE | WDOG_STCTRLH_CLKSRC | WDOG_STCTRLH_WDOGEN;  // WDOG_STCTRLH_WINEN | (3rd from right)
  // WDOG_TOVALL = (INTERVAL_MAX + PULSE_LEN) * 1.1;
  // WDOG_TOVALH = 0;
  // WDOG_PRESC = 0;

  // Serial.println("WDOG SET");
  // Serial.println(WDOG_STCTRLH_CLKSRC);

  CreateTrulyRandomSeed();
  randomSeed(seed);
}

void loop() {
}

Any help is highly appreciated
 
Not clear what "Sometimes the output just freezes for a few seconds" means? SerMon output or blinking LED?

Note two of these pins are the same #13 as that is what LED_BUILTIN resolves to.
#define N_PINS 3 const int pins[N_PINS] = { 13, 14, LED_BUILTIN };

Didn't look further not knowing what output is seen as freezing.

Not sure how this ever leaves the while()?
void CreateTrulyRandomSeed() { seed = 0; nrot = 32; // Must be at least 4, but more increased the uniformity of the produced // seeds entropy. while (nrot > 0) ; // wait here until seed is created }
 
thanks for the quick response defragster

Yes I now about the double pin, here I was not sure if the LED will be used or not just when using the pin as an output.

Didn't look further not knowing what output is seen as freezing.
The output which is sent over the Serial connection is just freezing, means if there is the message 1#123 and is updated every 1/60s it suddenly just stops for few seconds (maybe ~2), afterwards it seems to work again but the signal needs to arrive at a very specific timing to be used as as a sync.

if you look at the timestamps of the serial plotter you can see that it suddenly does not receive anything:
11:43:27.644 -> 0#1015
11:43:27.644 -> 0#1016
11:43:27.678 -> 0#1017
11:43:27.678 -> 0#1018
11:43:27.711 -> 0#1019
11:43:27.711 -> 0#1020
11:43:27.743 -> 0#1021
11:43:27.743 -> 0#1022
11:43:27.782 -> 0#1023
11:43:27.782 -> 0#1024
11:43:29.945 -> 0#1025

11:43:29.945 -> 0#1026
11:43:29.978 -> 0#1027
11:43:29.978 -> 0#1028
11:43:30.011 -> 0#1029
11:43:30.011 -> 0#1030

Not sure how this ever leaves the while()?
Later you can see, that the sendSerial60 interrupt function does take care about that and functions as a count down.
 
Last edited:
Why do you have interrupts disabled when printing the 1 or 0?

I don't think the code is freezing at all, you just have the output wrapped in a condition of nrot being less than zero but it only ever gets decremented, eventually it underflows to a positive value and takes ~2 seconds to roll back into negative values.

(60Hz = 120 ticks every 2 seconds, nearly exactly enough to match 128 positive values of nrot where output will be skipped...)
 
Last edited:
Why do you have interrupts disabled when printing the 1 or 0?
Here it is just to make sure to have the most recent and correct instance of LEDstate, just in case it changes exactly at the same time I am writing the message. It is also implemented as a volatile variable for that reason.

I don't think the code is freezing at all, you just have the output wrapped in a condition of nrot being less than zero but it only ever gets decremented, eventually it underflows to a positive value and takes ~2 seconds to roll back into negative values.

(60Hz = 120 ticks every 2 seconds, nearly exactly enough to match 128 positive values of nrot where output will be skipped...)
That is actually great input! I obviously did not think about that it just has a rollover. Exactly, the perfect 128 drove me slowly crazy as being a constant.
Just changed it to what gives a smoother output:
Code:
bool nInit = 0;
[...]
void CreateTrulyRandomSeed() {
  seed = 0;
  nrot = 32;  // Must be at least 4, but more increased the uniformity of the produced
              // seeds entropy.

  while (nrot > 0)
    ;  // wait here until seed is created

  nInit = 1;
}
[...]
void sendSerial60() {
  if (nInit) {
    counter++;

    noInterrupts();
    if (LEDstate)
      Serial.print("1");
    else
      Serial.print("0");
    Serial.print("#");
    interrupts();

    Serial.println(counter);
  }

  nrot--;
  seed = seed << 8;
  // seed = seed ^ TCNT1L;
}

There is still interesting behavior when,
INTERVAL_MIN = 250;
INTERVAL_MAX = 1500;
PULSE_LEN = 250;
As it might happen that on and off is either triggered right after each other or there are multiple instances of ons and offs, meaning it is not always alternating:
14:43:24.924 -> 0#448
14:43:24.924 -> OFF
14:43:24.958 -> 0#449
14:43:24.958 -> 0#450
14:43:24.992 -> 0#451
14:43:24.992 -> 0#452
14:43:25.029 -> 0#453
14:43:25.029 -> 0#454
14:43:25.075 -> 0#455
14:43:25.075 -> ON
14:43:25.075 -> 1#456
14:43:25.075 -> 1#457
14:43:25.109 -> 1#458
14:43:25.109 -> 1#459
14:43:25.143 -> 1#460
14:43:25.143 -> 1#461
14:43:25.176 -> 1#462
14:43:25.176 -> 1#463
14:43:25.209 -> 1#464
14:43:25.209 -> 1#465
14:43:25.243 -> 1#466
14:43:25.243 -> 1#467
14:43:25.277 -> 1#468
14:43:25.277 -> 1#469
14:43:25.324 -> 1#470
14:43:25.324 -> OFF
14:43:25.324 -> 0#471
14:43:25.324 -> 0#472
14:43:25.359 -> 0#473
14:43:25.359 -> 0#474
14:43:25.393 -> 0#475
14:43:25.393 -> 0#476
14:43:25.426 -> 0#477
14:43:25.426 -> 0#478
14:43:25.459 -> 0#479
14:43:25.459 -> 0#480
14:43:25.493 -> 0#481
14:43:25.493 -> 0#482
14:43:25.529 -> 0#483
14:43:25.529 -> 0#484
14:43:25.574 -> 0#485
14:43:25.574 -> OFF
14:43:25.574 -> 0#486
14:43:25.574 -> 0#487

Do you maybe also have an idea on the other issues, like a Teensy native register that behaves fairly random to increase the entropy of the randomness of the sync?
nrot--;
seed = seed << 8;
seed = seed ^ TCNT1L; <-------

I guess the watchdog is a different chapter yet still but also any help on it would be highly appreciated.
 
Last edited:
I don't have experience with the Teensy 3.2, only the Teensy 4.x (which has hardware RNG) but I think it can use the Entropy library (included as part of Teensyduino), or you can at least check that source code to see what it's doing.
 
I don't have experience with the Teensy 3.2, only the Teensy 4.x (which has hardware RNG) but I think it can use the Entropy library (included as part of Teensyduino), or you can at least check that source code to see what it's doing.
Yes, the Entropy library also works on Teensy 3.2.
Source code can be found at C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\Entropy\

Paul
 
I can confirm, on Teensy 3.2 (without hardware random number generator) the Entropy library configures the low power timer to run from the low power RC internal oscillator. The random bits come from comparison of slight difference in time measured using the low accuracy RC oscillator and the high accuracy crystal.
 
Thank you people for the definite confirmation on the entropy library! Checking it, the avr part of it was throwing me slightly off as Teensy 3.x is arm...

As the last topic there is still the watchdog.
How much does the prescaler effect the whole system as I would almost just set it to clock timing to make it easier to time for all interrupts.
 
Back
Top