У меня тоже ноль сети соединен с минусом питания, поэтому я не заморачивайся с лишними опторазвязками. Если ноль сети соединен с минусом питания, то зерокросс на тиньках прекрасно ловится через резистор на 1-2 мегаома, подключенного напрямую к пину прерывания. Такой вариант подсмотрел в атмеловсктх аппноутах. Кроме того, соединение минуса с нулем позволяет организовать бестрансформаторное питание, что я и сделал по принципу РМ-2.
Для измерения мгновенного напряжения сначала парился, потом перестал. Тоже измеряю только положительную полуволну. Подключил выходной контакт ТЭНа к входу АЦП через делитель, одно из плеч которого - мегаом, второе - с подстроечкиком, килоом 15. Параметры делителя настраиваю так, чтобы даже при экстремально повышенном напряжении сети на вход АЦП приходило не больше 2.5 вольт, так как для опоры использовал 431-й стабилизатор 2.54 вольта.По зерокроссу обнуляю счётчик суммы, делаю прерывания по таймеру 200 с чем-то раз за период. В каждом прерывании измеряю напругу, возвожу в квадрат и прибавляю к сумме. При очередном зерокроссе делю полученную сумму квадратов на количество придавленных за период значений, то есть строго по классике. Корень из суммы не извлекаю, поэтому полученное значение пропорционально не напряжению , а мощности. Сравнение вычисленной мощности с заданной обрабатываю аналогично м16. Если надо сделать больше, не важно на сколько, запускаю симистор на один тик таймера раньше, если меньше, то позже. Таймер тот-же, который разбивает период на части для замера напруги. Несмотря на то, что минус питания сидит на нуле сети, "поджигаю" симистор через 3023-ю моську. Просто привык. Хотя в другом устройстве делал запуск симистора напрямую с ножки тиньки, все работает.Главный недостаток схемы - постоянная и непрерывная занятость устройсива в прерываниях чаще 20000 раз в секунду. А при общении с датчиками температуры прерывания приходится запрещать. Поэтому раз в 6 секунд управление симистором прекращается на 2 периода. Если настроенная мощность меньше 50%, симистор на эти два периода оставляется закрытым, если больше 50% , открытым. Это вызывает незначительное мерцание, которое из нескольких сотен пользователей заметил только один, вернее не он сам, а его соседка на той-же фазе.