GPIO 的作用
GPIO(通用输入/输出)线路是播放器主板上的引脚,应用可以逐条读取和驱动。线路可以是读取高电平或低电平的输入,也可以是由应用设为高电平或低电平的输出。
输入感知房间:
- 按钮,例如“呼叫服务”或“下一页”按钮。
- 门或窗触点、干簧管开关或限位开关。
- 任何带干触点的传感器,例如流量开关或移动探测器上的继电器输出。
输出据此动作:
- 释放电控门锁、切换信号灯塔或让蜂鸣器鸣响的继电器。
- 点亮按钮的 LED。
屏幕上的应用通过 screenrig.device.gpio 完成工作,并用 emit 告知你的智能体发生了什么,因此“已请求服务”会进入项目事件日志。你的智能体像处理其他应用一样构建应用、上传并放置到屏幕上。硬件页面展示应用还能访问什么。
哪些播放器有 GPIO
| 播放器 | GPIO | 输入上下拉 | 输出空闲电平 | 引脚编号 |
|---|---|---|---|---|
| Raspberry Pi 3、4 和 5(Linux 播放器) | 是,在 40 针排针上。播放器会自动找到排针芯片 | "up","down" 或 "none" | 是 | BCM 编号 |
| 其他 Linux 板子 | 是,使用 SCREENRIG_GPIO_CHIP | "up","down" 或 "none" | 是 | 该芯片的线路编号 |
| Android 和 Amazon Signage Stick | 设备开放可写 sysfs GPIO 芯片的情况 | 否:请加电阻 | 是 | 该芯片的线路编号 |
| BrightSign | 是:GPIO 接口上的引脚 0 到 7,或 BrightSign USB 转 GPIO 适配器 | 内置上拉 | 是 | 引脚 0 到 7,以及 BrightSign 一节中的范围 |
| macOS、Windows、播放器 Web 应用、Samsung Smart Signage (Tizen)、LG webOS Signage | 否 | 否 | 否 | 否 |
标志交给页面的控制者,或交给独占其页面的应用。只有在具备 GPIO 的播放器和设备上,应用才会看到 capabilities["device.gpio"] 为 true,因此同一个构建也能在没有 GPIO 的屏幕上运行。
设置播放器
Raspberry Pi
Raspberry Pi 无需设置。Linux 播放器会自行打开 Pi 3、4 或 5 的排针芯片,引脚即其 BCM 编号。播放器的用户需要有权访问 /dev/gpiochip*。在 Raspberry Pi OS 上,默认用户属于 gpio 组,已具备该权限。--kiosk 安装只会把其账户加入 video 和 i2c 组,因此请为不同的 --kiosk-user 账户加入 gpio 组,然后重启播放器:
sudo usermod -aG gpio KIOSK_USER其他 Linux 板子
在其他板子上,请在播放器的启动环境中用 SCREENRIG_GPIO_CHIP 指定承载这些线路的芯片:
SCREENRIG_GPIO_CHIP=/dev/gpiochip4对于 --kiosk 安装,请用 sudo systemctl edit screenrig-player-kiosk.service 将其添加到服务中:
[Service]
Environment=SCREENRIG_GPIO_CHIP=/dev/gpiochip4此时引脚就是该芯片的线路编号。播放器的用户需要有权访问芯片的设备文件。
Android
当设备开放可写的 sysfs GPIO 芯片时(例如标牌主板或自定义镜像),Android 才有 GPIO。引脚是芯片的全局线路编号。标准电视盒没有这类芯片,应用会看到 device.gpio 为 false。播放器仅在应用使用期间持有线路。Android 无法设置输入的上下拉:请接电阻,如连接按钮所述。
选择引脚
pin 是 0 到 255 的整数:芯片的线路编号。在 Raspberry Pi 上它是 BCM 编号,即 Pi 文档中所用的 GPIO 编号,而不是引脚在排针上的位置。GPIO17 是物理引脚 11。常用线路:
BCM 编号(pin) | 物理引脚 | 备注 |
|---|---|---|
| 17 | 11 | 合适的首选线路 |
| 27 | 13 | |
| 22 | 15 | |
| 23 | 16 | |
| 24 | 18 | |
| 25 | 22 | |
| 5 | 29 | |
| 6 | 31 | |
| 12 | 32 | |
| 13 | 33 | |
| 16 | 36 | |
| 26 | 37 | |
| 20 | 38 | |
| 21 | 40 | |
| 2 和 3 | 3 和 5 | 带固定上拉的 I2C 线路;请保留给 I2C 使用 |
| 14 和 15 | 8 和 10 | 串口控制台的线路 |
| 0 和 1 | 27 和 28 | 保留用于 HAT 识别 |
接地是物理引脚 6、9、14、20、25、30、34 和 39,3.3 V 是引脚 1 和 17。Raspberry Pi 文档列出了完整的排针。已被其他程序占用的线路会以 pin_busy 拒绝,芯片没有的线路会以 pin_not_found 拒绝。
驱动继电器
请通过继电器板驱动继电器,绝不要直接从引脚驱动。引脚在 3.3 V 下只能提供几毫安,无法切换继电器线圈、电控门锁、信号灯塔或蜂鸣器,而且线圈的电压尖峰可能损坏主板。继电器板上带有晶体管和线圈保护。
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)让负载通过继电器触点由其自身电源供电。请选择输入在 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大多数板子在高电平时吸合。许多廉价板子是低电平有效:输入被拉低时继电器吸合。对低电平有效的板子请传入 idle: true,这样页面离开时会让继电器释放为关闭。参见空闲电平。
await sr.device.gpio.write(27, false, { idle: true }); // active-low board: relay on
await sr.device.gpio.write(27, true, { idle: true }); // relay offBrightSign 的输出是经 100 Ω 的 3.3 V,因此 BrightSign 驱动继电器板的方式相同。
仅限 3.3 V
每条 GPIO 线路都是 3.3 V 逻辑。Raspberry Pi 的引脚不耐受 5 V,引脚上接 5 V 可能损坏主板。只连接干触点:按钮、开关或自身不带电压的继电器输出。输出 5 V、12 V、24 V 或市电电压的传感器,需要在它与引脚之间接电平转换器、光耦或继电器。
消抖
机械触点会抖动:按下时会在高低电平之间闪烁几毫秒。播放器会过滤触点抖动,因此处理程序把按下听作一次变化,把释放听作另一次变化。Linux 或 Raspberry Pi 线路会忽略约 20 ms 内稳定下来的变化。你无需编写任何代码,而且比这更短的脉冲不适合用作 GPIO 输入。
监听线路
onChange(pin, handler, options) 监视一条线路。处理程序以布尔值接收电平,高电平为 true。首次调用携带播放器开始监视时线路的电平,之后每次调用都是一次变化。该调用返回一个停止监视的函数。
const stop = window.screenrig.device.gpio.onChange(17, function (high) {
doorOpen = high;
}, { pull: "up" });同时最多监视 16 条线路,第 17 条会抛出 invalid_request。同一线路上的两个处理程序共用其上下拉:第二个处理程序若使用不同的 pull,会立即抛出 invalid_request。
空闲电平
write(pin, value, options) 接受 idle 选项,即页面释放线路时播放器将线路驱动到的电平。默认为低电平。页面离开屏幕、其上下文结束以及调用 screenrig.destroy() 时,会释放线路。随后播放器释放该线路。某个引脚最近一次写入决定其空闲电平。
这就是页面离开后继电器不会保持吸合的原因。请把 idle 设为对你的板子表示“关闭”的电平:大多数板子为低电平,低电平有效的板子为高电平。
页面离开时
页面持有的资源随页面结束。页面离开屏幕时,其输入停止,每个输出变为其空闲电平并被释放。播放器停止或设备断电时,线路也随之消失。请据此规划负载:选择一种在断电时按建筑需要上锁或解锁的电控门锁。
限制和错误
- 引脚是 0 到 255 的整数。
- 同时最多监视 16 条线路。
write会以invalid_request拒绝(pin、value或idle无效),以pin_not_found拒绝(芯片没有该线路),以pin_busy拒绝(线路被其他进程占用),以gpio_unavailable拒绝(播放器打不开任何 GPIO 芯片)。onChange会针对第 17 条线路或冲突的pull抛出invalid_request。被拒绝的监视会记入日志,处理程序永不运行。- 调用在发送任何内容之前会检查
inert、not_supported和capability_denied。SDK 参考列出了顺序。带有idle的write在无法设置它的播放器上会以not_supported拒绝。
示例:呼叫服务
接地的 GPIO17 上的按钮会告知你的智能体有顾客需要帮助,GPIO27 上的 LED 或蜂鸣器继电器随即响应五秒。第一次读数是线路已有的电平,因此处理程序只在电平由高变低时才动作。
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();页面离开屏幕时会把线路 27 释放到其空闲电平(除非你传入 idle,否则为低电平),因此页面离开前刚按下的按钮不会让继电器保持开启。
你的智能体从事件日志中读取每一次按下:
screenrig events list --type application.event --screen-id scr_SCREEN示例:门开输入
接地的 GPIO17 上的干簧管开关在门关上时闭合,因此门关时线路读为低电平,门开时读为高电平。门开着时页面显示提示,并告知你的智能体。
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
BrightSign 播放器运行同一套 API。引脚 0 到 7 是 GPIO 接口的线路,该接口位于 XT、XD 和 HD 型号上(DA-15 插座),引脚 0 是接口的线路 0,引脚 7 是其线路 7。其输入带有固定上拉,因此不提供 pull,接地的按钮可直接使用。idle 与在每个播放器上一样工作。输出为经 100 Ω 的 3.3 V:请通过继电器板驱动继电器。
BrightSign 可通过 USB 再增加两组线路:
| 引脚 | 它们是什么 |
|---|---|
| 0 到 7 | GPIO 接口 |
| 8 到 39 | USB GPIO 扩展器,每个 8 个引脚,最多 4 个:引脚 8 到 15 是第一个扩展器,16 到 23 是第二个,依此类推 |
| 100 到 110 | BP200 或 BP900 按钮板,编号 0:引脚 100+k 作为输入是按钮 k,作为输出是其 LED |
| 120 到 130、140 到 150 和 160 到 170 | 按钮板 1、2 和 3,方式相同 |
向引脚 100+k 写入会点亮按钮 k 的 LED,监视引脚 100+k 可获知该按钮。未连接的板或扩展器,其引脚会以 pin_not_found 拒绝。
在 app dev 中试用
screenrig app dev 模拟 GPIO。测试台显示一个 GPIO 芯片开关和三条模拟线路:17(低电平)、27(高电平)以及 22,22 被其他进程占用,因此返回 pin_busy。上面的示例使用 17 和 27。点击某条线路的电平即可更改,应用在监视该线路时会收到变化。应用的写入会改变线路,面板显示它设置的空闲电平。测试台接受 pull 和 idle,因此构建可在到达屏幕之前先在此运行。在本地开发介绍各个控件。
参考
- SDK 参考中的
screenrig.device.gpio.write()和screenrig.device.gpio.onChange()。 - 应用可以使用的硬件:每个播放器及每项设备功能。
- Raspberry Pi 数字标牌:把 Pi 作为屏幕。
- Linux 和 Raspberry Pi:安装播放器。
常见问题
- 屏幕能驱动继电器吗?
- 可以,通过继电器板。应用把线路设为高电平或低电平,继电器板切换电控门锁、信号灯塔或蜂鸣器。绝不要直接从引脚驱动继电器。
- 按钮需要电阻吗?
- 在 Raspberry Pi 或其他 Linux 板子上不需要:请求上拉,并把按钮接地。在 Android 上,请在线路与 3.3 V 之间加一个约 10 kΩ 的电阻。BrightSign 内置上拉。
- 引脚应传哪个编号?
- 在 Raspberry Pi 上传 BCM 编号:GPIO17 就是 17,位于物理引脚 11。在其他板子上传其 GPIO 芯片的线路编号。在 BrightSign 上传 BrightSign 一节中的引脚范围。
- 页面切换时继电器会怎样?
- 播放器把线路驱动到其空闲电平(除非应用另选,否则为低电平),然后释放它。对低电平有效的继电器板请选高电平,这样继电器处于关闭状态。
- 应用需要一直运行吗?
- 应用在其页面显示在屏幕上时进行监听。页面离开后,输入停止,输出变为其空闲电平。
- 费用是多少?
- screenRIG 免费。主板、按钮和继电器的费用由你承担。