I am tuning some old code for zero-crossing detection, but as I'm stripping the code down things make little sense.
this is my circuit on the breadboard:
do you see it? like there is almost a pattern in there: what was missing in previous half period gets counted in in the next one... it's not exact but sort of like
Put a fullwave bridge rectifier between the transformer secondary and the opto, that way only one of the LEDs will be used but on both positive and negative voltage excursions.
No the H11AA1 is fine.
The difference is minuscule.
10000-9988 = 12usec
10000/12 = 833
180 degrees / 833 = 0.22 degrees. Such a small error will absolutely make no difference in a 50Hz phase cut circuit.
That your two current limiting resistors of 330 ohms each could be higher value and push less current through the LED and the hole thing would still work fine.
Check the data sheet and figure out a proper good enough current, I'm sure the little teeny LEDs in the opto would appreciate it.
Record the value of micros() in your ISR. Now you only set a flag, that zc happened, but it takes some time until that flag is read in loop() as in between iterations of loop() the ESP is doing other things, such as updating micros() and millis() and checking it's WiFi and whatnot. The time that takes may vary.
Also there's no need to detach and attach the interrupt all the time.
Very interesting, considering there is nothing that can possibly bounce. There's nothing mechanical involved that bounces. Do have a look at the signal you're getting though a scope. I'm curious what could possible cause such behaviour. I've never seen it before, and I have done zero crossing detection in various ways, and also done other signals through optocouplers. No "bounce" issues, ever.
Try a stronger external pull-up, something like 1k or 2k2. That should also improve the waveform on the output, especially considering you drive that opto VERY hard.
That are no doubt the "absolute maximum" ratings. Normal is 1.2V drop for an IR LED. A current of around 5 mA is enough for an optocoupler, and makes for a much happier and longer living LED. In that case you can also use a weaker pull-up, the internal pull-up of the pin is probably enough already.
bounce here means, re-triggering.
in opposite to what you saying I found people recommending stronger pull-up resistore. maybe because it is easier to ground it (ehm, very roughtly)
I don't think the interrupt inputs on an ESP32 are Schmidt trigger like they are on some Atmel chips so there could be some glitching from the slow transition of a sine wave.
The data sheet uses an I(F) of 0.010A on all of its graphs so I would think that more appropriate than 0.060A. Also a collector resistor of 10k would insure staying well within the recommended specs as 100k is at the max end.
I would do a quick test with a Schmidt trigger logic gate on the opto output as well.
They're in series, either way, even though they're at opposite ends.
Inasmuch, it's approx. 24vac / (330 + 330)
(I don't understand what it is with n00bs and forcing max current through LEDs.)
It's hard to tell from your scope traces but it looks like you don't always return to the minimum logic high level (0.7 * 3.3V ) when your opt turns off. I think if you reduce the forward current on the LED and use a stronger pull-up resistor that will change.
When I did zero-crossing (a million years ago) I used a half-wave rectifier and I just found the positive-going zero-crossings. If you find the positive-going and you know the line frequency, you know exactly when the next one is coming.
I also used a transformer for isolation so I didn't use an opto-isolator. I don't remember what I did for over-voltage protection, which is "automatically" taken care of by the opto-isolator.
Assuming you are using a TRIAC in a dimmer application, a little bounce/re-trigger isn't a problem because a TRIAC latches-on until current drops to zero (at the next zero crossing). If you get noise and it triggers too-soon, that can be a problem.
I actually triggered somewhere between zero and 90 degrees, and then calculated the true zero-crossing. (That required some trial-and-error calibration.)