domingo, 15 de diciembre de 2013

Proyecto: Evitar inyección con Arduino (II)

Hola Amigos, en la práctica de hoy, le daremos otra vuelta de tuerca más a nuestro proyecto.

En la entrada anterior vimos como medir la intensidad, y a partir de ahí calcular los Watios (suponiendo un voltaje de red de 230VA). Correcto?

Bueno, pues nuestro objetivo es no solo poder medir el voltaje de la red, sino también poder medir LA DIRECCION DE LA POTENCIA, es decir, si es de entrada o salida, y a partir de ahí, poner los mecanismos en marcha que eviten la inyección a red.

Nos ponemos manos a la obra, básicamente, vamos a duplicar el circuito que vimos anteriormente, pero midiendo esta vez el voltaje Alterno. Muchos os preguntareis, ¿esto es peligroso? Bueno, pues si lo medimos directamente, sí, pero vamos a reutilizar un cargador de movil, que genera energía alterna y continua. Este se encargará de pasar el voltaje de 220VA a 9VA. Luego dividimos dicho voltaje con varias resistencias para dejarlo en 5 VA.

Esto nos aislará del peligro de chispazo, y también nos permite adaptar la señal a algo medible por el arduino

 

2013-12-15 12.02.54 2013-12-08 11.28.50

 

 

Como resultado, tenemos

Sin carga: Podemos ver la señal de intensidad (la azul) estable.

image

Carga 110W: Vemos como fluctúa la intensidad.

image

Y ya si desplazamos los valores al eje de cero, tenemos algo muy bonito

 

image

 

Ahora viene lo interesante, chicos. Me surgen estas preguntas:

1.- ¿Como sé si estoy inyectando o no?

Si estoy inyectando, la intensidad apuntaría al lado contrario que el voltaje

2.- Porque los picos de corriente están “apuntando” a la misma curva del voltaje?

La potencia es positiva porque al multiplicar ambos valores da positivo. Si la intensidad fuera negativa, y el voltaje positivo en cada ciclo, detectamos inyección

3.- ¿porque son tan pequeños los valores de la intensidad?

La carga que tengo es de pocos watios, pero necesito mucha precisión, por lo que si amplio la señal más, cuando la carga sea grande se me irá de los valores soportados

 

Bueno, pues por simplificar mucho el tema, el voltaje y la intensidad se desplazan según la carga que tengamos en casa. Esto es, si son cargas “resistivas” o sea resistencias, las líneas serán similares, es decir, no habría desplazamiento en ellas.  Digamos que los picos de las ondas coincidirían.

En caso de que existan cargas no resistivas (motores de lavadoras, tubos fluorescentes…) se desplazarían ambas señales

Esto está muy bien explicado aquí: http://openenergymonitor.org/emon/buildingblocks/ac-power-introduction

Ejemplo de desplazamiento, con lavadora puesta:

image

Veis que se ven los picos más a la izquierda que antes.

El resultado, midiendo voltaje:

 

2013-12-15 12.03.11

 

El código fuente, lo voy a poner también. He seguido las recomendaciones de un seguidor que indicaba que para publicar un código debía escribirse muy bien que hace para que sea comprensible. Cierto es, así que lo he “maquetado” un poco. Aún no he terminado el proyecto, por lo que seguirá habiendo muchas cosas que cambiar y aclarar.

En todo caso, son bienvenidas todas las críticas constructivas, así que gracias Tex

 

#include <LiquidCrystal.h>
#include <LCDKeypad.h>
LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7);

const int currentPin = A1;
const int voltPin = A2;
const unsigned long sampleTime = 100000UL;                           // sample over 100ms, it is an exact number of cycles for both 50Hz and 60Hz mains
const unsigned long numSamples = 2500UL;                               // choose the number of samples to divide sampleTime exactly, but low enough for the ADC to keep up
const unsigned long sampleInterval = sampleTime/numSamples;  // the sampling interval, must be longer than then ADC conversion time

//Esta variable necesita ser ajustada en función al voltaje que te genere la placa. 2.5 voltios serían 514, pero siempre se pierde algo de voltaje en las resistencias
// TODO: Auto-Ajustarlo usando la media de una lista de tomas.
const int adc_zero = 507;                                                     // relative digital zero of the arudino input from ACS712 (could make this a variable and auto-adjust it)

void setup()
{
  Serial.begin(9600);
  //Inicializamos la pantalla LCD.
  lcd.begin(16, 2);
  lcd.clear();
}

void loop()
{
  unsigned long currentAcc = 0;
   int voltajemax= 0;
  unsigned int voltajemin=1025;
  unsigned int count = 0;
  unsigned long prevMicros = micros() - sampleInterval ;
  while (count < numSamples)
  {
    if (micros() - prevMicros >= sampleInterval)
    {
      // Leemos voltaje TODO: Comprobar si el voltaje <200 ERROR en conexión
      int voltaje=analogRead(voltPin);
      //Nos quedamos con el voltaje máximo y mínimo. Solo usaremos el máximo,
      //pero no cuesta nada dejar el mínimo para futuros usos incrementando precisión
      if(voltaje<voltajemin) voltajemin=voltaje;
      if(voltaje>voltajemax) voltajemax=voltaje;
      //Valor puntual de la corriente
      int adc_raw = analogRead(currentPin) - adc_zero;
      currentAcc += (unsigned long)(adc_raw * adc_raw);
      //Incrementamos contadores
      count++;
      prevMicros += sampleInterval;
    }
  }
  int voltaje=calcularVoltaje(voltajemax,voltajemin);

  float rms=calcularRMS(currentAcc,numSamples); 
  //Pasamos la intensidad en amperios, a Watios multiplicando por el voltaje
  int watios=rms*voltaje;

  writeLCDValues(watios,voltaje);
}

// Esta función calcula la intensidad medida en un rango de muestras.
// Es ajustada en función de las tomas y el voltaje del arduino.
// Para mas informacion consultar manual de arduino
float calcularRMS(unsigned long currentAcc,unsigned long numSamples){
  // The 75.7576 for the conversion comes from solving for X, 5 V / X = .066 V / 1 A from the
  // arduino max analog input voltage and the ACS712 sensitivity on the spec sheet respectively
  float rms = (sqrt((float)currentAcc/(float)numSamples) * (75.7576 / 1024.0));
  return rms;
}

//Calculamos el voltaje en funcion a los valores tomados por el voltímetro
// En diferentes tomas. Se extrapola el valor máximo del voltaje
int calcularVoltaje(int vmax,int vmin){
  return map(vmax,35, 981,0,227);
}

void writeLCDValues(int watios,int voltios){
  String textoWatios="Wats: ";
  String textoVoltios="Volt: ";
  // Limpiamos LCD
  lcd.clear();

  //Escribimos los watios en la primera fila 
  textoWatios= textoWatios + watios ;
  lcd.print(textoWatios);

  //Escribimos los voltios en la segunda fila
  lcd.setCursor(0,1);
  textoVoltios = textoVoltios +  voltios;
  lcd.print(textoVoltios);

}

Hasta la próxima semana!!