Documentación

Botones y relés en GPIO

Conecte un pulsador, un contacto de puerta o una placa de relés a los pines GPIO de una pantalla, y la aplicación de la pantalla recibe el botón, controla el relé e informa a su agente.

Qué hace GPIO

Las líneas GPIO (entrada/salida de propósito general) son los pines de la placa de un Player que una aplicación puede leer y controlar uno por uno. Una línea es una entrada que lee alto o bajo, o una salida que la aplicación pone en alto o bajo.

Las entradas escuchan la sala:

  • Un pulsador, como un botón de "llamar al servicio" o de "página siguiente".
  • Un contacto de puerta o ventana, un interruptor reed o un final de carrera.
  • Cualquier sensor con contacto seco, como un interruptor de flujo o la salida de relé de un detector de movimiento.

Las salidas actúan sobre ella:

  • Un relé que libera un cerradero eléctrico, acciona una torre de luces o hace sonar un zumbador.
  • Un LED que ilumina un botón.

La aplicación de la pantalla hace el trabajo mediante screenrig.device.gpio e informa a su agente de lo ocurrido con emit, de modo que "servicio solicitado" aparece en el registro de eventos del proyecto. Su agente crea la aplicación, la sube y la coloca en la pantalla como cualquier otra. La página de hardware muestra a qué más puede acceder una aplicación.

Qué Players tienen GPIO

PlayerGPIOPull de entradaNivel de salida en reposoNúmeros de pin
Raspberry Pi 3, 4 y 5 (Player de Linux)Sí, en el conector de 40 pines. El Player encuentra solo el chip del conector"up", "down" o "none"SíLos números BCM
Otras placas LinuxSí, con SCREENRIG_GPIO_CHIP"up", "down" o "none"SíLos números de línea de ese chip
Android y Amazon Signage StickDonde el dispositivo expone un chip GPIO sysfs escribibleNo: añada una resistenciaSíLos números de línea de ese chip
BrightSignSí: pines 0 a 7 en el conector GPIO, o un adaptador USB a GPIO de BrightSignPull-ups integradosSíPines 0 a 7, y los rangos de la sección BrightSign
macOS, Windows, la app web Player, Samsung Smart Signage (Tizen), LG webOS SignageNoNoNoNo

La marca llega al controlador de la página, o a la aplicación que está sola en su página. Una aplicación ve capabilities["device.gpio"] como true solo en un Player y un dispositivo que tienen GPIO, de modo que una misma compilación también se ejecuta en una pantalla sin él.

Configurar el Player

Raspberry Pi

Una Raspberry Pi no necesita configuración. El Player de Linux abre por sí mismo el chip del conector de una Pi 3, 4 o 5, y un pin es su número BCM. El usuario del Player necesita acceso a /dev/gpiochip*. En Raspberry Pi OS el usuario predeterminado pertenece al grupo gpio, que lo concede. Una instalación --kiosk añade su cuenta solo a los grupos video y i2c, así que dé el grupo gpio a una cuenta --kiosk-user distinta y reinicie el Player:

sudo usermod -aG gpio KIOSK_USER

Otras placas Linux

En otra placa, indique el chip que contiene las líneas con SCREENRIG_GPIO_CHIP, en el entorno de lanzamiento del Player:

SCREENRIG_GPIO_CHIP=/dev/gpiochip4

Para una instalación --kiosk, añádalo al servicio con sudo systemctl edit screenrig-player-kiosk.service:

[Service]
Environment=SCREENRIG_GPIO_CHIP=/dev/gpiochip4

Entonces un pin es un número de línea de ese chip. El usuario del Player necesita acceso al archivo de dispositivo del chip.

Android

Android tiene GPIO donde el dispositivo expone un chip GPIO sysfs escribible, como una placa de señalización o una imagen personalizada. Un pin es el número de línea global del chip. Un TV box estándar no tiene ese chip, y la aplicación ve device.gpio como false. El Player mantiene una línea solo mientras la aplicación la usa. Android no puede establecer el pull de una entrada: conecte una resistencia, como en Conectar un botón.

Elija un pin

pin es un entero de 0 a 255: el número de línea del chip. En una Raspberry Pi es el número BCM, el número GPIO que nombra la documentación de la Pi, y no la posición del pin en el conector. GPIO17 es el pin físico 11. Líneas habituales:

Número BCM (el pin)Pin físicoNota
1711Una buena primera línea
2713
2215
2316
2418
2522
529
631
1232
1333
1636
2637
2038
2140
2 y 33 y 5Líneas I2C con pull-ups fijos; déjelas para I2C
14 y 158 y 10Las líneas de la consola serie
0 y 127 y 28Reservado para la identificación de HAT

Tierra son los pines físicos 6, 9, 14, 20, 25, 30, 34 y 39, y 3.3 V son los pines 1 y 17. La documentación de Raspberry Pi enumera todo el conector. Una línea que otro programa ya mantiene se rechaza con pin_busy, y una línea que el chip no tiene se rechaza con pin_not_found.

Conectar un botón

Conecte un pulsador entre una línea GPIO y tierra, y active el pull-up de esa línea. La línea lee alto hasta que se pulsa el botón, y una pulsación la lleva a tierra, de modo que una pulsación lee bajo.

 GPIO17 (pin 11) -----+
                      |
                   [ button ]
                      |
 GND (pin 9) ---------+

En una Raspberry Pi u otra placa Linux, pida el pull-up al Player con pull: "up":

window.screenrig.device.gpio.onChange(17, handlePress, { pull: "up" });

pull: "down" sirve para un botón conectado a 3.3 V, que lee alto al pulsarse. "none" es el valor predeterminado: el Player no establece ninguna polarización, de modo que una entrada sin nada conectado queda flotante y un botón sin resistencia lee cambios aleatorios.

Android no establece ningún pull, así que añada una resistencia de unos 10 kΩ desde la línea a 3.3 V (un pull-up) para un botón conectado a tierra. Un BrightSign tiene pull-ups integrados en sus entradas, y un botón conectado a tierra funciona tal cual.

Pedir "up" o "down" en un Player que no puede establecerlo no detiene el manejador: el SDK vigila la línea sin pull y registra una entrada warn con el código gpio_pull_unsupported.

Controlar un relé

Controle un relé mediante una placa de relés, y nunca directamente desde un pin. Un pin suministra unos pocos miliamperios a 3.3 V, lo que no basta para accionar la bobina de un relé, un cerradero eléctrico, una torre de luces o un zumbador, y el pico de tensión de una bobina puede dañar la placa. Una placa de relés lleva el transistor y la protección de la bobina.

 5V (pin 2) -------------- VCC |
 GND (pin 6) ------------- GND | relay board
 GPIO27 (pin 13) --------- IN1 |
                               |  COM ---- supply for the load
                               |  NO  ---- the load (door strike, light, buzzer)

Alimente la carga desde su propia fuente a través de los contactos del relé. Elija una placa cuya entrada se active a 3.3 V.

const sr = window.screenrig;
await sr.device.gpio.write(27, true);   // relay on
await sr.device.gpio.write(27, false);  // relay off

La mayoría de las placas se activan en alto. Muchas placas económicas son de activación en bajo: el relé se activa cuando la entrada se lleva a bajo. Pase idle: true para una placa de activación en bajo, de modo que una página que se va deje el relé apagado. Consulte Nivel en reposo.

await sr.device.gpio.write(27, false, { idle: true }); // active-low board: relay on
await sr.device.gpio.write(27, true, { idle: true });  // relay off

Una salida de un BrightSign es de 3.3 V a través de 100 Ω, de modo que un BrightSign controla una placa de relés de la misma manera.

Solo 3.3 V

Toda línea GPIO usa lógica de 3.3 V. Los pines de una Raspberry Pi no toleran 5 V, y 5 V en un pin pueden dañar la placa. Conecte solo contactos secos: un botón, un interruptor o una salida de relé que no lleve tensión propia. Un sensor que da 5 V, 12 V, 24 V o tensión de red necesita un adaptador de nivel, un optoacoplador o un relé entre él y el pin.

Antirrebote

Un contacto mecánico rebota: durante unos milisegundos una pulsación oscila entre alto y bajo. El Player filtra el rebote de contacto, así que el manejador recibe una pulsación como un cambio y la liberación como otro más. Una línea de Linux o Raspberry Pi ignora los cambios que se estabilizan en unos 20 ms. No hace falta código propio, y un pulso más corto que eso no es un uso de la entrada GPIO.

Recibir los cambios de una línea

onChange(pin, handler, options) vigila una línea. El manejador recibe el nivel como booleano, true para alto. La primera llamada trae el nivel que tiene la línea cuando el Player empieza a vigilar, y cada llamada posterior es un cambio. La llamada devuelve una función que deja de vigilar.

const stop = window.screenrig.device.gpio.onChange(17, function (high) {
  doorOpen = high;
}, { pull: "up" });

Se vigilan como máximo 16 líneas a la vez, y una 17.ª lanza invalid_request. Dos manejadores en una misma línea comparten su pull: un segundo manejador con un pull distinto lanza invalid_request de inmediato.

Nivel en reposo

write(pin, value, options) admite una opción idle, el nivel al que el Player lleva la línea cuando la página la libera. El valor predeterminado es bajo. La página libera una línea cuando deja la pantalla, cuando termina su contexto y cuando llama a screenrig.destroy(). Entonces el Player libera la línea. La última escritura de un pin fija su nivel en reposo.

Por eso un relé no queda activado cuando la página se va. Ponga idle en el nivel que significa "apagado" para su placa: bajo para la mayoría de las placas, alto para una placa de activación en bajo.

Cuando la página se va

Lo que mantiene una página termina con la página. Cuando se va de la pantalla, sus entradas se detienen y cada salida pasa a su nivel en reposo y se libera. Cuando el Player se detiene o el dispositivo pierde la alimentación, las líneas se van con él. Planifique la carga para eso: elija un cerradero eléctrico que bloquee o desbloquee como necesite el edificio cuando falla la energía.

Límites y errores

  • Un pin es un entero de 0 a 255.
  • Se vigilan como máximo 16 líneas a la vez.
  • write rechaza con invalid_request si pin, value o idle no son válidos, con pin_not_found si el chip no tiene esa línea, con pin_busy si otro proceso la mantiene y con gpio_unavailable cuando el Player no puede abrir ningún chip GPIO.
  • onChange lanza invalid_request con una 17.ª línea o un pull en conflicto. Una vigilancia rechazada se registra, y el manejador nunca se ejecuta.
  • Una llamada comprueba inert, not_supported y capability_denied antes de enviar nada. La referencia del SDK indica el orden. Un write con idle rechaza con not_supported en un Player que no puede establecerlo.

Ejemplo: llamar al servicio

Un botón en GPIO17, conectado a tierra, avisa a su agente de que un cliente quiere ayuda, y un LED o el relé de un zumbador en GPIO27 responde durante cinco segundos. La primera lectura es el nivel que la línea ya tiene, así que el manejador actúa solo ante un cambio de alto a bajo.

const sr = window.screenrig;

function active() {
  return sr.readyState === "active";
}

async function start() {
  if (!sr) return;
  await sr.waitUntilActive();
  await sr.ready();
  if (!sr.supports("device.gpio") || !sr.capabilities["device.gpio"]) return;

  let wasHigh = null;
  sr.device.gpio.onChange(17, function (high) {
    const pressed = wasHigh === true && high === false;
    wasHigh = high;
    if (!pressed || !active()) return;
    sr.emit("service.requested");
    document.getElementById("message").hidden = false;
    sr.device.gpio.write(27, true).catch(function () {});
    setTimeout(function () {
      document.getElementById("message").hidden = true;
      if (active()) sr.device.gpio.write(27, false).catch(function () {});
    }, 5000);
  }, { pull: "up" });
}
start();

Cuando la página deja la pantalla, la línea 27 se libera en su nivel en reposo, bajo salvo que pase idle, de modo que un botón pulsado justo antes de que la página se vaya no deja el relé encendido.

Su agente lee cada pulsación del registro de eventos:

screenrig events list --type application.event --screen-id scr_SCREEN

Ejemplo: entrada de puerta abierta

Un interruptor reed en GPIO17, conectado a tierra, se cierra cuando la puerta está cerrada, así que la línea lee bajo con la puerta cerrada y alto con ella abierta. La página muestra un aviso mientras la puerta está abierta y avisa a su agente.

const sr = window.screenrig;
const notice = document.getElementById("door-notice");

function show(open) {
  notice.hidden = !open;
  document.body.classList.toggle("door-open", open);
}

async function start() {
  show(false);
  if (!sr) return;
  await sr.waitUntilActive();
  await sr.ready();
  if (!sr.supports("device.gpio") || !sr.capabilities["device.gpio"]) return;
  sr.device.gpio.onChange(17, function (high) {
    show(high);
    if (sr.readyState === "active") sr.emit(high ? "door.opened" : "door.closed");
  }, { pull: "up" });
}
start();

BrightSign

Un reproductor BrightSign ejecuta la misma API. Los pines 0 a 7 son las líneas del conector GPIO, el conector de los modelos XT, XD y HD (una toma DA-15); el pin 0 es la línea 0 del conector y el pin 7 su línea 7. Sus entradas tienen resistencias pull-up fijas, así que pull no se ofrece y un botón conectado a tierra funciona tal cual. idle funciona igual que en todos los Player. Las salidas son de 3.3 V a través de 100 Ω: controle un relé mediante una placa de relés.

Un BrightSign añade dos bancos más de líneas a través de USB:

PinesQué son
0 a 7El conector GPIO
8 a 39Expansores GPIO USB, 8 pines cada uno, hasta 4: los pines 8 a 15 son el primer expansor, 16 a 23 el segundo, y así sucesivamente
100 a 110Una placa de botones BP200 o BP900, número 0: el pin 100+k es el botón k como entrada, y su LED como salida
120 a 130, 140 a 150 y 160 a 170Placas de botones 1, 2 y 3, de la misma manera

Una escritura en el pin 100+k enciende el LED del botón k, y una vigilancia en el pin 100+k recibe el botón. Una placa o un expansor que no está conectado hace que sus pines se rechacen con pin_not_found.

Pruébelo en app dev

screenrig app dev simula GPIO. El entorno de pruebas muestra un interruptor de chip GPIO y tres líneas simuladas: 17 (bajo), 27 (alto) y 22, que mantiene otro proceso y por eso responde pin_busy. Los ejemplos anteriores usan 17 y 27. Haga clic en el nivel de una línea para cambiarlo, y su aplicación recibe el cambio cuando vigila la línea. Una escritura de la aplicación mueve la línea, y el panel muestra el nivel en reposo que estableció. El entorno de pruebas acepta pull y idle, de modo que una compilación se ejecuta allí antes de llegar a una pantalla. Desarrollar localmente explica los controles.

Referencia

Preguntas

¿Puede una pantalla controlar un relé?
Sí, mediante una placa de relés. Una aplicación pone una línea en alto o bajo, y la placa acciona el cerradero eléctrico, la torre de luces o el zumbador. Nunca controle un relé directamente desde un pin.
¿Un botón necesita una resistencia?
En una Raspberry Pi u otra placa Linux, no: pida el pull-up y conecte el botón a tierra. En Android, añada una resistencia de unos 10 kΩ a 3.3 V. Un BrightSign tiene pull-ups integrados.
¿Qué número paso para un pin?
En una Raspberry Pi, el número BCM: GPIO17 es 17 y está en el pin físico 11. En otra placa, el número de línea de su chip GPIO. En un BrightSign, los rangos de pines de la sección BrightSign.
¿Qué pasa con un relé cuando cambia la página?
El Player lleva la línea a su nivel en reposo, bajo salvo que la aplicación haya elegido otro, y la libera. Elija alto para una placa de relés de activación en bajo, de modo que el relé quede apagado.
¿La aplicación necesita estar en ejecución todo el tiempo?
La aplicación escucha mientras su página está en la pantalla. Cuando la página se va, las entradas se detienen y las salidas pasan a su nivel en reposo.
¿Cuánto cuesta?
screenRIG es gratis. La placa, el botón y el relé corren por su cuenta.