Lectura señal AC y control generando señales de disparo.

Hola a todos,
Estoy implementando un Semi-convertidor de una fase, y estoy utilizando una técnica de controlador de modo coseno para convertidores SCR.

Por el momento me encuentro atrancado con ello, dedo de diseñar el controlador, pero no estoy muy seguro de como leer con el arduino una tensión AC y luego integrarla para obtener un coseno.

EL PD del circuito e sun detector de pico y el Z.C.D un detector de cruce por cero.
Gracias

Dejo el los links del circuito

http://www.mediafire.com/file/1mhcddqtxvd9el3/Prototipo.pdf

Detector de cruce por cero

Por alguna razón no pudiste poner las imágenes de modo que se vieran directamente en lugar de tener que tediosamente descargarlas de Mediafire? Aprecio que te tomaste el trabajo pero la próxima subelos como adjuntos a este foro con la opción disponible y en el caso de las imagenes, captura el enlace generado y luego lo usas (edita tu post) para que se vea directamente asi como haré yo a continuación.

Captura.JPG

Detector de cruce por cero


Para llevar adelante tu idea, tienes que poner el ADC en modo FREE RUN cambiando el prescaler para que trabaje mas rapido. Acabo de responder a otra persona algo similar, asi que busca en Proyectos la respuesta a DELIMITAR TIEMPOS.. PERO COMO? y verás como configurar el ADC para lograr tiempos de conversión de 110 useg suficientes para tomar muestras de la señal AC que previamente deberás desplazar en 2.5V para que el AD pueda leerla.
Te recomiendo que estudias la rutina OpenEnergy
porque calcula muy bien la tensión RMS que involucra integración al menos por lo que ambos sabemos.

Luego podras adaptarla para hacer tu calculo de coseno.
Espero te sirva esta sugerencia.

Prototipo.pdf (302 KB)

Te agradezco mucho surbyte, te cuento que no pude subir la imagen, por alguna razón inserto el enlace como imagen y no queda.

Voy a revisar todo lo que dices, de openenergy te cuento que eh visto algo y eh querido revisar la libreria q se descarga como emotx si no estoy mal, no se si exista alguna forma de ver el código interno de la libreria, si de eso es lo q hablas de revisar la rutina.

Quizas este el codigo en github?

La librería es EmonLib

Te pregunto, Sabes algo de conectar el arduino con Matlab (expresamente con Simulink) Creo q de esa forma seria mas sencillo hacer las siguientes cosas:

  1. Integral la señal de entrada AC y convertirla en Coseno.
    2.Detectar el pico de la señal.
  2. La función de comparar tambien.
  3. y el detector de cruce por cero.( o sera mas conveniente implementar el circuito de ZCD)

No se si le este exigiendo mucho al arduino, sera mas adecuado el arduino uno o el arduino mega?

Os dejo dos links informativos.

Desde ya que si me das para elegir elijo un MEGA mas rápido que el UNO.
Todo esto

  1. Integral la señal de entrada AC y convertirla en Coseno.

2.Detectar el pico de la señal.
3. La función de comparar tambien.
4. y el detector de cruce por cero.( o sera mas conveniente implementar el circuito de ZCD)

Se puede hacer con Arduino.
Dejemos el punto mas exigente el 1.
2. Es una simple comparación. Pones un valor a 0, y con cada muestra si es mayor ajustar el Vpp valor pico a pico
3. comparar que?
4. el detector va a una Interrupción y resuelves lo que debas.. poner a 0 el buffer o ya dirás.

El punto 1 requiere una suma de cuadrados mínimos. Dt x muestra en valores unsigned int y sumarlos, al final como son 128 puedes hacer el 1/N como desplazamiento de bits, lo que es dramáticamente mas veloz que hacer una división.

Te agradezco mucho tu ayuda

Subo las imágenes para explicarme.

En respuesta de comparar que?

En el diagrama de bloques necesito comparar las señales Vc y Vd,
Donde Vc = 1+Vb
Vd= 1-Vb

Donde Vb es la salida de la señal ya integrada.

Adicionalmente Valpha es un potencio-metro, para poder tener un control del voltaje.

La otra pregunta, pienso q es mas adecuado trabajar con Matlab y simulink, ya que en este programa tengo mas experiencia y se puede programar los bloques, en fin los retos serian adquirir las señales, del voltaje de entrada, crear el comparador, leer los datos del potenciomentro.

Si no me equivoco lo puedo hacer así:

analogRead('pin number')

y en matlab seria:

a.analogRead('pin number')

Gracias nuevamente.

Adelante entonces. Este como te imaginarás es un foro de Arduino.
Si pasas a otro ambiente también pasas casi con seguridad a otro foro. Pocos manejan Matlab
La interfaz Arduino Matlab esta disponible asi que, no se en que puedo ayudarte.

Gracias, voy a seguir adelante.

si necesito profundizar en algo mas acerca del arduino, volveré por acá.

Hola.
La señal coseno va retrasada 90º (pi/2 radianes) respecto del seno. Si lo que quieres es obtener la señal coseno para aplicarle un detector de picos o de paso por cero o de lo que sea, mejor hazlo sobre la señal senoidal original y luego le aplicas un retardo de 5 ms para 50Hz o de 4.16 ms para 60Hz
Por cierto, la integral del seno no es el coseno.
Espero haberte ayudado.
Saludos

ratpenat gracias,

no había pensado en aplicarle un retraso de 90°, es una muy buena idea.

Hola de nuevo, he tenido que replantear las cosas, como había dicho anteriormente estaba usando la interfaz de Simulink de matlab para programar mi proyecto, debido por problemas de ser capaz de muestrear la señal AC correctamente a través de Simulink (Es posible que unos de los inconvenientes sea el acople de impendancias), eh tomado la decisión de hacerlo de la forma convencional con el sketch de arduino.

Explico de forma resumida lo que estoy intentando hacer, y si es posible me puedan colaborar con el planteamiento del código, matematicamente entiendo muchas cosas, pero me falta mas habilidad en conocer mejor el lenguaje de programación y si me pueden orientar de algun modo lo agradeceria mucho quizas con un diagrama de flujo como se hace con el visual designer de Proteus.

  1. Planeo usar el modo Free run de mi placa arduino mega para mejorar su velocidad y su tasa de muestreo, debido que necesito muestrear la señal AC de 60Hz, ya previamente acondicionada por mi como lo explican en el circuito de openenergy adjunto el codigo y foto del circuito:
// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

// set prescale to 16
sbi(ADCSRA,ADPS2) ;
cbi(ADCSRA,ADPS1) ;
cbi(ADCSRA,ADPS0) ;


void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

1.2 Como podria realizar el código para muestrear la señal. Por el teorema de Nyquist sé que la frecuencia de muestreo debe ser por lo menos unas 5 veces la frecuencia fundamental que serían unos 60hz.

  1. Esta señal la debo integrar y multiplicarla por un menos, para esto me sugirieron usar una suma de cuadrados mínimos, mostrando estos valores en un unsignet int, para sumarlos y al final hacer 1/N, esta señal la llamare Vb.

  2. El sombreado azul en la figura 1 del diagrama de bloques equivale a hacer esta operación Vc=1+Vb, y Vd=1-Vb, quizás no sea necesario utilizar el peak detector para realizarla, ya que con solo código creo que es posible hacerlo de forma más sencilla. Ver figura 2.


Figura 1


Figura 2


Figura 3

  1. Luego estos voltajes Vc, Vb son comparados con la variable de control , que corresponde a un potenciómetro de alrededor de 10K, configurado en una entrada análoga en el arduino mega alimentado con la salida de 3.3v, los resultados de esta comparación son Ve y Vf. ver figura 3.

  2. En el diagrama de bloques, Figura 1 se muestran unas compuertas AND, que se entienden de este modo Ve con Vk y Vf con el complemento de Vk, respectivamente, estas me deben generar las señales Vi’’ y Vj’’ Ver las ultimas dos graficas de la figura 3. estas son señales de disparo de salida del arduino mega, pueden ser pwm o salidas digitales.
    Nota: Estos disparos corresponden basicamente a los flancos de subida de las señales Ve y Vf, los flancos de bajada pueden ocacionar falsos disparos, por eso en las figuras Vi'' y Vj'' no aparecen.

Les agradesco muchisimo de antemano toda ayuda posible, y pido disculpas por mi falta de conocimiento del lenguage de programación.

Tambien encontre unos links interesantes, es muy posible que pueda hacer una adaptación de ellos.

http://frenki.net/2013/10/fast-analogread-with-arduino-due/

https://forum.arduino.cc/index.php?topic=156849.0

http://forum.arduino.cc/index.php?topic=137635.5

http://forum.arduino.cc/index.php?topic=117989.0

http://forum.arduino.cc/index.php/topic,74895.0.html

http://forum.arduino.cc/index.php?topic=111739.0

Hola, porfin eh adelantado algo de codido, podrian mirar haber que piensan y que podrian sugerirme para mejorarle, por el momento no estoy leyendo la señal AC por el pin analogo ni la señal del potenciometro, la señal AC la ingreso en void loop como una función, tambien intente graficarla con el serial.print pero no se ve muy bien, el Valpha que vendria siendo el potenciometro le puse un valor constante por el momento de 0.8.
No esoy seguro de haber integrado bien la señal Va, esta señal integral la llame como Vb.

Me falta definir las compuertas and para las señlas Vi y Vj, y el zero cross detector para este ultimo( no se si se pueda programar solamente o es mejor usar un circuito con un optoacoplador para detectar el cruce por cero de la señal Va.
y el peak detector de la señal Vb( en el momento coloque un "1" en el resultado que serían Vc y Vd.

En este link encontre un poco como hacer el detector de cruce por cero.

Muchas gracias.
Codigo en arduino Mega, quizas utilice el Due.

int tiempo,x;
float Va,Vb,Vc,Vd,Vi,Vj,deltaT=0.1;
float T=1e6/60.0;
float Vbant,Valpha=0.8; 
void setup() {
  Serial.begin(9600);
  pinMode(A0,INPUT);
  pinMode(A1,INPUT);  
  pinMode(13,OUTPUT);
}
void loop() {
  tiempo=micros();    
  Va=sin(2*3.1416/T*micros());
  Vb=deltaT/1e6*Va+Vbant;
  Vc=1+Vb;
  Vd=1-Vb;
  
  if (Vc>Valpha)
  {
    Vi=1;digitalWrite(13,HIGH);
    }
  else
  {
    Vi=0;digitalWrite(13,LOW);
  }
    
  if (Vd<Valpha)
  {
    Vj=1;digitalWrite(12,HIGH);
    }
  else
  {
    Vj=0;digitalWrite(12,LOW);
    }//    Vj=1;}else{Vj=0;}
  Vbant=Vb;

  //Serial.println("Va+1:");
  //Serial.println(Va+1);
  //Serial.println(analogRead(A1));
 Serial.println(Va);
 Serial.print("Vc:");
 Serial.println(Vc); 
 Serial.print("Vd:");
 Serial.println(Vd); 
 Serial.print("Vi:"); Serial.println(Vi); Serial.print("Vj:");Serial.println(Vj);
 //Serial.print(" ") ;Serial.println("Valpha:");  Serial.println(Valpha);
  //Serial.println("Vd:");Serial.print(Vd);  Serial.print(" "); Serial.println("Valpha:"); Serial.println(Valpha);
  deltaT=(micros()-tiempo);
}

Bueno de tanto en tanto llega alguien y desafía a todo el foro como en tu planteo.

1.2 Como podria realizar el código para muestrear la señal. Por el teorema de Nyquist sé que la frecuencia de muestreo debe ser por lo menos unas 5 veces la frecuencia fundamental que serían unos 60hz.

Lo primero que te diré es que el teorema de Nyquist no dice que deba ser 5 Veces, dice que para poder reconstruir exactamente una señal debe ser al menos mayor o igual a 2 veces la frencuencia de su ancho de banda y en tu caso sería 120 Hz

Cito el teorema

El teorema demuestra que la reconstrucción exacta de una señal periódica continua en banda base a partir de sus muestras, es matemáticamente posible si la señal está limitada en banda y la tasa de muestreo es superior al doble de su ancho de banda.

El MEGA para algo de 120Hz es mas que suficiente, incluso un UNO/NANO lo es. Luego el resto de procesamiento es otra cosa.

CONVERTIDOR DE FASE.
Enfatizo el titulo porque luego de ubicarme en el tema debo hacerte un comentario.

A menos que estes obligado por alguna razón especial a hacerlo de este modo creo que equivocas el enfoque.
El objetivo final es disparar la compuerta de los SCR pero hay un modo mucho mas simple de hace las cosas.

Si detectas el cruce por cero de tu AC, y sincronizas un TIMER para darle la resolución que tu necesites a fin de que cuando quieras iniciar el disparo lo hagas. Supongamos 1k pero he leido en tu pdf que se habla de hasta 65Khz. No hay problema por eso.
Ahora imagina que tienes una interrupción sincronizada con el cruce por cero de la AC. Tu potenciometro dice 45 grados asi que se cuenta el tiempo con micros() y simplemente disparas.
Ahora bien, hay que detectar si estamos en fase positiva o negativa porque de ello depende que SCR hay que hacer que conduzca.

Muy fácil y con un código simple.
De hecho hay un código que te puede servir en el playground que es este AC Phase Control, esta pensando para un dimmer pero sirve a tu objetivo.
Este ejemplo dispara un triac en todo momento. Solo debes separar los disparos por semiciclo.

Tal vez te sirva o tal vez no.

Hola,

Muy interesante lo que dices, de algun modo tambien estaba pensando si existia alguna forma de hacerlo mas sencillo,confieso que eh sido un poco riguroso en el metodo por la conclusion que debo llegar,(adjunto la imagen) en lo que pienso que si es posible hacerlo de otro modo y estoy deacuerdo con tigo, te agradezco el playground.
Me dispongo a realizar los ajustes necesarios y pruebas para luego verificar si la funcion de trasnferencia del voltaje en la carga Vo del puente de SCRs es lineal con Valpha de mi potenciometro.

Gracias por todo.

Ya leí que el método del coseno lineariza la salida de tu semi.convertidor de fase.

No puedo asegurarte que ocurra lo mismo, pero si puedo decirte que en el peor de los casos podrás crear una tabla tal que para cada valor de salida sepas que angulo de fase debas indicarle al sistema.

en algunos codigos tengo visto usar array de 128 elementos o similar para saber el seno o cos de una señal. en tu caso puedes crear un array de 1023 elementos (yo emepezaria con uno pequeño 128: indice=analogread(a1)>>3;).

#include <avr/pgmspace.h>

prog_uint16_t tiempo[128] PROGMEM  ={8333, 8332, 8328, 8322, 8313, 8302, 8288, 8272, 8253, 8232, 8208, 8182,
8154, 8123, 8090, 8054, 8016, 7976, 7933, 7888, 7841, 7792, 7741, 7687, 7631, 7573, 7513, 7451, 
7388, 7322, 7254, 7184, 7113, 7040, 6965, 6888, 6810, 6730, 6649, 6566, 6482, 6396, 6309, 6220, 
6131, 6040, 5948, 5855, 5761, 5666, 5570, 5474, 5376, 5278, 5179, 5080, 4980, 4879, 4778, 4677, 
4575, 4473, 4371, 4269, 4167, 4064, 3962, 3860, 3758, 3657, 3555, 3454, 3354, 3254, 3154, 3055, 
2957, 2860, 2763, 2667, 2572, 2478, 2385, 2293, 2203, 2113, 2025, 1938, 1852, 1767, 1685, 1603, 
1523, 1445, 1369, 1294, 1220, 1149, 1079, 1012, 946, 882, 820, 760, 702, 646, 593, 541, 492, 445, 
400, 357, 317, 279, 244, 210, 179, 151, 125, 101, 80, 61, 45, 31, 20, 11, 5, 1};

utilizo define para reducir el uso de ram pues son demasiados datos. Para generarla use excel la ecuación es: =(cos(entrada hasta 128 *PI()/128)+1 )*1000000/240

240 para 60hz y 200 para 50hz

ahora mismo no se me ocurre como comprobar que sea lineal la conversión pero matemáticamente tiene buena pinta. si llegas a comprobar que es correcto avísame para guardar este codigo

Gracias, voy a seguir revisando sus aportes, cuando ya tenga la solución les escribire.

Lo que el quiere hacer es un rectificador controlado por SCR. de modo que lo que hace falta es poder encontrar la linealización correspondiente entre el ángulo de fase de disparo del SCR y la tensión de salida del rectificador controlado.
O te pones a evaluar toda la matemática involucrada cosa que hice en mi época universitaria pero ya no tengo el nivel para hacerlo, o simplemente creas una tabla tal que para determinada salida DC requieres tal ángulo de fase. (ya lo escribí en un post anterior).