THX @ec2021 for the sketch and the wokwi demo.
I have used the same idea a few times. When there is a non-blocking resource-light sketch, one can stand up a testing functionality that produces inputs to test the main problem the sketch is hoping to solve. And maybe even reads outputs for verification.
IRL I have used a second Arduino board to do the same. So far, the wokwi makes using two Arduino boards difficult, and I haven't checked back since someone said it's not too bad. When I looked it didn't seem well-supported. So in the simulator, I just run the second sketch along side as was done here.
IDK if it is a terribly important technique, but it is a great deal of fun.
I had my own ideas about the main problem; I won't share my solution. I will say it was a bit more of a challenge than I first thought, partly because I tend to write before enough thinking has been done. Then I get late, and it's tired and hacking deserves all the criticism it garners. 
I like that the pulse simulation includes some random variations. I rearranged things so that the simulated pulse code was separate - the only connection between the solution code and the pulse generator were calls to a setup() and loop(), and one wire grabbing the pulse off the LED. Maybe it is so in the original - my first step was to understand just enough to rip the beating heart isolate and understand the pulse generation, so I wasn't paying too much attention.
Thorough testing was not easy even with the sidecar which was the pulse simulator. A stubborn flaw led me to wonder whether IRL one might want to count off a few pulses all of a same long (or short) nature before making any conclusion.
And just switching the pulse electrically made me look closer - I had to add some logic (I thought) to ignore narrow fractional pulses. When I found my real issues, I removed that and could not seem to switch the input on in such a manner as to present a spurious input to my algorithm.
Things like that bother me. So in a real deployment, I'd hate to see it go from missing pulses (unknown) to short detected and then stable reporting of long detection, and it would be unfortunate to make the higher level use of the detector account for that itself. Hence the counting off idea. At the expense of delaying the report.
All for a simple enough problem; one can see how any kind of real program could make testing and verification very difficult.
Here's the sketch with my logic removed, an blank page where one can write a solution in any way she desires.
// I used @ec2021's hardware and moved any code I repurposed "below the fold"
//
// here an empty-ish sketch that just echoes the pulse generator
/*
Forum: https://forum.arduino.cc/t/convert-led-into-a-digital-signal/1380846
Wokwi: https://wokwi.com/projects/430758590508506113
Example how to measure a blink rate non-blocking
ec2021
2025/05/12
*/
const byte optoInput = 27; // the input from the monitored LED
const byte optoTellTale = 26; // diagnostic: just follows the opto input
void setup() {
// setup for @ec2021
setupSimulatedPulse();
// rest of setup is for the detector
pinMode(optoInput, INPUT_PULLUP);
pinMode(optoTellTale, OUTPUT);
}
unsigned long lastPulseTime; // the "alive" timer, time of last rising edge
void loop() {
// service @ec2021
loopSimulatedPulse();
// rest of loop is for the detector
digitalWrite(optoTellTale, digitalRead(optoInput));
}
//
// turtles from here on down. Just makes the pulse on pin 17
//
constexpr byte blinkOut {17};
constexpr byte switchPin {12};
// constexpr byte blinkIn {5};
constexpr unsigned long connectRate {500};
constexpr unsigned long disconnectRate {250};
constexpr long tolerance {25};
void blink() {
static unsigned long lastBlink = 0;
static byte state = LOW;
static long diff = 0;
unsigned long blinkRate = digitalRead(switchPin) == LOW ? connectRate : disconnectRate;
if (millis() - lastBlink >= blinkRate + diff) {
diff = random(-tolerance / 2, tolerance / 2);
lastBlink = millis();
state = !state;
digitalWrite(blinkOut, state);
}
}
void setupSimulatedPulse()
{
pinMode(blinkOut, OUTPUT);
pinMode(switchPin, INPUT_PULLUP);
}
void loopSimulatedPulse()
{
blink();
}
a7