Skip to content

Instantly share code, notes, and snippets.

@jbonyun
Created September 24, 2019 16:50
Show Gist options
  • Save jbonyun/6263ccc0e4d9456f5f9807a00aeb00d3 to your computer and use it in GitHub Desktop.
Save jbonyun/6263ccc0e4d9456f5f9807a00aeb00d3 to your computer and use it in GitHub Desktop.
Arduino code to send a synchronizing signal to cameras
// JB 20130421
// output square wave + LED frame counter + LED sub-frame measurement
// Square Wave: sent to FSIN on the cameras, maintaining the frame rate
// Counter: LEDs count in binary for each frame
// Sub-frame: each of 8 LEDs lights up in turn, 1/8th of the way through a frame
// constants for pins
// pins for input switches
const int LEDSWITCHPIN = 48;
const int SYNCSWITCHPIN = 50;
const int SPEEDSWITCHPIN = 52;
// output led pins for counting
const int LEDPINS[8] = {42, 40, 38, 36, 34, 32, 30, 28};
// output led pins for binary count
const int LEDBINPINS[4] = {43, 41, 39, 37};
// output pins for sync
const int SYNCPIN = 22;
// How often should we send an FSIN signal?
// We don't actually have to send it every frame, because the
// cameras have an internal timer too. You can send a sync
// signal less often to keep them disciplined, and let the interal
// clock handle the frames in between.
const int FRAMESBETWEENSYNC = 10;
// global variables for state
// number of milliseconds counted on LEDs
unsigned long count = 0;
// last time the count was incremented
unsigned long lastCountMicros = 0;
// read the speed switch to get a frame rate
double ReadFreq()
{
// 125fps is slipping 1/8th of a frame every 5 seconds
// it appears that the cameras like 124 fps instead of 125 fps
// doesn't give artifacts in the frames that way and still is nice and stable
return (digitalRead(SPEEDSWITCHPIN) ? 125.0 : 124.0);
}
// convert a frequency to a period in microseconds
unsigned long FreqToMicros(double freq)
{
return (unsigned long)(1000000.0 / freq);
}
void WriteLED()
{
for (int i = 0; i < 8; ++i) digitalWrite(LEDPINS[i], count % 8 == i ? HIGH : LOW);
for (int i = 0; i < 4; ++i) digitalWrite(LEDBINPINS[i], count & (0x08 << i) ? HIGH : LOW);
}
void WriteLEDOff()
{
for (int i = 0; i < 8; ++i) digitalWrite(LEDPINS[i], LOW);
for (int i = 0; i < 4; ++i) digitalWrite(LEDBINPINS[i], LOW);
}
void UpdateLED()
{
if (digitalRead(LEDSWITCHPIN))
{
WriteLED();
}
else
{
WriteLEDOff();
}
}
void UpdateSyncWave()
{
if (digitalRead(SYNCSWITCHPIN))
{
// we are updating the wave, but is it time?
if (count % (8 * FRAMESBETWEENSYNC) == 0)
{
// rising edge
digitalWrite(SYNCPIN, HIGH);
}
else if (count % (8 * FRAMESBETWEENSYNC) == 4)
{
// falling edge
digitalWrite(SYNCPIN, LOW);
}
}
else
{
// always off because we aren't outputing a sync wave
digitalWrite(SYNCPIN, LOW);
}
}
void setup()
{
// set pin modes
pinMode(LEDSWITCHPIN, INPUT);
pinMode(SYNCSWITCHPIN, INPUT);
pinMode(SPEEDSWITCHPIN, INPUT);
for (int i = 0; i < 8; ++i) pinMode(LEDPINS[i], OUTPUT);
for (int i = 0; i < 4; ++i) pinMode(LEDBINPINS[i], OUTPUT);
pinMode(SYNCPIN, OUTPUT);
// set initial time
lastCountMicros = micros();
// set initial LED state
UpdateLED();
// set initial sync wave state
UpdateSyncWave();
}
void loop()
{
unsigned long nowMicros = micros();
// count happens 8 times per frame (bc we have 8 LEDs)
unsigned long countPeriod = FreqToMicros(ReadFreq() * 8.0);
unsigned long nextCountMicros = lastCountMicros + countPeriod;
if (nowMicros >= nextCountMicros)
{
// update the count
++count;
// avoid slippage by adding period to last time
// rather than adding period to current time
lastCountMicros = nextCountMicros;
// update the LEDs, if they are turned on
UpdateLED();
// update the sync wave, if it is turned on
UpdateSyncWave();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment