Sistema de apertura de un escaparate con arduino

Descripción

La finalidad del proyecto es crear un sistema selectivo de apertura de escaparates.

Los requerimientos son los siguientes:

  • Hay un total de 8 escaparates.
  • Se han de poder abrir cada uno de los 8 escaparates de forma independiente.
  • Se han de poder abrir todos los escaparates a la vez.
  • El tiempo durante el cual los cerrojos deben de estar abiertos es de 1 minuto.
  • Hay 3 cerrojos por escaparate.
Descripcion_01
Escaparate

Instrucciones

Componentes usados

Los componentes usados han sido:

Componente_01
Cerrojo

Montaje del circuito

El esquema en Fritzing es el siguiente:

Esquema_01
Esquema usando Fritzing

Como puede observarse en las siguientes imágenes, el sistema ha sido montado sobre una placa pcb de 9x15. La fuente de alimentación se ha elegido de 30A porque cada uno de los cerrojos usa 900 mA y hay 24 de estos. El móldulo LM2596s ha sido usado para reducir el voltaje de entrada a el arduino de 12V a 6V.

Imágenes del sistema montado dentro del laboratorio:

Galeria_01
Detalle superior de la placa montada
Galeria_02
Detalle inferior de la placa montada
Galeria_03
Teclado y bloque de relés
Galeria_04
Conexión del bloque de relés
Galeria_05
Sistema completo

Software

Para comprobar la dirección I2C del bloque de relés se ha usado el programa llamado Arduino I2c Scanner.

Las librerías usadas han sido:

  • I2C_RL8xxM: librería usada para acceder al bloque de relés.
  • Wire: librería usada para las conexiones I2C y dependencia de la librería I2C_RL8xxM.
  • keypad: librería usada para la gestión del teclado 4x3.

El código del arduino es el siguiente:

#include <Wire.h>
#include <I2C_RL8xxM.h>
#include <Keypad.h>

/**
Filas y columnas del teclado
*/
const byte ROWS = 4;
const byte COLS = 3;

/**
@brief Asignación de pins de las patas
*/
byte rowPins[ROWS] = {9, 8, 7, 6};
byte colPins[COLS] = {5, 4, 3};

/**
@brief Define los simbolos de los botones del teclado
*/
char Keys[ROWS][COLS] =
{
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};

/**
@brief Inicializa el teclado
*/
Keypad keypad = Keypad(makeKeymap(Keys), rowPins, colPins, ROWS, COLS);

char key;

//Tiempo restante de botones
int botones[8] = { 0, 0, 0, 0, 0, 0, 0, 0};

int estadoBotones[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // 0 es desactivado y 1 es activado.

int segundosEspera = 60;

//Se declara una variable que almacenará el tiempo actual (real) transcurrido
//desde que se enciende la placa.
unsigned long tiempo = 0;

//Se declara una variable que almacenará el último valor de tiempo en el que se
//ejecutó la instrucción (delay).
unsigned long t_actualizado = 0;

//Se declara una variable que almacenará el tiempo que se desea que dure el delay.
unsigned long t_delay = 1000; // Por ser milisegundos, nos esperamos un segundo.


int DirReles = 32;

I2C_RL8xxM rb (DirReles);

int pinLed = 13;

void setup()
{
  Serial.begin(9600); //Para debug
  Serial.println("Inicio");

  Wire.begin(); //Inicializa el I2C como master
  keypad.addEventListener(keypadEvent); // Añade un gestor de eventos para el teclado

  pinMode(13, OUTPUT);
}

void activaRele(int numRele)
{
  Serial.print("Rele activado: ");
  Serial.println(numRele);

  if (estadoBotones[numRele - 1] == 0)
  {
    estadoBotones[numRele - 1] = 1;
    botones[numRele - 1] = segundosEspera + 2;

    rb.Switch (numRele, true);
  }
  Serial.println("Rele activado: FIN");
}

void apagaRele(int numRele)
{
  Serial.print("Rele desactivado: ");
  Serial.println(numRele);

  if (estadoBotones[numRele - 1] == 1)
  {
    estadoBotones[numRele - 1] = 0;

    rb.Switch (numRele, false);
  }
  Serial.println("Rele desactivado: FIN");
}

/**
Gestión de la tecla pulsada
*/
void keypadEvent(KeypadEvent key)
{
  Serial.print("Tecla pulsada: ");
  Serial.println(key);

  switch (keypad.getState()) {
    case PRESSED: //pulsado + soltado
      Serial.println("PRESSED");
      digitalWrite(13, HIGH);
      if (key == '0')
      {
        activaRele(1);
        activaRele(2);
        activaRele(3);
        activaRele(4);
        activaRele(5);
        activaRele(6);
        activaRele(7);
        activaRele(8);
      } else if (key == '1')
      {
        activaRele(1);
      } else if (key == '2')
      {
        activaRele(2);
      } else if (key == '3')
      {
        activaRele(3);
      } else if (key == '4')
      {
        activaRele(4);
      } else if (key == '5')
      {
        activaRele(5);
      } else if (key == '6')
      {
        activaRele(6);
      } else if (key == '7')
      {
        activaRele(7);
      } else if (key == '8')
      {
        activaRele(8);
      } else if (key == '9')
      {

      } else if (key == '#')
      {

      } else if (key == '*')
      {
      }
      break;

    case RELEASED: //Soltado
      Serial.println("RELEASED");
      digitalWrite(13, LOW);
      break;

    case HOLD: //Mantenido el botón pulsado
      Serial.println("HOLD");
      break;
  }
}


void testReles()
{
  for (int i = 0; i < 8; i++)
  {
    if (botones[i] == 1)
    {
      apagaRele(i + 1);
    }
    if (botones[i] > 0)
    {
      botones[i]--;
    }
  }
  //Serial.println("Comprobación estado relés");
}

//Se quita, si no el SoftTimer no funciona. Este lo tiene definido dentro.
void  loop()
{
  key = keypad.getKey();
  /*
    if (key) {
      Serial.print("Tecla pulsada: ");
      Serial.println(key);
    }*/

  //Se almacena el tiempo que ha transcurrido desde que se encendió el Arduino.
  tiempo = millis();

  //Si ese tiempo es mayor que el intervalo de deseado (equivalente al tiempo
  //de delay) se actualiza el intervalo y se ejecutan las instruciones relacionadas.
  //La idea detrás de este algoritmo consiste en pensar que si han transcurrido
  //20ms y se desea un delay de 30ms cada vez, cuando se superen esos 30ms la
  //variable con la que se compara pasa a ser 60ms. Una vez se alcanzan los 60ms
  //pasa a ser 90ms y así sucesivamente.
  if ( tiempo > t_actualizado + t_delay)
  {
    //Se actualiza el tiempo que ha de transcurrir para el próximo delay.
    t_actualizado = tiempo;

    testReles();
  }

}

Lugares complementarios y adicionales en los que se ha publicado el artículo:

results matching ""

    No results matching ""