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

时间:2014-02-09 09:30:40

标签: php windows serial-port arduino wamp

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

我发现了类似的问题,但所有答案都没有达成。通常只为Linux提供解决方案,或者只解决了从串行端口获取Windows以读取(而不是写入)所需的许多挑战的一部分。

我尝试了以下方法让PHP只需读取任何串行数据:

  • 我首先尝试了建议的php_serial类,但很快发现它只允许在Windows上编写,而其他堆栈溢出问题(Serial Communication Arduino to PHP)的答案仅建议Linux的替换代码部分代码,而不是Windows。

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

  • 最后,我尝试使用名为serproxy的程序,该程序将网络套接字重定向到串行端口或从串行端口重定向。这个确实有一点需要注意,我在Arduino的GND和RESET引脚上添加了一个10uF电容,以防止在PHP serial port data return from Arduino中提到的新串行连接上重置。

现在,我让我的Arduino通过USB线将数据发送到我的电脑,只要我在Arduino的串口监听器中监控数据,一切看起来都应该如此。当我在PHP中回显相同的数据时,我开始看到额外的或丢失的数据以及流。所以发送文本“AOK AOK AOK”有时会变成“好吗?Pz [R”或类似的东西从我的PHP脚本中回显。

我试图从PHP socket_read()获取 clean 串行数据:

  • 使用各种mb_convert_encoding(如'ASCII'或'utf-8')进行讨论

  • 设置串行数据的奇偶校验。我尝试在serproxy配置和DOS中设置它为“偶数”(运行命令为“模式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调用,并且回显的内容将加载到我的主页面上的内容中。

我的最终目标是发送一个1或0的流来发送到我的PHP脚本,以指示应该切换它的背景颜色。我宁愿确定那些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");
}

1 个答案:

答案 0 :(得分:0)

所以我运行了你的代码并且与我的Arduino和加速度计有相同的问题。我找到了三种方法来缓解这个问题。

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

其次,只是延迟Arduino端的数据。显然,数据丢失是一个已知的问题&#34;关于Arduinos和串口。此人在martinmelchior.be的网站上有一些代码可以延迟从Ardunio发送的数据流;

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

向下滚动到&#34;但不要那么快......&#34;找到那个片段。

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

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

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

tl;博士:我不认为有一个简单的解决方案。