If your sketch can't keep up, you could always try moving to a country with 50 Hz electricity. Like, for example, New Zealand. Or one half of Japan ( I forget which half ).
QuotetickCounter += TIMER_CYCLE_COUNT; You are chasing a wrong direction here, I think. You should want to redefined a "tick" so that tick = CycleTime/BrightnessLevels (or, for 8.3ms and 256 brightness levels, about 32 us.) That means that the clock always ticks by 1 in your ISR. The actual clock or instruction rate of the cpu ought to be irrelevant. Sure, at some level it's the limiting factor, but you want to have your code running in a way that it's so much faster than the problem, that there's no actual dependency...Looking at the code generated when tick and powerDelay are both uint8_t, it looks to be about 480 instructions. 32 us is about 512 instructions. Now, every ISR execution doesn't execute all the instructions, and all the instructions are not one cycle, so it's hard to tell whether this would actually be fast enough. It does indicate (to me) a couple of things:1) It would be pretty close; certainly close enough to worry about.2) wider math (32bit tick and powerDelay) probably isn't going to work at all. (1100 instructions! (odd that it isn't more.))3) going to, say, 100 ticks/halfcycle instead of 256 ticks/halfcycle, would probably give you all the breathing room you need.
tickCounter += TIMER_CYCLE_COUNT;
Similarly, since serial messages are only occasional and not more than every 50ms, while AC cycles happen every 1/120 s (8.3ms),get rid your calculations of powerDelay in ZeroCrossDetected and move them into the serial receive code.
You can. You shouldn't. It won't make any difference...In each ISR each element of powerDelay is accessed just once (read in one ISR; written in the other). Removing volatile only helps when there are multiple accesses. Removing volatile eliminates redundant loads from memory but there aren't any.
This would get better if powerDelay isn't volatile, and if it's smaller, but it still doesn't need to happen every half-cycle.Or you could look at making the copy into a memcpy() call, which would "short circuit" the (correct) volatile declarations.
Working?! Already! Excellent!I was fun to help with a well-defined, well-expressed problem with existing well-commented code, and someone who was responsive to the suggestions made. MUCH better than all the "Is a MEGA too slow to handle 32 channels of dimming? Do I need a Due?" questions that result in an extended "discussion" of 8 vs 32 bit cpus, during which the original poster disappears...
Most interesting is that they seem to be leaking enough power to dimly light a string of LEDs. It isn't a code problem, there is definitely power leaking through the relays. You don't notice it until you connect a string of LEDs, incandescent lights don't have the issue. I wonder if replacing the relays with random cross relays is showing a flaw in the sainsmart board design.