I modified a 16mm film synchronizer to add an audible footage counter. This helps me spool down large loads of film in the dark. Conventional wisdom says that 42 turns of the (4:1 geared) rewinds will fill a 100ft daylight spool. I was curious to see if that’s accurate. (It is.) More importantly, I can barely count without using my fingers, so why not make a robot do the work!
What I did
- Cleaned the synchronizer and checked for scratches. Don’t wanna scratch the film!
- Glued a magnet to one of the gangs, with a matching reed switch on the frame. Each pass of the magnet will momentarily close the reed switch. 1 pulse = 1 foot.
- Mounted a handy mint box enclosure containing an Arduino with a piezo buzzer and reset button. Each foot is marked with a beep, each 10th foot with a higher beep, until finally 100ft causes a long beep at a still higher frequency. (I chose frequencies within the resonant band of the piezo to get maximum volume.)
- If you are using this in the dark, remember to remove or cover the Arduino power LED! If your board has an LED on pin 13, it will flash during boot/reset, so cover that too.
How It Sounds
Arduino Code
- Requires the ToneAC library
- At boot/reset you’ll hear a few beeps to let you know it’s running
- You can monitor the count via serial for debugging
- If you uncomment the LED lines, Pin 13 will go high for odd feet & low for even feet.
/*
Foot-counter for 16mm synchronizer, based on debounce example and ToneAC library for louder piezo.
Attach a reed switch or opto sensor to the sync block for 1 pulse per foot.
Uses toneAC library to drive piezo:
toneAC( frequency [, volume [, length [, background ]]] ) - Play a note.
frequency - Play the specified frequency indefinitely, turn off with toneAC().
volume - [optional] Set a volume level. (default: 10, range: 0 to 10 [0 = off])
length - [optional] Set the length to play in milliseconds. (default: 0 [forever], range: 0 to 2^32-1)
background - [optional] Play note in background or pause till finished? (default: false, values: true/false)
toneAC() - Stop output.
noToneAC() - Same as toneAC().
*/
#include "toneAC.h" //This alternative library is much louder than the "tone" library, but needs specific pins (9 & 10)
// constants won't change. They're used here to set pin numbers:
const int buttonPin = 2; // the number of the pushbutton pin
const int ledPin = 13; // the number of the LED pin
// Variables will change:
int ledState = LOW; // the current state of the output pin
int buttonState; // the current reading from the input pin
int lastButtonState = LOW; // the previous reading from the input pin
int feetCount = 0;
// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
unsigned long debounceDelay = 5; // the debounce time; increase if the output flickers
void setup() {
Serial.begin(9600);
pinMode(buttonPin, INPUT_PULLUP);
pinMode(ledPin, OUTPUT);
// set initial LED state
digitalWrite(ledPin, ledState);
Serial.println("Footage Counter RESET");
toneAC(2300, 10, 50);
delay(50);
toneAC(2300, 10, 50);
delay(50);
}
void loop() {
// read the state of the switch into a local variable:
int reading = digitalRead(buttonPin);
// check to see if you just pressed the button
// (i.e. the input went from LOW to HIGH), and you've waited long enough
// since the last press to ignore any noise:
// If the switch changed, due to noise or pressing:
if (reading != lastButtonState) {
// reset the debouncing timer
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer than the debounce
// delay, so take it as the actual current state:
// if the button state has changed:
if (reading != buttonState) {
buttonState = reading;
// increment count on high-going transition of button
if (buttonState == HIGH) {
ledState = !ledState;
Serial.println(String(feetCount) + " ft");
if (feetCount % 100 == 0 && feetCount > 1) {
toneAC(2500, 10, 3000);
} else if (feetCount % 10 == 0 && feetCount > 1) {
toneAC(2300, 10, 75);
} else {
toneAC(2000, 10, 20);
}
feetCount++;
}
}
}
// set the LED:
//digitalWrite(ledPin, ledState);
// save the reading. Next time through the loop, it'll be the lastButtonState:
lastButtonState = reading;
}