简体   繁体   English

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

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

Data I send to the serial port from the Arduino Uno can be viewed exactly as expected in the Arduino serial monitor, but when reading the data from PHP through serproxy in my WAMP environment I am getting some missing or extra characters (often a character that looks like a question mark inside of a black diamond, for example).我从 Arduino Uno 发送到串行端口的数据可以在 Arduino 串行监视器中完全按照预期查看,但是在我的 WAMP 环境中通过 serproxy 从 PHP 读取数据时,我得到了一些丢失或额外的字符(通常是一个看起来例如,像黑色钻石内的问号)。

I've found similar questions posted, but all of the answers fell short.我发现发布了类似的问题,但所有答案都不足。 Often solutions were given for Linux only, or solved only part of the many challenges it takes to even get Windows to read (not write) from a serial port.通常仅针对 Linux 提供解决方案,或者仅解决了使 Windows 从串行端口读取(而不是写入)所需的众多挑战的一部分。

I tried the following to get PHP to simply read any serial data:我尝试了以下方法让 PHP 简单地读取任何串行数据:

  • I first tried the php_serial class suggested, but quickly found out it only allows writing on Windows, and the answer for one of the other stack overflow questions ( Serial Communication Arduino to PHP ) suggested replacement code only for the Linux portion of the code, not Windows.我首先尝试了建议的 php_serial 类,但很快发现它只允许在 Windows 上编写,并且其他堆栈溢出问题之一的答案(从Arduino 到 PHP 的串行通信)建议只为代码的 Linux 部分替换代码,而不是视窗。

  • The article at Serial comm with PHP on Windows also mentions limited capacity on Windows for php_serial class and suggests an alternative serial extension (also mentioned here and here ), but this would not load on my WAMP environment with PHP 5.4.12 VC9 build when I used the correct matching extension version, added the extension to the correct php.ini, and restarted the server. Serial comm with PHP on Windows 上的文章还提到了 Windows 上 php_serial 类的容量有限,并建议了一个替代串行扩展(也提到这里这里),但是当我使用 PHP 5.4.12 VC9 构建时,这不会加载到我的 WAMP 环境中使用正确的匹配扩展版本,将扩展添加到正确的 php.ini,然后重新启动服务器。 I received a "Module win_serial is not compiled into PHP" after following all of the steps.完成所有步骤后,我收到“模块 win_serial 未编译为 PHP”。 If anyone else has had this issue please let me know as I would be willing to look into this again.如果其他人遇到此问题,请告诉我,因为我愿意再次调查此问题。

  • Finally, I tried using a program called serproxy which redirects network sockets to and from serial ports.最后,我尝试使用一个名为serproxy的程序,该程序将网络套接字重定向到串行端口和从串行端口返回。 This does work with the caveat that I added a 10uF capacitor on the Arduino's GND and RESET pins to prevent reseting on new serial connections as mentioned at PHP serial port data return from Arduino .确实适用于我在 Arduino 的 GND 和 RESET 引脚上添加了一个 10uF 电容器以防止在新的串行连接上重置,如PHP 串行端口数据从 Arduino 返回中所述。

So now, I have my Arduino sending data to my computer via the USB cable, and so long as I am monitoring the data in Arduino's serial monitor, everything looks as it should.所以现在,我让我的 Arduino 通过 USB 电缆将数据发送到我的计算机,只要我在 Arduino 的串行监视器中监控数据,一切看起来都应该如此。 The moment I echo out that same data in PHP I begin to see extra or missing data along with the stream.当我在 PHP 中回显相同的数据时,我开始看到与流一起出现的额外或缺失数据。 So sending the text "AOK AOK AOK" sometimes becomes "OK?Pz[R" or something similar when echoed out of my PHP script.因此,当我的 PHP 脚本回显时,发送文本“AOK AOK AOK”有时会变成“OK?Pz[R”或类似的东西。

Things I've tried to get clean serial data from PHP socket_read():我试图从 PHP socket_read() 获取干净的串行数据的事情:

  • Messed around with various mb_convert_encoding (like 'ASCII' or 'utf-8')搞砸了各种 mb_convert_encoding(如 'ASCII' 或 'utf-8')

  • Setting parity of serial data.设置串行数据的奇偶校验。 I tried setting it to "EVEN" in serproxy config and DOS (ran command of "mode COM4: BAUD=9600 PARITY=E data=8 stop=1 XON=off TO=on" and recieved a valid response/output that command worked as expected)我尝试在 serproxy 配置和 DOS 中将其设置为“EVEN”(运行“mode COM4: BAUD=9600 PARITY=E data=8 stop=1 XON=off TO=on”的命令并收到有效的响应/输出该命令有效正如预期的那样)

  • Verified baud rate is set to 9600 in PHP code and serproxy config已验证的波特率在 PHP 代码和 serproxy 配置中设置为 9600

  • Attempted simple trimming and/or regular expressions to filter out noise, but it doesn't help as some normal alphanumeric characters are randomly mixed in the output as well尝试了简单的修剪和/或正则表达式来滤除噪音,但这无济于事,因为一些正常的字母数字字符也在输出中随机混合

Having modified some example socket code for TCP/IP from php.net , I have a PHP script that writes 2048 bits of data from the serial port via serproxy.php.net修改 TCP/IP 的一些示例套接字代码后,我有一个 PHP 脚本,它通过 serproxy 从串行端口写入 2048 位数据。 This page is called via jQuery from another page every 10th of a second and the echoed content is loaded into the contents of a on my main page.该页面每 10 秒通过 jQuery 从另一个页面调用一次,并且回显的内容被加载到我主页上的 a 的内容中。

My end goal is to send a stream of either 1's or 0's to be sent to my PHP script to indicate that a should toggle it's background color.我的最终目标是将 1 或 0 的流发送到我的 PHP 脚本,以指示 a 应该切换它的背景颜色。 I would prefer to be certain those 1's or 0's were not just randomly echoed among the extra characters and truly came from the serial stream itself.我更愿意确定那些 1 或 0 不只是在额外字符中随机回显,而是真正来自串行流本身。

Does anyone know if serproxy is the cause of the adding or removing the unwanted data that I'm seeing in PHP?有谁知道 serproxy 是否是我在 PHP 中看到的添加或删除不需要的数据的原因?

The fact that the serial monitor is showing the correct data indicates to me that it's something in the way PHP is receiving or parsing the data.串行监视器显示正确数据的事实向我表明这是 PHP 接收或解析数据的方式。

I'm running out of ideas on what else I could check.我已经没有什么可以检查的想法了。 Maybe another pair of eyes on this will bring to light something I've overlooked or did incorrectly.也许另一双眼睛会发现我忽略或做错的事情。

Please see my code below for specific examples below:请参阅下面的代码以获取以下具体示例:

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

<?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 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 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");
}

So I ran your code and had the same issues with my Arduino and an accelerometer.所以我运行了你的代码,我的 Arduino 和加速度计也遇到了同样的问题。 I found three ways to alleviate the issue.我找到了三种方法来缓解这个问题。

First is just to error check your data in terms of what you expected.首先只是根据您的预期错误检查您的数据。 If the data doesn't match what you expected, just discard it.如果数据与您的预期不符,请丢弃它。 If you are getting data 10x a second, I suppose you can afford to lose some.如果您每秒获得 10 倍的数据,我想您可以承受损失一些数据。 [BTW: serproxy crashes on me in under 10 minutes, so it's of limited use to me]. [顺便说一句:serproxy 在不到 10 分钟内就崩溃了,所以它对我的用处有限]。

Second, just delay the data on the Arduino side.其次,只是延迟Arduino端的数据。 Apparently the data loss is a "known issue" regarding Arduinos and serial ports.显然,数据丢失是关于 Arduinos 和串行端口的“已知问题”。 This person's site at martinmelchior.be has some code to delay the data stream being sent from the Ardunio;这个人在martinmelchior.be的网站有一些代码来延迟从 Ardunio 发送的数据流;

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

Scroll down to "But not so fast..." to find that snippet.向下滚动到“但不是那么快...”以找到该片段。

Finally, you could just try what many others are doing and buy a cheap wireless router and use that as your owninexpensive wi-fi shield .最后,您可以尝试许多其他人正在做的事情并购买便宜的无线路由器并将其用作您自己的廉价 Wi-Fi 防护罩 Which, oddly enough is what the site linked above does!其中,奇怪的是上面链接的网站是做什么的!

It is also good to note that that router's maximum current draw at 5V is 185mA (OpenWrt boot), average current draw with WiFi at 18dBm is 100mA, without WiFi 80mA.还需要注意的是,路由器在 5V 时的最大电流消耗为 185mA(OpenWrt 启动),WiFi 为 18dBm 时的平均电流消耗为 100mA,没有 WiFi 时为 80mA。 Hence the average router power consumption is 0.5W, which is incredibly low.因此,路由器的平均功耗为 0.5W,非常低。

Also, thank you for the code you posted, I was searching for a way to do exactly what you were doing, so I implemented your code, hit the same wall, solved my issue by slowing down the Arduino's output in javascript and discarding dirty data, then branched out into other options.另外,感谢您发布的代码,我正在寻找一种完全按照您正在做的事情的方法,所以我实现了您的代码,遇到了同样的问题,通过减慢 Arduino 在 javascript 中的输出并丢弃脏数据来解决我的问题,然后扩展到其他选项。

tl;dr: I don't think there is a simple solution. tl; dr:我认为没有简单的解决方案。

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

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