电话
400 9058 355
PHP无法直接输出稳定PWM信号控制舵机,必须借助pigpio等底层库;推荐用PHP通过socket调用pigpiod服务,或以Python脚本为中间层执行exec调用。
树莓派或类似 Linux 单板机上用 PHP 控制舵机,本质是调用底层硬件接口(如 GPIO),而 PHP 没有内置 PWM 支持。你看到的“PHP 控制舵机”,实际是 PHP 调用外部工具(如 gpio 命令、servo 工具)或通过系统调用操作 /dev/gpiomem,再配合 C 库(如 wiringPi、pigpio)实现。纯 PHP 的 sleep() 或循环延时无法生成稳定 PWM,误差大、抖动严重,舵机会乱转或不动。
pigpio 是目前 Raspberry Pi 上最可靠的用户态 PWM 方案,支持精确到微秒级的脉宽控制,且自带
daemon(pigpiod),PHP 只需发 TCP 命令即可。它不依赖 root 权限(启动时加 -l 参数),比直接 mmap /dev/gpiomem 更安全。
sudo pigpiod -l
sudo netstat -tuln | grep 8888
$socket = fsockopen('127.0.0.1', 8888, $errno, $errstr, 1);
if ($socket) {
// 设置 GPIO 12 为 servo 模式,脉宽 1500μs(0°~180° 对应 500~2500μs)
fwrite($socket, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00");
fwrite($socket, "\x01\x00\x00\x00\x0C\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"); // set_servo_pulsewidth
fwrite($socket, "\x02\x00\x00\x00\x0C\x00\x00\x00\xB8\x05\x00\x00\x00\x00\x00\x00"); // 1500 decimal = 0x05B8
fclose($socket);
}注意:上面是简化示意,真实项目建议用封装好的 PHP 客户端库(如 php-pigpio),避免手动拼二进制协议。
舵机角度不是线性对应脉宽,但大多数标准舵机(如 SG90、MG90S)按如下近似映射:
500μs ≈ 0°1500μs ≈ 90°(中位)2500μs ≈ 180°但不同型号存在偏差,必须实测校准。另外,PHP 调用时若传入物理引脚号(如 Pin 12)而非 BCM 编号(GPIO 12),会控制错引脚;pigpio 使用的是 BCM 编号,不是 BOARD 编号。
如果不想处理 socket 协议,更简单的方式是写一个 Python 脚本(用 RPi.GPIO 或 gpiozero),接收角度参数,生成 PWM 并控制舵机,PHP 用 exec() 触发:
#!/usr/bin/env python3 import sys import time from gpiozero import Servo from time import sleepif len(sys.argv) != 2: print("Usage: python servo.py ") sys.exit(1)
angle = float(sys.argv[1])
注意:gpiozero 的 Servo 默认范围 -1 ~ +1,需换算(0°→-1, 180°→+1)
value = (angle / 90.0) - 1.0 value = max(-1.0, min(1.0, value))
servo = Servo(12) # GPIO 12 servo.value = value sleep(0.5) servo.close()
然后 PHP 中:exec('python3 /path/to/servo.py 90 2>&1', $output, $return);。这种方式开发快,但每次调用有启动开销,不适合高频调节(如每秒多次转动)。
真正稳定控制舵机的关键不在 PHP 语法,而在 PWM 时序精度和硬件抽象层的选择。绕过 pigpio 直接用 PHP 操作寄存器或延时模拟 PWM,基本不可行。别在 PHP 里写 for 循环控舵机——那不是控制,是试探运气。
邮箱:8955556@qq.com
Q Q:8955556
本文详解如何将Go官方present工具(用于生成HTML5...
PySNMP在不同版本中对SNMP错误状态(errorSta...
time.Sleep仅阻塞当前goroutine,其他gor...
PHPfopen()创建含特殊符号的文件名失败主因是操作系统...
WooCommerce中通过代码为分组产品动态聚合子商品的属...
io.ReadFull返回io.ErrUnexpectedE...
本文详解Yii2中控制器向视图传递ActiveRecord数...
本文详解为何通过wp_set_object_terms()为...
Pytest中使用@mock.patch类装饰器会导致补丁泄...
带缓冲的channel是并发安全的FIFO队列;make(c...