arduino-cruce-por-cero-h11aa1

Detector de cruce por cero con Arduino y optoacoplador H11AA1

¿Qué es un H11AA1?

El H11AA1 es un detector de cruce por cero (zero crossing), un dispositivo que emite un pulso cuando una señal de tensión pasa por 0V. Por supuesto, podemos conectar un detector de paso por cero a un procesador como Arduino.

Cuando trabajamos con corriente alterna, como la red de distribución (230V 50Hz), en muchas ocasiones resulta interesante detectar el instante en el que la tensión atraviesa el punto cero. Así, por ejemplo, resulta una forma sencilla de medir la frecuencia de red. También es posible rectificar el desfase angular introducido por transformadores empleados al realizar la medición de la tensión.

Otro uso frecuente es determinar el momento para conmutar una carga, por ejemplo, mediantes un relé o un relé de estado sólido. Las cargas deberían ser conectadas y desconectadas únicamente cuando la tensión atraviesa el cero en sentido ascendente. De lo contrario estaríamos realizando la conexión con la carga en tensión lo que provoca la generación de armónicos y, posiblemente, la reducción de la vida útil de los componentes.

Los detectores de paso por cero como el H11AA1 también son necesarios para realizar una regulación de potencia (dimmer) con un SSR, por ejemplo, para regular la intensidad de la luz de una bombilla o la velocidad de giro de un motor. Es necesario sincronizar la señal de disparo del SSR con la frecuencia de red, o y aplicar un desfase temporal entre el paso por cero y el disparo, o provocaremos parpadeos en la carga.

Industrialmente, los detectores de paso por cero son ampliamente utilizados en aplicaciones que funcionan con corriente alterna, tanto para realizar mediciones como para realizar acciones. También son componentes habituales en aplicaciones de sonido y sistemas de comunicación.

Nosotros podemos emplearlo en nuestros proyectos, por ejemplo, para medición de la frecuencia de red distribución eléctrica, medición de tensión junto con un transformador, monitorización de consumos, para mejorar el comportamiento de la conmutación de un relé, o para realizar un dimmer con un relé de estado sólido.

Precio

Los detectores de paso por cero como el H11AA1 son dispositivos muy baratos. Podemos encontrarlos por 0.25€ en vendedores internacionales de eBay o AliExpress.

arduino-zero-crossing-h11aa1-componente

¿Cómo funciona el H11AA1?

En la entrada usar un optoacoplador con Arduino vimos de forma extensa estos dispositivos que permiten transmitir información de un circuito a otro empleando luz, manteniendo el aislamiento galvánico entre circuitos. Ya entonces adelantamos que existían diversos tipos de optoacopladores, con más usos.

El H11AA1 es un optoacoplador bidireccional, compuesto por dos LED de GaAr junto con un fototransistor NPN en un único integrado DIP de 6 pins. Cuando cualquiera de dos LED emite luz, el fototransistor está en conducción. Únicamente estará en corte cuando ambos LED estén apagados.

Por tanto, el H11AA1 nos permite conectar una corriente alterna en el principio primario. El secundario se comportará como un interruptor cerrado excepto cuando la tensión en el primario inferior a una tensión próxima a 0V, que se comportará como interruptor abierto.

arduino-zero-crossing-h11aa1-curvas

Combinado con el H11AA1 con una resistencia de Pull-Up podemos generar un pulso cuando la tensión del primario sea cercana a 0V lo que nos permite, entre otras cosas, detectar cuando una tensión alterna pasa del semiperiodo negativo al positivo.

Esquema de montaje

El esquema de montaje es muy sencillo. Por un lado, conectamos la señal en la que queremos detectar los pasos por cero a los terminales A/C y C/A, que controlan los LED del optoacoplador. Deberemos añadir en serie resistencias que limiten la corriente que atraviesa los LED.

Deberemos ajustar el valor de estas resistencias a le tensión que estemos empleando. Vimos como calcular este valor en la entrada Conectar un LED con Arduino. Por ejemplo, para una tensión de 230VAC podemos usar una resistencia de entre 22K-47K de 2W.

Por otro lado, conectamos el secundario a una entrada digital cualquiera de Arduino. Si empleamos la resistencia interna de Pull-Up, no necesitaremos ningún componente adicional para conectar el secundario a Arduino.

arduino-zero-crossing-h11aa1-esquema

Podemos usar cualquier entrada digital pero en la mayoría de los casos querremos emplear una interrupción para realizar la detección. La conexión, vista desde Arduino, sería la siguiente.

arduino-zero-crossing-h11aa1-interrupcion

Ejemplos de código

Lectura del estado por pool

En el primer ejemplo, aprendemos a leer el estado del H11AA1 con las entradas digitales de Arduino, como si fuera un pulsador.

const int inputPin = 2;
 
int value = 0;
 
void setup() {
  Serial.begin(9600);
  pinMode(inputPin, INPUT_PULLUP);
}
 
void loop(){
  value = digitalRead(inputPin);  //lectura digital de pin
 
  //mandar mensaje a puerto serie en función del valor leido
  if (value == HIGH) {
      Serial.println("Encendido");
  }
  else {
      Serial.println("Apagado");
  }
  delay(1000);
}

Medir la frecuencia con interrupción

En este ejemplo, realizamos la lectura del H11AA1 con el uso de interrupciones, y medimos la frecuencia entre pulsos.

// period of pulse accumulation and serial output, milliseconds
const int inputPin = 2;
const int MainPeriod = 100;
long previousMillis = 0; // will store last time of the cycle end

volatile unsigned long previousMicros=0;
volatile unsigned long duration=0; // accumulates pulse width
volatile unsigned int pulsecount=0;

// interrupt handler
void freqCounterCallback() 
{
  unsigned long currentMicros = micros();
  duration += currentMicros - previousMicros;
  previousMicros = currentMicros;
  pulsecount++;
}

void reportFrequency()
{
    float freq = 1e6 / float(duration) * (float)pulsecount;
    Serial.print("Frec:");
    Serial.print(freq);
    Serial.println(" Hz"); 

     // clear counters
    duration = 0;
    pulsecount = 0;
}

void setup()
{
  Serial.begin(19200); 
  pinMode(inputPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(inputPin), freqCounterCallback, RISING);
}

void loop()
{
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= MainPeriod) 
  {
    previousMillis = currentMillis;    
    reportFrequency();
  }
}

Descarga el código

Todo el código de esta entrada está disponible para su descarga en Github. github-full