2012-10-20 24 views
8

Sto usando un dispositivo seriale per un progetto, e quello che sto cercando di realizzare sul lato PC, è ascoltare un comando inviato dal dispositivo seriale, interpretare la query, eseguire codice in base alla query e trasmettere di nuovo il risultato.Interprete e interprete di porte seriali Linux?

A dire il vero ho provato a utilizzare PHP come ascoltatore e funziona, purtroppo il ciclo infinito richiesto per far funzionare lo script come ricevitore, carica la CPU al 25%. Quindi non è davvero l'opzione migliore.

Attualmente sto usando cygwin, mi piacerebbe creare uno script bash usando i comandi nativi di linux.

posso ricevere dati utilizzando:

cat /dev/ttyS2 

E inviare una risposta con:

echo "command to send" > /dev/ttyS2 

La mia domanda è, come faccio a fare un ascoltatore automatizzato per essere in grado di ricevere e inviare dati ? Il problema principale che ho, è in realtà come faccio a interrompere il comando cat/dev/ttyS2 una volta che le informazioni sono state ricevute, metterle in una variabile che poi potrei confrontare con un interruttore o una serie di if else then blocks. In seguito rispedisci una risposta e ricomincia il ciclo?

Grazie

+0

bash non sarebbe la mia prima scelta. Potrebbe essere un buon momento per provare un po 'di python o perl - entrambi hanno librerie ed esempi per questo. – stark

+0

Oppure prova ad usare la programmazione del sistema C e linux. Ancora. Stai cercando di creare un tipo di programma client-server nello script di bash? – askmish

+0

Ho provato ad usare C++, tuttavia non ho mai messo le mani su quel tipo di linguaggio di programmazione, quindi non ho funzionato .. Usare bash ha più senso per me, dato che posso usare facilmente sia Windows che Linux con Cygwin . Un comando può usare un file eseguibile o bat di Windows per salvare l'output su una variabile che io passo al dispositivo seriale, e posso usare comandi Linux (come wget) sull'altra linea senza dover scrivere un'intera funzione da fare quindi in C++. – Matt

risposta

9

Non è questo quello che stai cercando?

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

Grazie, questo è esattamente ciò di cui avevo bisogno :) – Matt

+0

È solo per me, ma nel mio caso l'Arduino viene resettato ogni volta " bubblebath

+1

@bubblebath: Questo è certamente possibile, e la soluzione sarebbe sposta ' rici

0

Se si utilizzano strumenti giusti, è possibile avere in realtà l'utilizzo della CPU per essere esattamente 0 quando il dispositivo non ha alcun output.

Per fare ciò, è necessario utilizzare un linguaggio di livello superiore (Perl, Python, C/C++ farebbe, ma non bash) e utilizzare il ciclo di selezione sopra l'handle di file del dispositivo seriale. Questo è un esempio per Perl http://perldoc.perl.org/IO/Select.html, ma è possibile utilizzare qualsiasi altra lingua purché abbia il supporto per select() syscall.

+0

Utilizzando Cygwin, il processo listener, creato con il ciclo fornito da rici, (come mostrato nel Task Manager) utilizza CPU 0% e solo 100k di memoria. Tuttavia, una volta ricevuta una richiesta dal dispositivo seriale, la CPU aumenta a seconda della complessità dell'output richiesto (come la corrispondenza di espressioni regolari, l'arricciatura per ottenere informazioni da pagine Web, ecc.), E va dallo 0% al 25%. Immagino che usando un linguaggio di livello superiore questo sarebbe più piccolo, ma sono contento dei risultati, poiché è molto meglio che avere loop PHP infinitamente con il 25% di utilizzo della CPU :) – Matt

1

Per rimanere abbastanza indipendenti dal sistema, utilizzare un linguaggio di programmazione multipiattaforma: come Python, utilizzare una libreria seriale multipiattaforma come: pySerial ed eseguire l'elaborazione all'interno di uno script. Ho usato pySerial e ho potuto eseguire lo script su più piattaforme senza quasi modifiche al codice sorgente. Usando BASH ti stai limitando un po '.

+0

In un certo senso sto limitando me stesso, ma dall'altro hand bash è nativo in Linux e in Mac e disponibile su Windows tramite Cygwin. Inoltre, non sto utilizzando alcun software/pacchetto/libreria aggiuntivo che non sarebbe disponibile su più piattaforme nello stato nativo. Usando comandi semplici come 'while read -r line/dev/ttyS2' Sto rimuovendo la dipendenza delle librerie o del software richiesti che potrebbero non essere trasferiti su piattaforme diverse o che interagiscono in modo diverso con il sistema operativo in questione. Il tuo metodo è anche più logico, suppongo, ma non ho dimestichezza con Python :) – Matt

+0

ha fatto uso di cygwin per accedere a Windows com port work? –

+0

@Matt anche se stai usando cygwin stai ottenendo librerie con esso :) infatti un intero strato UNIXY in cima a windows –

0

Vorrei raccomandare di usare C/C++ con Qt 5.1.1, è davvero facile e se si ha familiarità con il framework sarà un pezzo di torta !!! Here potete trovare ulteriori informazioni e here altri esempi utili, provatelo, è davvero indolore !! Inoltre puoi sviluppare su win e quindi trasferire il tuo codice su linux ... in modo semplice.

dichiarare un oggetto come questo:

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

Poi aggiungere questo codice:

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