Thanks to all, for the suggestions. I've spent a day experimenting with the thing, but really didn't go far.
Regarding my measurement setup - I perform measurements using 16 bit timer input capture interrupt of ATmega 328. MCU is running at 16MHz on a crystal. This is the code of the interrupt:
ISR(TIMER1_CAPT_vect){
if(HIGH == digitalRead(

){
TCNT1 = 0;
TCCR1B &= ~_BV(ICES1);
} else {
pulseLength = ICR1;
semaphore = 1;
TCCR1B |= _BV(ICES1);
}
}
As fas as I understood the variation in ZC pulse length is caused by a mains sine crossing zero at steeper or more shallow angle and this is caused by mains sine peaks being higher or lower, OR by a smaller ripple riding on the mains sine that gets aliased by sampling it at 100Hz AND this might be partially caused by mains frequency instability (is it something like 0.2%? If so, it contributes 20uS difference in period length)
I get different rise/fall times than specified in a datasheet, probably due to different input conditions, as you can see below, decreasing the value of pullup does not increase the rise time. I've checked the signal on the scope - with decreased pullup values, I get more triangle-like pulse with long edges. I've tried varying the led drive current - this shortens the pulse and decreases the amount of noise, but not significantly.
I've meda mesurements in 5 different combinations of AC mains input resistors and pullups. Below are my results. I'm very eager to hear your comments on them.
At first - just plain recording of adjacent pulse lengths.




Then the FFTs. I've used a rectangular window, so it might be showing bananas here, but anyway, some low frequency components can be noted.




In the final graph I try to show how different are lenghts of adjacent pulses.