View Full Version : programma porta RS232
gurutech
22-04-2007, 01:05
ciao a tutti,
sto scrivendo per l'università un programma per spedire/ricevere dati dalla porta
seriale, per pilotare un robot.
penso di aver quasi finito (devo mettere una fork per gestire in parallelo l'invio e la ricezione) ma ho un problema:
sto provando il programma tra due pc collegati con un cavo null modem, ma pare che quando uno dei due invia all'altro un carattere 0x0d (carriage return) questo venga trasformato in un 0x0a (newline). qualcuno sa dirmi perchè? l'ora è tarda e non riesco più a concentrarmi, magari è una cavolata!
in allegato trovate il programma, il codice è coperto da licenza GPLv2 o, a vostra scelta, una versione successiva :)
gurutech
22-04-2007, 10:54
ecco, ho migliorato un po' il tutto.
ora i caratteri vengono spediti e ricevuti in maniera raw.
sono riuscito a trasferire un archivio tar.gz tra due pc
ho aggiunto il colore per differenziare i byte spediti da quelli ricevuti
ho messo i commenti al codice
ho bisogno di qualche parere sulle cose che si possono migliorare. grazie
http://www.gurutech.it/files/sendserial.zip
ilsensine
26-04-2007, 08:40
- Non hai indicato se intendi abilitare o meno il controllo di flusso hardwate (CRTSCTS). A meno che uno dei due nodi non lo supporta, sarebbe bene abilitarlo.
- Hai impostato l'fd come non bloccante, ma non controlli il risultato della write (potrebbe restituire -1 con errno==EAGAIN). Con una corretta gestione del flow control e dei risultati della write, potresti scrivere anche più di un byte alla volta, per una maggiore efficienza.
- Perché le usleep?
gurutech
26-04-2007, 09:07
- Non hai indicato se intendi abilitare o meno il controllo di flusso hardwate (CRTSCTS). A meno che uno dei due nodi non lo supporta, sarebbe bene abilitarlo.
devo controllare se il sensore laser che voglio controllare lo supporta
- Hai impostato l'fd come non bloccante, ma non controlli il risultato della write (potrebbe restituire -1 con errno==EAGAIN). Con una corretta gestione del flow control e dei risultati della write, potresti scrivere anche più di un byte alla volta, per una maggiore efficienza.
provo ad aggiungerlo appena ho un po' di tempo.
- Perché le usleep?
nelle specifiche del sensore che voglio pilotare c'è scritto che devono passare almeno 55 usec tra una richiesta e l'altra. lo so che non essendo in realtime non potrò mai controllare bene questo parametro, ma io ci ho messo delle usleep da 100 usec e buonanotte al secchio.
ilsensine
26-04-2007, 12:19
nelle specifiche del sensore che voglio pilotare c'è scritto che devono passare almeno 55 usec tra una richiesta e l'altra. lo so che non essendo in realtime non potrò mai controllare bene questo parametro, ma io ci ho messo delle usleep da 100 usec e buonanotte al secchio.
/me molto confused...
A 9600 baud, considerando 8 bit/char + 1 bit di stop, occorrono almeno 940 us per trasferire un carattere...
/me molto confused...
A 9600 baud, considerando 8 bit/char + 1 bit di stopConsiderando anche il bit di start siamo sopra il millisecondo. ;)
gurutech
26-04-2007, 16:45
ecco un pezzo del manuale (niente di segreto, roba che si reperisce su internet)
4.3 Time Conditions During Bi-Directional Communication
No longer than 6 ms must elapse between two bytes within a telegram sent to the LMS 2xx, otherwise a timeout is detected. The telegram is then ignored.
An interval of up to 14 ms can elapse between two bytes sent from the LMS 2xx within a telegram.
The minimum interval between two bytes sent to the LMS 2xx should be at least 55 μs.
ad ogni modo inizialmente ho cercato di pilotare direttamente l'apparato con gtkterm ma ho avuto un po' di problemi... infatti mi metteva delle letture spurie e non capivo perchè. inserendo le usleep è tutto ok. l'apparato che sto cercando di pilotare è un lettore laser per ambienti interni, fa n misure nel raggio di 180° e te le ritorna. oggi ho ottenuto per la prima volta una scansione "pulita". ho chiuso l'intorno del sensore con 3 cartoni in modo da formare una stanza. eccola
http://www.gurutech.it/files/scan1.jpg
ilsensine
27-04-2007, 07:47
Non so, andrebbe studiato un pò meglio. Innanzitutto la usleep causa uno sleep effettivo di almeno 1 ms, che è il tick dello scheduler; nel tuo caso, visto l'intervallo esiguo di attesa, avrebbe forse più senso un busy-loop o l'utilizzo del timer rtc (in entrambi i casi, eventualmente con scheduler RR). Metterei anche due bit di stop invece di uno, introduci a costo 0 un ulteriore ritardo di 100us tra i byte. Se non funziona, allora hai un problema da qualche altra parte!
Nota inoltre che questa condizione
No longer than 6 ms must elapse between two bytes within a telegram sent to the LMS 2xx, otherwise a timeout is detected.
rischia di non essere soddisfatta sui kernel 2.4. Per me l'intero "telegram" dovrebbe essere inviato dalla uart, quindi scritto con una unica write. Cercherei di farlo funzionare in questo modo, se ci riesci.
Ricapitolando, per me dovresti:
- due bit di stop
- invio di un "telegram" intero con una unica write (se il telegram è "piccolo", di pochi byte, entra completamente nel buffer della uart; altrimenti devi usare più write con delle poll per controllare lo stato del buffer)
- eventuale attesa tra l'invio di più "telegram". tcdrain può esserti di aiuto qui, per evitare usleep con valori "magici".
gurutech
27-04-2007, 08:13
...nel tuo caso, visto l'intervallo esiguo di attesa, avrebbe forse più senso un busy-loop o l'utilizzo del timer rtc (in entrambi i casi, eventualmente con scheduler RR)....
una breve ricerca mi ha portato alla funzione sched_setscheduler, a
questo (http://www.oreilly.com/catalog/linuxkernel/chapter/ch10.html) e a quest'altro (http://en.wikipedia.org/wiki/Round-robin_scheduling).
però non so bene di cosa parla. non sono un programmatore del kernel, più che altro sono un programmatore della domenica (il mio avatar ricorda che sarò un ing. elettronico)
Metterei anche due bit di stop invece di uno, introduci a costo 0 un ulteriore ritardo di 100us tra i byte.
questo dipende dalla velocità della seriale. su RS232 posso comunicare al massimo a 38400 con il sensore, ma in futuro potrei passare a RS422 per avere 500 Kbps.
- due bit di stop
- invio di un "telegram" intero con una unica write (se il telegram è "piccolo", di pochi byte, entra completamente nel buffer della uart; altrimenti devi usare più write con delle poll per controllare lo stato del buffer)
- eventuale attesa tra l'invio di più "telegram". tcdrain può esserti di aiuto qui, per evitare usleep con valori "magici".
non so se posso configurare i bit di stop, ci devo guardare. comunque per il momento devo solo ricevere i dati, ma in futuro dovrò ricevere i dati nel minor tempo possibile, perchè devo ricostruire un ambiente durante il movimento del robot sul quale è montato il sensore.
per l'unica write provo e ti faccio sapere.
ilsensine
27-04-2007, 11:11
questo dipende dalla velocità della seriale. su RS232 posso comunicare al massimo a 38400 con il sensore, ma in futuro potrei passare a RS422 per avere 500 Kbps.
Se l'intervallo tra i caratteri deve essere al max di 55us è abbastanza inutile alzare la velocità della porta oltre un certo limite.
non so se posso configurare i bit di stop
Sì che puoi, abilita CSTOPB e verificalo. I bit di stop sono sostanzialmente dei "tempi morti", vengono ignorati da chi legge i dati.
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.