Hello! First time caller, long time listener.
I am building a shutter speed tester using an Arduino Uno R3, 20x4 LCD, a KY-008 laser, and a DS18B20 (ISO203) laser sensor. I know shutter speed testers have been made by oodles of people before, but mine is a bit different. I have a switch to enable the timing process. I think of it as a faux-menu.
See my circuit below.
My problem right now is I can't figure out how to get the Arduino to calculate the amount of time the sensor reads HIGH (or 1). I have been searching posts and tinkering with code for the past 2 months, and cannot figure out how to get what I want. Currently, it automatically starts calculating the variables I have.
My code is below. I do have it printing results via Serial for debugging purposes. Eventually, I plan to have the final product able to be used by itself and print results on the LCD.
THE CODE:
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
//variables that will change are below
int Fired = 0; //when Fired = 1, that means the shutter has opened and closed. This is reset to 0 once the time has been calculated and shown on screen.
int lastSensorState = 0;
int RisingFlag = 0;
int FallingFlag = 0;
unsigned long Start;
unsigned long Stop;
//variables that will NOT change are below
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 20, 4);
const int STATUSLED = 13;
#define SENSOR 2 //pin 2 is the laser sensor
#define LASER 8 //pin 8 is the laser emitter
void setup() //This part of the program is run exactly once on boot
{
Serial.begin(9600); //opens a serial connection.
lcd.init();
lcd.backlight();
pinMode(STATUSLED, OUTPUT); //initialize the status LED as an output:
pinMode(LASER, INPUT); //initialize the laser as an input.
pinMode(SENSOR, INPUT); //initialize the sensor as an input.
lcd.setCursor(0,0);
lcd.print("Shutter Tester");
delay(750);
digitalWrite(STATUSLED,1);
lcd.setCursor(0,1);
lcd.print("V:1.3 | JMC2021");
delay(1500);
digitalWrite(STATUSLED,0);
delay(1000);
lcd.clear();
}
void loop() // this part of the program is run, over and over again
{
lcd.setCursor(0,0);
lcd.print("Press Start");
lcd.setCursor(0,1);
lcd.print("to enable. ");
int enabled = digitalRead(LASER);
while(enabled == 1)
{
digitalWrite(STATUSLED, 1);
lastSensorState = 0;
RUN();
}
}
void RUN()
{
int enabled = digitalRead(LASER);
int sensorState = digitalRead(SENSOR); //sensorState is based off of what pin 2 is reading. When starting, pin 2 should be LOW since the shutter is in blocking the laser.
int RisingFlag = 0;
int FallingFlag = 0;
while(enabled == 0)
{
digitalWrite(STATUSLED, 0);
loop();
}
if(sensorState = 0 && (lastSensorState == 0))
{
lcd.setCursor(0,0);
lcd.print("Enabled! ");
lcd.setCursor(0,1);
lcd.print("Fire Shutter! ");
}
if(sensorState = 1 && (lastSensorState == 0))
{
RisingFlag = 1;
lastSensorState = 1;
}
if(sensorState == 0 && (lastSensorState == 1))
{
FallingFlag = 1;
}
if(RisingFlag = 1)
{
Start = micros();
RisingFlag = 0;
lastSensorState = 1;
}
if(FallingFlag = 1)
{
Stop = micros();
FallingFlag = 0;
lastSensorState = 0;
Fired = 1;
}
if(Fired == 1)
{
lcd.clear();
long Speed = (Stop - Start);
Serial.print("Start: ");
Serial.println(Start);
Serial.print("Stop: ");
Serial.println(Stop);
Serial.print("Micros: ");
Serial.println(Speed);
float SS = (float)Speed/1000000;
float SS2 = 1/SS;
Serial.print("shutter speed: ");
if (SS2 < 1) // if SS is shorter than 1 second, it will be shown as such.
{
Serial.println("1/" + String(1/SS) + "s");
lcd.setCursor(0,0);
lcd.print("Shutr: 1/" + String(1/SS) + "s");
lcd.setCursor(0,1);
lcd.println(Speed);
lcd.setCursor(0,2);
lcd.println(SS );
lcd.setCursor(8,2);
lcd.println(SS2 );
}
else //if SS is 1 second or longer, it will display in full seconds.
{
Serial.println(String(SS) + "s");
lcd.setCursor(0,0);
lcd.print("Shutr2 " + String(SS) + "s");
lcd.setCursor(0,1);
lcd.println(Speed);
lcd.setCursor(0,2);
lcd.println(SS );
lcd.setCursor(8,2);
lcd.println(SS2 );
}
Serial.println(SS);
Serial.println(SS2);
Serial.println();
lcd.println();
Start = 0;
Stop = 0;
Fired = 0;
RisingFlag = 0;
FallingFlag = 0;
delay(2000);
lcd.clear();
lcd.print("FINISHED");
delay(1000);
lastSensorState = 0;
}
}
I know it's not perfect, but with this being my first Arduino project, it's bound to have a few flaws.
The current result I am getting is as soon as I turn the switch on to activate RUN( );, the program immediately calculates SS2, even without me directing light to the sensor.
I just added the three "if" statements to the beginning of RUN() tonight. Originally, I had it only triggering by sensorState, but I was still having difficulty getting it to calculate how much time the sensor was triggered for.
I need a fresh set of eyes on this to see just how many things I'm doing wrong... or if this project is even feasible.
Maybe it's just nonsensical to have a switch to enable the timing process, but I just don't want the screen running on and on with results as I'm fumbling with my cameras or setting it up.
My circuit diagram is below. I can take a picture of my actual setup, but this diagram is exactly what I'm dealing with.
Thoughts?