le 04-22-2021 06:51 AM
Bonjour tout le mode,
J'ai un problème pour écrire un Double dans une adresse de registre via le protocole MODBUS.
Ce double évolue en continu et peu passer du positif au négatif.
Mon problème est que lorsqu'il passe au négatif, il ne va pas plus loin que -1. Pour allez plus loin je dois relancer le programme avec déjà -1 en mémoire.
Actuellement je fais un complément à deux pour résoudre le problème, mais la condition sur laquelle je m'appuie est de vérifier que ma valeur à écrire est inférieur à 0. Cependant dès que je passe le Zéro, je me retrouve avec une valeur à 4million (le max du type).
Comment puis faire ??
Résolu ! Accéder à la solution.
le 04-22-2021 01:54 PM
@DavidFrance44 a écrit :
Bonjour tout le mode,
J'ai un problème pour écrire un Double dans une adresse de registre via le protocole MODBUS.
Ce double évolue en continu et peu passer du positif au négatif.
Mon problème est que lorsqu'il passe au négatif, il ne va pas plus loin que -1. Pour allez plus loin je dois relancer le programme avec déjà -1 en mémoire.
Actuellement je fais un complément à deux pour résoudre le problème, mais la condition sur laquelle je m'appuie est de vérifier que ma valeur à écrire est inférieur à 0. Cependant dès que je passe le Zéro, je me retrouve avec une valeur à 4million (le max du type).
Comment puis faire ??
Qu'est-ce que ton appareil s'attend à recevoir comme format? Tu peux nous donner quelques exemples numériques? Par exemple valeur dbl = 25.5 on écrit la valeur U16 xxxx dans le registre x et le U16 yyyy dans le registre y, même chose pour une valeur négative, dbl = -7.2 valeur U16 dans les registres x = xxxx et y = yyyy.
Ton code est rempli de conversion qui font très peu de sens, il y a des doubles, des tableau de booléen, des I16, des U32. Tout cela peut être remplacé par du code très simple, mais il faudrait d'abord savoir quel est le format attendu.
Note, il n'y a rien d'anormal à obtenir 4 milliard en passant d'un nombre signé à non-signé 32 bits pour les valeurs négatives. Maintenant quelle représentation ton appareil espère recevoir pour les nombre négatif? Tu as des détails sur le protocole?
Ben64
04-23-2021 02:46 AM - modifié 04-23-2021 03:25 AM
Attention, les valeurs des registres Modbus sont des Words! Donc des u16. Cela signifie que pour transmettre un double 64bits signé tu dois faire une manipulation. Regarde dans la doc de ton appareil pour savoir qu'est-ce qu'il attend comme valeur, et dans quel registre.
04-23-2021 03:21 AM - modifié 04-23-2021 03:22 AM
Par exemple ça pourrait ressembler à cela :
le 04-23-2021 06:20 AM
@Walker34 a écrit :
Par exemple ça pourrait ressembler à cela :
@Walker34, ce code ne fonctionnera pas. Il faut utiliser la fonction ToI64 (To signed Quad Integer) et non pas un Typecast. Dans ce cas le typecast vers un U64 retournera le codage 64 bits IEEE754 d'un double et non pas sa valeur numérique.
Par exemple pour une valeur dbl = 10 le typecast retournera 0100000000100100000000000000000000000000000000000000000000000000 alors que ToI64 retournera 0000000000000000000000000000000000000000000000000000000000001010.
ToU64 retournera 0 pour les nombres négatifs alors il faut utiliser une conversion vers un entier signé. Dans le cas présent comme seulement 2 registres sont utilisés on pourrait convertir en I32. Le code à utiliser serait donc:
Un single serait probablement plus approprié qu'un double dans cette situation.
Ben64
04-23-2021 08:14 AM - modifié 04-23-2021 08:18 AM
@ben64 a écrit :
@Walker34 a écrit :
Par exemple ça pourrait ressembler à cela :
@Walker34, ce code ne fonctionnera pas. Il faut utiliser la fonction ToI64 (To signed Quad Integer) et non pas un Typecast. Dans ce cas le typecast vers un U64 retournera le codage 64 bits IEEE754 d'un double et non pas sa valeur numérique
Non je ne suis pas d'accord. Un appareil sur Modbus peut tout à fait transmettre la valeur binaire d'un double réparti sur 4 Words. Il faut ensuite la reconstruire de l'autre côté. Le cast en u64 c'est juste parce que un double c'est 64bits et qu'un u64 splitté en 4 ça donne 4x u16.
Si je regarde ton example: la valeur du double convertie en i32 va perdre toutes les informations des décimales. Comme si c'était arrondi. Si par exemple tu veux récupérer une valeur analogique, ce n'est clairement pas le but.
D'ailleurs ça se construit déconstruit sans perte de données :
Après c'est juste un exemple, finalement chaque appareil aura ses propres spécifications, il faudra s'adapter.
le 04-23-2021 09:06 AM
Bien sur que ça reconstruit en réutilisant le typecast, tu reconvertis le codage IEEE754 en nombre. Cependant au niveau modbus on s'attend probablement à recevoir une valeur numérique pas la représentation codée.
note: si on ne fait que transmettre une valeur à reconstruire tu as raison que ta méthode fonctionne. Mais si on veut changer la valeur d'un registre pour effectuer une action (comme pour commander la température d'une chambre thermale,mon interprétation) alors ça ne fonctionnera pas.
La conversion a I32 est utilisée car Il y a deux registres modbus dans l'exemple du message original donc 32 bits.
Ben64
le 04-23-2021 12:30 PM
Bon, je suis allé voir le protocole modbus et le protocole supporte le IEEE 32-bit floating point, donc dans ce cas on pourrait bien utiliser le typecast (désolé Walker34 tu avais raison pour le typecast!). Voir la section 2.3 du document joint (Modbus.pdf). Mon expérience du Modbus est avec des chambres thermales qui utilisent des valeurs numérique complément à 2 pour les négatifs et un entré registre diviseur pour la partie fractionelle.
Cependant comme c'est le 32-bits qui est supporté il faut donc convertir en single avant avant de faire un type cast. Je "typecaste" le double directement vers un tableau de U16, ainsi on peut connecter directement la sortie à l'entrée "registers to write" du vi Modbus Write Multiple Registers.
J'ai validé avec le tableau de la p.5 du pdf et découvert une erreur dans le tableau, 55.32 devrait être 425D47AE
Ben64
le 04-28-2021 02:09 AM
Bonjour, et merci,
Cependant il s'agit d'écrire un nb à virgule dans un automate schneider via toujours Modbus.
J'ai fait les modif et ai en entré un SGL puis j'adapte le type tel que vous me l'avez conseillé en ayant une représentation en U32, puis je décompose en 2 et construit un tableau avec mes 2 et envoie via modbus.
Le résultat lu dans l'automate est complètement incohérent.
Voici mon code :
Voici ma face avant avec le tableau de valeur qui doivent être transmis en modbus et dans l'ordre de défilement :
Et donc lorsque je regarde les mouvements dans le régistre concerner ici %MW1006 (type REAL sous schneider), ce n'ai pas cohérant avec mon tableau. J'ai bien du négatif et positif, mais rien n'est en ordre et bcp de valeur n'existe pas dans mon tableau.
Seriez vous ce qui peu poser problème.
schneider :
Cette dernière valeur par exemple ne fait pas partie du tout de mon tableau.
Les valeurs que je doit transmettre varie de -10 à 10.
Merci d'avance pour votre temps et vos conseilles.
David
04-28-2021 05:44 AM - modifié 04-28-2021 05:53 AM
C'est peut-être parce que certains produits Schneider utilisent des mots inversés . Voici ce que tu peux faire:
Ben64