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

问题描述 投票:2回答:1

我从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构建,将扩展名添加到正确的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()获取干净的串行数据的事情:

  • 用各种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");
}
php windows serial-port arduino wamp
1个回答
0
投票

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

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

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

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.