【问题标题】:Reading data from serial port from Arduino on Windows via PHP. Data not matching serial monitor output通过 PHP 从 Windows 上的 Arduino 串口读取数据。数据与串行监视器输出不匹配
【发布时间】: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(也提到了 herehere),但是当我使用正确的匹配时,这不会在我的 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


    【解决方案1】:

    所以我运行了你的代码,我的 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);
      }
    } `
    

    向下滚动到“但没那么快...”以找到该 sn-p。

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-10
      相关资源
      最近更新 更多