【发布时间】:2014-02-09 09:30:39
【问题描述】:
我从 Arduino Uno 发送到串行端口的数据可以在 Arduino 串行监视器中完全按照预期查看,但是在我的 WAMP 环境中通过 serproxy 从 PHP 读取数据时,我得到了一些丢失或额外的字符(通常是例如,在黑色菱形中看起来像问号的字符)。
我发现发布了类似的问题,但所有答案都不足。通常仅针对 Linux 提供解决方案,或者仅解决了让 Windows 从串行端口读取(而不是写入)所需要的众多挑战中的一部分。
我尝试了以下方法让 PHP 简单地读取 any 串行数据:
我首先尝试了建议的 php_serial 类,但很快发现它只允许在 Windows 上编写,并且其他堆栈溢出问题之一的答案 (Serial Communication Arduino to PHP) 建议仅替换 Linux 部分的代码代码,而不是 Windows。
文章Serial comm with PHP on Windows 还提到了 Windows 上 php_serial 类的容量有限,并建议了一个替代方案 serial extension(也提到了 here 和 here),但是当我使用正确的匹配时,这不会在我的 PHP 5.4.12 VC9 构建的 WAMP 环境中加载扩展版本,将扩展添加到正确的 php.ini 中,然后重新启动服务器。完成所有步骤后,我收到“模块 win_serial 未编译为 PHP”。如果其他人遇到此问题,请告诉我,因为我愿意再次调查。
最后,我尝试使用一个名为serproxy 的程序,它将网络套接字重定向到串行端口和从串行端口传出。这确实适用于我在 Arduino 的 GND 和 RESET 引脚上添加了一个 10uF 电容器以防止在PHP serial port data return from Arduino 中提到的新串行连接上的重置。
所以现在,我让我的 Arduino 通过 USB 电缆将数据发送到我的计算机,只要我在 Arduino 的串行监视器中监控数据,一切看起来都应该如此。当我在 PHP 中回显相同的数据时,我开始看到与流一起出现的额外或缺失数据。因此,当我的 PHP 脚本回显时,发送文本“AOK AOK AOK”有时会变成“OK?Pz[R”或类似的东西。
我试图从 PHP socket_read() 获取 clean 串行数据的事情:
搞砸了各种 mb_convert_encoding(如 'ASCII' 或 'utf-8')
设置串行数据的奇偶校验。我尝试在 serproxy 配置和 DOS 中将其设置为“EVEN”(运行“mode COM4: BAUD=9600 PARITY=E data=8 stop=1 XON=off TO=on”的命令并收到有效的响应/输出该命令有效正如预期的那样)
经过验证的波特率在 PHP 代码和 serproxy 配置中设置为 9600
尝试了简单的修剪和/或正则表达式来滤除噪音,但这并没有帮助,因为一些普通的字母数字字符也会随机混合在输出中
从php.net 修改了一些用于 TCP/IP 的示例套接字代码后,我有一个 PHP 脚本,它通过 serproxy 从串行端口写入 2048 位数据。该页面每 10 秒通过 jQuery 从另一个页面调用一次,并且回显的内容被加载到我主页上的 a 的内容中。
我的最终目标是将 1 或 0 的流发送到我的 PHP 脚本,以指示 a 应该切换它的背景颜色。我更愿意确定那些 1 或 0 不只是在额外字符中随机回显,而是真正来自串行流本身。
有谁知道 serproxy 是否是我在 PHP 中看到的添加或删除不需要的数据的原因?
串行监视器显示正确数据的事实向我表明这是 PHP 接收或解析数据的方式。
我没有什么可以检查的想法了。也许另一双眼睛会发现我忽略或做错的事情。
下面的具体例子请看我的代码:
serial.html
<!DOCTYPE html>
<head>
</head>
<body>
<div id="serial" name="serial" class="serial"></div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<script src="js/main.js"></script>
</body>
</html>
serial_output.php
<?php
// Set service port to 5334 for serproxy
$service_port = 5334;
// Using localhost address
$address = '127.0.0.1';
/* Create a TCP/IP socket. */
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
}
// Attempting to connect to '$address' on port '$service_port'...";
$result = socket_connect($socket, $address, $service_port);
if ($result === false) {
echo "socket_connect() failed.\nReason: ($result) " . socket_strerror(socket_last_error($socket)) . "\n";
}
// Read 2048 bits of data from socket and convert encoding to ASCII
$out = mb_convert_encoding(socket_read($socket, 2048), 'ASCII');
// Filter out anything that is not "AOK"
if(preg_match("/AOK/", $out)){
echo 1;
} else {
// Else output raw data so we can see what was actaully sent
echo $out;
}
// Closing socket...
socket_close($socket);
?>
main.js
// Set #serial background color to red when receiving a "1"
function setBgColor(){
var serial = $('#serial');
// Set #serial background color to red when receiving a "1"
if($('#serial').html() == "1") {
serial.css('background-color','red');
} else {
// Set #serial background to white if we did not receive a "1"
serial.css('background-color', 'white');
}
}
var intervalId = window.setInterval(function(){
$('#serial').load('serial_output.php');
setBgColor();
}, 100);
arduino_serial.ino
#include <avr/pgmspace.h>
void setup() {
// Initialize serial and wait for port to open:
// Currently I have parity on my serial port set to "EVEN" hence SERIAL_8E1
Serial.begin(9600, SERIAL_8E1);
}
void loop() {
Serial.println("AOK");
}
【问题讨论】:
标签: php windows serial-port arduino wamp