Mostrando entradas con la etiqueta arduino. Mostrar todas las entradas
Mostrando entradas con la etiqueta arduino. Mostrar todas las entradas

martes, 16 de agosto de 2016

Incubadora para germinación con Arduino Leonardo

Incubadora con Arduino Leonardo. En interfaz con la PC es posible guardar valor de temperatura interior y luminosidad (intensidad lumínica) exterior durante las 24 horas. Datalogger!!!

También es posible agregar un módulo Bluetooth HC06 o HC05 agregando un nuevo canal de comunicación serial (RX - TX), llamado digamos MySerial y enviando por él la cadena String salidaDatos mediante una instrucción MySerial.println(salidaDatos);. Con este dispositivo, se pueden leer los datos temperatura e intensidad lumínica empatando un teléfono inteligente que tenga instalado BTconsole, AruinoDroid o alguna app semejante.

El código está escrito para mantener la temperatura en un rango de 25 a 30 °C. Cuando la temperatura baja de 25 °C se encienden las dos lámparas, una incandescente de 40W para generar calor y una lámpara LED para incrementar la luminosidad sin generar más calor. Si se necesita calentar un mayor volumen hay que usar dos lámparas incandescentes o un sistema de calefacción si se requiere calefaccionar una habitación completa. Cuando la temperatura interior rebasa los 30 °C se enciende un ventilador de 12 V de corriente directa.

Controlador (Arduino Leonardo), ventilador, placa de relevadores y cable de alimentación

Por la parte interna lámparas (una incandescente de 40W y una LED) para proporcionar iluminación y calor. Sensor de temperatura LM35.

Placa Arduino Leonardo, protoboard con circuitos accesorios y LEDs indicadores (verde indica que el ventilador está activo; ámbar indica que las lámparas están encendidas; rojo indica que la temperatura está dentro de rango y tanto ventilador como lámparas están apagadas)

Listado de materiales:

  • Arduino (UNO o Leonardo)
  • Módulo con dos relevadores de 5.0V
  • Fuente de alimentación de 12V 3A
  • Ventilador de 12V CD
  • Mini Protoboard
  • 2 Socket de cerámica
  • 1 foco incandescente de 40W
  • 1 foco led
  • 2 m  de cable duplex con clavija
  • 1 hielera de poliuretano o unicel
  • 3 LED de 5mm 
  • 3 resistencias de 330 Ohm
  • 1 sensor de temperatura LM35
  • 1 m de alambre calibre 22 para proyectos en protoboard (pueden usarse jumpers macho- macho)
  • 1 fotoresistencia (LDR) de 2 M_Ohm (opcional)
  • 1 resistencia de 10 K_Ohm (opcional, para el circuito sensor de luminosidad)


El código Arduino queda de la siguiente manera:

/*
Indicador heat  fan
ledRojo   LOW   LOW
ledVerde  LOW   HIGH
ledAmbar  HIGH  LOW

Arduino-Leonardo:
PWM: 3, 5, 6, 9, 10, 11, and 13. Provide 8-bit PWM output with the analogWrite() function
*/

// Configuracion de pines
#define ledRojo 2
#define ledVerde 3
#define ledAmbar 4
#define ventilador 5
#define iluminacion 6
int flagPrimario,flagSecundario;

void setup() {
  /* Inicializacion */
  pinMode(ledRojo,OUTPUT);
  pinMode(ledVerde,OUTPUT);
  pinMode(ledAmbar,OUTPUT);
  pinMode(ventilador,OUTPUT);
  pinMode(iluminacion,OUTPUT);
  Serial.begin(9600);
  /* Secuencia de inicio */
  cicloActivo();
  digitalWrite(ledVerde,HIGH);
  ventiladorActivo();
  delay(10000);
  ventiladorParo();
  digitalWrite(ledVerde,LOW);
  delay(100);
  iluminacionActivo();
  digitalWrite(ledAmbar,HIGH);
  delay(10000);
  iluminacionParo();
  digitalWrite(ledAmbar,LOW);
  delay(1000);
  Serial.println("El sistema se ha inicializado ...");
}

void loop() {
  iluminacionParo();
  ventiladorParo();
  // Comprueba si en el ciclo anterior se ejecutó la
  // funcion cicloEstable() como ciclo de espera
  if (flagPrimario == 1){
    flagSecundario=1;
  }
  else {
    flagSecundario=0;
  }
  // Activa ventilador o iluminacion en funcion de la temperatura
  if (temp()>30.00){
    ventiladorActivo();
    iluminacionParo();
    Serial.println("Temp > 30");
    digitalWrite(ledVerde,HIGH);
    digitalWrite(ledAmbar,LOW);
    digitalWrite(ledRojo,LOW);
    flagPrimario=0;
    delay(30000);
    ventiladorParo();
  }
  else if ((temp()>25.00) && (temp()<=30.00)){
    ventiladorParo();
    iluminacionParo();
    Serial.println("25 < Temp < 30");
    digitalWrite(ledVerde,LOW);
    digitalWrite(ledAmbar,LOW);
    digitalWrite(ledRojo,HIGH);
    flagPrimario=1;
    delay(60000);
  }
  else if (temp()<=25.00){
    ventiladorParo();
    iluminacionActivo();
    Serial.println("Temp < 25");
    digitalWrite(ledVerde,LOW);
    digitalWrite(ledAmbar,HIGH);
    digitalWrite(ledRojo,LOW);
    flagPrimario=0;
    delay(30000);
    iluminacionParo();
  }
  ventiladorParo();
  iluminacionParo();
  // Asigna el ciclo de espera con flagSecundario como criterio

  if (flagSecundario==1){
    cicloEstable();
  }
  else {
    cicloActivo();
  }
  // Despliega lectura de sensores
  String salidaDatos="";
  salidaDatos+=temp();
  salidaDatos+="\t";
  salidaDatos+=luz();
  Serial.println(salidaDatos);
}
/*****     #####     FUNCIONES     #####     *****/
float temp()
{
  analogReference(INTERNAL);
  delay(10);
  int val;
  for (int v=0; v<=10; v++){
    val=analogRead(A0);
  }
  val=analogRead(A0);
  float t_celsius=val/9.31;
  t_celsius=t_celsius+12.44;
  analogReference(DEFAULT);
  delay(10);
  //Serial.println(t_celsius);
  return(t_celsius);
}

int luz(){
  int val=analogRead(A1);
  delay(10);
  //Serial.println(val);
  return(val);
}

void cicloEstable(){
  ventiladorParo();
  iluminacionParo();
  for (int s=0; s<=100; s++){
    // 800 mS por ciclo
    digitalWrite(ledRojo,HIGH);
    digitalWrite(ledVerde,LOW);
    digitalWrite(ledAmbar,LOW);
    delay(50);
    digitalWrite(ledRojo,LOW);
    digitalWrite(ledVerde,HIGH);
    digitalWrite(ledAmbar,LOW);
    delay(50);
    digitalWrite(ledRojo,LOW);
    digitalWrite(ledVerde,LOW);
    digitalWrite(ledAmbar,HIGH);
    delay(50);
    digitalWrite(ledRojo,LOW);
    digitalWrite(ledVerde,LOW);
    digitalWrite(ledAmbar,LOW);
    delay(50);
    digitalWrite(ledRojo,HIGH);
    digitalWrite(ledVerde,HIGH);
    digitalWrite(ledAmbar,HIGH);
    delay(100);
    digitalWrite(ledRojo,LOW);
    digitalWrite(ledVerde,LOW);
    digitalWrite(ledAmbar,LOW);
    delay(200);
    digitalWrite(ledRojo,HIGH);
    digitalWrite(ledVerde,HIGH);
    digitalWrite(ledAmbar,HIGH);
    delay(100);
    digitalWrite(ledRojo,LOW);
    digitalWrite(ledVerde,LOW);
    digitalWrite(ledAmbar,LOW);
    delay(200);
  }
}

void cicloActivo(){
  ventiladorParo();
  iluminacionParo();
  // 800 mS por ciclo
  for (int s=0; s<=10; s++){
    digitalWrite(ledRojo,HIGH);
    digitalWrite(ledVerde,LOW);
    digitalWrite(ledAmbar,LOW);
    delay(50);
    digitalWrite(ledRojo,LOW);
    digitalWrite(ledVerde,HIGH);
    digitalWrite(ledAmbar,LOW);
    delay(50);
    digitalWrite(ledRojo,LOW);
    digitalWrite(ledVerde,LOW);
    digitalWrite(ledAmbar,HIGH);
    delay(50);
    digitalWrite(ledRojo,LOW);
    digitalWrite(ledVerde,LOW);
    digitalWrite(ledAmbar,LOW);
    delay(50);
    digitalWrite(ledRojo,HIGH);
    digitalWrite(ledVerde,HIGH);
    digitalWrite(ledAmbar,HIGH);
    delay(100);
    digitalWrite(ledRojo,LOW);
    digitalWrite(ledVerde,LOW);
    digitalWrite(ledAmbar,LOW);
    delay(200);
    digitalWrite(ledRojo,HIGH);
    digitalWrite(ledVerde,HIGH);
    digitalWrite(ledAmbar,HIGH);
    delay(100);
    digitalWrite(ledRojo,LOW);
    digitalWrite(ledVerde,LOW);
    digitalWrite(ledAmbar,LOW);
    delay(200);
  }
}

void ventiladorActivo(){
  digitalWrite(ventilador,HIGH);
  digitalWrite(iluminacion,LOW);
  Serial.println("Ventilador activo");
}

void iluminacionActivo(){
  digitalWrite(ventilador,LOW);
  digitalWrite(iluminacion,HIGH);
  Serial.println("Iluminacion activo");
}

void ventiladorParo(){
  digitalWrite(ventilador,HIGH);
  digitalWrite(iluminacion,HIGH);
  Serial.println("Ventilador en paro");
}

void iluminacionParo(){
  digitalWrite(ventilador,HIGH);
  digitalWrite(iluminacion,HIGH);
  Serial.println("Iluminacion en paro");
}

#nfjh


viernes, 14 de noviembre de 2014

Python para comunicación con Arduino.

Python para comunicación con Arduino.


Categoría: 1. Programación y electrónica.

Introducción.

Los microcontroladores son dispositivos electrónicos que permiten interactuar elementos electrónicos como sensores, interruptores, entradas y salidas analógicas y digitales y comunicarlos con un PC o con redes de datos como internet, bluetooth WiFi, entre otras. Esto los convierte en equipos muy versátiles para controlar equipos en respuesta a cambios registrados por sensores (retroalimentación o control de lazo cerrado) o bien para operar equipos a distancia.

Una aplicación de bastante utilidad es el censado de variables ambientales en sistemas naturales o en sistemas controlados para registrar el estado real del sistema durante todo el tiempo de operación. No importa si es de día o de noche, el censado se realiza conforme a la frecuencia programada. El resultado puede ser un registro de datos que se puede analizar en tiempo real, o bien, utilizarse para un análisis posterior, o ambas cosas. El sistema permite además controlar equipos en respuesta a cambios ambientales. Desde encender una lámpara cuando la intensidad lumínica baja de un valor establecido o encender un sistema de enfriamiento cuando la temperatura se eleva por encima del límite máximo, hasta controlar el vuelo de un dron equipado con GPS siguiendo un itinerario previamente establecido y registrando variables ambientales de interés o registrando imágenes en archivos electrónicos.

En este blog he publicado otras entradas sobre proyectos con la tarjeta electrónica Arduino. Accede AQUÍ.

Desarrollo del proyecto.

En este ejercicio se utiliza un programa en Python para abrir un puerto de comunicación serial. A través de este puerto se recibe una linea de datos generada por una tarjeta electrónica Arduino, que tiene un sensor de temperatura LM35. El dato se guarda en un archivo de texto, junto con la fecha y la hora en que fue realizada la lectura. 

# Abre un puerto de comunicacion con Arduino. Continuo.
from time import sleep
from time import strftime
import serial
serialPort=3
baudRate=115200
storeFile='E:/ArduinoDataFile.txt'
arduino=serial.Serial(serialPort,baudRate)
if (arduino.isOpen()):
        print "Arduino is available ..."
  arduino.close()
if (~arduino.isOpen()):
  arduino.open()
  print "Arduino is open ..."
  while (arduino.isOpen()):
                hora=strftime("%H:%M:%S")
  fecha=strftime("%Y-%m-%d")
  arduino.flush()
  print fecha,"\t",hora,"\t",arduino.readline()
  f=open(storeFile,'a')
  f.write(str(fecha)+"\t"+str(hora)+"\t"+str(arduino.readline()))
  f.close()
  sleep(2.0)
raw_input()  # Esta linea de codigo para archivo.py.


El programa se hizo para Python 2.7 y se instaló la librería PySerial para poder establecer la comunicación a través del puerto serie. También se utiliza la librería time para obtener la fecha y la hora del sistema.

En la consola de salida se despliega el valore de la temperatura junto con la fecha y la hora en que se realizó la lectura (Figura 1). La lectura se repite cada 2.0 segundos, dejando un tiempo de espera con la instrucción sleep().

El sensor de temperatura se instaló en una tarjeta electrónica ArduinoUNO, en la entrada digital A1. El código que se cargó en el microcontrolador es el siguiente:

void setup()
{
  Serial.begin(115200);
}
void loop()
{
  Serial.print(tempSensor());
  Serial.print("\t");
  Serial.println(analogRead(A0));
  delay(1000);
}

float tempSensor()
{
    analogReference(INTERNAL);
    int sens;
    for (int k=0; k<10;k++)  /* Lecturas mientras estabiliza despues de analogReference. */
    {
        sens=analogRead(A1);
        delay(5);
    }
    float temp=sens/9.31;
    analogReference(DEFAULT);
    return temp;
}

Para tomar la lectura del sensor analógico de temperatura se utilizó un ciclo for con 10 iteraciones. Esto con el fin de estabilizar la lectura y obtener un dato preciso. Normalmente las primeras dos o tres lecturas del LM35 después de cambiar la referencia de voltaje analógico con la instrucción analogReference(), se obtienen lecturas bastante alejadas del valor real.

Figura 1. Salida en Python de la función que abre el puerto serial, obtiene la lectura de temperatura y lo guarda en un archivo de texto.


Figura 2. Salida de Python a un archivo de texto donde se guarda el valor de temperatura (°C) junto con la fecha y la hora en que se realizó la lectura.


Para obtener lecturas de manera ininterrumpida, debe sustituirse la linea de código - while (k<25) - por la linea - while (arduino.isOpen()) -. Para detener la lectura simplemente se cierra la ventana de salida de Python.



Bibliografía

Arduino: www.arduino.cc/

Python 2.7: https://www.python.org/download/releases/2.7/



martes, 29 de julio de 2014

Calibración de un termistor.

Calibración de un termistor.

Categoría: 2. Ciencia y tecnología.

Calibración de los sensores de temperatura.
Uno de los sensores se calibró leyendo valores de temperatura con un termómetro de mercurio marca Taylor (-20 a 110 °C) al mismo tiempo que se obtuvieron valores analógicos mostrados en el monitor serial del ambiente de programación Arduino. El rango de la calibración comprendió valores de 1 a 40 °C. A continuación se realizó una regresión lineal por mínimos cuadrados para obtener la ecuación que relaciona la temperatura en función del valor analógico medido con el sensor electrónico.

Los otros sensores se calibraron contra los valores obtenidos por el sensor calibrado contra el termómetro de mercurio. Para esto se utilizaron lecturas de 24 horas, cada cinco minutos, con los dos sensores colocados en el mismo sitio. El sensor exterior se calibró colocando la sonda calibrada junto a la sonda en el exterior, tomando lecturas al mismo tiempo. Así también, se colocó el sensor calibrado junto al sensor interior, tomando lecturas al mismo tiempo. Con estos datos se realizó una regresión lineal por mínimos cuadrados. Así se obtuvieron las ecuaciones de temperatura en función del valor analógico para cada una de las sondas de temperatura (Ver: Censado de datos. Monitorea un ambiente.).

Figura 1. Calibración del termómetro T_3 contra un termómetro de mercurio marca Taylor (-20 a 110 °C). Se tomaron lecturas analógicas (0 a 1023) con el sensor de temperatura y de manera simultánea se registraron las temperaturas medidas con el termómetro de mercurio. Con estos valores se obtuvo el gráfico y la ecuación por regresión lineal.

Figura 2. Calibración del termómetro T_2 tomando como referencia los valores de temperatura leídos con el sensor T_3, que fue previamente calibrado contra un termómetro de mercurio marca Taylor (-20 a 110 °C).

Figura 3. Calibración del termómetro T_1 tomando como referencia los valores de temperatura leídos con el sensor T_3, que fue previamente calibrado contra un termómetro de mercurio marca Taylor (-20 a 110 °C).

Figura 4. Mediciones de temperatura e iluminación una vez que se calibraron los sensores de temperatura. T_1 y T_3 se colocaron juntos en el interior de la habitación. T_2 se colocó en el exterior de la habitación. El sensor de iluminación se colocó en una ventana dentro de la habitación recibiendo la luz del exterior 

Una vez que se calibraron los tres termómetros, se colocó la sonda para medición de la iluminación. Así se hizo una medición de prueba con los cuatro sensores, registrando lecturas cada cinco minutos.

Termómetro1. Temperatura interior:                y=0.1591*x-56.113
Termómetro2 Temperatura exterior:                y=0.1116*x-35.358
Termómetro3 Temperatura del sistema:           y=0.13318*x-43.9853

En las ecuaciones de calibración el valor X corresponde al valor obtenido por el convertidor analógico / digital, AnalogRead(). Con ellas se calculan las temperaturas en grados Celsius, mismas que se despliegan en el monitor serial y se guardan en una tarjeta micro SD.

Una calibración más precisa, sin embargo, requiere algo más de trabajo. Puedes consultar el método de Steinhar-Hart y también utilizar una calculadora.







Censado de datos. Monitorea un ambiente.

Censado de datos. Monitorea un ambiente.

Categoría: 1. Programación y electrónica.

Este ejercicio es de utilidad para realizar un registro puntual o permanente de las condiciones de temperatura y luminosidad de un ambiente que se maneja automáticamente. De esta manera verificar que las condiciones que se programaron o se ajustaron en los equipos acondicionadores funcionan correctamente. Los datos se registran en un archivo de texto cada 10 minutos. También se despliegan en una pagina web muy simple que se refresca cada cinco segundos.

Una de las ventajas de este programa es que mientras estás visualizando la página web, los datos se refrescan cada 5 segundos (esto puede modificarse en el código) pero si cierras la página, el registro de datos continúa, refrescándose cada 60 segundos por default (también lo puedes programar con otra frecuencia).

El hardware para este ejercicio consiste en lo siguiente:
- Placa de desarrollo Arduino UNO R3.
- Shield Ethernet Arduino.
- Placa para prototipos.
- Tres termorresistencias (termistor) conectadas a GND con una resistencia de 10k_Ohm y calibradas.
- Una fotorresistencia de 2M_Ohm, conectada a GND con una resistencia de 10k_Ohm.
- Un led con resistencia de 1k_Ohm conectada a GND.
- Un buzzer.
- Fuente de alimentación 9Vcc.

En esta aplicación se combina el uso de las funciones de Ethernet y de la micro SD de Arduino Ethernet Shield. Se utilizaron como base los ejemplos DataLogger y WebServer que acompañan al IDE de Arduino. Además se trata de poner este equipo a trabajar de manera indepenciente. Es decir, no necesita estar conectado al puerto USB de la computadora, pero se pueden visualizar los datos en tiempo real en una computadora conectada a la misma red donde se conecta el servidor (Ethernet Shield).

De esta manera, no se depende del monitor serial para el despliegue de los datos censados ni se dedica una conexión USB para alimentar el circuito. 

Como aplicaciones para este sistema se sugiere el monitoreo de temperatura e iluminación durante un periodo de tiempo determinado, 24 a 48 h por ejemplo, y así detectar si la temperatura se mantiene dentro del rango deseado, o si se está fuera de las condiciones durante ciertas horas del día o la noche. También podemos calcular con cierta precisión la hora en que se encienden y apagan las luces. Esto puede ser útil si tenemos un sistema controlado automáticamente, pero queremos tener un registro de que esto está ocurriendo realmente. Podemos poner por ejemplo el caso en que una luminaria quede fuera de servicio. El equipo funciona correctamente, pero la iluminación no se encendió a la hora requerida. 

Esta aplicación se puede llevar a un invernadero donde las plantas necesitan un fotoperiodo mínimo para crecer o para no florear. Un laboratorio de cultivo de tejidos vegetales in vitro, donde se necesita exponer los cultivos a un fotoperiodo mínimo, normalmente 16 horas de iluminación por 8 horas de oscuridad. Una instalación donde se crían peces o aves y que requieren que la temperatura ambiente (aire o agua) estén siempre dentro de rango óptimo. 

En ambos casos, iluminación y temperatura, podemos agregar una alerta sonora cuando una de las condiciones salga de rango.

El sistema se puede manejar de manera permanente, teniendo cuidado de vaciar el archivo de destino cada semana o cada mes. Para no saturar la capacidad de la tarjeta de la memoria micro SD del Shield Arduino.

Este ejemplo se puede ampliar a otro tipo de mediciones, como pH, potencial redox, humedad relativa, presión atmosférica, concentración de CO (monóxido de carbono), entre otros. Contando con los sensores necesarios.

Así mismo es posible aumentar el número de sensores hasta 6 en el caso de ArduinoUNO. Si se trata de censar mayor número e variables se puede usar el Arduino Mega (16 entradas analógicas), que también es compatible con Ethernet Shield.


Gráfico 1. 

Los datos almacenados durante las 24h del día en un archivo de texto pueden procesarse con una hoja de cálculo (Microsoft Excel en este caso) para hacer un análisis visual de un gráfico. En él se puede distinguir claramente las horas de insolación y las horas de oscuridad. Para eso es necesario colocar la hora de inicio del censado, esto debe hacerse manualmente abriendo el archivo de texto y agregando la hora y fecha en el encabezado. En el editor de textos, menú [Editar] [Hora y fecha]. Es recomendable colocar en el encabezado del archivo de texto las ecuaciones de los sensores y la entrada analógica a la que se conectaron A0-A5 (para Arduino UNO).

Las temperaturas interior y en el sistema monitoreado (agua) se mantienen dentro de un rango estrecho, mientras que la temperatura exterior muestra una amplia variación, que durante el día se comporta de manera semejante a la intensidad luminosa (Ampliar el gráfico para ver detalles).

Los sensores de temperatura se encapsularon en un tubo de ensayo (vidrio) con bolitas de plomo unidas con silicón en el fondo (para evitar flotación). El tapón del tubo se selló con silicón para mantener siempre seco el termistor (Imagen 1).

Imagen 1.

La calibración de los termistores se hizo contra un termómetro de mercurio (Ver: calibración de un termistor). Colocando agua con hielo y tomando lecturas analógicas (0 - 1023) y de temperatura simultáneamente, hasta que el agua alcanza la temperatura ambiente. Otra serie de datos se toma en un vaso con agua caliente, hasta que se temperatura es la misma que el ambiente.

A continuación se muestra el código del programa (IDE Arduino).

/**********************************************
DataLogger_&_WebServer

Basado en:
DataLogger
 created  24 Nov 2010
 modified 9 Apr 2012
 by Tom Igoe

WebServer
 created 18 Dec 2009
 by David A. Mellis
 modified 9 Apr 2012
 by Tom Igoe

**********************************************/

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

int buzzer = 6;
int redLed = 9;
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1,177);  // 192.168.1.177
EthernetServer server(80);
const int chipSelect = 4;
float sensor[5];
long double tiempoActual,tiempoPrevio,tiempoPrevio2;
long double intervalo = 600000;  // 10 minutos
long double intervalo2 = 60000;  // 1 minuto

void setup() {
  Serial.begin(9600);
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());

  Serial.print("Inicializando SD card ...");
  pinMode(10,OUTPUT);
  if (!SD.begin(chipSelect))
  {
    Serial.println("Falla en tarjeta. Inserte tarjeta ...");
    return;
  }
  Serial.println("Se inicalizo tarjeta SD ...");

  pinMode(buzzer,OUTPUT);
  pinMode(redLed,OUTPUT);
}


void loop() {
  tiempoActual=millis();
  EthernetClient client = server.available();

  if (client)
  {
    digitalWrite(redLed,HIGH);
    refreshWebServer();
    digitalWrite(redLed,LOW);
  }

  else
  {
    if (tiempoActual - tiempoPrevio2 > intervalo2)
    {
      digitalWrite(redLed,HIGH);
      refreshOutWeb();
      tiempoPrevio2 = millis();
      digitalWrite(redLed,LOW);
    }
  }

  if (tiempoActual - tiempoPrevio > intervalo)
  {
    digitalWrite(buzzer,HIGH);
    digitalWrite(redLed,HIGH);
    escribeArchivo();
    tiempoPrevio=millis();
    digitalWrite(buzzer,LOW);
    digitalWrite(redLed,LOW);
  }
}

/*********************        *********************/

void escribeArchivo()
{
  String dataString = "";
  int dato;  // Solo acepta int en la funcion String(dato);
  int tiempo = tiempoActual/60000;

  dataString += "\n";
  dataString += String(tiempo);
  dataString += "\t";

  for (int analogPin = 0; analogPin < 4; analogPin++)
  {
    dato = sensor[analogPin];
    dataString += String(dato);
    dataString += "\t";
  }

  File dataFile = SD.open("datalog.txt", FILE_WRITE);
  if (dataFile)
  {
    dataFile.println(dataString);
    dataFile.close();
    Serial.println(dataString);
  }
  else {
    Serial.println("error opening datalog.txt");
  }
}


/*******************         **********************/

void refreshWebServer()
{
  EthernetClient client = server.available();

    digitalWrite(redLed,HIGH);
 
    Serial.println("new client");
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        if (c == '\n' && currentLineIsBlank) {
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");
 client.println("Refresh: 5");
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
          for (int analogChannel = 0; analogChannel < 4; analogChannel++) {
            float sensorReading = analogRead(analogChannel);
            client.print("analog input ");
            client.print(analogChannel);
            client.print(" is \t");
            if (analogChannel == 0)
            {
              client.print("Interior ");
              sensorReading = 0.1591*sensorReading - 56.113;
              sensor[analogChannel]=sensorReading;
              client.print(sensorReading);
              client.print(" Celsius degree.");
            }
            if (analogChannel == 1)
            {
              client.print("Exterior ");
              sensorReading = 0.1116*sensorReading - 35.358;
              sensor[analogChannel]=sensorReading;
              client.print(sensorReading);
              client.print(" Celsius degree.");
            }
            if (analogChannel == 2)
            {
              client.print("Sistema ");
              sensorReading = 0.13318*sensorReading - 43.9853;
              sensor[analogChannel]=sensorReading;
              client.print(sensorReading);
              client.print(" Celsius degree.");
            }
            if (analogChannel == 3)
            {
              client.print("Iluminacion ");
              sensor[analogChannel]=sensorReading;
              client.print(sensorReading);
              client.print(" Digital value (0-1023).");
            }
            else
            {
              client.println(" ");
            }
            client.println("<br />");    
          }
          client.println("</html>");
          break;
        }
        if (c == '\n') {
         currentLineIsBlank = true;
        }
        else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    delay(1);
    client.stop();
    Serial.println("client disonnected");
 
    digitalWrite(redLed,LOW);
}


/*******************        ***********************/

void refreshOutWeb()
{
          for (int analogChannel = 0; analogChannel < 4; analogChannel++)
          {
            float sensorReading = analogRead(analogChannel);
            if (analogChannel == 0)
            {
              sensorReading = 0.1591*sensorReading - 56.113;
              sensor[analogChannel]=sensorReading;
            }
            if (analogChannel == 1)
            {
              sensorReading = 0.1116*sensorReading - 35.358;
              sensor[analogChannel]=sensorReading;
            }
            if (analogChannel == 2)
            {
              sensorReading = 0.13318*sensorReading - 43.9853;
              sensor[analogChannel]=sensorReading;
            }
            if (analogChannel == 3)
            {
              sensor[analogChannel]=sensorReading;
            }
            else
            {
            }
          }
}

Los datos de calibración de los termómetros se graficaron en Excel y se ajustaron a una recta por el método de regresión por mínimos cuadrados. Las ecuaciones obtenidas son las siguientes:

Termometro1. Temperatura interior:              y=0.1591*x-56.113               Pin: A0
Termometro2. Temperatura exterior:             y=0.1116*x-35.358               Pin: A1
Termometro3. Temperatura del sistema:        y=0.13318*x-43.9853           Pin: A2

La fotorresistencia no se calibró. Para este dispositivo se registran los valores digitales leídos por el convertidor analógico digital (valores de 0 a 1023).

Figura 2.

Para poder visualizar los datos censados, se abre una ventana en el explorador y en la barra de direcciones se escribe la dirección IP que se utiliizó en el código del programa. Los valores se refrescan cada 5 segundos, lo cual es adecuado, ya que por ser una página web tan sencilla casi no consume recursos de la computadora en que se despliegan.

El valor de tiempo registrado en el archivo de texto está en minutos. Para poderlo manejar en Excel se recomienda convertir los datos de esa columna a valores de hora (00:00 a 23:59). Esto se hace fácilmente con la función TIEMPO(hora,minuto,segundo). Como el dato está en minutos, se colocan ceros en hora y segundo, en el atributo minuto se escribe la dirección de la celda que se va a convertir). En la primer celda de la siguiente columna se coloca la hora de inicio y a partir de la segunda se coloca una fórmula que suma esa primera celda (fija, como en $C$7+B8).

En el siguiente enlace puedes encontrar un proyecto para la construcción de un medidor de pulso utilizando optoelectrónica.

Dispositivos electrónicos programables como el que se utilizó en este ejemplo, pueden servir para la automatización de otras aplicaciones. En este enlace puedes ver unas notas sobre automatización de un invernadero. O en forma de presentación (automatización de un invernadero).






sábado, 28 de septiembre de 2013

Ecología urbana. La huella de carbono.

Ecología urbana. La huella de carbono.

Categoría: 2. Ciencia y tecnología.

En la ecología urbana existe el concepto de servicio ambiental, que se refiere a los beneficios que aportan las áreas verdes al medio ambiente en términos de fijación de carbono, generación de oxígeno, e incluso la producción de biomasa que eventualmente puede utilizarse para fabricar biocombustibles.
Kevin y col., 2013, mencionan que las áreas verdes urbanas dedicadas a mantener poblaciones arbóreas pueden almacenar o inmovilizar considerablemente mayores cantidades de carbono que las áreas cubiertas con césped, las cuales a pesar de tener una gran productividad en términos de biomasa, tienen la desventaja de que el carbono fijado es rápidamente liberado en forma de CO2 tras su degradación biológica. Las zonas urbanas son grandes consumidores de oxígeno por la combustión que mueve transportes y maquinaria industrial, por lo cual, las áreas verdes urbanas son importantes puntos de reposición, aunque parcial, del oxígeno consumido. Una tercera forma de servicio ambiental es la posibilidad de destinar la biomasa generada en áreas verdes urbanas para la fabricación de biocombustibles, de manera que el ciclo del carbono se cierra en el tiempo presente, lo que no sucede con el uso de combustible obtenido en depósitos fósiles.
Otra forma en que se puede obtener servicios ambientales en las zonas urbanas es mediante el aumento de la eficiencia de uso de la energía. Hay muchas formas en que se puede mejorar esta eficiencia, mediante el uso de energía solar para precalentar el agua y reducir el consumo de combustible para obtener la temperatura final, otra es la instalación de celdas fotovoltaicas para sustituir al menos una fracción del consumo eléctrico total, el uso de energía geotérmica para la calefacción de interiores se está popularizando en ciudades de latitudes norte o sur más allá de los trópicos. El uso de vehículos eléctricos (conectables) o híbridos (conectables o no conectables) también es una forma de aumentar la eficiencia en el consumo de energía en los medios de transporte.
La evaluación del ciclo de vida (life cycle assessment) que se realiza como parte del diseño de nuevos productos y procesos industriales permite conocer el grado en que la fabricación, uso y disposición final impacta en los diferentes componentes del medio ambiente, es decir, la generación de contaminantes atmosféricos, generación de residuos sólidos no reciclables, generación de residuos peligrosos no reutilizables y agua residual. De esta manera, los productos que contengan mayor porcentaje de componentes reciclables y reutilizables y cuya producción genere la menor cantidad neta de contaminantes atmosféricos y agua residual, serán los más eficientes en términos ambientales. El consumidor final se va a familiarizar paulatinamente con esta información y podrá utilizarla como criterio antes de realizar la adquisición. Uno de los primeros parámetros que el consumidor podrá utilizar para la adquisición de un producto o servicio será el llamado huella de carbono. Aunque en lo sucesivo se integrarán otros.
Los bonos de CO2 son un instrumento financiero internacional que sirven para financiar proyectos sustentables con recursos provenientes de empresas que por su naturaleza no pueden evitar emisiones de contaminantes a la atmósfera. Así aportan recursos para proyectos que secuestran carbono, proyectos que desplazan actividades que emiten gases perjudiciales (gases de efecto invernadero, gases que dañan la capa de ozono, gases que promueven la formación de ozono en las capas inferiores de la atmósfera, como los compuestos orgánicos volátiles y los óxidos de nitrógeno). Con esta medida se trata que las actividades contaminantes obligadas, puedan reducir su huella de carbono de manera indirecta.
Un concepto que sintetiza todos los anteriores es el de huella de carbono, que incluso puede medirse. Dentro de poco tiempo se tendrá la posibilidad de instalar una app en los teléfonos inteligentes que nos permitirá medir nuestra huella de carbono individual (carbon footprint).
Se estima que el 28 por ciento de las tierras agrícolas del mundo producen cultivos que se desperdician. En el proceso, se despilfarran 250 km³ de agua y la huella de carbono de los alimentos producidos y no consumidos se estima en 3,3 gigatoneladas de CO² equivalente (FAO, 2013 – La huella del desperdicio de alimentos, impacto en los recursos naturales)

Ejemplo de automatización.
Aumenta la eficiencia de tus procesos y reduce tu huella de carbono.
En esta entrada se propone un ejercicio sencillo o relativamente sencillo para hacer más eficiente el uso de energía eléctrica en el popular pasatiempo de la acuariofilia o bien, con algunas modificaciones, aplicarlo al cuidado de otras mascotas, como el calentamiento del hábitat para reptiles. Se propone un control automatizado que acciona la bomba de aire durante la mitad del tiempo, evitando mantenerla encendida continuamente (la relación tiempo encendido/apagado puede variarse a voluntad, según las necesidades particulares). En especies menos demandantes se puede mantener apagada la bomba de aire durante la noche, lo cual también se muestra en el control automático propuesto. El usuario puede identificar muchos otros casos cotidianos en los que puede aplicarse este control automático.
El proyecto tiene como base un pic programable (circuito integrado programable, pic). En este caso se propone utilizar la tarjeta de desarrollo Arduino UNO (ATMEGA328) que cuenta con 13 entradas/salidas digitales y con 6 entradas analógicas. La asignación de pines es como sigue:

A0 – entrada analógica con una fotorresistencia de 2Mohm.
I/O 3 – salida digital con un relevador de voltaje de 5V, 15A.
I/O 4 – salida digital con un LED rojo indicador de noche.
I/O 5 – salida digital con un LED verde indicador de noche.
I/O 6 – salida digital con un LED rojo indicador de encendido del dispositivo conectado al relevador de voltaje (bomba de aire de acuario).

Se escribieron tres versiones del programa que se va a cargar en el pic programable. Uno utiliza la función millis() para asignar el momento de encendido / apagado de los pines, con pulsos de encendido / apagado de igual duración. El segundo utiliza la función millis() para asignar el momento de encendido / apagado de los pines, con pulsos de encendido / apagado de distinta duración. El tercero utiliza la función delay() para asignar el momento de encendido / apagado de los pines, con pulsos de encendido / apagado de duración igual o diferente duración, a criterio del programador. La tercera forma del programa es la más simple y es la más recomendable para quienes no han tenido contacto previo con este tipo de programas. Los programas primero y segundo son más elaborados y permiten la programación de un gran número de eventos sucediendo simultáneamente pero con temporizaciones independientes unas de otras. En la práctica es la forma más versátil de programar eventos, pero la complejidad se incrementa rápidamente a medida que agregamos tareas al pic; aunque tiene la ventaja de que una vez que se ha programado un bloque de pines, este ya no se modifica cuando se programan los demás bloques.

El código para el primer programa queda de la siguiente manera:
/*
Programa: HuellaDeCarbonoUno
Este programa asigna intervalos de encendido / apagado de igual
duración (10 minutos)
Se utiliza la función millis() para manejar el momento de
encendido / apagado.
*/
const int ledPin =  13;
const int pinRelay = 3;
const int pinLedDia = 4;
const int pinLedNoche = 5;
const int pinLedRelay = 6;
int valorIluminacion;
unsigned long previousMillis = 0;       
unsigned long intervaloLed = 1000;  
unsigned long relayIntervalo = 600000; // 10 minutos
unsigned long previousRelayMillis;
byte ledState = LOW;
byte estadoRelay = LOW;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(pinRelay, OUTPUT);
  pinMode(pinLedDia, OUTPUT);
  pinMode(pinLedNoche, OUTPUT);
  pinMode(pinLedRelay, OUTPUT); 
}

void loop()
{
  unsigned long actualMillis = millis();
  if(actualMillis - previousMillis > intervaloLed) {
    previousMillis = actualMillis;  
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;
    digitalWrite(ledPin, ledState);
  }

  valorIluminacion = analogRead(A0);
  if (valorIluminacion > 764)  {
    digitalWrite(pinLedDia, HIGH);
    digitalWrite(pinLedNoche, LOW);
    if (actualMillis - previousRelayMillis > relayIntervalo)  {
      previousRelayMillis = actualMillis;
      if (estadoRelay == LOW)  {
        estadoRelay = HIGH;  }
      else  {
        estadoRelay = LOW;              }
      digitalWrite(pinRelay, estadoRelay);
      digitalWrite(pinLedRelay, estadoRelay);  }  }
  else  {
    digitalWrite(pinRelay, LOW);
    digitalWrite(pinLedDia, LOW);
    digitalWrite(pinLedNoche, HIGH);  }  }
Tamaño binario del sketch: 1286 bytes, de un máximo de 32256 bytes.

El código para la segunda versión del programa queda de la siguiente manera:
/*
Programa: HuellaDeCarbonoDos
Este programa asigna intervalos de encendido / apagado de distinta
duración.
Se utiliza la función millis() para manejar el momento de
encendido / apagado.
*/
const int ledPin =  13;
const int pinRelay = 3;
const int pinLedDia = 4;
const int pinLedNoche = 5;
const int pinLedRelay = 6;
int valorIluminacion;
unsigned long previousMillis = 0;       
unsigned long intervaloLed = 1000;  
unsigned long relayIntervaloOn = 120000; // 2 minutos
unsigned long relayIntervaloOff = 480000;  // 8 minutos
unsigned long previousRelayMillis;
byte ledState = LOW;
byte estadoRelay = LOW;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(pinRelay, OUTPUT);
  pinMode(pinLedDia, OUTPUT);
  pinMode(pinLedNoche, OUTPUT);
  pinMode(pinLedRelay, OUTPUT); 
}

void loop()
{
  unsigned long actualMillis = millis();
  if(actualMillis - previousMillis > intervaloLed) {  // codigo para un bloque de pines
    previousMillis = actualMillis;  
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;
    digitalWrite(ledPin, ledState);
  }

  valorIluminacion = analogRead(A0);
  if (valorIluminacion > 764)  {    // codigo para un segundo bloque de pines
    digitalWrite(pinLedDia, HIGH);
    digitalWrite(pinLedNoche, LOW);
      if (estadoRelay == HIGH)  {
        if (actualMillis - previousRelayMillis > relayIntervaloOff)  {
          previousRelayMillis = actualMillis;
          estadoRelay = LOW;
        digitalWrite(pinRelay, estadoRelay);
        digitalWrite(pinLedRelay, estadoRelay);  }  }
      if (estadoRelay == LOW)  {
        if (actualMillis - previousRelayMillis > relayIntervaloOn)  {
          previousRelayMillis = actualMillis;
          estadoRelay = HIGH;
        digitalWrite(pinRelay, estadoRelay);
        digitalWrite(pinLedRelay, estadoRelay);  }  }  }
  else  {
    digitalWrite(pinRelay, LOW);
    digitalWrite(pinLedDia, LOW);
    digitalWrite(pinLedNoche, HIGH);  }  }
Tamaño binario del sketch: 1386 bytes, de un máximo de 32256 bytes.

El código para la tercera versión del programa queda de la siguiente manera:
/*
Programa: HuellaDeCarbonoTres
Este programa asigna intervalos de encendido / apagado de distinta
duración.
Se utiliza la función delay() para manejar el momento de
encendido / apagado.
*/
const int ledPin =  13;
const int pinRelay = 3;
const int pinLedDia = 4;
const int pinLedNoche = 5;
const int pinLedRelay = 6;
int valorIluminacion;
// unsigned long previousMillis = 0;       
// unsigned long intervaloLed = 1000;  
// unsigned long relayIntervaloOn = 120000; // 2 minutos
// unsigned long relayIntervaloOff = 480000;  // 8 minutos
// unsigned long previousRelayMillis;
byte ledState = LOW;
// byte estadoRelay = LOW;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(pinRelay, OUTPUT);
  pinMode(pinLedDia, OUTPUT);
  pinMode(pinLedNoche, OUTPUT);
  pinMode(pinLedRelay, OUTPUT); 
}

void loop()
{
  if (ledState == HIGH)  {
    ledState = LOW;
    digitalWrite(ledPin, ledState);  }
  else  {
    ledState = HIGH;
    digitalWrite(ledPin, ledState);  }
   
  valorIluminacion = analogRead(A0);
  if (valorIluminacion > 764)  {   
    digitalWrite(pinRelay, HIGH);
    digitalWrite(pinLedRelay, HIGH);
    delay(480000);
   
    digitalWrite(pinRelay, LOW);
    digitalWrite(pinLedRelay, LOW);
    delay(120000);  }
  else  {
    digitalWrite(pinRelay, LOW);
    digitalWrite(pinLedDia, LOW);
    digitalWrite(pinLedNoche, HIGH);  }  }

Tamaño binario del sketch: 1272 bytes, de un máximo de 32256 bytes.

La lectura analógica para determinar si es de día o de noche, se utilizó como criterio un valor de 3(255)-1=764, que sería el 75% de la iluminación máxima detectada por el sensor. Este valor se tendría que ajustar (entre 0 y 1023 o 4(255)-1=1023) dependiendo de la ubicación del sensor.
El pin de entrada analógica (A0) no requiere declaración dentro de la función void setup(), pero si se desea, se le puede asignar un nombre de variable del mismo modo que se hizo con las salidas (o entradas, según sea el caso) digitales.
Como puede verse, estos sencillos programas ocupan muy poca memoria en el chip programable, por lo que se puede utilizar pines adicionales pines para manejar otras funciones, según se desee. En el caso de un hábitat para reptiles puede ser útil colocar un termistor para regular la temperatura, encendiendo y apagando la calefacción, a manera de un termostato.

El circuito electrónico
Para realizar el montaje de los diferentes circuitos electrónicos que comprende este pequeño proyecto se recomienda utilizar, como ya se mencionó, la tarjeta de desarrollo Arduino UNO y una tabla de montaje de prototipos (protoboard, como es su nombre en inglés). Si se trabaja con la tarjeta de desarrollo MSP430G2xx3, de Texas Instruments, utilizando el software Energia, se puede utilizar el mismo código, con algunas pequeñas modificaciones en la declaración de las entradas/salidas digitales y la entrada analógica, también se tendrán que utilizar los componentes electrónicos apropiados, como un relevador que trabaje a 3.3.Vcc y los valores apropiados de resistencias para los led’s.



El diodo en D1 puede ser un 1N4004.

Bibliografía
Kevin JG., Avila, JML., and Edmondson JL. 2013. Managing urban ecosystems for goods and services. Journal of Applied Ecology 2013:1-11.

Arduino. Sitio web. http://www.arduino.cc/.









viernes, 31 de mayo de 2013

Sensor analógico y señal luminosa con Arduino UNO

Sensor analógico y señal luminosa con Arduino UNO.

Categoría: 1. Programación y electrónica.

Este es un programa sencillo para Arduino UNO, que envía pulsos a un LED cuya duración se ajusta instantáneamente a la intensidad de la iluminación detectada con un sensor (fotorresistencia de 10kOhm) colocado en la entrada analógica A0.
Tres LEDs (puede ser uno o dos si se prefiere) se conectan a los pines digitales I/O 9, 10 y 11 por el ánodo. El cátodo de cada LED se conecta a una resistencia de 220Ohm, conectada a tierra (GND). La fotorresistencia se conecta entre los pines A0 y +5V. En una de las terminales de la fotorresistencia se conecta una resistencia de 10kOhm que se conecta a tierra (GND).
El código es el siguiente:
/*
LedRBG_AnalogRead
*/

#define Blue 9
#define Green 10
#define Red  11

int sensorValue;
unsigned long tiempoTotal, ultimoRegistro, ultimoReporte;
int intervalo;
int reporte = 1500;
byte ultimoEstado = LOW;
byte estadoActual = LOW;

void setup()  {
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  Serial.begin(9600);
}

void loop()  {
  sensorValue = analogRead(A0);
  intervalo = sensorValue / 2;
  tiempoTotal = millis();

  if (tiempoTotal - ultimoRegistro > intervalo)  {
    // digitalWrite(Blue, estadoActual);
    // digitalWrite(Red, estadoActual);
    digitalWrite(Green, estadoActual);
    ultimoRegistro = millis();
    if (estadoActual == LOW)
      estadoActual = HIGH;
    else
      estadoActual = LOW;
  }

  double iluminacion = sensorValue;
  iluminacion = iluminacion * 100 / 1023;

  if (tiempoTotal - ultimoReporte > reporte)  {
    Serial.print("La iluminacion actual es: ");
    Serial.print(iluminacion);
    Serial.println(" %");
    ultimoReporte = millis();  }
}




Figura 1. Aspecto del circuito ya montado.


En el código se utilizó el método de contar el tiempo mediante la función millis(). De esta manera, se pueden controlar muchos procesos independientes unos de otros sin que haya interferencias como sucede con la instrucción delay(ms).
Si se disminuye la iluminación que recibe la fotorresistencia el pulso enviado al LED disminuye su duración y también el tiempo que dura la pausa (LOW), que es de la misma duración.

Bibliografía
Sitio Arduino Homepage: http://www.arduino.cc/