簡體   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