電路板+電源
MPU晶片
板子上rs232的線
rs232轉usb接頭線
需求:
web server透過rs232送一串hex code給MPU晶片,MPU晶片會輸出hex code給web server,讓使用者透過網頁介面操控板子上的功能
尋找裝置:
透過dmesg得知插入板子的usb線後是 /dev/ttyUSB0 這個裝置
設定stty:
# stty -F /dev/ttyUSB0 raw speed 9600 -crtscts cs8 -parenb -cstopb #設定,指定device,注意:重新開機後要重新設定stty 不然收到的output會有錯誤(空白或斷掉)
# stty -F /dev/ttyUSB0 -a # 檢查,注意:要指定device
簡單的測試:
# cat /dev/ttyUSB0 > rs232.log # 因為板子傳hex編碼回來,把他倒到log檔再用sublime以hexadecimal開啟
# echo -en '\x01\x01\xCA\x60\x00\x03\xA9' > /dev/ttyUSB0 #送指令到板子上,output輸出到rs232.log
使用minicom監控:
安裝minicom後
# minicom -s
選Serial port setup(會依你使用者的設定檔而出現不同語言的介面),設定Serial Device和Bps/Par/Bits成9600 8N1(依你板子通訊協議而異),然後Save setup as dfl => Exit
因為板子要送指令才會有output,在另一個視窗送指令到板子,這邊才會顯示output,但因板子送回來的是hex code,這邊顯示是亂碼,故不使用minicom監控
minicom的操作方式
ctrl+a - z 顯示說明
ctrl+a - x 離開minicom
因操作指令和screen衝突且在我的screen設定下minicom介面會跑板,所以不在screen下操作
用php讀取hex code的檔案:
$handle = @fopen("rs232.log", "r"); if ($handle) { while (!feof($handle)) { $hex = bin2hex(fread ($handle , 4 )); print $hex."\n"; } fclose($handle); }
使用PHP-Serial控制:
https://github.com/Xowap/PHP-Serial
以examples/dummy.php為例:
include 'PhpSerial.php'; // Let's start the class $serial = new PhpSerial; // First we must specify the device. This works on both linux and windows (if // your linux serial device is /dev/ttyS0 for COM1, etc) $serial->deviceSet("/dev/ttyUSB0"); #改為你device的位置 // We can change the baud rate, parity, length, stop bits, flow control $serial->confBaudRate(9600); # 改頻率 $serial->confParity("none"); # 8N1的N $serial->confCharacterLength(8); # 8N1的8 $serial->confStopBits(1); # 8N1的1 $serial->confFlowControl("none"); // Then we need to open it $serial->deviceOpen(); // To write into $serial->sendMessage("\x01\x02\xCA\x60\x00\x03\x01\x03\x02\xAA"); # PHP的 "\x01" 直接是16進制字串,要使用\x01的字串要跳脫"\\x01",可從vim的highlight看出來。device直接吃hex code,所以這邊這樣寫。 // Or to read from $read = $serial->readPort(); $hex = bin2hex($read); #將output從binary轉成hex顯示到螢幕 echo "$hex\n"; // If you want to change the configuration, the device must be closed $serial->deviceClose(); // We can change the baud rate $serial->confBaudRate(9600); #改成你device的頻率
不能打開device:
錯誤訊息:
PHP Warning: Unable to open the device in php_serial.class.php on line 159
...
PHP Warning: Device must be opened to read it in php_serial.class.php on line 476
解法:
php.ini設定open_basedir 加入 /dev/
當兩個script同時去讀寫device時,output會發生互相影響的錯誤:
解法: 使用flock()
在PhpSerial.php
$this->_dHandle = @fopen($this->_device, $mode); #在後面加入:
if (flock($this->_dHandle, LOCK_EX|LOCK_NB)) {
$this->_lock = true;
print "\nNo problems, I got the lock, now I'm going to sit on it.";
} else {
$this->_lock = false;
print "\nDidn't quite get the lock. Quitting now. Good night.";
}
把sendMessage改成:
if($this->_lock){
$this->_buffer .= $str;
if ($this->autoflush === true) $this->flush();
usleep((int) ($waitForReply * 1000000));
}
Class新增屬性:
var $_lock = false;
將"00" 轉成hex code "\x00":
pack('H*',"00"); // hex code
使用C存取:
read.c:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
int main() {
unsigned char byte;
char ctl[] = "\x01\x01\xCA\x60\x00\x03\xA9";
// for(int i=0;i<strlen(ctl);i++)
// printf("%x",ctl[i]);
int fd = open("/dev/ttyUSB0", O_RDWR);
printf("fd=%d\n",fd);
write(fd, ctl, 8);
puts("Writed");
int i;
for(i =0;i<10;i++){
int size = (int)read(fd, &byte, 1);
if(size<1)break;
printf("Read %d bytes hex=%X c=%c\n",(int)size,byte,byte);
}
return 0;
}
# make read
# ./read
output:
fd=3
Writed
Read 1 bytes hex=1 c=
Read 1 bytes hex=1 c=
Read 1 bytes hex=CA c=�
Read 1 bytes hex=60 c=`
Read 1 bytes hex=0 c=
Read 1 bytes hex=3 c=
Read 1 bytes hex=81 c=�
Read 1 bytes hex=0 c=
Read 1 bytes hex=2 c=
Read 1 bytes hex=2A c=*
網頁無法執行PhpSerial,但能在console執行
ex.
# php dummy.php
0102ca600003aa
而
http://domain/dummy.php
Fatal error: No stty availible, unable to run.
(把PhpSerial _exec()裡面的$out印出來的錯誤是:
Array ( [0] => [1] => stty: standard input: Inappropriate ioctl for device ) )
方法1. 指定stty絕對位置
結果:失敗,/bin/stty 和 /usr/bin/stty都出現一樣錯誤
方法2. 加一下 system(' ls /dev/ttyUSB0 -l');
PHP:
system('which stty');
echo "<br />";
system(' ls /dev/ttyUSB0 -l');
output:
/usr/sbin/stty
crw-rw---- 1 http http 188, 0 Oct 20 11:07 /dev/ttyUSB0
看起來正常
方法3. 修改PhpSerial.php
在PhpSerial()中
- if ($this->_exec("stty") === 0) {
register_shutdown_function(array($this, "deviceClose"));
} else {
trigger_error(
"No stty availible, unable to run.",
E_USER_ERROR
);
}
結論:apache找不到stty設定(http@xxx $ stty ,出來是空白的),要指定設備才行
相關問題:
http://forum.arduino.cc/index.php?topic=38818.0;wap2
added the apache user (www-data) to the dialout group and it now works OK!! (但是我測試機是Arch Linux,沒有dialout,無法驗證。)
使用apache(httpd)執行command line:
修改/etc/passwd
$ sudo su http #就能切換成http執行指令了
把http使用者增加到root群組:
# gpasswd -a http root
Adding user http to group root
沒有留言:
張貼留言