Como o pessoal já respondeu, vou deixar minha sugestão caso queira usar :)
Retificar o sinal AC e clampar p/ 5 volts. Ou seja, sempre que o sinal for positivo, dá ~5V num ponto, quando negativo dá 0V. Não importa se é exatamente quando o sinal cruza de - pra +. O que importa é que em cada período sempre aconteça no mesmo momento.
Ligue esse ponto em uma das entradas com interrupção do Atmega e programe pra sempre que ir pra 5V executar o seguinte código:
void Interrupção() {
T = valor do timer;
Reseta o valor do timer;
Freq = 16.000.000 / T; // trocar o 16 se usar um cristal diferente de 16Mhz.
qq coisa mais...
}Usar interrupção é crucial pra seja preciso, já que o código é executado no exato momento do evento.
Também é importante que o valor seja resetado sempre no mesmo momento, nesse caso 2 instruções após a interrupção. Então não pode adicionar uma instrução com tempo variável antes de resetar o timer, por exemplo fazer um analogRead() que o tempo é variável.
O ideal é resetar o timer logo que o sinal chegar, como é feito no exemplo.
Abraços,
Maurício Féo Rivello
engenheirando.com