The design of the zero_crosss_int() ISR is unreliable. After each interrupt it unconditionally turns on the triac, even in the OFF position. Since the dimming value in that case is close to the AC cycle duration, it may miss the current cycle and turn on duringearly in the next cycle. This may happen e.g. due to noise in zero crossing input.
75 us * 128 = 9.6 ms. Assuming 50 Hz AC, cycle duration is 1000 ms / 100 = 10 ms. You only have 4% margin.
You need to avoid turning on the triac close to the end of the AC cycle. Limit the maximum value of dimming variable to, say, 75% of the AC cycle. This will impose a lower limit on the output power. However, you want to do this anyway because motors need a minimum power to start rotating. Adjust the ISR so that in the OFF position it does not send a positive pulse at all.
ADDED: so you just need to add an if statement to you ISR code:
void zero_crosss_int() // function to be fired at the zero crossing to dim the light { if (dimming > 96) // choose this value experimentally, adding some margin return; ... everything else goes here ... } ADDED2: Blocking for extended duration in the ISR is not a good idea in general. If you happen to need to do anything else in addition to 'dimming' a fan, you will almost certainly need to get rid of this. You could start a timer in the ISR and send the output pulse in the timer ISR, making sure that the timer ISR does not get executed after the next zero-crossing ISR...