Summary
My use-case is a film scanner. Film is constantly moving and, upon detecting one of the holes at the edges, I need to flash LEDs and take a picture to capture the film frame. In this use-case, the timing of each exposure should be as precise as possible. Checking elapsed micros in the main loop reduces my "clock" resolution to the time it takes the loop to complete. I tried the solution below...but couldn't get it to behave as expected. I suspect my shallow knowledge of timers and interrupts is preventing me from seeing a better option.
Requirements
- LEDs should turn on as soon as a hole is detected (and other logic conditions are met) [solution = hardware interrupt runs ISR where I turn the lights on]
- Duration of LED flash should be highly consistent. [solution = use a timer]
Logic pseudo-code
Actual code
My use-case is a film scanner. Film is constantly moving and, upon detecting one of the holes at the edges, I need to flash LEDs and take a picture to capture the film frame. In this use-case, the timing of each exposure should be as precise as possible. Checking elapsed micros in the main loop reduces my "clock" resolution to the time it takes the loop to complete. I tried the solution below...but couldn't get it to behave as expected. I suspect my shallow knowledge of timers and interrupts is preventing me from seeing a better option.
Requirements
- LEDs should turn on as soon as a hole is detected (and other logic conditions are met) [solution = hardware interrupt runs ISR where I turn the lights on]
- Duration of LED flash should be highly consistent. [solution = use a timer]
Logic pseudo-code
Code:
// On hole detection (rising edge)...
// Check hole counter (some types of film have one hole per frame, others four, so you don't always take a picture here)
// If value of hole counter is less than the number of holes per frame, increment it
// If equal (or greater), turn on lights, start timer
//
// When timer is done...
// Turn off lights, reset counter
Actual code
C++:
// NOTE: a button is used to simulate high/low signals from the hole sensor,
// and a standard LED is used in place of the full-power LED driver.
#include <TimerOne.h>
const int holeInterruptPin = 2;
volatile int holeCounter = 0;
const int holesPerFrame = 4;
const int LEDpin = 5;
void holeDetected(void) {
if (holeCounter < holesPerFrame) {
holeCounter = holeCounter +1;
} else {
digitalWrite(LEDpin, HIGH);
Timer1.start();
}
}
void LEDoff(void) {
digitalWrite(LEDpin, LOW);
holeCounter = 0;
Timer1.stop();
}
void setup() {
pinMode(LEDpin, OUTPUT);
attachInterrupt(digitalPinToInterrupt(holeInterruptPin), holeDetected, RISING);
Timer1.initialize(3000000);
Timer1.attachInterrupt(LEDoff);
Timer1.stop();
}
void loop() {
delay(10); // could be causing issues? But same result without this.
}