Thanks for all the replies :). I used olikraus' solution, and it now works, but inconsistently. It works sometimes, but other times it misses the beam break or only one of them triggers. Is there a way to make it even faster? My modified code is below:
#include <U8glib.h>
// Pins
extern const int PHOTOGATE_1_PIN = 7; //D7
extern const int PHOTOGATE_2_PIN = 4; //D4
// Distance between photogates in meters and feet
const float DIST_METERS = 0.055;
const float DIST_FEET = 0.1804;
// Phase of detection
int phase = 0;
/*
* Phase 0 = Idle
* Phase 1 = First IR Beam Broken
* Phase 2 = Second IR Beam Broken
*/
// Time photogates are broken in milliseconds
long unsigned int timeFirstBroken = 0;
long unsigned int timeSecondBroken = 0;
// Speed in Meters per Second and Feet per Second respectivly
float speedMS;
float speedFPS;
// State of each photogate (true = broken, false = not broken)
bool photogate1 = false;
bool photogate2 = false;
// Previous values of photogates
bool photogate1Prev = false;
bool photogate2Prev = false;
/* SLboat Add Device */
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_FAST); // I2C 128x64(col2-col129) SH1106,Like HeiTec 1.3' I2C OLED
void u8g_prepare(void) {
// Set font
u8g.setFont(u8g_font_helvB10);
}
// Draws two strings displaying the status of each of the two photogates, used for debug purposes
void drawPhotogateStatus()
{
// Prepare the strings to be drawn
String val;
String val1;
if(digitalRead(PHOTOGATE_1_PIN) == HIGH)
val = "true";
else
val = "false";
if(digitalRead(PHOTOGATE_2_PIN) == HIGH)
val1 = "true";
else
val1 = "false";
String str1 = "Photogate 1: " + val;
String str2 = "Photogate 2: " + val1;
// Draw the strings
u8g.drawStr(0, 30, str1.c_str());
u8g.drawStr(0, 60, str2.c_str());
}
// Draws the chronograph
void drawChronograph()
{
// Set up each string
String strMS = String(speedMS) + "m/s";
String strFPS = String(speedFPS) + "f/s";
// Set the font
u8g.setFont(u8g_font_helvB12);
// Draw strings
if(speedMS != 0)
{
u8g.drawStr(0, 30, strMS.c_str());
u8g.drawStr(0, 60, strFPS.c_str());
}
else
u8g.drawStr(0, 45, "Ready");
}
// Calculates the velocity
void getVelocityBetweenGates(long unsigned int t1, long unsigned int t2)
{
//Get time between beam breaks
float t = float(t2 - t1);
//Convert to seconds
t = t * 0.001;
//Find speed with v=d/t
speedMS = DIST_METERS/t;
speedFPS = DIST_FEET/t;
}
//Fast Loop
void fastLoop()
{
// Store current photogate values
photogate1 = digitalRead(PHOTOGATE_1_PIN);
photogate2 = digitalRead(PHOTOGATE_2_PIN);
// Wait for first photogate to be broken, when it it, proceed to next statement
if(phase == 0 && photogate1 && photogate1 != photogate1Prev)
{
phase = 1;
// Store current time value
timeFirstBroken = millis();
}
// Wait for the second photogate to be broken, when it is, proceed to next statement
if(phase == 1 && photogate2 && photogate2 != photogate2Prev)
{
phase = 2;
// Store current time value
timeSecondBroken = millis();
}
// Calculate the velocity, then set phase to 0 to start over again
if(phase == 2)
{
getVelocityBetweenGates(timeFirstBroken, timeSecondBroken);
phase = 0;
}
//Set the previous values
setPrevTrackers();
}
// sets previous values
void setPrevTrackers()
{
photogate1Prev = digitalRead(PHOTOGATE_1_PIN) == HIGH;
photogate2Prev = digitalRead(PHOTOGATE_2_PIN) == HIGH;
}
void draw_page(void)
{
static uint8_t is_next_page = 0;
// call to first page, if required
if ( is_next_page == 0 )
{
u8g.firstPage();
is_next_page = 1;
}
// draw our screen
drawChronograph();
// call to next page
if ( u8g.nextPage() == 0 ) {
is_next_page = 0; // ensure, that first page is called
}
}
void setup(void)
{
// Display Setup
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
// Photogate 1 Setup
pinMode(PHOTOGATE_1_PIN, INPUT);
digitalWrite(PHOTOGATE_1_PIN, HIGH);
// Photogate 2 Setup
pinMode(PHOTOGATE_2_PIN, INPUT);
digitalWrite(PHOTOGATE_2_PIN, HIGH);
setPrevTrackers();
u8g.begin();
}
void loop(void)
{
fastLoop();
draw_page();
}