Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Manufacturing Technology >> Proceso de manufactura

Lanzador de infrarrojos WiFi

Componentes y suministros

Espressif ESP8266 ESP-01
Puede hacer esto con un ESP8266 estándar en su lugar o con el kit de desarrollo NodeMCU
× 1
Arduino Nano R3
× 1
Transistor de uso general NPN
× 1
Adafruit IR LED
× 1

Herramientas y máquinas necesarias

Soldador (genérico)

Aplicaciones y servicios en línea

Arduino IDE
firmware NodeMCU

Acerca de este proyecto

Dos pasos adelante ...

Parece que los principales fabricantes de teléfonos se están alejando de los blásters de infrarrojos integrados, por lo que estoy buscando una manera de preparar mis dispositivos "tontos" para el futuro que actualmente no se integran con mi infraestructura de IoT. Tengo una casa inteligente en red en malla, pero necesito encontrar un control remoto físico para encender mi televisor. Tiene que haber una mejor manera.

Recientemente construí un blaster IR que controla acondicionadores de aire independientes en mi casa y otro proyecto anterior fue un respiradero HVAC conectado con una aplicación web conectada a Android. Básicamente, todo lo que necesito hacer es combinar estas dos cosas en un emisor de infrarrojos conectado a la web con una interfaz de aplicación web para poder presionar los botones de mi teléfono y enviar señales de infrarrojos a mis centros de medios. Estos pueden implementarse en todas las habitaciones y controlarse en cualquier lugar desde una única interfaz, por lo que las aplicaciones para esto son extremadamente amplias.

Creación rápida de prototipos

Cogí algo de hardware sin usar y conecté todo lo que necesitaba para conectarme a mi WiFi, aceptar conexiones HTTP y enviar señales de infrarrojos.

Esto funcionó bien, ya que podía solicitar una URL específica en la IP asignada al ESP8266 y hacer que Arduino emitiera una señal de "Energía" al LED de infrarrojos. Solo necesitaba averiguar dónde alojar la aplicación web, enviar las URL al emisor de infrarrojos y luego analizar esas solicitudes en códigos de infrarrojos específicos. Esto fue muy tedioso de hacer usando comandos AT con el ESP8266, y hubo algo que causó un retraso de 1-2 segundos entre el envío de la solicitud y el parpadeo del LED.

NodeMCU

Seguí adelante con la placa de desarrollo NodeMCU ESP8266 porque tiene regulación de potencia incorporada, interfaz USB a serie y muchos pines de E / S en este pequeño paquete (también es compatible con la placa de pruebas). Resulta que ya hay una biblioteca de servidor web ESP8266 que acepta solicitudes GET que pude adaptar para enviar códigos IR y la biblioteca IRremote normal funciona de inmediato.

El ESP8266 en NodeMCU no es lo suficientemente potente como para alojar la propia aplicación web, así que lo ejecutaré en un C.H.I.P. Computadora de $ 9 que ya se está ejecutando en mi red doméstica. Otra limitación es que el ESP8266 es que es una placa de 3.3v, por lo que los LED IR impulsados ​​directamente desde un pin de E / S eran muy tenues y tenían que estar justo al lado del dispositivo al que estaba enviando la señal. En su lugar, utilicé el pin de E / S para activar un transistor npn para encender / apagar el voltaje de suministro de 5v.

DESCANSO ... ish

Después de investigar un poco, encontré un excelente tutorial para implementar una API REST para que Arduino controle los LED en adafruit. Usé sus archivos JavaScript y PHP para enviar las solicitudes cURL y las cargué en el CHIP que ya está ejecutando Apache pero que podría alojarse fácilmente en la nube. Después de crear una página HTML básica para el control remoto, agregué los archivos manifest.json y de ícono para que pueda ejecutarse como una aplicación web nativa en un teléfono Android.

En el lado de Arduino, recorté el servidor web para aceptar una solicitud GET, analizar la URL, enviar un 200 OK y luego desconectar. Basado en la URL, el Arduino enviaría el código IR que se asignó al botón presionado.

Remonster universal

Todo funciona a la perfección con cero retrasos. Descubrí que los LED de infrarrojos que estoy usando tienen un ángulo muy estrecho, por lo que debo tener cuidado de que apunten correctamente. Un poco de velcro industrial me permite montarlo debajo de un estante, fuera de la vista, y se asegura de que quede apuntado a los receptores de infrarrojos del otro extremo. Agregué un cable de calibre grueso a los cables del LED para que puedan ajustarse con precisión.

Tener resistencias para los LED de infrarrojos hizo que fueran casi inutilizables, por lo que el transistor los está alimentando con 5v no regulados. Esto me permite rebotar IR en las paredes y montar el blaster en la habitación, pero definitivamente tendrá un efecto en la longevidad. Espero que, dado que se usan con poca frecuencia y las señales de infrarrojos son pulsos súper cortos (ciclo de trabajo más bajo que la mayoría de las señales PWM tenues), no necesitaré reemplazar los LED durante algún tiempo. Me aseguré de pedir algunos LED IR de gran angular y de mayor salida para la versión 2, así que cuando finalmente mueran, los reemplazaré junto con una resistencia en línea.

Actualización de 3 meses y funciones futuras

Lo uso todos los días y ha funcionado perfectamente. Incluso agregué un segundo dispositivo en nuestra sala familiar para controlar nuestra unidad de aire acondicionado de ventana y otro televisor.

Planes para el futuro:

  • Migre la interfaz de usuario web a un servicio en la nube
  • Integrar con Amazon Echo para comandos de voz (Listo)
  • La próxima iteración de hardware también tendrá un sensor de temperatura DHT22 y estoy investigando formas de transmitir RF para mis ventiladores de techo
  • Agregue un receptor de infrarrojos para una función de aprendizaje, de modo que pueda "enseñar" los comandos del emisor de infrarrojos desde los controles remotos existentes
  • Integrarme con la automatización / seguridad de mi hogar para apagar los electrodomésticos cuando no estén en uso

Este pequeño emisor de infrarrojos conectado está llenando lentamente la brecha entre mi hogar inteligente y los electrodomésticos heredados.

Código

  • WiFi IR Blaster para ESP8266 Arduino Sketch
  • script.js
  • index.html
  • curl.php
  • manifest.json
WiFi IR Blaster para ESP8266 Arduino Sketch C / C ++
Necesitará la biblioteca wifi ESP8266 e IRremote.h. También debe optar por no usar los códigos IR sin procesar si su control remoto es compatible con la biblioteca. Adapté este boceto de un controlador de aire acondicionado que construí que usaba códigos IR no estándar.
 / * * WiFi IR Blaster de Buddy Crotty * Use un módulo ESP8266 o placa de desarrollo para recibir la solicitud HTTP GET * y luego envíe códigos IR a un LED de infrarrojos adjunto en función de esas solicitudes. * Esto funciona mejor con otro servidor web que actúa como una interfaz que * envía solicitudes de cURL en función de los botones que se presionan. * formato cURL:http:// ESP8266 / IRcode * / # include  #include  #include  const char * ssid ="AP_SSID"; const char * password ="AP_Pass "; MDNSResponder mdns; int khz =38; // Frecuencia portadora de 38 kHz para NEC y SamsungIRsend irsend (4); // un LED IR está conectado a GPIO4 (pin D2 en NodeMCU) // Inserte la señal IR RAW para "TV Power" unsigned int irTVpwr [] ={4650,4250, 700,1550, 650,1550, 700,1550, 650,450 , 650,500, 600,500, 600,500, 600,550, 550,1700, 550,1650, 600,1650, 550,550, 600,500, 600,550, 550,550, 600,500, 600,550, 550,1650, 600,550, 550,550, 600,500, 600,550, 550,550, 600,500, 600 , 1650, 600,500, 600,1650, 550,1700, 550,1650, 600,1650, 550,1650, 600,1650, 600}; // SAMSUNG E0E040BF // Insertar señal RAW IR para "TV Source" unsigned int irTVsrc [] ={4600,4300, 700,1550, 650,1550, 650,1600, 650,450, 650,450, 600,550, 550,550, 600,500, 600, 1650, 550,1650, 600,1650, 550,550, 600,500, 600,550, 550,550, 550,550, 600,1650, 550,550, 550,550, 600,500, 600,500, 600,550, 550,550, 600,500, 600,550, 550,1650, 550,1700, 550, 1650, 600,1600, 600,1650, 600,1600, 600,1650, 550}; // SAMSUNG E0E0807F // Insertar señal RAW IR para "TV Mute" unsigned int irTVmute [] ={4650,4250, 700,1550, 650,1550, 700,1550, 650,450, 650,500, 600,500, 600,500, 600,500, 600, 1650, 600,1600, 600,1650, 550,550, 600,500, 600,550, 550,550, 600,500, 600,1650, 550,1650, 600,1650, 550,1650, 600,550, 550,550, 550,550, 600,500, 600,550, 550,550, 550,550, 600,500, 600,1650, 550,1650, 600,1650, 550,1650, 600}; // SAMSUNG E0E0F00F // Insertar señal RAW IR para "TV Volume Down" unsigned int irTVvdn [] ={4650,4250, 700,1550, 650,1550, 700,1550, 650,450, 650,450, 650,450, 600,550, 550,550, 600 , 1650, 550,1650, 550,1650, 600,550, 550,550, 550,550, 600,500, 600,500, 600,1650, 600,1600, 600,500, 600,1650, 550,550, 600,500, 600,500, 600,550, 550,550, 600,500, 600,1650 , 550,550, 550,1650, 600,1650, 550,1650, 600,1650, 550}; // SAMSUNG E0E0D02F // Insertar señal RAW IR para "TV Volume Up" unsigned int irTVvup [] ={4600,4300, 650,1600, 650,1550, 650,1600, 600,500, 600,550, 600,500, 600,550, 550,550, 550 , 1700, 550,1650, 600,1650, 550,550, 600,500, 600,550, 550,550, 600,500, 600,1650, 600,1650, 550,1650, 600,550, 550,550, 600,500, 600,550, 550,550, 600,500, 600,550, 550,550, 600 , 1600, 600,1650, 600,1650, 550,1650, 600,1650, 600}; // SAMSUNG E0E0E01F // Insertar señal RAW IR para "TV Channel Up" unsigned int irTVchup [] ={4650,4250, 700,1550, 650,1600, 650,1550, 650,500, 600,500, 600,500, 650,500, 600,500, 600 , 1650, 550,1650, 600,1650, 600,500, 600,500, 600,550, 550,550, 600,550, 550,550, 550,1650, 600,550, 600,500, 600,1650, 550,550, 600,500, 600,550, 550,1650, 600,550, 550,1650 , 600,1650, 600,500, 600,1650, 600,1600, 600,1650, 600}; // SAMSUNG E0E048B7 // Insertar señal RAW IR para "TV Channel Down" unsigned int irTVchdn [] ={4600,4350, 650,1550, 650,1600, 650,1600, 600,500, 600,500, 600,550, 550,550, 600,550, 550 , 1650, 600,1650, 550,1700, 550,550, 550,550, 600,500, 600,550, 550,550, 600,500, 600,550, 550,550, 550,550, 600,1650, 600,500, 600,500, 600,550, 550,1650, 600,1650, 600,1650 , 550,1650, 600,550, 550,1650, 600,1650, 600,1650, 550}; // SAMSUNG E0E008F7 // Insertar señal RAW IR para "Receiver Power" unsigned int irRECpwr [] ={9050,4350, 650,500, 600,1600, 600,500, 650,500, 600,1600, 600,550, 600,1600, 600,1650, 550,550, 600,500, 600,1600, 650,1600, 600,500, 600,1650, 600,1600, 600,500, 600,1650, 600,1600, 600,550, 600,1600, 600,500, 600,550, 600,1600, 600,1600, 650,500, 600,500, 600,1600, 650,500, 600,1600, 600,1650, 600,500, 600,500, 600}; // NEC 4B36D32C // Inserta la señal RAW IR para "Receiver Power On" unsigned int irRECpwrON [] ={9000,4400, 600,550, 600,1600, 600,500, 600,550, 600,1600, 600,500, 600,1600, 650,1600 , 600,1600, 600,500, 650,1600, 600,1600, 600,500, 650,1600, 600,1600, 600,500, 600,550, 600,500, 600,1600, 600,550, 600,500, 600,500, 650,500, 600,500, 600,1600, 650 , 1600, 600,500, 600,1600, 650,1600, 600,1600, 600,1600, 600,1600, 650}; // NEC 4BB620DF // Insertar señal RAW IR para "Receptor apagado" unsigned int irRECpwrOFF [] ={9000,4400, 600,550, 550,1650, 600,550, 550,550, 600,1650, 550,550, 600,1650, 550,1650 , 600,550, 550,550, 550,1650, 600,1650, 600,550, 550,1650, 600,1650, 550,550, 600,1650, 550,1650, 600,1650, 600,500, 600,550, 550,550, 600,1650, 550,550, 600,500 , 600,550, 550,550, 550,1700, 550,1650, 600,1650, 550,550, 600,1650, 550}; // NEC 4B36E21D // Insertar señal RAW IR para "Receiver Mute" unsigned int irRECmute [] ={9000,4400, 650,450, 650,1600, 600,500, 600,500, 650,1600, 600,500, 600,1650, 600,1600, 600,1600, 650,500, 600,1600, 650,1600, 600,500, 600,1600, 650,1600, 600,500, 600,1650, 600,500, 600,1600, 650,500, 600,500, 600,500, 600,500, 650,500, 600,500, 600, 1600, 650,500, 600,1600, 600,1600, 650,1600, 600,1650, 600,1600, 600}; // NEC 4BB6A05F // Insertar señal RAW IR para "Receiver Volume Down" unsigned int irRECvdn [] ={9150,4250, 750,350, 700,1550, 700,400, 700,450, 650,1550, 700,450, 600,1600, 650,1600 , 600,1650, 600,500, 600,1650, 600,1600, 600,550, 600,1600, 600,1650, 600,500, 600,1650, 600,1600, 650,500, 600,500, 600,500, 650,500, 600,500, 600,500, 600,550, 600,500 , 600,1650, 600,1600, 600,1650, 600,1650, 600,1600, 600,1650, 600}; // NEC 4BB6C03F // Insertar señal RAW IR para "Receiver Volume Up" unsigned int irRECvup [] ={9050,4400, 650,500, 600,1600, 600,550, 600,500, 600,1650, 600,500, 600,1600, 650,1600 , 600,1600, 600,550, 600,1600, 600,1600, 650,500, 600,1600, 650,1600, 600,500, 600,550, 600,1600, 600,550, 600,500, 600,550, 600,500, 600,550, 600,500, 600,1600, 650,500 , 600,1600, 600,1650, 600,1600, 600,1650, 600,1600, 600,1600, 600}; // NEC 4BB640BF // Insertar señal RAW IR para "Receiver Source CBL / SAT" unsigned int irRECsrc [] ={8950,4450, 600,500, 600,1650, 600,500, 600,500, 600,1650, 600,500, 600,1600, 600 , 1650, 600,1600, 600,550, 600,1600, 600,1650, 600,500, 600,1600, 600,1650, 600,500, 600,500, 600,1650, 600,1600, 600,1650, 600,500, 600,500, 600,500, 650,500 , 600,1600, 600,500, 600,550, 600,500, 600,1600, 600,1650, 600,1600, 600,1650, 600}; // NEC 4BB6708F // Crea una instancia del servidor // especifica el puerto para escuchar como un argumentoWiFiServer server (80); void setup () {Serial.begin (115200); retraso (10); irsend.begin (); // Conectarse a la red WiFi Serial.println (); Serial.println (); Serial.print ("Conectando a"); Serial.println (ssid); WiFi.begin (ssid, contraseña); while (WiFi.status ()! =WL_CONNECTED) {retraso (500); Serial.print ("."); } Serial.println (""); Serial.println ("WiFi conectado"); // Inicie el servidor server.begin (); Serial.println ("Servidor HTTP iniciado"); // Imprime la dirección IP Serial.print ("Dirección IP:"); Serial.println (WiFi.localIP ()); if (mdns.begin ("IRBlasterLR", WiFi.localIP ())) {Serial.println ("MDNS Responder iniciado"); } Serial.println (); Serial.println ();} void loop () {// Compruebe si un cliente se ha conectado WiFiClient client =server.available (); if (! cliente) {retorno; } // Espere hasta que el cliente envíe algunos datos Serial.println ("nuevo cliente"); while (! client.available ()) {retraso (1); } // Leer la primera línea de la solicitud String req =client.readStringUntil ('\ r'); Serial.println (req); cliente.flush (); // Hacer coincidir la solicitud if (req.indexOf ("/ irTVpwr")! =-1) {irsend.sendRaw (irTVpwr, sizeof (irTVpwr) / sizeof (irTVpwr [0]), khz); Serial.println ("IRreq irTVpwr enviado"); } else if (req.indexOf ("/ irTVsrc")! =-1) {irsend.sendRaw (irTVsrc, sizeof (irTVsrc) / sizeof (irTVsrc [0]), khz); Serial.println ("IRreq irTVsrc enviado"); } else if (req.indexOf ("/ irTVmute")! =-1) {irsend.sendRaw (irTVmute, tamaño de (irTVmute) / tamaño de (irTVmute [0]), khz); Serial.println ("IRreq irTVmute enviado"); } else if (req.indexOf ("/ irTVvdn")! =-1) {irsend.sendRaw (irTVvdn, tamaño de (irTVvdn) / tamaño de (irTVvdn [0]), khz); Serial.println ("IRreq irTVvdn enviado"); } else if (req.indexOf ("/ irTVvup")! =-1) {irsend.sendRaw (irTVvup, sizeof (irTVvup) / sizeof (irTVvup [0]), khz); Serial.println ("IRreq irTVvup enviado"); } else if (req.indexOf ("/ irTVchup")! =-1) {irsend.sendRaw (irTVchup, tamaño de (irTVchup) / tamaño de (irTVchup [0]), khz); Serial.println ("IRreq irTVchup enviado"); } else if (req.indexOf ("/ irTVchdn")! =-1) {irsend.sendRaw (irTVchdn, sizeof (irTVchdn) / sizeof (irTVchdn [0]), khz); Serial.println ("IRreq irTVchdn enviado"); } else if (req.indexOf ("/ irALLpwr")! =-1) {irsend.sendRaw (irRECpwrON, sizeof (irRECpwrON) / sizeof (irRECpwrON [0]), khz); irsend.sendRaw (irTVpwr, tamaño de (irTVpwr) / tamaño de (irTVpwr [0]), khz); retraso (2000); irsend.sendRaw (irRECsrc, tamaño de (irRECsrc) / tamaño de (irRECsrc [0]), khz); Serial.println ("IRreq irALLpwr enviado"); } else if (req.indexOf ("/ irRECpwr")! =-1) {irsend.sendRaw (irRECpwr, sizeof (irRECpwr) / sizeof (irRECpwr [0]), khz); Serial.println ("IRreq irRECpwr enviado"); } else if (req.indexOf ("/ irRECpwrON")! =-1) {irsend.sendRaw (irRECpwrON, sizeof (irRECpwrON) / sizeof (irRECpwrON [0]), khz); Serial.println ("IRreq irRECpwrON enviado"); } else if (req.indexOf ("/ irRECpwrOFF")! =-1) {irsend.sendRaw (irRECpwrOFF, sizeof (irRECpwrOFF) / sizeof (irRECpwrOFF [0]), khz); Serial.println ("IRreq irRECpwrOFF enviado"); } else if (req.indexOf ("/ irRECmute")! =-1) {irsend.sendRaw (irRECmute, sizeof (irRECmute) / sizeof (irRECmute [0]), khz); Serial.println ("IRreq irRECmute enviado"); } else if (req.indexOf ("/ irRECvdn")! =-1) {irsend.sendRaw (irRECvdn, sizeof (irRECvdn) / sizeof (irRECvdn [0]), khz); Serial.println ("IRreq irRECvdn enviado"); } else if (req.indexOf ("/ irRECvup")! =-1) {irsend.sendRaw (irRECvup, sizeof (irRECvup) / sizeof (irRECvup [0]), khz); Serial.println ("IRreq irRECvup enviado"); } else {Serial.println ("solicitud no válida"); client.stop (); regreso; } client.flush (); // Envía la respuesta al cliente //client.print(s); client.print ("HTTP / 1.1 200 OK \ r \ n"); retraso (1); Serial.println ("Cliente desconectado"); Serial.println (); // El cliente realmente se desconectará // cuando la función regrese y el objeto 'cliente' se destruya} 
script.js JavaScript
javascript para webapp (requiere jquery)
 // Función para enviar comandos IR función buttonClick (clicked_id) {if (clicked_id =="irTVpwr") {$ .get ("curl.php", {room:"192.168.1.62" , botón:"irTVpwr"}); } if (clicked_id =="irTVsrc") {$ .get ("curl.php", {habitación:"192.168.1.62", botón:"irTVsrc"}); } if (clicked_id =="irTVmute") {$ .get ("curl.php", {habitación:"192.168.1.62", botón:"irTVmute"}); } if (clicked_id =="irTVvdn") {$ .get ("curl.php", {habitación:"192.168.1.62", botón:"irTVvdn"}); } if (clicked_id =="irTVvup") {$ .get ("curl.php", {habitación:"192.168.1.62", botón:"irTVvup"}); } if (clicked_id =="irTVchup") {$ .get ("curl.php", {habitación:"192.168.1.62", botón:"irTVchup"}); } if (clicked_id =="irTVchdn") {$ .get ("curl.php", {habitación:"192.168.1.62", botón:"irTVchdn"}); } if (clicked_id =="irRECpwr") {$ .get ("curl.php", {habitación:"192.168.1.62", botón:"irRECpwr"}); } if (clicked_id =="irALLpwr") {$ .get ("curl.php", {habitación:"192.168.1.62", botón:"irALLpwr"}); } if (clicked_id =="irRECpwrON") {$ .get ("curl.php", {habitación:"192.168.1.62", botón:"irRECpwrON"}); } if (clicked_id =="irRECpwrOFF") {$ .get ("curl.php", {habitación:"192.168.1.62", botón:"irRECpwrOFF"}); } if (clicked_id =="irRECmute") {$ .get ("curl.php", {habitación:"192.168.1.62", botón:"irRECmute"}); } if (clicked_id =="irRECvdn") {$ .get ("curl.php", {habitación:"192.168.1.62", botón:"irRECvdn"}); } if (clicked_id =="irRECvup") {$ .get ("curl.php", {habitación:"192.168.1.62", botón:"irRECvup"}); }} 
index.html HTML
HTML básico para mostrar botones.
           



TV



Fuente

       


Receptor





curl.php PHP
script php para enviar solicitudes GET a ESP8266
  
manifest.json JSON
Esto permitirá que la página web se ejecute como una aplicación web nativa en Android.
 {"name":"WiFi Remote", "icons":[{"src":"remote_icon_36.png", "tamaños":"36x36" , "tipo":"imagen / png", "densidad":0.75}, {"src":"icono_remoto_48.png", "tamaños":"48x48", "tipo":"imagen / png", "densidad" :1.0}, {"src":"remote_icon_128.png", "tamaños":"128x128", "tipo":"image / png", "densidad":1.0}, {"src":"remote_icon_192.png" , "tamaños":"192x192", "tipo":"imagen / png", "densidad":1.0}], "alcance":"/ remoto /", "inicio_url":"/remote/index.html", "pantalla":"pantalla completa", "orientación":"retrato"} 

Esquemas

Realmente no hay nada, solo alimentación y un solo pin conectado a un transistor NPN para controlar dos LED IR en serie (sin resistencias) fuera del voltaje de suministro de 5v. Si desea ejecutar LED adicionales o necesita menos caída de voltaje de una fuente de 3.3v, puede usar un NPN transistor para cambiar varios transistores PNP (uno por LED). Esta configuración le permite usar tantos LED como su fuente de voltaje pueda suministrar corriente.

Proceso de manufactura

  1. Las deficiencias de WiFi RTLS
  2. Nueva tecnología inalámbrica 2015
  3. Cómo instalar un servidor web integrado seguro en un dispositivo WiFi de $ 3
  4. Comunicación MQTT entre NodeMCU y Raspberry Pi 3 B +
  5. ROBOT WIFI DE FRAMBUESA PI CONTROLADO DESDE EL TELÉFONO INTELIGENTE DE ANDROID
  6. Robot controlado por Wifi usando Raspberry Pi
  7. ¿Qué son las llamadas WiFi? ¿Cómo funciona?
  8. IOT - Smart Jar usando ESP8266, Arduino y sensor ultrasónico
  9. WebServerBlink usando Arduino Uno WiFi
  10. Cerradura de puerta inteligente usando la página de inicio de sesión de WiFi de Arduino y ESP8266
  11. ¿Qué es un Bead Blast? Una guía para el granallado