Brandon Engineer

Shopping cart

Subtotal 0,00 

View cartCheckout

Brandolinera

blank

Resumen del proyecto

El objetivo del proyecto a realizar es automatizar el proceso de llenado de combustible de los vehículos de la empresa y la gestión de las revisiones periódicas de los vehículos.

Objetivos a realizar

A continuación se describirá todos los objetivos obligatorios que propone el cliente sobre el proyecto y son de obligado cumplimiento para su implementación con éxito.

  • Lectura de litros suministrados por operario
  • Envío automatizado de los litros a administración
  • Claves únicas para cada operario
  • Imposibilidad de suministro sin el rellenado de los datos del operario
 

Objetivos propuestos por mi

Se va a desarrollar todas las ideas para optimizar el uso de la Brandolinera propuestas por mi

  • Creación de base de datos con para la revisión de los gastos
  • Envío automatizado de avisos de pasar ITV de los vehículos
  • Envió automatizado de revisiones periódicas de los vehículos; cambio de correa de distribución, cambio de aceite, filtros…

Información del proyecto

Cliente:

Sistein

Categoría:

IOT y automatización

Fecha:

Febrero de 2024

Dirección:

Molina de segura

Topología del proyecto

Para la topología del proyecto se ha propuesto un diseño sencillo el cual constará de un 1200 de siemens + un dispositivo IOT el cual repartira la información con el resto de usuarios tanto los operarios como los administradores. Para el HMI se ha decidido intentar usar al propio dispositivo IOT como un servidor web con el que se podrá acceder desde una pantalla conectada por HDMI o conectándose a la red que emitirá el propio dispositivo y conectandose mediante una app que simplemente será un iframe que mostraría la web. Depende del cliente se optará por uno u otro, incluso utilizar ambos. Adjunto un diagrama del funcionamiento

blank

**NOTA: Francisca es la encargada de administración de revisar el diese y Pepe y Juan Diego son los encargados del almacén.

Material

El material propuesto para el proyecto constará de:

  • Contador de litros (MGI 110)
  • Autómata (1200 siemens 6ES7211-1AE40-0XB0)
  • Dispositivo IOT (Raspberry industrial de industrial shield)
  • Dispositivos de protección (Magneto y diferencial)
  • Pantalla HMI Weintek (—–)
  • Cuadro eléctrico (Pendiente de dimensionar)
  • Contactor de siemens para activar la bomba (—-)
  • Selector de Manual-Automático para en caso de fallo poder forzar el contactor y permitir el funcionamiento manualmente.

HMI

Como este proyecto es propuesto y desarrollado por mi para iniciarme en el desarrollo IOT industrial quise hacer algo que no he visto en otros proyectos y es hacer una pantalla desarrollada con el software libre Fuxa el cual tiene un proyecto en Github y la verdad me parece un software muy potente. Espero que se siga desarrollando y que salga al mercado formalmente porque tiene un gran potencial de competir con Aveva e Ignition

Debido a decisiones monetarias el HMI en vez de poner un monitor táctil resultó más económico tanto en desarrollo como en precio de producto y fiabilidad poner una pantalla táctil de la marca Weintek

PLC

Configuración de hardware

Para la programación del PLC se decidió que realizase las tareas OT más sencillas y que todo el tratamiento de datos lo ejecutase el dispositivo IOT que al usar JavaScript será más sencillo de programar y depurar ya que JavaScript es un lenguaje interpretado.

Para ello se creo un objeto tecnológico para poder aprovechar las entradas rápidas del 1200 y contar de forma sencilla los pulsos del caudalímetro. Para hacerlo primero hubo que configurar el hardware del PLC:

blank

Configuración contador rápido (Función)

En el siguiente apartado se configura la entrada de PLC que vamos a evaluar

blank

Configuración contador rápido (Configurar entrada PLC)

Aquí podemos encontrar el ID software del contador rápido

blank

Configuración contador rápido (Lectura ID Hardware)

Por último deberemos crear en un DB con un tipo de dato «HSC_Count»

blank

Crear dato estructurado para el contador rápido

Programación

Una vez terminada la configuración de hardware hay que agregar el objeto tecnológico al programa donde:

-HSC es el ID hardware que hemos obtenido anteriormente

-CTRL es el DB donde almacenaremos la información del contador rápido

blank

Configuración contador rápido (Configurar objeto tecnológico)

Para la monitorización de la temperatura de la sala se agrego un normalizado y escalado:

blank

Normalizar temperatura y humedad

Para preparar los datos a mostrar en pantalla se agrego un pequeño ajuste con el que mostrará toda la información en el HMI

				
					#dummy_real := DINT_TO_REAL("Datos_Cont".Mi_HSC1.CurrentCount);
"HMI_DB".litros := #dummy_real / #pulsos_litro;
"IOT_DB".price_supply := "IOT_DB".Price * "HMI_DB".litros;
"HMI_DB".temperature := "temperatura";
"HMI_DB".humedad := "humedad";
"HMI_DB".pulsos := "Datos_Cont".Mi_HSC1.CurrentCount;
				
			

Máquina de estados

Para gestionar las diferentes situaciones se preparó una maquina de estados que gestiona cada una de las etapas por la que tiene que pasar en el proceso de surtir:

1º Inicio de sesión

2º Comprobar coche

3º Surtir

4º Inyección en base de datos


CASE "DB_Aux".SQL OF
// ██ ██████  ██      ███████ 
// ██ ██   ██ ██      ██      
// ██ ██   ██ ██      █████ 
// ██ ██   ██ ██      ██    
// ██ ██████  ███████ ███████ 
//                            
"Iddle": // Estado de espera
// Inicializa todas las variables a FALSE
"HMI_DB".CurrentWindow := 10;
"Datos_Cont".Mi_HSC1.EnCV := false;
"IOT_DB".Car_Fail := FALSE;
"IOT_DB".Car_Pass := FALSE;
"IOT_DB".LOG_IN_Fail := FALSE;
"IOT_DB".LOG_IN_Pass := FALSE;
"HMI_DB".ResetStateSupply := FALSE;
"IOT_DB".Check_log := FALSE;
"IOT_DB".Start_SQL := FALSE;
"IOT_DB".Stop_SQL := FALSE;
// Si hay un cambio de estado  cambia el estado a #supply  
IF "HMI_DB".int_Change_state = 1 THEN
"HMI_DB".aux_kilometro := "HMI_DB".kilometer;
"HMI_DB".aux_business := "HMI_DB".business;
"DB_Aux".SQL := "Check_Log";
"IOT_DB".Check_log := TRUE;
"HMI_DB".int_Change_state := 0;
END_IF;
// Si se detecta un aumento en los litros sin haber pasado por log in fuerza las variables de "Surtido no autorizado"
IF "HMI_DB".litros > 1 THEN
"HMI_DB".employee := 9999;
"HMI_DB".pass := 1596;
"HMI_DB".matricula := '00000000';
"HMI_DB".kilometer := 0;
"HMI_DB".business := FALSE;
"DB_Aux".SQL := "Check_Log";
END_IF;
// ███████ ██   ██ ███████  ██████ ██   ██         ██       ██████   ██████ 
// ██      ██   ██ ██      ██      ██  ██          ██      ██    ██ ██      
// ██      ███████ █████   ██      █████           ██      ██    ██ ██   ███ 
// ██      ██   ██ ██      ██      ██  ██          ██      ██    ██ ██    ██ 
//  ██████ ██   ██ ███████  ██████ ██   ██ ███████ ███████  ██████   ██████  
//                                                                         
"Check_Log": // Estado de verificación de log
//Forzamos las variables para que mp se modifiquen en medio del surtido
"HMI_DB".kilometer :=  "HMI_DB".aux_kilometro;
"HMI_DB".business  :=  "HMI_DB".aux_business;
// Si se resetea el estado de suministro, permanece en #Iddle
IF "HMI_DB".ResetStateSupply OR "HMI_DB".int_Change_state = 1 THEN
"HMI_DB".int_Change_state := 0;
"DB_Aux".SQL := "Iddle";
END_IF;
//En caso de fallar el inicio de sesion mostrar la pantalla 13 en el HMI
IF "IOT_DB".LOG_IN_Fail THEN
"HMI_DB".CurrentWindow := 13;
END_IF;
// Si el inicio de sesión fue exitoso, cambia el estado a #Check_Car
IF "IOT_DB".LOG_IN_Pass THEN
"DB_Aux".SQL := "Check_Car";
END_IF;
// ██████ ██   ██ ███████  ██████ ██   ██          ██████  █████  ██████ 
// ██      ██   ██ ██      ██      ██  ██          ██      ██   ██ ██   ██ 
// ██      ███████ █████   ██      █████           ██      ███████ ██████  
// ██      ██   ██ ██      ██      ██  ██          ██      ██   ██ ██   ██ 
//  ██████ ██   ██ ███████  ██████ ██   ██ ███████  ██████ ██   ██ ██   ██ 
//                                                                        
"Check_Car": // Estado de verificación del coche
"HMI_DB".kilometer := "HMI_DB".aux_kilometro;
"HMI_DB".business := "HMI_DB".aux_business;
// Si se resetea el estado de suministro, vuelve a #Iddle
IF "HMI_DB".ResetStateSupply OR "HMI_DB".int_Change_state = 1 THEN
"HMI_DB".int_Change_state := 0;
"DB_Aux".SQL := "Iddle";
END_IF;
// Si el coche pasó la verificación, cambia el estado a #Supply
IF "IOT_DB".Car_Pass THEN
"DB_Aux".SQL := "Supply";
END_IF;
//En caso de de fallo de vehiculo llevar a la pantalla 14
IF "IOT_DB".Car_Fail THEN
"HMI_DB".CurrentWindow := 14;
END_IF;
// ███████ ██    ██ ██████  ██████  ██   ██    ██ 
// ██      ██    ██ ██   ██ ██   ██ ██    ██  ██  
// ███████ ██    ██ ██████  ██████  ██     ████  
//      ██ ██    ██ ██      ██      ██      ██  
// ███████  ██████  ██      ██      ███████ ██ 
//                                             
"Supply": // Estado de suministro
"HMI_DB".CurrentWindow := 11;  //Cambiamos a la pantalla de surtido
//Forzamos las variables en pantalla a las que estaban previamente insertadas
"HMI_DB".kilometer := "HMI_DB".aux_kilometro; 
"HMI_DB".business := "HMI_DB".aux_business;
// Activa el motor
"Arranque_motor" := TRUE;
// Si los litros actuales son iguales a los anteriores, activa un temporizador de 30 segundos
IF "DB_Aux".litros_before = "HMI_DB".litros AND "HMI_DB".litros > 0 THEN
"IEC_Timer_0_DB".TON(IN := TRUE,
PT := T#30s);
ELSE
"IEC_Timer_0_DB".TON(IN := false,
PT := T#30s);
// Actualiza el valor de litros antes con los litros actuales
"DB_Aux".litros_before := "HMI_DB".litros;
END_IF;
// Si hay un cambio de estado o el temporizador expira con litros mayores a 0, cambia el estado a #Insert
IF "HMI_DB".int_Change_state = 1 OR ("IEC_Timer_0_DB".Q AND "HMI_DB".litros > 0) THEN
"HMI_DB".int_Change_state := 0;
"IEC_Timer_0_DB".TON(IN := FALSE,
PT := T#30s);
"DB_Aux".SQL := "Insert";
END_IF;
// ██ ███    ██ ███████ ███████ ██████  ████████ 
// ██ ████   ██ ██      ██      ██   ██    ██    
// ██ ██ ██  ██ ███████ █████   ██████     ██ 
// ██ ██  ██ ██      ██ ██      ██   ██    ██ 
// ██ ██   ████ ███████ ███████ ██   ██    ██ 
//                                            
"Insert": // Estado de inserción de datos
"HMI_DB".kilometer := "HMI_DB".aux_kilometro;
"HMI_DB".business := "HMI_DB".aux_business;
// Inicia la operación de SQL para insertar datos
"IOT_DB".Start_SQL := TRUE;
// Detiene el motor
"Arranque_motor" := FALSE;
// Suma los litros actuales a los litros totales
"IOT_DB".Litres := "IOT_DB".Litres + "HMI_DB".litros;
// Si se completó la operación de SQL, resetea el contador de alta velocidad y vuelve al estado #Iddle
IF "IOT_DB".Stop_SQL THEN
"Datos_Cont".Mi_HSC1.EnCV := TRUE;
"HMI_DB".employee := 0;
"HMI_DB".pass := 0;
"HMI_DB".matricula := '00000000';
"HMI_DB".kilometer := 0;
"Temporizador_BBDD".TON(IN:=TRUE,
PT:=T#500ms);
IF "Temporizador_BBDD".Q THEN
"DB_Aux".SQL := "Iddle";
"Temporizador_BBDD".TON(IN := FALSE,
PT := T#500ms);
END_IF;
END_IF;
END_CASE;


Alarmas

(En construcción)

Seguridad

(En construcción)

Registros

(En construcción)

IOT

Node red

Para la instalación del IOT se ha usado la configuración de Raspberry OS 64 bits. Una vez instalado se han ejecutado las líneas de comando

Primero actualizamos el sistema operativo a la última versión


sudo apt-get update
sudo apt-get upgrade

Instalamos el NodeRed, reservamos la memoria de 256 MB y habilitamos el servicio para que autoarranque al iniciar el sistema operativo


bash <(curl -sL https://raw.githubusercontent.com/node-red/linux-installers/master/deb/update-nodejs-and-nodered)
node-red-pi --max-old-space-size=256
sudo systemctl enable nodered.service

Instalamos los nodos «node-red-contrib-excel», «node-red-contrib-s7», «node-red-dashboard», «node-red-mysql-r2» y «node-red-node-email»


npm install node-red-contrib-excel
npm install node-red-contrib-s7
npm install node-red-dashboard
npm install node-red-mysql-r2
npm install node-red-node-email

en_USEnglish