[C/C++] Problème d'écriture/lecture sur port série.

Problème d'écriture/lecture sur port série. [C/C++] - C++ - Programmation

Marsh Posté le 21-05-2008 à 16:39:46    

[POST MIS A JOUR]
Voici une description plus précise :
 
Je vous explique mon projet. Il s'agit de commander un appareil électronique
relié au compteur EDF de l'école. Cet appareil sert à recueillir les
informations sur la charge, la consommation électrique etc... Moi je dois
écrire un programme qui communique avec lui pour récupérer des valeurs puis
les mettre dans une base de donnée accessible depuis l'intranet de l'école.
On doit prendre des mesures toutes les secondes.
 
L'appareil est un DIRIS C. Il possède une connexion série de
type RS485 (ou EIA 485). C'est une connexion sur deux fils, les deux fils
transmettant le même signal mais inversé (pour la résistance aux bruits entre
autre). Du côté PC, on m'a fournit un câble USB->RS232 puis un adaptateur
RS232->RS485 (la datasheet est jointe). En sortie de ce convertisseur, on a
branché les fils de connexion sur le "terminal block". Les bornes T+, R+ et la
borne + du diris sont reliées ensembles. De même pour les bornes T-, R- et -
du diris. Par soucis d'adaptation d'impédance, on a remplacé les fils entre T-
et R-, T+ et R+ par des résistances.
 
Voilà pour la partie montage.
 
Sur le PC, j'ai fedora 8 installé.
Le cable USB->RS232 s'installe facilement. Le driver est souvent présent de
base sur les diverses distributions de linux (la puce est un PL2303). Le port
se programme à travers un port série RS232 virtuel /dev/ttyUSB0.
 
Le diris communique à l'aide du protocole modbus en mode RTU (8bits de
données). La connexion est réglée comme ceci : 9600bauds, parité nulle, 1 bit
de stop.
 
Je programme en C++. Pour gérer le protocole modbus et le port série,
j'utilise des classe existantes rlModbus et rlSerial...( rl-library ).
 
J'ai écrit un petit programme de test séquentiel pour tester la
lecture/écriture sur le port série.
 
Quand je connecte les bornes T+ R+ et T- R- du convertisseur ensembles (sans
résistances ni connexion au diris), je reçois bien ce que j'envoie (j'ai même
analysé la trame avec un oscilloscope numérique). Dans ce cas, j'ouvre le port
série une seule fois et je le ferme en fin d'utilisation.
 
Quand je reconnecte tout comme décrit au début. Si j'ouvre le port au début du
programme et le ferme en fin de programme, je me retrouve sur la ligne avec
une multitude de répliques de ma trame d'envoi, collées à la première. Bien
entendu, le diris ne répond pas. Plus j'exécute le programme, et plus la trame
d'envoi grossit. A l'oscillo, elle arrivait même à durer plusieurs dixièmes de
seconde alors que je n'ai qu'une dizaine de caractères à transmettre.
 
Ce problème de répliques se règle en fermant le port entre l'écriture et la
lecture. J'arrive donc à recevoir ce que le diris m'envoie... mais une fois
sur 4 environ. Comme j'ai ma sortie branchée sur l'entrée (au niveau du
terminal block du convertisseur RS 232/485), je reçois systématiquement ce que
je transfère. La structure d'un requête d'envoi et celle d'une réponse ne sont
pas identiques. Je dois donc faire appel à une 1ère fonction pour lire ce que
j'envoie puis à une deuxième pour écouter ce que le diris m'envoie (Si la
fonction "réponse" reçoit une requête d'envoi, elle retourne une erreur).
Sur le papier, ça fonctionne, mais pas en vrai.
 
Lorsque je demande au diris de m'envoyer des données, je lui demande en fait
l'adresse physique de la 1ère valeur à m'envoyer puis le nombre (toutes les
valeurs dont j'ai besoin sont écrites de manière contigüe dans sa mémoire).
J'ai besoin de 13 valeurs codées sur 4 octets (2 mots). Si je les lui demande
toutes, en une seule fois, le programme reçoit quelque chose correctement une
fois sur 4 environ. Moins je lui demande de données, plus la probabilité de
recevoir correctement augmente. On arrive même à 100% avec une seule donnée.
Mais on ne peut pas en prendre 13 en 1 seconde. (environ 2 requêtes peuvent
être traitées sur ce temps). J'avais testé ça en mettant une alarme et un
signal handler qui écrit quand une seconde est passée.
 
J'ai remarqué aussi ceci : Si je demande successivement (toujours en fermant
le port série entre chaque lecture/écriture) 1 fois ma requête complète puis 4
fois une seule valeur, je reçois ma grande requête toujours correctement, mais
la 1ère (ou la deuxième) des petites est erronée à la réception. Sur
l'oscilloscope, les trames du diris ont toujours l'air correctes.
 
J'ai remarqué aussi que les probabilités de réception peuvent varier un peu
(en bien ou en mal) en changeant les flags lors de l'ouverture du port (en
modifiant les sources des rl-libs). Mais à vrai dire, ils me semblaient bien
configurés...
 
J'ai essayé aussi de créer une fonction qui ouvre le port en RW et une autre
en RD. Résultat identique 1/4 (toujours en fermant le port entre lecture et
écriture).
 
Ce que je pense de tout ca :
 
Au vu des repliques de trames... je dirais que la lecture a une incidence sur
le buffer (plysique) d'écriture. Comme c'est un port série virtuel, je ne sais
pas si c'est logiciel ou hardware (usb) comme buffer.
Ensuite je ne reçois pas très bien. Soit le message du diris et le mien sont
trop proches, le port les confond. A priori, si je reçois instantanément ce
que j'envoie, je devrais recevoir ce que le diris me dit. En effet, la norme
veut qu'il réponde au moins à 3.5 fois le temps d'un caractère (env
100microsecondes à 9600 bauds) après la fin de la réception du message. Donc
ça devrait être bon, mais non.
 
Voila. Si vous avez eu le courage de lire jusqu'au bout :)  
C'est assez urgent comme truc on doit rendre mardi -_-
Donc si vous avez des idées je les écoute volontier.


Message édité par vort3x le 24-05-2008 à 01:22:18
Reply

Marsh Posté le 21-05-2008 à 16:39:46   

Reply

Marsh Posté le 21-05-2008 à 16:49:28    

Petite précision... en ouvrant et en fermant le port apres chaque opération, je n'ai plus aucune réplique. Il doit y avoir un flag à mettre à jour ou à Reset, mais lequel?
 
Je suis preneur de bonnes idées.

Reply

Marsh Posté le 17-07-2008 à 12:21:59    

Salut, j´arrive trop tard pour t´aider dans ton sujet, mais il est fort probable que toi, tu puisses me donner un coup de main.
 
Je suis actuellement en stage, et je dois programmer des capteurs sans fils en C. Je travaille sous Linux, et j´utilise le port serie pour communiquer. Pour commencer, j´essaye simplement au travers de la console, mais deja la, ca bloque.  
En effet, j´utilise un sniffeur, qui me permet d´intercepter les sinaux qui partent depuis linux vers le capteur, et j´ai beau essayer d´envoyer des donnees, rien ne passe par rx et tx.  
 
Ma liaison serie se fait au travers d´un adaptateur Usb/rs232, comme toi. Je fais lsusb, et je vois le peripherique. Avec dmesg, je vois qu´il s´appelle ttyUSB0.
 
Seulement, quand je fais  
echo "0xFF" > /dev/ttyUSB0, rien ne se passe.
Si tu as une idee...

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed