Hi everyone, I am fairly new to Arduino. I am using an Arduino Uno to digitalRead from two photodiodes. The photodiodes are usually high, and they go low when triggered. I am expecting the time between one photodiode going low and the second going low to be 68 millisec (confirmed with oscilloscope). However, the Arduino is telling me that the time difference between the two going low is 8 microsec. I believe the sampling rate is high enough to get an accurate read, so I am not sure why this is happening. My code is below. Any help would be appreciated!
// Define the pin numbers
const int photodiode1Pin = 9;
const int photodiode2Pin = 8;
int pd1 = 0;
unsigned long time1 = 0;
int pd2 = 0;
unsigned long time2 = 0;
void setup() {
// Initialize the serial communication
Serial.begin(9600);
// Set the photodiode pins as inputs
pinMode(photodiode1Pin, INPUT);
pinMode(photodiode2Pin, INPUT);
}
void loop() {
// Wait until the first photodiode goes low
while (digitalRead(photodiode1Pin) != LOW) {
// Do nothing, just wait
}
time1 = micros(); // Capture the time when the first photodiode goes low
// Wait until the second photodiode goes low
while (digitalRead(photodiode2Pin) != LOW) {
// Do nothing, just wait
}
time2 = micros(); // Capture the time when the second photodiode goes low
// Calculate and print the time difference
unsigned long timeDifference = time2 - time1;
Serial.print("Time between inputs going low: ");
Serial.print(timeDifference);
Serial.println(" microseconds");
}
If your program is only dealing with microseconds, why do you think it should be using milliseconds? But do you understand the microseconds roll over after a certain time? If you want milliseconds, you need to use milliseconds.
If both pins are already LOW when loop() begins, then you will get a very small difference between time1 & time2. Maybe your code should wait until both pins are high before waiting for them to change to LOW?
This is too slow, it will take several milliseconds to print all the characters. Probably more than 50ms.
Change it to: Serial.begin(115200);
and print less characters, just the number.
But there should be some other problem. How the signals look in the oscilloscope? are they clean? how long they stay low and how long high?
Maybe you could wait until both signals are high to start measuring.
Schematic? It may seem unnecessary, but then, we don't know what's wrong, do we?
edit - never mind, if the scope says it's real it's real.
It's a pretty simple test to wait for a double high, so why not do it and see?
Thanks for the idea, but changing the baud rate did not work - I am still seeing 8 microsec. The signals on the oscilloscope are clean. They are low for 160 millisec and high for 1.6 sec. I don't understand how waiting until both signals are high would improve this. Can you explain?
I apologize, I don't quite understand why a double high would be helpful in this case. If I am waiting for a low in my while loops, I am in essence at a double high right?
Because: 'interrupt is always better'... more seriously because interrupts are asyncronous, are called when event occur.
In your example in the main loop you have two while cycles that block the execution of the main loop.
This is ok for this simple example but it will not work ( or it will complicate things ) as soon you will add new functionalities: for example reading a button..
It is generally a good idea having a main loop... that loops ( without long delays ), not blocking.
// Define the pin numbers
const int photodiode1Pin = 9;
const int photodiode2Pin = 8;
int pd1 = 0;
unsigned long time1 = 0;
int pd2 = 0;
unsigned long time2 = 0;
void setup() {
// Initialize the serial communication
Serial.begin(115200);
// Set the photodiode pins as inputs
pinMode(photodiode1Pin, INPUT_PULLUP);
pinMode(photodiode2Pin, INPUT_PULLUP);
}
void loop() {
// Check for the first photodiode going low
byte r1 = digitalRead(photodiode1Pin);
static byte r1prev;
if (r1 == LOW and r1prev == HIGH) {
time1 = micros(); // Capture the time when the first photodiode goes low
}
r1prev = r1;
// Check for the second photodiode going low
byte r2 = digitalRead(photodiode2Pin);
static byte r2prev;
if (r2 == LOW and r2prev == HIGH) {
time2 = micros(); // Capture the time when the second photodiode goes low
// Calculate and print the time difference
unsigned long timeDifference = time2 - time1;
Serial.print("Time between inputs going low: ");
Serial.print(timeDifference);
Serial.println(" microseconds");
}
r2prev = r2;
}
Because 8µs of difference looks like both signals are low when you measure it. Just to try something and see if there is any effect.
Could be that the pins are reversed? As they are low during 160ms, if you are detecting first the second pin going low, the other one would be still low by then, so both would be low at the same time.
Just a possibility.
Don't apologize. The thing is, none of us knows your setup as well as you. You also have blind spots, because otherwise, you'd not be here asking what's wrong. So, sometimes, we ask for things that aren't necessarily solutions, but which may shed light into the dark corners of your setup.
It's okay if you don't oblige, but sometimes, it's easier to just fill in that blank than to fight about it. You're not going there, and I'm done. Best of luck.
The oscilloscope measurement records a delay of 16.67ms.
The Arduino reports a delay time of 16660µs or 16.66ms.
The oscilloscope and Arduino closely agree.
But see what happens next (look at the serial monitor timestamps).
Next time round loop because both inputs are already low you go straight through the two while loops, and immediately take another measurement, which is recorded as either 4µs or 8µs.
This continues as long as the two signals remain low.
Then we get another correct reading approximately 2s later, after the signals have been high, and do a high to low transition.
This is followed by another stream of erroneous measurements.