2012-10-20 10 views
8

Używam urządzenia szeregowego do projektu, a to, co próbuję wykonać po stronie komputera, nasłuchuje polecenia wysłanego przez urządzenie szeregowe, interpretuje zapytanie, uruchamia jakiś kod w zależności od zapytania i przesyła z powrotem wynik.Słuchacz portu szeregowego Linux i interpreter?

Szczerze mówiąc, próbowałem używać PHP jako słuchacza, i działa niestety nieskończona pętla wymagana do tego, aby skrypt działał jako odbiornik, ładuje procesor do 25%. Więc nie jest to najlepsza opcja.

Używam teraz cygwin, chciałbym utworzyć skrypt bash za pomocą natywnych poleceń systemu Linux.

mogę odbierać dane przy użyciu:

cat /dev/ttyS2 

i wysłać odpowiedź z:

echo "command to send" > /dev/ttyS2 

Moje pytanie brzmi, jak mogę zrobić zautomatyzowany słuchacz będzie w stanie odbierać i wysyłać dane ? Głównym problemem, jaki mam, jest w rzeczywistości, jak zatrzymać polecenie cat/dev/ttyS2 po otrzymaniu informacji, umieścić ją w zmiennej, którą wtedy mógłbym porównać z przełącznikiem, lub serię bloków if else then. Następnie odeślij odpowiedź i rozpocznij cykl od nowa?

Dzięki

+0

bash nie będzie moim pierwszym wyborem. Może być dobry czas na wypróbowanie małego pytona lub perla - oba mają biblioteki i przykłady tego. – stark

+0

Lub spróbuj użyć programowania systemu C i Linux. Nadal. Próbujesz stworzyć program typu serwer-klient w skrypcie Bash? – askmish

+0

Próbowałem już używać C++, jednak nigdy nie wkładałem rąk w tego rodzaju język programowania, więc nie udało mi się ... Używanie bash ma dla mnie większy sens, ponieważ mogę też z łatwością korzystać z aplikacji Windows i Linux z Cygwin . Jedno polecenie może użyć pliku wykonywalnego Windows lub pliku bat, aby zapisać wyjście do zmiennej, którą przekazuję do urządzenia szeregowego, i mogę używać poleceń Linuksa (takich jak wget) na drugiej linii bez konieczności pisania całej funkcji do wykonania więc w C++. – Matt

Odpowiedz

9

Czy tego nie szukasz?

while read -r line < /dev/ttyS2; do 
    # $line is the line read, do something with it 
    echo $result > /dev/ttyS2 
done 
+0

Dziękuję, to jest dokładnie to, czego potrzebowałem :) – Matt

+0

Jest tylko dla mnie, ale w moim przypadku Arduino jest resetowany za każdym razem, gdy " bubblebath

+1

@bubblebath: To na pewno możliwe, a rozwiązaniem byłoby przenieś ' rici

0

Jeśli używasz odpowiednich narzędzi, możliwe jest, aby rzeczywiście mieć swoje użycie procesora być dokładnie 0, gdy urządzenie nie ma żadnego wyjścia.

Aby to osiągnąć, powinieneś użyć języka wyższego poziomu (Perl, Python, C/C++ to zrobi, ale nie bash) i użyć pętli wyboru na górze uchwytu pliku urządzenia szeregowego. Jest to przykład dla Perl http://perldoc.perl.org/IO/Select.html, ale możesz używać dowolnego innego języka, o ile ma on obsługę select() syscall.

+0

Używając Cygwin, proces odsłuchiwania, utworzony za pomocą pętli podanej przez rici, (jak pokazano w Menedżerze zadań) wykorzystuje 0% CPU i tylko 100k pamięci. Jednak po otrzymaniu żądania z urządzenia szeregowego, procesor przyspiesza w zależności od złożoności wymaganego wyniku (takiego jak dopasowanie regexp, zwijanie w celu uzyskania informacji ze stron internetowych itp.), Waha się od 0% do 25%. Wydaje mi się, że używanie języka wyższego poziomu byłoby mniejsze, ale jestem zadowolony z wyników, ponieważ jest o wiele lepszy niż posiadanie pętli PHP w nieskończoność przy użyciu 25% procesora :) – Matt

1

Aby zachować niezależność od systemu, należy używać języka programowania wieloplatformowego: na przykład Python, należy użyć wieloplatformowej biblioteki szeregowej, na przykład: pySerial, i wykonać przetwarzanie wewnątrz skryptu. Użyłem pySerial i mogłem uruchomić skryptową platformę krzyżową bez prawie żadnych zmian w kodzie źródłowym. Korzystając z BASH, ograniczasz się do sprawiedliwego rozwoju.

+0

W pewnym sensie ograniczam się, ale z drugiej strony hand bash jest natywny w Linuksie, a także na Macu i jest dostępny w systemie Windows przez Cygwin. Nie używam też żadnego dodatkowego oprogramowania/pakietów/bibliotek, które nie byłyby dostępne na platformie w stanie natywnym. Za pomocą prostych poleceń, takich jak 'while read -r line/dev/ttyS2" Usuwam zależność wymaganych bibliotek lub oprogramowania, które mogą nie być przenoszone między różnymi platformami lub inaczej współpracują z danym systemem operacyjnym. Twoja metoda jest również bardziej logiczna, jak sądzę, ale nie znam Pythona :) – Matt

+0

czy używałeś cygwin do dostępu do pracy z portem Windows? –

+0

@Matt również jeśli używasz cygwin JESTEŚMY uzyskując biblioteki z nim :) zainfekuj całą UNIXY warstwę na górze okien –

0

Polecam używać C/C++ z Qt 5.1.1, to naprawdę proste i jeśli dobrze znasz framework to będzie bułka z masłem !!! Here możesz znaleźć więcej informacji i here więcej przydatnych przykładów, spróbuj, to naprawdę bezbolesne !! Możesz także rozwijać się po wygraniu, a następnie przenieść swój kod na Linuksa ... prosto.

zadeklarować obiekt tak:

QSerialPort mPort; //remember to #include <QtSerialPort/QSerialPort> 
//also add QT += serialport to your .pro file 

Następnie dodać ten kod:

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) 
{ 
    setupUi(this); 


    connect(this->pushButton,SIGNAL(clicked()),this,SLOT(sendData())); 

    mPort.setPortName("ttyS0"); 
    mPort.setBaudRate(QSerialPort::Baud115200); 
    mPort.setParity(QSerialPort::EvenParity); 

    if(!mPort.open(QSerialPort::ReadWrite)) 
    { 
     this->label->setText(tr("unable to open port, %1").arg(mPort.error())); 
    } 

    connect(&(this->mPort),SIGNAL(readyRead()),this,SLOT(readData())); 
} 

void MainWindow::sendData() 
{ 

    QByteArray data = lineEdit->text().toLatin1(); 
    if(mPort.isOpen()) 
    { 
     mPort.write(data); 
    } 
    else 
    { 
     this->label->setText(tr("port closed %1").arg(mPort.error())); 

    } 
} 


void MainWindow::readData() 
{ 

    QString newData; 
    int bread=0; 
    while(bread < mPort.bytesAvailable()){ 
     newData += mPort.readAll(); 
     bread++; 
    } 
    this->textEdit->insertPlainText("\n" + newData); 
}