Tecnologías de la Fabricación Digital – Escaneo 3D en dispositivos Móviles

Nuevos tiempos y nuevas formas de fabricar, con el tiempo pensar en una fabricación personalizada es cada vez menos descabellado, ya no hablamos de la segmentación y producción por perfiles agrupando a los usuarios por edad, ingresos, etc; sino por el conjunto de atributos que lo definen como tal y único y en consecuencia la serie de elecciones y transformaciones que puede realizar entre ellos los productos que pueda fabricar; a la corriente cultural que acercan al usuario a crear sus propios productos se ha denominado  cultura Maker, que es el símil en terrenos del hardware a lo que significó la apertura hacia el software libre en los terrenos de la informática, esta cultura maker se ha hecho tangible a través de la reducción del costo de adquisición de máquinas, acceso al conocimiento a su creación y a la fabricación de productos, dentro de las técnicas de fabricación, existe un conjunto de herramientas que se denominan fabricación digital, este tipo de fabricación tiene como flujo:

Átomos - Bits - Átomos

¿Qué es lo que muestra este flujo?, pues  que la fabricación de un producto puede darse desde el modelado del mismo a partir de la abstracción o la captura de un objeto físico ya existente, el primero es el diseño digital tal y como lo conocemos y que existen infinidad de programas para lograrlo, el segundo si bien es cierto tiene algo de tiempo en la escena tecnológica pero no ha sido muy popularizado, su principal representante es el escáner 3D   el cual por los altos costos que representó su adquisición no ayudó mucho a su difusión; sin embargo, con las mejoras de procesamiento y captura de imágenes (cámaras) de los teléfonos móviles, se abrió una posibilidad de acercar al usuario al escaneo 3D, así que en esta ocasión abordaremos las aplicaciones que nos permiten escanear objetos con nuestro teléfono móvil; ¿Qué deben tener en común las aplicaciones de escáner 3D? pues que puedan exportarse a un fichero STL que es el formato común entre diversas impresoras 3D y que además puede (no es obligatorio) permitir la manipulación en programas CAD, entonces empecemos:

Scann3D

unnamed

Es de descarga gratuita y solicita que te identifiques con tu cuenta de google, solicita acceso a la carpeta de fotos e imágenes ya que ha de hacer uso del espacio en memoria que dispongas, incluso te recomiendan que te hagas con espacio al usarlo. Los comentarios en la google play no son nada positivos, esto es quizá porque se espera mucho de una aplicación que de por sí se tiene que adaptar a todo tipo de arquitectura que compongan tu teléfono móvil, aunque hay que tomarlos un poco en cuenta. Su menú principal tiene 3 opciones:

  • Nuevo Modelo: Apertura indicaciones de como tomar las imágenes (tomar en cuenta mucho el tema de la luz, y eso aplica como norma incluso para los de tipo profesional), e incluso tiene un guía en tiempo real para la toma de imágenes.
  • Mis Modelos: Si en caso haz decidido guardar alguno de los modelos
  • Continuar (si ya estuviste realizando uno).

Al finalizar la secuencia de fotos, tienes la posibilidad de obtener tu modelo con todos los detalles o simplemente la básica, esta última es gratuita y las demás implican un coste de suscripción (versión PRO), de forma similar ofrece la posibilidad de exportar el modelo en el formato STL.

Nota Personal: Realicé pruebas con él en Huawei Mate 10 PRO, en la noche pero con fuerte iluminación, hice dos pruebas y no salieron como esperaba, hice pruebas en el día, y tampoco obtuve los resultados esperados, quizá sea sesgado pero puede que funcione solo con objetos grandes.

Qlone 3D Scanning & AR Solutions

qlone.png

Es otra de las aplicaciones populares, al igual que populares resultan las opiniones positivas y negativas en el centro de descarga, pero al menos hay opiniones positivas; sin embargo, aunque no es preponderante las opiniones nos sirven para darnos una idea de la adaptabilidad del software a las diversas arquitecturas que presentan los teléfonos móviles. El programa es de descarga gratuita, pide acceso a tu cámara mas no a tu memoria, así también te da indicaciones para la impresión de la hoja patrón de la cual hacen uso, esta hoja patrón puede ser redimensionada en función del tamaño del objeto que haz de escanear lo cual, definitivamente te da una idea que no es muy ideal para el escaneo de monumentos en plazas, por ejemplo. Aquí les dejo un vídeo de las impresiones con esta aplicación:

Nota Personal: Sinceramente lo restrictivo es la hoja de impresión para el registro del escaneo, lo que limita las dimensiones del objeto a escanear.

NOTA PERSONAL GENERAL

Las pruebas se realizaron en un Huawei Mate 10 PRO, y al menos en Android no funcionan de forma correcta las aplicaciones para escanear, he leído que en dispositivos Apple hay mejores resultados, esto dado porque la arquitectura está totalmente definida, lo que hace que ya no te preocupes de la versatilidad del software, lastimosamente no se pudo realizar pruebas al respecto al no tener un dispositivo de dicha marca.

¿Cuál es el principio en común?

El principio en común en muchas de las aplicaciones es la fotogrametría, así que me puse a revisar las diversas técnicas que implican su uso encontrando un vídeo muy explicativo de como realizar tu propio escaneo:

 

¿Cómo se hace en Perú? – o Al menos en algunos lados

Como tema experimental en Perú existen cursos que dentro de sus tópicos incluyen el desarrollo de asignaciones con el escaneo en 3 dimensiones, este curso se denomina fabacademy y es ofrecido por algunas universidades en Perú y en Latinoamérica.

 

 

Anuncios

Arduino y Envío de Datos a un Servidor Parte 2

Anteriormente:

Habíamos ya obtenido la configuración necesario de los servicios y estábamos creando los ficheros en cada una de las carpetas del esqueleto de nuestra aplicación:

inicio7

Ahora vamos a seguir las demás carpetas:

Carpeta Routes

La carpeta routes es la encargada del direccionamiento de las peticiones que se hagan a través del cliente, por ejemplo cuando un cliente accede a nuestra página web lo que está haciendo es una petición de la raíz (“/”) y si tuviéramos un menú como por ejemplo data, es el cliente quién realiza una petición a la ruta (“/data”), para ello usamos una instancia de la clase Router de Express, entonces dentro de la carpeta creamos un archivo rutas.js,  este fichero ha de gestionar dos tipos de solicitud, una relacionada a los datos y otra a la raíz, entonces:

const servicio=require("../services/servicio");//las rutas son las que consumen los servicios que hemos creado
const rutas=require("express").Router(); //creamos la instancia de Router
//cuando se ingresa a la aplicación se realiza una petición get
rutas.get("/",(req,res)=>{
 res.render("index"); // ¿recuerdan el archivo index.pug?, pues aquí se renderiza

});

rutas.get("/data,async(req,res)=>{
 let datos=await servicio.getDatos();
 res.send(datos);
});

module.exports=rutas;

Expliquemos un poco esto, anteriormente hemos creado un fichero index.pug, en el cual cuando se renderice arrojará un fichero index.html, ahí radica la magia, render es un método de express relacionado con la respuesta hacia el cliente. La segunda ruta que es “/data”, tiene como callback una función que posee async/await pero, ¿Por qué lo posee?, pues esta función ha de hacer uso del servicio y su método getDatos() y getDatos es una función que está trabajando con las promesas y esto toma su tiempo, así que es como decir que si getDatos ha de tomar su tiempo la función que lo use también ha de tomar su tiempo, ahora que recordemos que lo retorna getDatos es un arreglo de datos y que será enviado a través del método send asociado a la respuesta al cliente. Finalmente exportamos las rutas.

El fichero Index.js

El  fichero index es el fichero más importante pues es el que ha de poner en marcha el servidor, en el se encuentra todas las configuraciones globales requeridas para el despliegue de nuestra aplicación, entonces vamos a colocar todo el contenido y procederemos a explicar las sentencias más importantes:

const express=require("express");
const config=require("./backend/config/config");
const path=require("path");
const mongoose=require("mongoose");
const rutas=require("./backend/routes/rutas");
const app=express();

//motor de vistas
app.set("views",path.join(_dirname,"/backend/views"));
app.set("view engine","pug);
//middlewares
app.use(express.urlenconded({extended:true});
app.use(express.json());
app.use(express.static(path.join(_dirname,"frontend/public/")));
app.use(rutas);
mongoose.connect(config.mongodb.URI,{useNewUrlParser:true}).then(db=>{
 app.listen(config.puerto,()=>{console.log("Estamos conectados");});
});   

Nuestra aplicación ha de ser gestionada por el framework express.js  por lo tanto debemos de requerirlo, necesitamos de las configuraciones relacionadas al puerto y la dirección de la base de datos que se encuentran en el fichero config, así también necesitamos enlazar la ruta raíz de la aplicación con valga la redundancia con nuestra aplicación, esto lo hacemos con el módulo path que pertenece a nodejs y enlazaremos estas rutas con su método join que une segmentos de ruta, para saber la ruta raíz hacia nuestra aplicación utilizamos la variable de entorno _dirnamenecesitaremos también hacer uso de las bases de datos entonces requerimos a mongoose, También requerimos decirle a express como se han de gestionar las rutas y ello lo definimos en el fichero rutas.js es por eso que lo requerimos.

Cuando todos los módulos que necesitamos ya los hemos instanciado, lo primero que debemos de hacer es crear nuestra aplicación de express y esto lo hemos hecho con:

  const app=express();

Con nuestra aplicación debemos de configurarla y una de las primeras configuraciones es decirle como  y quien ha de renderizar las vistas (views -> index.pug), entonces debemos de configurar el motor de vistas y eso se ha realizado con las instrucciones:

app.set("views",path.join(_dirname,"/backend/views")); //indicamos donde están las vistas
app.set("view engine","pug);//y quien las va a gestionar;

Luego de ello debemos de implementar los middlewares, los middlewares son funciones que realizan acciones previas a la entrega o canalización de solicitudes de datos, los middlewares al realizar acciones pueden hacer tratamiento de los datos y pasarlos a otras funciones o ser ellas mismas la función final, una mejor definición aquí, los middlewares son empleados o llamados a través del método use, los middlewares más importantes de nuestra aplicación son las rutas y el uso de páginas estáticas (que solo necesitan ser cargadas una vez) (express.static):

app.use(express.static(path.join(_dirname,"frontend/public/")));
app.use(rutas);

Por último, ya que estamos usando mongo como la base de datos para almacenar y solicitar los datos, no tiene sentido que la aplicación inicie si las conexión con la base de datos no se ha concretado, ya que podríamos obtener muchos errores, entonces:

 mongoose.connect(config.mongodb.URI,{useNewUrlParser:true}).then(db=>{
     app.listen(config.puerto,()=>{console.log("Estamos conectados");});
})

La conexión a la base de datos se realiza a través del método connect el cual se gestiona a través de las promesas, entonces si es que se logró la conexión con la base de datos, ponemos nuestro servidor con todas las configuraciones previas en funcionamiento, esto se hace a través del método listen de la aplicación express().

La carpeta JS de la ruta frontend/public

En esta carpeta creamos el fichero main.js, este fichero será el que solicite la data constantemente, entonces:

$document.ready(function(){ //cuando el documento haya cargado llamará a la función
  setInterval(function(){ //creamos una función anónima
   $.get("/data,{},res=>{
     console.log(res);
    });
  },5000);
});

Expliquemos lo puesto hasta ahora, recordemos que el fichero index es:

2

Estamos haciendo de la librería jquery, entonces lo que queremos es que cuando el documento esté cargado se llame a una función, en este caso una función anónima donde implementaremos la función setInterval, la cual ejecutará una función cada intervalo de tiempo que le asignemos:

setInterval(function(){ 
    $.get("/data,{},res=>{
     console.log(res);
    });
  },5000);

Nuestra función será ejecutada cada 5 segundos, ¿Y qué es lo que haremos cada 5 segundos? pues debemos hacer una solicitud get a la ruta “/data” (recordemos que esa ruta ya la hemos implementado en el servidor), nuestra solicitud no incluirá parámetro alguno, y por el momento cuando obtiene la respuesta simplemente la imprime por consola, recordemos que la data que se nos envía es un arreglo de objetos que tienen un atributo “Y” donde se almacenó el valor del sensor.

Muy bien, tenemos los datos, pero no solo deseamos imprimirlos por consola,sino que estos se muestren a través del navegador en un gráfico de barras, para ello hemos de usar chart.js, para hacer uso de chart.js lo hemos incluido en nuestro index, pero también hemos creado un canvas el cual tiene como id:”mi_grafico”, entonces el primer paso es capturar el id e indicar que el contexto será un gráfico en 2d (getContext), y esto lo hacemos con:

let elemento_dom=documento.getElementById("mi_grafico").getContext("2D");

Ahora creamos un arreglo vacío, en este arreglo lo que queremos es almacenar los últimos 10 valores que contenga nuestra base de datos, es decir los últimos 10 valores obtenidos en la respuesta del método get, es por ello que luego recorremos la respuesta y asignamos sus valores al arreglo.

let datos=[];
for(let i=res.length-1;i>res.length-11;i++){
 datos.push(res[i].y);
}

Al tener los datos podemos pasarlo al constructor del gráfico de barras de chart.js, el constructor de barras es de la siguiente forma:

var myBarChart = new Chart(ctx, {
    type: 'bar',
    data: data,
    options: options
})

El atributo ctx es la variable donde hemos capturado el canvas, entonces podemos hacer los siguiente:

let chart=new Chart(elemento_dom,{
  type:"bar",
  data:{contenido}


}); 

Debemos de poner especial interés en el atributo data, data posee un conjunto de propiedades como por ejemplo las etiquetas de cada uno de los elementos del gráfico (eje x), como estamos capturando los últimos 10 elementos, entonces el mismo de captura será pues como una etiqueta, las etiquetas pueden ser un arreglo de etiquetas y una etiqueta puede tomar un número o una cadena de texto, las etiquetas se expresan en el atributo labels. Luego necesitamos configurar el datasets (dataset_properties) es un arreglo de objetos con propiedades, haremos uso de la propiedad label y llamaremos a nuestro gráfico “Datos”, luego usaremos la propiedad data y le asignaremos el arreglo de objetos datos, entonces quedando finalmente:

data:{
 labels:datos,
 datasets:[{
  label:"Datos",
  data:datos
 }]
}

Entonces nuestro archivo main.js quedaría:

main.png

Con esto está todo listo de nuestra aplicación, que nos queda, pues ponerla en marcha para ello debemos de ir a la terminal y hacer lo siguiente:

node index.js

Incluso mejor que ello deberíamos instalar el módulo nodemon de forma global de la siguiente forma (esto hará que siempre esté instalado y sea de uso para cualquier otra aplicación), igualmente en la terminal:

npm i -g nodemon
//cuando terminó de instalar hacemos en el terminal
nodemon 

Nodemon por defecto siempre buscará el archivo index.js y estará atento a todo cambio que se suceda en los ficheros de js, entonces toca finalmente ir al navegador y hacer en el:

localhost:3000

Arduino y Envío de Datos a un Servidor Parte 1

Anteriormente habíamos podido conectar nuestro arduino a la red (aquí), tal que cualquier cliente se conecte al ip que hemos asignado a nuestro dispositivo pueda ver los datos que se obtienen del sensor de luz. En esta ocasión hemos de enviar la data a un servidor que montemos y que se muestre a través de gráficos para que se aprecie en tiempo real la data y como esta cambia en el transcurso del tiempo; sin embargo, la variante es que lo haremos a través de JavaScript y el uso de Firmata, así que no entraremos mucho en detalle del significado de las sentencias a menos que sea uno nuevo, así que empecemos.

conjunto

Del lado de Arduino

Para la programación utilizaremos el arduino web editor; sin embargo en esta ocasión la programación no recae con fuerza sobre lo que programemos sobre Arduino sino que lo que queremos lograr en palabras comprensibles es que Arduino sea reconocido por así decirlo como un periférico y que podemos acceder a los datos que recibe a través del sensor (recordar que estamos usando el sensor del artículo anterior, que es un sensor de luz), para lograr ello hemos de usar el protocolo Firmata, ¿Qué es Firmata?, podemos usar esta definición:

Firmata es un protocolo genérico para la comunicación con microcontroladores desde software instalado en un ordenador. Este protocolo se puede implementar en cualquier arquitectura de microcontroladores, así como en cualquier paquete de software. El objetivo de firmata es permitir controlar completamente Arduino desde software instalado en un ordenador, sin escribir una sola línea de código de Arduino (autor).

Muy bien entonces abrimos el arduino web editor, como definitivamente ya tienes instalado el plugin de arduino (sino no funcionaría tu arduino con el arduino web editor) buscamos el icono en la barra de tareas de windows, hacemos click derecho en el y marcamos la opción “go to Arduino create” , cuando se abre la interfaz en el navegador seleccionamos arduino web editor y ahora sí estaremos en la interfaz principal, en la interfaz principal debes ir a examples, marcar la pestaña “from libraries” (te saldrá una lista de librería) desplazarte hasta la librería firmata hacer click en el y en el menú que se despliega seleccionar el fichero “StandardFirmataPlus“, opcionalmente puedes guardar el fichero cambiando su nombre y guardando o simplemente quemando de una sola vez su contenido en nuestro arduino, y eso es todo lo que tendremos que hacer con el arduino

1.png

52608784_263557454562541_5756407597242515456_n.jpg

Del Lado del Servidor

Para el servidor te recomiendo que leas esto (parte 1, parte 2), con el fin que puedas entender o conocer los módulos que hemos de emplear, es cierto que se podría hacer un poco más ligero; sin embargo, quedarían en el aire más preguntas de las que podrían quedar con este post, es decir, muchas librerías de lado del cliente construyen su propio servidor, al cual pues poco o nada de control puedes tener sobre el, o existen otras que las instrucciones se centran exclusivamente en el desarrollo de la recepción de datos de Arduino.

logo

Dicho esto para poder trabajar con el servidor lo haremos con NodeJs, lo que significa que lo debes de instalar, así también se ha de usar mongo para las bases de datos con lo cual también debes de instalarlo, así también no te olvides de iniciar Mongo, o agregarlo para el inicio automático cuando el computador se encienda; hecha la instalación, crea una carpeta, dale un nombre, y abre tu editor favorito (en mi caso VSCode) y navegas hasta la carpeta que haz creado con tu editor, bueno abres la terminal incorporada de VSCODE (Ver->Terminal o abres la terminal de node js y navegas hasta la carpeta que haz creado) y haces:

npm init --yes

Dicha instrucción es el arranque de un proyecto en NodeJs, ahora hemos de proceder a instalar los módulos necesarios, ¿Qué módulos hemos de necesitar?, para el manejo del servidor, las rutas, los ficheros hemos de utilizar express, express no tiene una curva de aprendizaje muy alta y hace gran parte del trabajo que necesitamos hacer en NodeJs, luego necesitamos gestionar las base de datos, y aunque podríamos hacerlo directamente con mongo, para agilizar el trabajo hemos de utilizar mongoose, mongoose nos permite realizar todas las operaciones y configuraciones que haríamos con mongo pero de una forma más sencilla, también necesitamos un motor de vistas y para ello utilizaremos pug, pug nos permite desplegar páginas en html que tengan un tratamiento previo, el tratamiento previo es muy utilizado cuando nuestra páginas han de desplegar contenidos dinámicos (como por ejemplo un red social donde cada usuario tiene su propio perfil), en nuestro caso o para la dimensión de la aplicación esto un paso opcional, ya que podríamos utilizar solo las páginas estáticas, pero lo quise montar ya que con esta aplicación podrías intentar ir más allá de  lo que representa este ejemplo; finalmente y quizá el más importante es la instalación de jhonny-five, jhonny-five es una librería que te permite usar JavaScript para poder ejecutar ordenes o recibir datos desde tu arduino, y esto es lo vital pues tenemos a nuestro arduino enviando datos y debemos de capturarlos y podemos hacer ello a través de Jhonny-five; procedemos a instalar las librerías:

npm i express pug mongoose

johnny-five-fb

Ahora procedemos a instalar jhonny-five, para instalar esta librería debes saber que tiene unos pre-requisitos, los cuales están listados aquí, estos incluyen el módulo del conjunto de herramientas de windows los cuáles podrían tener sus propios pre-requisitos, entonces:

npm i -g --production windows-build-tools
npm i -g node-gyp
npm i johnny-five

Hecha la instalación de los módulos, debes de crear la siguiente estructura de archivos:

inicio7

Aunque esta estructura es genérica, habrá algunas carpetas que en su momento te darás cuenta que no son necesarias, muy bien entonces vamos carpeta por carpeta, dentro de

Carpeta Config

la carpeta config creamos un fichero que se llame config y sea del tipo js, dentro del fichero colocamos:

const config={
 puerto:process.env.PORT || 3000,
 mongodb:{
           URI:process.env.MONGODB_URI || "mongodb://localhost:27017/arduino1"
         }
}module.exports=config;

El fichero config se encarga de almacenar las direcciones o accesos a bases de datos o puertos, como podemos observar estamos requiriendo en primera instancia a las propiedades del entorno (PORT y MONGO_URI) que por lo general son brindadas cuando subimos nuestra aplicación a la nube, en caso de no existir dichas propiedades lo que se haces asignar arbitrariamente un valor como por ejemplo en el caso del puerto el cual mientras esté en el localhost será de 3000, esto de igual forma ocurre con la dirección de la base de datos, sobre la base de datos no te preocupes si esta no existe, pues si mongo detecta que no existe la crea.

Carpeta Views

Dentro de la carpeta views creamos un fichero de tipo pug que se llame index (index.pug), dentro del index vamos a hacer uso de las librería de jQuery y ChartJS (para la creación de las barras estadísticas) y todo ello será centralizado en nuestro propio fichero que se llama main.js, quedando de la siguiente forma:

2.png

Como podrás notar hemos creado un canvas que tiene como id mi_grafico, este canvas será donde despleguemos nuestra gráfica de barras, esto es todo sobre la carpeta views.

Carpeta Database

Su nombre está más que claro de cual es el fin que persigue esta carpeta, mongoose trabaja a través de esquemas, estos esquemas podríamos decir que son representaciones de la estructura de los documentos pertenecientes a la base de datos y que se expresa a través de los modelos, entonces debemos de crear un fichero que se llame modelo.js y en el hacemos:

const mongoose=require("mongoose");//requerimos al módulo general mongoose
const Schema=mongoose.Schema; // creamos una instancia de Esquema

const datos=new Schemma({//creamos un esquema que se llama datos
  y:Number // el cual tiene un único tipo de dato que se llama "Y" y es de tipo Number
});

//exportamos el modelo, así cuando otro fichero lo requiera importará el modelo ya implementado.
module.exports=mongoose.model("data",datos);

Carpeta Services

Dentro de esta carpeta crearemos ficheros que serán los encargados de realizar toda la lógica que se necesita en la aplicación, como lo es guardar elementos en la base de datos o llamar a los elementos de la base de datos, necesitamos dos ficheros, uno de los cuáles será el que realice los servicios relacionados a la recepción de datos de parte del sensor y lo almacene dentro de la base de datos que hemos creado, este fichero lo llamaremos servicio_sensor.js, y debe contener lo siguiente:

const five=require("johnny-five") //requerimos el módulo johnny-five el cual se comunica con el arduino
const Modelo=require("../database/modelo"); //requerimos el modelo que hemos creado
const placa=new five.Board({port:"COM5"});

let valor=0; //creamos una variable general que este almacene el valor del sensor y que pueda ser utilizada por todas las demás funciones
placa.on("ready",function(){ //nos ponemos a la escucha de eventos en nuestra placa
  let luz=new five.Light("A0");
  luz.on("change",function(){
     valor=this.value;
  });
});
async function guardar(){
 let x=new Modelo({y:valor}); // creamos un documento a través del modelo
 await x.save(); //guardamos el documento
}
module.export=setInterval(guardar,2000); //exportamos la función

Expliquemos un poco lo que hay aquí, la instrucción:

new five.Board({port:"COM5"});

Crea una representación de tu placa física (del arduino) y debemos de indicarle el puerto en el que está conectado tu arduino, en el caso de windows es a través del COM, ahora bien Board (el enlace posee información de los parámetros, métodos y eventos de la clase, como ready por ejemplo) tiene más propiedades y parámetros, luego hemos asignado esta instancia ha la constante placa, luego debemos de poner a la escucha a nuestra placa y para ello utilizamos el método on, este método requiere estar a la escucha pero de eventos y el primer evento que debe escuchar es el evento ready, ready sucede luego que la placa se haya inicializado, cuando ocurre ready este llama a un callback (función), es en esta función en el que  inicializamos la escucha del sensor (sensor de luz recuerda) a través de:

let luz=new five.Light("A0");
luz.on("change",function(){
valor=this.value;
});

La clase Light  opcionalmente puede recibir el parámetro relacionado al pin (pero por lo general sino lo colocas no podrá detectarlo, así que lo tomaremos como obligatorio), el pin es el pin donde se encuentra tu sensor en la placa física, en nuestro caso en el pin A0. A la instancia de la clase (luz) debemos de ponerla a la escucha del evento “change” el cual es el evento que está a la escucha de cualquier valor que se obtenga desde el pin, cuando se captura un valor este forma parte de las propiedades de la instancia Light, y podemos obtener dicho valor a través de la propiedad value (value devuelve el valor en crudo sin tratamiento alguno), finalmente el valor obtenido lo asignamos a la variable general “valor” que hemos creado.

Pero necesitamos guardar dicho valor dentro de nuestra base de datos, entonces por eso hemos creado una función que realice ello:

async function guardar(){
let x=new Modelo({y:valor}); // creamos un documento a través del modelo
await x.save(); //guardamos el documento
}}

Como el guardar puede tomar su tiempo, debemos de manejarlo a través de las promesas, esto quiere decir que debemos de implementar el async/await para estar a la espera que concluya el guardado de los datos, el guardado de los documentos (ver sección updating)se hace creando una instancia de los mismos a través del uso del modelo y haciendo uso del método save; así también debemos de asegurar que el guardado se ejecute cada intervalo de tiempo, para ello cuando exportemos el fichero, lo que exportaremos será la función setIntervalsetInterval el cual tiene como requisito indicar una función y el tiempo en mili segundos en el cual se ha de volver a ejecutar dicha función, hemos colocado que se guarden los datos cada 2000 mili segundos lo que hace 2 segundos, esto variable ya que dependerá del comportamiento que desees, es decir que debes someterlo a la pregunta ¿Qué tan drástico será el cambio de valores en el sensor cada cierto tiempo x?, en nuestro caso estamos colocando a 2 segundos con fines demostrativos, pero piénsalo, bueno con esto hemos terminado con el fichero de servicio relacionado al sensor.

Ahora debemos de crear un fichero de servicio que atienda la lógica de la obtención de datos de parte del servidor, a este fichero lo llamaremos servicio.js y debe contener:

const Modelo = require("../database/modelo");
require("./sensor_servicio"); //ponemos en marcha el guardado de datos desde el sensor a la bbdd
async function getDatos(){
 let datos=[];
 datos=await Modelo.find();
 return datos;
}
module.exports={getDatos}

La recuperación también toma un tiempo por lo cual debemos de usar async/await; la recuperación lo hacemos a través del modelo y su método find, este método puede incluir un parámetro de búsqueda; sin embargo, como nosotros requerimos de todos los datos, podemos dejarlo en vacío, ahora bien cuando se devuelven los datos se devuelven un arreglo de estos datos, es por eso que hemos creado un arreglo y finalmente lo que hace la función es retornar dicho arreglo pero ya con los campos poblados. Con esto hemos finalizado todo lo requerido respecto a la carpeta services.

Así concluye la primera parte de este tutorial. Saludos.

Arduino y como conectarlo a internet

Todo aquél entusiasta de la electrónica y de la potencia de sus aplicaciones se ha topado con el término Arduino tanto en su IDE como en su placa, y qué básicamente es el proyecto bandera en lo que a open-hardware se refiere, su arquitectura y  su interacción con otros componentes lo hace de forma muy sencilla y legible de entender con lo cual resulta una herramienta de entrada y aprendizaje dentro del mundo de la electrónica, con el tiempo ha ido ampliando su espectro tal que en los furores del “Internet en las cosas” se ha convertido en una de las fuentes básicas de aprendizaje para entender las potencialidades de esta corriente tecnológica de seguir conectándonos más y más.
En esta ocasión vamos a conectar a Internet nuestra placa arduino y que esta envíe datos a través de una conexión ethernet, para ello hemos de usar un Arduino UNO y un Arduino Ethernet Shield V1.

En términos del IDE, la web de arduino nos ofrece dos opciones de descarga, podemos descargar el IDE, el cual es el medio clásico por el cual se programa el Arduino:

800px-Arduino_IDE_-_Blink

O como en mi caso, que por lo general entre menos aplicaciones tenga en mi PC mejor, puede que te decantes por el Arduino Web Editor, el cual podríamos decir que es una IDE online que te permite programar el arduino, no es muy complicado de hacer uso de el, ya que básicamente solo tienes que crearte una cuenta (que es gratuita) y descargar el plugin, hecho esto de la descarga del plugin y del logeo, conectamos nuestro arduino al computador y en la interfaz de entrada del arduino web editor debemos ver:

2.png

En donde se encuentran listados los tipos de placa la conexión con nuestro puerto COM (lo siento pero el tutorial está hecho bajo un usuario de windows), si en caso se reportase algún problema este puede deberse a causas tales como a que no haz seleccionado el COM, el plugin no se ha puesto en marcha automáticamente o simplemente (como lo que me sucedió) no lo tengas instalado.

Lo primero que hemos de probar es que el quemado de la placa ocurra desde el entorno del navegador, para ello haremos un clásico que es el parpadeo del led que viene incorporado en el Arduino y que por lo general está conectado al PIN 13:

AjpdSoft_pphael_030

Entonces

int ledPin=13

void setup(){
  pinMode(ledPin,OUTPUT);
}
void loop(){
  digitalWrite(ledPin,HIGH);
  delay(1000);
  digitalWrite(ledPin,LOW);
  delay(1000);
}

¿Qué hemos hecho?, pues básicamente hemos declarado el pin (ledPin), luego en la función void setup (que básicamente es la función donde se inicializan todos los elementos que hemos de requerir) indicamos que el pin será del tipo “Salida” a través del método pinMode, recordemos que en arduino podemos tener pines que funcionen como entrada y otros como salida, las entradas por lo general ocurren cuando se conectan sensores que recogen datos del entorno (que son análogos) y las salidas (que por lo general son digitales) ocurren cuando a la entrada de datos queremos comunicar de forma organoléptica o a través del envío de datos, nuestro ejemplo es organoléptico al ocurrir el evento de encendido y apagado y que es perceptible por nuestros ojos; entonces luego de ello en el void loop (función que como su nombre lo dice estará haciendo una repetición infinita (por defecto a menos que lo detengamos) del código que contenga) colocaremos el comportamiento el cual es que el pin se prenda y apague y esto se logra a través del uso del método digitalWrite, el cual tiene dos estados que son High y Low (High y Low significa que pase a través del pin los 3.3V o 0V respectivamente), ahora estos estados tendrá una demora de 1000 mili-segundos (que equivalen a 1 segundo) para que el evento sea perceptible a nuestros ojos, sino siempre parecerá que el led está encendido.

Muy bien hecho el código lo que resta son dos cosas:

3

Verificar la consistencia de nuestro programa, y finalmente quemar el programa en el arduino, si todo está correcto te aparecerá un mensaje haciendo alusión que la operación se ha llevado a cabo con éxito.

Montaje del Ethernet Shield

Ahora procedemos al montaje, el cual debe suceder de la siguiente forma:

arduino-ethernet-shield-w5100-conexion

Nos debemos percatar que los pines del 13 al 10 en el ethernet shield se encuentran marcados, estos pines son usados por la placa para comunicarse con el W5100 y la tarjeta SD, así que el uso de esos pines está descartado, luego de ello conectamos el cable ethernet que proviene desde nuestro router de internet en la ranura de tipo RJ45.

Necesitamos asignar una dirección IP, esta dirección IP debe estar inscrita dentro del rango que maneja nuestro router, ¿Cómo podemos saber esto?, pues presionamos la tecla window y escribimos “CMD” que abrirá la consola, dentro de la consola escribimos

ipconfig

4

Esto quiere decir que nuestro router asigna el ip 192.168.1.42 a la máquina, podemos entonces jugar con el ip  y podríamos asignar al ethernet shield el ip 192.168.1.51, si en caso esto no te funcione es porque ya existe otro equipo en tu red con dicha ip asignada con lo cual deberías de probar otras (sí, es cierto, aún no lo hemos probado, tranquilo).

Ahora todos nuestros esfuerzos han de centrarse en la interfaz del arduino que queremos obtener, pues hemos de colocar un sensor de luz y que los datos que se obtengan viajen y estén disponibles para todo aquel que se conecte a la ip asignada al  ethernet shield, entonces que debemos hacer:

  • Todas nuestras aplicaciones por lo general han de trabajar con dos librerías, la ethernet y la SPI, la librería ethernet está diseñada para trabajar con el ethernet shield (vaya, eso no me lo esperaba) y el segundo usado para la comunicación entre dos microcontroladores (lo cual cobra sentido dado que tenemos montado dos placas), en consecuencia debemos de incluirlas, para incluirlas vamos a la opción libraries, se apertura una menú de búsqueda y escribimos las librerías (ethernet y spi), cuando aparezca librería veremos que hay una opción de include y  con ello se agregará a nuestro fichero la librería:

5

  • Debemos de agregar una dirección MAC y que sea global (es decir que no esté dentro de setup o loop):
byte mac[]={0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
  • Luego debemos de asignar el IP, la asignación se realiza a través de la clase IPAddress, pero también debemos de crear una instancia de servidor que esté a la escucha de la conexión al puerto que asignaremos, por defecto este es el puerto 80 y lo haremos a través de EthernetServer:
byte mac[]={0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(192,168,1,51);
EthernetServer servidor=EthernetServer(80);
  • Nuestro sensor lo colocaremos en el A0 de nuestro Arduino, entonces debemos declarar e inicializar una variable que haga referencia a dicho pin, además de una variable que ha de recibir la data que se lea desde el sensor y que será la que enviemos a los clientes:
byte mac[]={0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; 
IPAddress ip(192,168,1,51);
EthernetServer servidor(80);
int sensorPin=A0;
int valor_sensor=0;
  • Ahora debemos de iniciar la comunicación con el puerto serial y los servicios que otorga ethernet, los cuales se inicializan en la función setup, el primero lo hemos de hacer con el método Serial.begin(velocidad) con una velocidad de 9600 baudios, el segundo lo haremos con el método Ethernet.begin(), este método tiene sobrecarga de constructores que están en función de todas las propiedades que hayamos implementado, en nuestro caso solo tenemos la MAC y el IP, con lo cual queda de la siguiente forma:
byte mac[]={0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; 
IPAddress ip(192,168,1,50);
EthernetServer servidor(80);
int sensorPin=A0; 
int valor_sensor=0;

void setup(){
 Serial.begin(9600);
 Ethernet.begin(mac,ip);
}
  • Existe un detalle, no deberíamos iniciar los servicios de ethernet si es que el serial no ha iniciado, como esto podría tomar algo de tiempo, puede darse el caso que tengamos cero datos o incluso errores, para ello debemos de asegurarnos que mientras no exista el serial pues simplemente entre en un bucle infinito de la siguiente forma:
void setup(){
 Serial.begin(9600);
 while(!Serial){}
 Ethernet.begin(mac,ip);
}
  • Asumiendo que no existen errores tales como hayamos olvidado de montar la placa ethernet o que no hayamos conectado el cable rj45, podemos dar inicio al servidor con el método begin():
void setup(){
 Serial.begin(9600);
 while(!Serial){}
 Ethernet.begin(mac,ip);
 servidor.begin();
}
  • Eso es todo lo que tenemos que hacer en la función setup, ahora corresponde hacer código en el loop,  lo que esperamos en el loop  es que estemos a la escucha de los clientes, si existe un cliente debe darse una respuesta; los clientes debemos de crearlos a través de la función EthernetClient() el cual valga la redundancia crea un objeto cliente, pero existe un detalle, este cliente no tiene conocimiento de las propiedades de conexión que se han realizado de lado del servidor, esto se lo podemos otorgar a través del método ClientConnect() o usando uno de los métodos del servidor que es available, avaible retorna un objeto EthernetClient con toda la configuración que hemos realizado, esto resulta un poco más coherente.
void loop(){
 EthernetClient cliente=servidor.available();
}
  • Para la lectura del cliente  podemos suscribirlo a un condicional tal que si existen datos estos se puedan leer, lo hacemos de la siguiente forma, cuando el core del código se ejecute detenemos la conexión a través del método stop():
void loop(){
 EthernetClient cliente=servidor.available();
 if(cliente){
  //código
 delay(1);
 cliente.stop();
 }
 
}
  • Nos vamos a centrar en el contenido dentro del condicional, ¿Qué debemos de hacer ahora?, pues debemos de garantizar que se transmita alguna información solo si es que el cliente está conectado (connected) y habilitado (available), además de crear una variable booleana que nos sirve para saber cuando una consulta http ha finalizado, esto es por lo general en una línea vacía o blanca, sí el cliente está conectado y disponible procedemos a leer los bytes a través del método read() entonces:
if(cliente){
 bool linea_blanca=true;
  while(cliente.connected(){
     if(cliente.available(){
        char c=cliente.read();
     }

 }
}
  • Entonces si detectamos un fin de línea y una línea blanca procedemos a generar la respuesta
      if (c == '\n' && linea_blanca) {
          // enviamos una respuesta estandar http a la cabecera
          cliente.println("HTTP/1.1 200 OK");
          cliente.println("Content-Type: text/html");
          cliente.println("Connection: close");  //La conexión se cerrará una vez completada la respuesta
          cliente.println("Refresh: 3");  // la pagina se actualizará automáticamente cada 3 segundos
          cliente.println();
          cliente.println("");
          cliente.println("");
          //aquí está nuestro sensor de luz
          valor_sensor=analogRead(sensorPin);
          cliente.print("El sensor de luz marca:");
          //aquí se imprime el valor del sensor
          cliente.print(valor_sensor);
          cliente.println("");
          break;
        }
  • Finalmente evaluamos si obtenemos una nueva línea o detectamos un carácter :
        if (c == '\n') {
          // se está reiniciando una nueva línea
          linea_blanca = true;
        } else if (c != '\r') {
          // tenemos un caracter en la línea
          linea_blanca = false;
        }

¿Cómo queda nuestro código finalmente ?

/ Ethernet - Version: Latest 
#include 
// SPI - Version: Latest 
#include 

byte mac[]={0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(192,168,1,51);
//creamos un servidor que esté a la escucha de los clientes
EthernetServer servidor(80);
//sensor de luz y su pin
int sensorPin=A0;
//seteamos una variable que ha de recibir el valor de lectura desde el sensor
int valor_sensor=0;
void setup() {
  //configuramos el puerto serial para la comunicación
  Serial.begin(9600);
  while(!Serial){}
  Ethernet.begin(mac,ip);
  servidor.begin();
   Serial.println(Ethernet.localIP());

}

void loop() {
    EthernetClient cliente = servidor.available();
  if (cliente) {
    // una consulta http termina en una línea blanca
    bool linea_blanca = true;
    while (cliente.connected()) {
      if (cliente.available()) {
        char c = cliente.read();
        if (c == '\n' && linea_blanca) {
          // enviamos una respuesta estandar http a la cabecera
          cliente.println("HTTP/1.1 200 OK");
          cliente.println("Content-Type: text/html");
          cliente.println("Connection: close");  //La conexión se cerrará una vez completada la respuesta
          cliente.println("Refresh: 3");  // la pagina se actualizará automáticamente cada 3 segundos
          cliente.println();
          cliente.println("");
          cliente.println("");
          valor_sensor=analogRead(sensorPin);
          cliente.print("El sensor de luz marca:");
          cliente.print(valor_sensor);
          cliente.println("");
          break;
        }
        if (c == '\n') {
          // se está reiniciando una nueva línea
          linea_blanca = true;
        } else if (c != '\r') {
          // tenemos un caracter en la línea
          linea_blanca = false;
        }
      }
    }
    // Le damos un tiempo al navegador para recibir la data
    delay(1000);
    // cerramos la conexión:
    cliente.stop();
    Serial.println("el cliente esta desconectado");
  }else{
   // Serial.println("error");
  }
}

Finalmente, quemamos nuestra placa con el código, si todo está ok, veremos un mensaje indicando que la operación se ha realizado con éxito, entonces toca ir al cliente (191.168.1.51) en donde debemos de  observar

6

Valor que irá cambiando a medida que el sensor tenga otros valores, le dejo una imagen del montaje, por cierto yo usé un Arduino Grove (para evitar el paso de como armar las conexiones del sensor, pero se puede realizar tranquilamente sin él).

52590216_10216678238081576_8417620212026703872_n

PD: El código

De la Fabricación Digital y sus Implicancias en la Industria Peruana – Parte 2

Hace un par de días inicie esta serie de apartados con la finalidad de generar algún tipo de reflexión sobre la fabricación digital y sus implicancias en la industria peruana, en el post anterior mencioné que existen 3 palabras claves alrededor de este análisis, Revoluciones industriales, Fabricación Digital e Industria Peruana, se abordó sobre la implicancia de la tercera revolución industrial que aunque ya se haya acuñado el nombre de la cuarta a la tercera aún le queda mucho por recorrer  aun más cuando nos acercamos a la siguiente evolución de la digitalización con el uso intensivo del internet de las cosas y que si bien la cuarta hace hincapié en los sistemas biológicos estos aún no resultan tan factibles de ser implementados en la industria, estos sistemas siguen siendo la frontera más lejana, que puede que ya haya demostrado su factibilidad pero no su rendimiento (aquí la nota) y aplicación. En este apartado nos dedicaremos a la fabricación digital.

La Fabricación Digital

La fabricación digital es un sistema de técnicas y metodologías que se basa en el proceso

aba

Y aunque cada uno de sus componentes representa un proceso con un resultante único no pueden llamarse fabricación digital sino se realiza como mínimo dos de los procesos en conjunto sea cual fuere el orden. El proceso productivo finalmente sigue siendo el mismo con detalles que lo caracterizan como propios de la tercera revolución industrial

fabricacionDigital

La fabricación digital hace uso intensivo del Control Numérico por Computador.

La manufactura aditiva (expresada en la impresión 3D).

Los programas por computador especializados CAM y CAD.

La ola de la electrónica libre

Las máquinas y programas de computador mostrados comparten algo en común, son accesibles económicamente o tienen una vía freeware, se aprovechan de la corriente prosumer que en términos de fabricación se expresa en las comunidades Maker. Los fabricantes de máquinas y software apuestan por una reducción de la complejidad en el uso y diversificación de posibilidades de creación. La consecuencia directa del uso de máquinas CNC es requerir el uso de materiales de formas regulares como lo son los tableros de madera, en especial los denominados MDF. Existe una fuerte inclinación hacia el diseño del producto, lo que brinda una complejidad y ventaja competitiva dura, esto aunado a la corriente de la personalización de los productos hace que los desarrollos puedan darse de forma comunitaria fortaleciendo el diseño al verse expuesto, lo físico sigue la dinámica que sigue desde hace mucho el software y que ya tiene comunidades de desarrollo muy cimentadas.

Una ventaja competitiva dura la podemos definir como aquella que se encuentra intrínsecamente ligada al diseño del producto y se expresa a través de los componentes del producto y su relación entre ellos, esto tiene una consecuencia directa sobre las ventajas que puede aprovechar una empresa:

caramelo

Cuando no se dispone de una ventaja competitiva dura, los productos entre una empresa y otra siempre serán los mismos, una silla será similar a otra tanto en materiales y proceso constructivo; sin diferenciación se puede entrar en una suerte de guerra de costos, para evitar ello las empresas estilan adquirir lo que definimos como ventajas competitivas blandas (sin relación alguna con habilidades blandas o duras), cuando usamos el término de duro o blando solo queremos referirnos a su fácil penetración o copia, una ventaja competitiva blanda puede expresarse en una apuesta hacia el marketing, mejor gestión, mejora del proceso productivo, podemos tener una sumatoria de las mismas y siempre seguirían siendo solo envolturas respecto a un producto que no posee una ventaja en sí mismo, recordemos que el diseño del producto re-define el proceso de fabricación, y es en el donde se define la estética y funcionalidad de un producto.

touch1

De la Fabricación Digital y sus Implicancias en la Industria Peruana – Parte 1

Hace un par de días, producto de una presentación que tenía para validar un viaje, me acusó una serie de reflexiones sobre la fabricación digital y sus implicancias para con la industria peruana, y como tal observé y me sorprendí lo diferenciado de pensamiento entre muchos entendidos del tema que se esta alrededor de si sus potencialidades impactan sobre la industria peruana existente o está generando una nueva (parte de las industrias creativas) y si esta representa uno de los tantos medios para acoplarse a la tercera o cuarta revolución industrial, este contenido, por ser producto de un análisis y propia conclusión, siempre puede estar sujeto a cualquier tipo de discrepancia, pero entonces, vayamos por partes.

Este análisis parte de 3 palabras claves: fabricación digital, revoluciones industriales e industria peruana (solo para contextualizar). Cuando hablamos de las revoluciones industriales, hablamos de momentos de cambios de paradigma sobre el como se produce, está demás decir que dichos cambios traen cambios de carácter social y cultural de la mano.

Revoluciones Industriales

Podemos resumir a las revoluciones industriales que nos han sucedido en el siguiente gráfico, esto ha sido abordado desde la observación de la evolución de las máquinas herramientas.

lasrevoluciones

 Y nos ceñiremos a lo siguiente: ¿Qué es la tercera y cuarta revolución industrial?; la tercera revolución tiene un fuerte componente tecnológico, en especial el causado por la evolución exponencial de las comunicaciones a través del internet, estamos en la era de lo inteligente (¿realmente inteligente?, quizá más en la exploración de lo inteligente), este término de “Tercera Revolución Industrial” fue acuñado por Jeremy Rifkin en su libro del mismo nombre en el 2011, en su libro se sostiene que lo que caracteriza la tercera revolución industrial es lo siguiente:

  • La transición hacia el uso de energías renovables
  • Una transformación cada vez mayor a edificaciones que generen energía
  • Mejora de las tecnologías de almacenamiento (baterías, pilas de hidrógeno).
  • Desarrollo de una red eléctrica inteligente o red de distribución de energía eléctrica
  • Transporte basado en vehículos eléctricos

La cuarta revolución industrial fue un término acuñado por Klaus Schwab, el cual en su artículo: “La cuarta revolución industrial: Qué significa, como responder” menciona:

La Primera Revolución Industrial utilizó la energía del agua y el vapor para mecanizar la producción. La Segunda uso energía eléctrica para crear producción en masa. La Tercera utilizó la electrónica y la Tecnología de Información para automatizar la producción. Ahora, la Cuarta Revolución Industrial se basa en la Tercera, la revolución digital que se viene produciendo desde mediados del siglo pasado. Se caracteriza por una fusión de tecnologías que está difuminando las líneas entre las esferas física, digital y biológica.”.

Frente a este enunciado, Jeremy Rifkin respondió en su artículoEl Foro económico mundial falla con su tema La Cuarta Revolución Industrial“:

¿Realmente importa si clasificamos la configuración tecnológica emergente como una Tercera o Cuarta Revolución Industrial? Yo creo que sí. Tanto el profesor Schwab como yo estamos de acuerdo en que la introducción de la tecnología digital en la sociedad durante el último medio siglo ha generado enormes redes interconectadas, cambiando fundamentalmente la manera en que organizamos nuestra vida económica, política y social. Los dos también estaríamos de acuerdo en que la digitalización es el sello distintivo y la tecnología que define a lo que se conoce como la Tercera Revolución Industrial.

Y hace la observación en que a la Tercera Revolución industrial le queda mucho camino por delante desde el momento en que nos aproximamos a la explosión que significaría el internet de las cosas lo cual traería una nueva etapa de digitalización.

internet-of-thingsEs importante acotar que ya se están realizando alcances sobre sistemas biológicos que tengan una implicancia para la industria;sin embargo, es muy pronto para decir que ello tiene un impacto a corto plazo, producto de las revoluciones de las comunicaciones (internet es uno de los mejores exponentes), estamos a un proceso de sofisticación de la maquinaria, pero al mismo tiempo en una reducción de sus costos, estos costos son empujados por la creación colaborativa que se vive a través de internet.

Esto trae otra dinámica de comportamiento del usuario:

Pasamos de una forma de consumo, donde no participamos de forma activa en la definición del producto, con el tiempo ha ido cambiando, donde podemos participar pero solo de forma pasiva, opiniones, focus-group, etc.

2darev

A una más activa con la tercera revolución industrial y que aprovecha la figura del prosumer, un usuario más activo en el proceso productivo, que crea y que comparte información, esto ha escapado más allá del software y se  traslada al mundo físico.

3era

Es una de las manifestaciones de la tercera revolución industrial, donde es posible que la innovación ya no sea propia de un trabajo intensivo de pocos, sino la búsqueda colaborativa de una solución a una necesidad común sin importar las cercanías geográficas.

Este post, ya se ha extendido mucho, seguimos en otro…