Ayuda calcular desfase y factor de potencia (FP).

Hola, requiero medir el desfase entre una señal de voltaje y corriente (que mediremos indirectamente mediante la tensión que cae en un resistor), de una carga conectada a la línea (120V - 60Hz). Tenemos un detector de cruce por cero, con un LM339, que nos arroja una señal cuadrada (0V - 5V) para ambas señales.

Éste es mi código:

#include <avr/interrupt.h>
#include <avr/io.h>
// seleccionar entradas digitales para sensar flancos V e I
int V = 2;
int I = 4;
// contadores flancos
unsigned long ContV;
unsigned long ContI;
unsigned long Cont; //Guardar la diferencia de contadores para Theta
// estados Anterior y Actual
int vAnt;
int vAct;
int iAnt;
int iAct;
// señales para calcular FP
unsigned long Theta;
unsigned long FP;
void setup()
{
** Serial.begin(9600);**
** pinMode( V, INPUT );**
** pinMode( I, INPUT );**

}
void loop()
{
** //comenzar contadores V e I ← Flanco Subida**
** vAct = digitalRead(V);**
** iAct = digitalRead(I);**
if (vAct == HIGH && vAnt == LOW)
{
** ContV = micros();**
** Serial.println( “FlancoV” );**
}
vAnt = vAct;
if (vAct == HIGH && vAnt == HIGH)
{
** if ( iAct == HIGH && iAnt == LOW )**
** {**
** ContI = micros();**
** Serial.println( “FlancoI” );**
** void Desfase();**
** }**
}
}
void Desfase()
{
** Cont = ContI - ContV;**
** Serial.println( “cont” + Cont );**
__ Theta = ( 360 * Cont ) / 16666;__
** FP = ( cos( Theta ) );**
** Serial.println( FP );**
** void ReIni();**

}
void ReIni()
{
** ContV = 0;**
** ContI = 0;**
** Cont = 0;**
** delay(10000);**
}

como el periodo de la señal es 16,667ms, he preferido usar micros() para los cálculos.

El problema es que sólamente en la salida serial me dice que mide el flanco de subida del voltaje (Serial.println( “FlancoV” ):wink: y yo nocesito que me muestre FP (FP = ( cos( Theta ) );).

¿Qué me recomiendan? Gracias

Medir cosas que ocurren mas rápidamente que 8.33 mseg que corresponde a un semiperíodo con un código como el que presentas me parece incorrecto.
Debes usar un código basado en interrupciones.
Ahora para tener una idea puede servir pero mira el código de Nick Gammon para medir duty cycle. buscalo asi.
Justamente hace unos dias alguien tuvo un problema similar asi que si buscas yo puse en su respuesta el enlace de ese código o lo buscas como te he indicado.
O sea, tienes un detector de cruce por cero para la tensión y otro asociado a una R en serie con la carga que da otro cruce por cero de la corriente.
Yo conectaría una salida al Pin2 INT0 y la otra al Pin3 INT1.
Uno arranca y el otro cierra la cuenta. Usando un timer. Mira el ejemplo y obtendrás gran precisión.

En tu caso, usas

vAct = digitalRead(V);
iAct = digitalRead(I);

y luego una serie de instrucciones pierdes muchos microsegundos en cada loop, no se cuantos pero son muchos. Supongamos 50 useg.
En cambio un par de interrupciones disparadas, no pierden practicamente nada de ninguno de los eventos.
Pero esta es una discusión de la precisión de la lectura. Tu preguntas otra cosa.
Ahora miro el resto y edito esta respuesta.