繁体   English   中英

通过 PHP 从 Windows 上的 Arduino 串口读取数据。 数据与串行监视器输出不匹配

[英]Reading data from serial port from Arduino on Windows via PHP. Data not matching serial monitor output

我从 Arduino Uno 发送到串行端口的数据可以在 Arduino 串行监视器中完全按照预期查看,但是在我的 WAMP 环境中通过 serproxy 从 PHP 读取数据时,我得到了一些丢失或额外的字符(通常是一个看起来例如,像黑色钻石内的问号)。

我发现发布了类似的问题,但所有答案都不足。 通常仅针对 Linux 提供解决方案,或者仅解决了使 Windows 从串行端口读取(而不是写入)所需的众多挑战的一部分。

我尝试了以下方法让 PHP 简单地读取任何串行数据:

  • 我首先尝试了建议的 php_serial 类,但很快发现它只允许在 Windows 上编写,并且其他堆栈溢出问题之一的答案(从Arduino 到 PHP 的串行通信)建议只为代码的 Linux 部分替换代码,而不是视窗。

  • Serial comm with PHP on Windows 上的文章还提到了 Windows 上 php_serial 类的容量有限,并建议了一个替代串行扩展(也提到这里这里),但是当我使用 PHP 5.4.12 VC9 构建时,这不会加载到我的 WAMP 环境中使用正确的匹配扩展版本,将扩展添加到正确的 php.ini,然后重新启动服务器。 完成所有步骤后,我收到“模块 win_serial 未编译为 PHP”。 如果其他人遇到此问题,请告诉我,因为我愿意再次调查此问题。

  • 最后,我尝试使用一个名为serproxy的程序,该程序将网络套接字重定向到串行端口和从串行端口返回。 确实适用于我在 Arduino 的 GND 和 RESET 引脚上添加了一个 10uF 电容器以防止在新的串行连接上重置,如PHP 串行端口数据从 Arduino 返回中所述。

所以现在,我让我的 Arduino 通过 USB 电缆将数据发送到我的计算机,只要我在 Arduino 的串行监视器中监控数据,一切看起来都应该如此。 当我在 PHP 中回显相同的数据时,我开始看到与流一起出现的额外或缺失数据。 因此,当我的 PHP 脚本回显时,发送文本“AOK AOK AOK”有时会变成“OK?Pz[R”或类似的东西。

我试图从 PHP socket_read() 获取干净的串行数据的事情:

  • 搞砸了各种 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 接收或解析数据的方式。

我已经没有什么可以检查的想法了。 也许另一双眼睛会发现我忽略或做错的事情。

请参阅下面的代码以获取以下具体示例:

序列号.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>

串行输出.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");
}

所以我运行了你的代码,我的 Arduino 和加速度计也遇到了同样的问题。 我找到了三种方法来缓解这个问题。

首先只是根据您的预期错误检查您的数据。 如果数据与您的预期不符,请丢弃它。 如果您每秒获得 10 倍的数据,我想您可以承受损失一些数据。 [顺便说一句:serproxy 在不到 10 分钟内就崩溃了,所以它对我的用处有限]。

其次,只是延迟Arduino端的数据。 显然,数据丢失是关于 Arduinos 和串行端口的“已知问题”。 这个人在martinmelchior.be的网站有一些代码来延迟从 Ardunio 发送的数据流;

`void slowSerialPrint(char text[]) {
  for ( int i ; i < strlen(text) ; i ++ ) {
    Serial.print(text[i]);
    delay(5);
  }
} `

向下滚动到“但不是那么快...”以找到该片段。

最后,您可以尝试许多其他人正在做的事情并购买便宜的无线路由器并将其用作您自己的廉价 Wi-Fi 防护罩 其中,奇怪的是上面链接的网站是做什么的!

还需要注意的是,路由器在 5V 时的最大电流消耗为 185mA(OpenWrt 启动),WiFi 为 18dBm 时的平均电流消耗为 100mA,没有 WiFi 时为 80mA。 因此,路由器的平均功耗为 0.5W,非常低。

另外,感谢您发布的代码,我正在寻找一种完全按照您正在做的事情的方法,所以我实现了您的代码,遇到了同样的问题,通过减慢 Arduino 在 javascript 中的输出并丢弃脏数据来解决我的问题,然后扩展到其他选项。

tl; dr:我认为没有简单的解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM