Prise en compte FC23 (Read/Write Multiple Registers)

Bonjour @Michel_F,

Maintenant que pymodbus 3.XX est entrée en stable je te sollicite pour le support de cette fonction pour la prise en charge de l’ecosystème Mastervolt / Masterbus.
Pour plus de détail sur son fonctionnement chez Mastervolt voici sa documentation :
https://images.mastervolt.nl/files/10000020472-ManualModbus-FR.pdf
J’espère que cela n’implique pas trop de développement et je serai biensur dispo pour tester en mode RTU dont j’ai le hardware dès que la version bêta la proposera.

Merci par avance pour cette étude de faisabilité et peut-être prise en compte :crossed_fingers:

A+
Renaud

Bonjour,

Merci pour ton intérêt pour MyModbus.

La fonction 23 est dispo dans pymodbus donc c’est possible. Par contre pour respecter le principe de Jeedom et de MyModbus, si je l’intègre, seule la partie lecture sera dans le cycle de polling et il faudra créer une commande action pour la partie écriture.

Ben justement, j’avais plus d’idée sur quoi rajouter à MyModbus :slight_smile:

Par contre je ne donne pas de délai (je pars bientôt en vacances, je ne veux rien promettre).

A+
Michel

1 « J'aime »

Je suis content de l’accueil pour cette évolution, espérons y arriver. Je n’ai pas trouvé beaucoup de systèmes qui interagissent avec Mastervolt. Ce sont pourtant de bons équipements pour la production électrique en isolé du réseau.
Aucun pb pour le délai, je serai également bientôt en vacances. et j’ai encore du pain sur la planche pour l’installation à proprement dite.
A+

Ca veut dire que ce n’est pas encore installé et donc si je te donne un script à tester, tu ne peux pas encore le tester ?

Je vais avoir des tests de faisabilité, parce que la fonction 23 est spéciale et en plus l’adaptation qui en est faite dans le convertisseur Modbus/Masterbus de Mastervolt rajoute une particularité.

A priori je me suis avancé en disant que c’est intégrable à MyModbus.
Alors… oui et non… Oui c’est intégrable mais pas pour ta passerelle à cause de la taille des données à envoyer : 12 octets, soit 6 registres. Il n’existe pas de format de donnée qui fait cette taille, sauf un string dans Jeedom. En tout cas, pas à ma connaissance.

Aujourd’hui MyModbus sait lire et écrire des variables numériques de 1 (que en lecture), 2, 4 et 8 octets. MyModbus sait lire une chaine de caractères qu’elle qu’en soit la longueur, du moment que l’appareil sait répondre.

MyModbus pourrait avoir la fonction 23 mais pour des types de variables compatibles et gérables.

Là c’est très spécifique comme format de données, la trame à construire est spéciale.

Ce que je veux dire, c’est que via MyModbus, ce ne sera pas possible à moins que je trouve le moyen d’écrire des plages de registres. Mais pour ça, il faut construire ladite plage de registres (dans votre cas, 6 registres).
Je doute de l’utilité d’une telle fonction (l’écriture d’une plage de registres). Jamais personne ne m’en a parlé et je ne vois pas d’application autre que la tienne.

Par contre, il serait tout à fait envisageable que je t’aide à développer un script capable de faire ce dont tu as besoin. Je te propose un script, tu le testes, je corrige, tu testes… ou tu me laisses la main sur ton Jeedom et je teste (ça irait plus vite, mais ce n’est pas obligatoire).

Donc je ne te lâche pas, mais ce ne sera pas intégré à MyModbus. Pas sous la forme dont tu as besoin en tout cas.

Non non j’ai déjà monté une VM Virtualbox , trouvé le port série et coté Mastervolt un réseau Masterbus avec qqs composants. C’est coté câblage électrique, il me reste le MPPT et les PV à monter.

Donc pas de soucis pour essayer un script on verra ce que l’on peut arriver à faire…

Pour info j’avais trouvé cet exemple d’intégration : Reading MODBUS function 23 and apply IEEE754 conversion | DATATAKER FORUM

Merci pour la proposition de regarder malgré les difficultés.
A+

Pour l’intégration, on va se débrouiller.

La VM est une bonne idée.

Par contre coté Masterbus et notamment pour l’utilisation et la configuration de MasterAdjust (le soft de Mastervolt), je ne vais absolument pas pouvoir t’aider. Je sais juste qu’il te faut un convertisseur USB/Masterbus (product code 77030100) pour configurer la passerelle avec ce soft.
De ce coté, tu as tout ? Tu maitrises ?

J’ai trouvé les paramètres de vitesse de transmission etc. pour le port série mais je ne sais pas quelle interface série tu utilises dans la VM.

Oui, oui, je l’ai et j’ai déjà noté qqs IDB et IDAL .
J’ai déjà réfléchi à la construction d’une trame, il me manque plus que le CRC.
Alors après je ne maitrise pas non plus mais je suis prêt pour apprendre :slight_smile:

Très bonne nouvelle. Il faut aussi les TabNr et Index, mais on va commencer avec une variable.

Le CRC est calculé par pymodbus, je ne le gère jamais, c’est totalement transparent.

Tu as un accès terminal à ta VM ?
Si je te donne un script, tu sais le copier sur ta VM ?
Je demande parce que je ne connais pas ton niveau d’aisance avec Linux, le terminal, etc.

wahoo je ne suis pas un expert mais comme tout jeedomien je bricole :wink:

Je veux bien ton script et qqs instrucutions :hugs:

Il faut d’abord que je le fasse :wink:

1 « J'aime »

Bonjour,

j’ai préparé quelque chose, voilà une procédure pour tester sachant que ça risque fortement de ne pas fonctionner puisque le script n’a jamais été testé.

1. Créer le script

Dans Réglages / Système / Editeur de fichiers, créer un fichier dans le répertoire tests avec cette icone :
image

Renommer ce fichier fc23.py
Double cliquer sur ce fichier et coller le script suivant :

#!/usr/bin/env python3

import logging
import argparse

from pymodbus import pymodbus_apply_logging_config

from pymodbus.client import ModbusSerialClient
from pymodbus.exceptions import ModbusException
from pymodbus.pdu import ExceptionResponse
from pymodbus import FramerType


pymodbus_apply_logging_config(logging.ERROR)
logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(levelname)s %(message)s')
_logger = logging.getLogger(__file__)


def parse_args():
    parser = argparse.ArgumentParser(description="Script de test de la fonctionnalité de lecture/écriture avec FC23")
    parser.add_argument("--port", type=str, default="/dev/serial0", help="Interface série à utiliser")
    parser.add_argument("--address", type=int, default=1, help="Device ID. Numéro de l'esclave")
    parser.add_argument("--idb", type=str, default="0217C1", help="Bus ID IDB (18 bit dans 3 octets)")
    parser.add_argument("--idal", type=str, default="0E", help="Bus ID IDAL (5 bit dans 1 octet)")
    parser.add_argument("--tabNr", type=int, default=0, help="Tab number")
    parser.add_argument("--index", type=int, default=1, help="Index")
    return parser.parse_args()


def main() -> None:
    args = parse_args()
    _logger.info("### Début du programme")

    assert 0 <= args.address <= 247, "L'adresse doit être entre 0 et 247"  
    assert len(args.idb) == 6, "IDB doit être long de 6 caractères pour représenter 3 octets"
    assert len(args.idal) == 2, "IDAL doit être long de 2 caractères pour représenter 1 octet"
    assert 0 <= args.tabNr <= 4, "Tab number doit être entre 0 et 4"
    assert 0 <= args.index <= 255, "Index doit être entre 0 et 255"

    # Construction des registres à envoyer
    registers = idx2reg(args.idal, args.idb)
    registers.append(args.tabNr)
    registers.append(args.index)
    
    # valeur à utiliser d'une manière ou d'une autre
    value = 0
    write_value = ModbusSerialClient.convert_to_registers(value, ModbusSerialClient.DATATYPE.FLOAT32)
    registers.extend(write_value) # valeur à écrire

    _logger.info("### Connexion au client")
    client = ModbusSerialClient(
        port=args.port,
        parity="E",
        framer=FramerType.RTU,
        timeout=5,
    )
    client.connect()
    _logger.info("### Client connecté")
    
    error = False

    try:
        # write_address => 0: read, 1: write d'après la documentation
        rr = client.readwrite_registers(read_address=0, read_count=0, write_address=0, values=registers, slave=args.address)
    except ModbusException as exc:
        _logger.error(f"Exception Modbus : {exc!s}")
        error = True
    if not error and rr.isError():
        _logger.error(f"Erreur")
        error = True
    if not error and isinstance(rr, ExceptionResponse):
        _logger.error(f"Response exception : {rr!s}")
        error = True
    
    if not error:
        _logger.info(f"Réponse: {rr.registers}")
        value = client.convert_from_registers(rr.registers[-4], client.DATATYPE.FLOAT32)
        _logger.info(f"Valeur lue: {value}")
    else:
        _logger.error("Une erreur est survenue")

    client.close()
    _logger.info("### Fin du programme")

def idx2reg(idal, idb) -> list[int]:
    registers = bytearray()
    registers.extend(bytes.fromhex(idal))
    registers.extend(bytes.fromhex(idb))
    ret = []
    for i in range(0, len(registers), 2):
        ret.append(int.from_bytes(registers[i:i+2], byteorder='big', signed=False))
    return ret

if __name__ == "__main__":
    main()

Cliquer sur le bouton Sauvegarder & Fermer :

2. Préparer le terrain

Ouvrir une session terminal (ssh ou console locale sur la VM) et se placer dans le répertoire tests et rendre le script exécutable :

cd ~www-data/html/tests
chmod +x fc23.py

2.1. Installer pymodbus

Pour éviter de perturber le système avec d’éventuelles dépendances supplémentaires à gérer on va faire ça dans un venv isolé. Dans le shell :

python3 -m venv modbus

Cette commande va créer un venv nommé modbus. Dans l’éditeurs de fichiers, si tu réactualises l’affichage, tu verras qu’un répertoire modbus est créé.
Pour activer ce venv :

source modbus/bin/activate

Maintenant on peut installer pymodbus et les dépendances pour les liaisons série dont tu as besoin dans le venv actif :

pip install pymodbus[serial]

3. Exécuter le script

Le script prend les paramètres suivants :

  • port : le port série à utiliser /dev/ttyUSB1 par exemple
  • address : device ID tel que défini dans la documentation chapitre 3 : 1 par exemple
  • idb : la valeur idb telle que définie dans la doc (en héxadécimal mais sans 0x devant) mais sur 2 caractères impérativement : 0E par exemple (pour reprendre l’exemple de la doc)
  • idal : la valeur idal telle que définie dans la doc (en héxadécimal mais sans 0x devant) mais sur 6 caractères impérativement : 0217C1 par exemple (pour reprendre l’exemple de la doc)
  • tabNr : la valeur tabNr telle que définie dans la doc : 0 pour monitoring
  • index : la valeur index telle que définie dans la doc : 1 pour reprendre l’exemple de la doc

Test avec la commande suivante. C’est à toi de renseigner les bons paramètres :

./fc23.py --port /dev/ttyUSB1 --address 1 --idb 0E --idal 0217C1 --tabNr 0 --index 1

Et à partir de là je ne peux plus tester chez moi, à toi de me dire ce qu’il se passe.

Si tout va bien tu vas avoir des log de retour dont une ligne avec Valeur lue : xxx. Si tu as ça du premier coup, je serai très étonné, un script ne fonctionne jamais du premier coup.

→ A toi de jouer !

Cela perdrait de son charme si cela fonctionnait du premier coup :wink:
Je suis impatient de me lancer dans les tests mais trop peu de temps aujourd’hui.
En tous cas je te remercie infiniment pour le temps que tu as déjà consacré à mon cas.
Bon weekend !

1 « J'aime »

Hello,

J’ai l’impression que c’est bien en place, excellent modeop :slight_smile:
En revanche , ça ne remonte pas de valeur mais j’ai bien un retour :

(modbus) root@jeedom:/var/www/html/tests# ./fc23.py --port /dev/ttyACM0 --address 1 --idb 039195 --idal 1B --tabNr 0 --index 1
2025-02-09 01:38:38,634 INFO ### Début du programme
2025-02-09 01:38:38,634 INFO ### Connexion au client
2025-02-09 01:38:38,640 INFO ### Client connecté
Traceback (most recent call last):
  File "/var/www/html/tests/./fc23.py", line 96, in <module>
    main()
  File "/var/www/html/tests/./fc23.py", line 65, in main
    rr = client.readwrite_registers(read_address=0, read_count=0, write_address=0, values=registers, slave=args.address)
  File "/var/www/html/tests/modbus/lib/python3.9/site-packages/pymodbus/client/mixin.py", line 632, in readwrite_registers
    return self.execute(no_response_expected, pdu_reg.ReadWriteMultipleRegistersRequest( read_address=read_address, read_count=read_count, write_address=write_address, write_registers=values,dev_id=slave))
  File "/var/www/html/tests/modbus/lib/python3.9/site-packages/pymodbus/client/base.py", line 203, in execute
    return self.transaction.sync_execute(no_response_expected, request)
  File "/var/www/html/tests/modbus/lib/python3.9/site-packages/pymodbus/transaction/transaction.py", line 104, in sync_execute
    self.pdu_send(request)
  File "/var/www/html/tests/modbus/lib/python3.9/site-packages/pymodbus/transaction/transaction.py", line 159, in pdu_send
    packet = self.framer.buildFrame(self.trace_pdu(True, pdu))
  File "/var/www/html/tests/modbus/lib/python3.9/site-packages/pymodbus/framer/base.py", line 62, in buildFrame
    data = message.function_code.to_bytes(1,'big') + message.encode()
  File "/var/www/html/tests/modbus/lib/python3.9/site-packages/pymodbus/pdu/register_message.py", line 108, in encode
    self.validateCount(125, count=self.read_count)
  File "/var/www/html/tests/modbus/lib/python3.9/site-packages/pymodbus/pdu/pdu.py", line 49, in validateCount
    raise ValueError(f"1 < count {count} < {max_count} !")
ValueError: 1 < count 0 < 125 !

Et voici la config de l’interface modbus, il y a peut-être qq chose à paramétrer ?

conf-modbus

OK, j’ai corrigé les paramètres de connexion et le nombre count qui pose problème. voilà le nouveau script, il suffit de remplacer par ceci :

#!/usr/bin/env python3

import logging
import argparse

from pymodbus import pymodbus_apply_logging_config

from pymodbus.client import ModbusSerialClient
from pymodbus.exceptions import ModbusException
from pymodbus.pdu import ExceptionResponse
from pymodbus import FramerType


pymodbus_apply_logging_config(logging.ERROR)
logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(levelname)s %(message)s')
_logger = logging.getLogger(__file__)


def parse_args():
    parser = argparse.ArgumentParser(description="Script de test de la fonctionnalité de lecture/écriture avec FC23")
    parser.add_argument("--port", type=str, default="/dev/serial0", help="Interface série à utiliser")
    parser.add_argument("--address", type=int, default=1, help="Device ID. Numéro de l'esclave")
    parser.add_argument("--idb", type=str, default="0217C1", help="Bus ID IDB (18 bit dans 3 octets)")
    parser.add_argument("--idal", type=str, default="0E", help="Bus ID IDAL (5 bit dans 1 octet)")
    parser.add_argument("--tabNr", type=int, default=0, help="Tab number")
    parser.add_argument("--index", type=int, default=1, help="Index")
    return parser.parse_args()


def main() -> None:
    args = parse_args()
    _logger.info("### Début du programme")

    assert 0 <= args.address <= 247, "L'adresse doit être entre 0 et 247"  
    assert len(args.idb) == 6, "IDB doit être long de 6 caractères pour représenter 3 octets"
    assert len(args.idal) == 2, "IDAL doit être long de 2 caractères pour représenter 1 octet"
    assert 0 <= args.tabNr <= 4, "Tab number doit être entre 0 et 4"
    assert 0 <= args.index <= 255, "Index doit être entre 0 et 255"

    # Construction des registres à envoyer
    registers = idx2reg(args.idal, args.idb)
    registers.append(args.tabNr)
    registers.append(args.index)
    
    # valeur à utiliser d'une manière ou d'une autre
    value = 0
    write_value = ModbusSerialClient.convert_to_registers(value, ModbusSerialClient.DATATYPE.FLOAT32)
    registers.extend(write_value) # valeur à écrire

    _logger.info("### Connexion au client")
    client = ModbusSerialClient(
        port=args.port,
        framer=FramerType.RTU,
        timeout=5,
    )
    client.connect()
    _logger.info("### Client connecté")
    
    error = False

    try:
        # write_address => 0: read, 1: write d'après la documentation
        rr = client.readwrite_registers(read_address=0, read_count=6, write_address=0, values=registers, slave=args.address)
    except ModbusException as exc:
        _logger.error(f"Exception Modbus : {exc!s}")
        error = True
    if not error and rr.isError():
        _logger.error(f"Erreur")
        error = True
    if not error and isinstance(rr, ExceptionResponse):
        _logger.error(f"Response exception : {rr!s}")
        error = True
    
    if not error:
        _logger.info(f"Réponse: {rr.registers}")
        value = client.convert_from_registers(rr.registers[-4], client.DATATYPE.FLOAT32)
        _logger.info(f"Valeur lue: {value}")
    else:
        _logger.error("Une erreur est survenue")

    client.close()
    _logger.info("### Fin du programme")

def idx2reg(idal, idb) -> list[int]:
    registers = bytearray()
    registers.extend(bytes.fromhex(idal))
    registers.extend(bytes.fromhex(idb))
    ret = []
    for i in range(0, len(registers), 2):
        ret.append(int.from_bytes(registers[i:i+2], byteorder='big', signed=False))
    return ret

if __name__ == "__main__":
    main()

Hello,

Oui c’est mieux, il y a 3 essais qui font bien clignoter la led « TX » de l’« USB TO RS485 » mais pas de réaction sur l’interface Modbus Mastervolt.

(modbus) root@jeedom:/var/www/html/tests# ./fc23.py --port /dev/ttyACM0 --address 1 --idb 039195 --idal 1B --tabNr 0 --index 1
2025-02-09 14:38:28,540 INFO ### Début du programme
2025-02-09 14:38:28,540 INFO ### Connexion au client
2025-02-09 14:38:28,547 INFO ### Client connecté
2025-02-09 14:38:48,569 ERROR transaction:118 No response received after 3 retries, continue with next request
2025-02-09 14:38:48,569 ERROR No response received after 3 retries, continue with next request
2025-02-09 14:38:48,569 ERROR Exception Modbus : Modbus Error: [Input/Output] No response received after 3 retries, continue with next request
2025-02-09 14:38:48,570 ERROR Une erreur est survenue
2025-02-09 14:38:48,633 INFO ### Fin du programme

J’avais cablé les 2 appareils comme cela :

Dis moi si je dois recreuser ce point ?

Merci @Michel_F

Ah maintenant j’ai compris la question… Je suis lent à la détente, désolé !
Oui, il faut paramétrer comme dans la doc :

  • Adresse : autre chose que 1 puisque 1 est pris par la passerelle (mets 101 par exemple)
  • Parité : paire, a priori sans bit de stop (si j’ai bien compris)
  • Vitesse 19200 → ok

Pour la câblage, c’est bien :

  • GND → GND
  • A → A
  • B → B

Ton adaptateur USB/RS485 est compatible RTU ?

Et du coup, comme je pensais, à tord, que c’était le configuration de la passerelle, j’ai modifié le script pour y coller mais il faut revenir en arrière pour cette partie :

#!/usr/bin/env python3

import logging
import argparse

from pymodbus import pymodbus_apply_logging_config

from pymodbus.client import ModbusSerialClient
from pymodbus.exceptions import ModbusException
from pymodbus.pdu import ExceptionResponse
from pymodbus import FramerType


pymodbus_apply_logging_config(logging.ERROR)
logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(levelname)s %(message)s')
_logger = logging.getLogger(__file__)


def parse_args():
    parser = argparse.ArgumentParser(description="Script de test de la fonctionnalité de lecture/écriture avec FC23")
    parser.add_argument("--port", type=str, default="/dev/ttyACM0", help="Interface série à utiliser")
    parser.add_argument("--address", type=int, default=1, help="Device ID. Numéro de l'esclave")
    parser.add_argument("--idb", type=str, default="0217C1", help="Bus ID IDB (18 bit dans 3 octets)")
    parser.add_argument("--idal", type=str, default="0E", help="Bus ID IDAL (5 bit dans 1 octet)")
    parser.add_argument("--tabNr", type=int, default=0, help="Tab number")
    parser.add_argument("--index", type=int, default=1, help="Index")
    parser.add_argument("--baudrate", type=int, default=19200, help="Vitesse de transmission")
    parser.add_argument("--bytesize", type=int, default=8, help="Longueur des données")
    parser.add_argument("--parity", type=str, default="E", help="Parité")
    parser.add_argument("--stopbits", type=int, default=0, help="Bits de stop")
    return parser.parse_args()


def main() -> None:
    args = parse_args()
    _logger.info("### Début du programme")

    assert 0 <= args.address <= 247, "L'adresse doit être entre 0 et 247"  
    assert len(args.idb) == 6, "IDB doit être long de 6 caractères pour représenter 3 octets"
    assert len(args.idal) == 2, "IDAL doit être long de 2 caractères pour représenter 1 octet"
    assert 0 <= args.tabNr <= 4, "Tab number doit être entre 0 et 4"
    assert 0 <= args.index <= 255, "Index doit être entre 0 et 255"
    assert args.baudrate in [300,600,1200,2400,4800,9600,14400,19200,38400,56000,57600,115200,128000,230400,256000], "Vitesse de transmission invalide"
    assert args.bytesize in [7,8], "Longueur des données invalide"
    assert args.parity in ["N","E","O"], "Parité invalide"
    assert args.stopbits in [0,1,2], "Bits de stop invalide"

    # Construction des registres à envoyer
    registers = idx2reg(args.idal, args.idb)
    registers.append(args.tabNr)
    registers.append(args.index)
    
    # valeur à utiliser d'une manière ou d'une autre
    value = 0
    write_value = ModbusSerialClient.convert_to_registers(value, ModbusSerialClient.DATATYPE.FLOAT32)
    registers.extend(write_value) # valeur à écrire

    _logger.info("### Connexion au client")
    client = ModbusSerialClient(
        port=args.port,
        baudrate=args.baudrate,
        bytesize=args.bytesize,
        parity=args.parity,
        stopbits=args.stopbits,
        framer=FramerType.RTU,
        timeout=5,
    )
    client.connect()
    _logger.info("### Client connecté")
    
    error = False

    try:
        # write_address => 0: read, 1: write d'après la documentation
        rr = client.readwrite_registers(read_address=0, read_count=6, write_address=0, values=registers, slave=args.address)
    except ModbusException as exc:
        _logger.error(f"Exception Modbus : {exc!s}")
        error = True
    if not error and rr.isError():
        _logger.error(f"Erreur")
        error = True
    if not error and isinstance(rr, ExceptionResponse):
        _logger.error(f"Response exception : {rr!s}")
        error = True
    
    if not error:
        _logger.info(f"Réponse: {rr.registers}")
        value = client.convert_from_registers(rr.registers[-4], client.DATATYPE.FLOAT32)
        _logger.info(f"Valeur lue: {value}")
    else:
        _logger.error("Une erreur est survenue")

    client.close()
    _logger.info("### Fin du programme")

def idx2reg(idal, idb) -> list[int]:
    registers = bytearray()
    registers.extend(bytes.fromhex(idal))
    registers.extend(bytes.fromhex(idb))
    ret = []
    for i in range(0, len(registers), 2):
        ret.append(int.from_bytes(registers[i:i+2], byteorder='big', signed=False))
    return ret

if __name__ == "__main__":
    main()

J’ai rajouté des paramètres avec lesquels tu vas pouvoir « jouer » :

./fc23.py --port /dev/ttyUSB1 --address 1 --idb 0E --idal 0217C1 --tabNr 0 --index 1 --baudrate 19200 --bytesize 8 --parity E --stopbits 0

Voici les nouveau paramètres optionnels possibles :

  • baudrate peut avoir une de ces valeur : 300,600,1200,2400,4800,9600,14400,19200,38400,56000,57600,115200,128000,230400 ou 256000
    Si pas précisé baudrate vaut 19200
  • bytesize peut prendre la valeur 7 ou 8
    Si pas précisé c’est 8
  • parity peut valoir N (none/aucune), E (even/paire) ou O (odd/impaire)
    Si pas précisé c’est E
  • stopbits peut valoir 0, 1 ou 2
    Si pas précisé c’est 0

Les valeurs par défaut sont tirées de la documentation. Regarde le chapitre 3 pour les valeurs acceptées par la passerelle. Le script accepte plus de possibilités puisqu’il s’appuie sur les possibilités de pymodbus, mais limite-toi à ce que sait faire la passerelle. La parité et le nombre de bits de stop sont liés, regarde bien la doc.

Les paramètres port et address peuvent être omis, par défaut c’est : --port /dev/ttyACM0 --address 1
Tu peux donc te concentrer sur les autres paramètres :

./fc23.py --idb 039195 --idal 1B --tabNr 0 --index 1

→ fonctionnera pareil

C’est peut-être lié au fait que j’ai changé la parité, maintenant par défaut c’est la bonne parité dans le script. Il faudrait peut-être aligner la configuration de l’adaptateur USB/RS485… pas sûr.
Ou alors il faut faire quelque chose pour activer la passerelle ? Je ne sais pas…

1 « J'aime »

Oh yes beaucoup plus complet pour s’amuser :slight_smile:
Les qqs combinaisons que j’ai essayé remontent toujours les 3 retry en echec, je vais continuer.

Par contre il y a le paramètre – stopbits 0 qui me renvoie (qq soit la parité) cette erreur :

(modbus) root@jeedom:/var/www/html/tests# ./fc23.py --port /dev/ttyACM0 --address 101 --idb 039195 --idal 1B --tabNr 0 --index 1 --baudrate 19200 --bytesize 8 --parity E --stopbits 0
2025-02-09 23:07:54,139 INFO ### Début du programme
2025-02-09 23:07:54,139 INFO ### Connexion au client
2025-02-09 23:07:54,140 ERROR serial:250 Not a valid stop bit size: 0
2025-02-09 23:07:54,140 ERROR Not a valid stop bit size: 0
2025-02-09 23:07:54,140 INFO ### Client connecté
2025-02-09 23:07:54,140 ERROR serial:250 Not a valid stop bit size: 0
2025-02-09 23:07:54,140 ERROR Not a valid stop bit size: 0
2025-02-09 23:07:54,141 ERROR Exception Modbus : Modbus Error: [Connection] Failed to connect[ModbusSerialClient /dev/ttyACM0:0]
2025-02-09 23:07:54,141 ERROR Une erreur est survenue
2025-02-09 23:07:54,141 INFO ### Fin du programme

il y a peut-être un loup ?

Sinon quelques retours :

Ca a l’air bon, d’après des utilisateurs il fonctionne pour connecter un JK BMS au Victron Cerbo GX.

Enfin, si je passe l’adresse de ma passerelle Modbus/Masterbus à 101, il faut bien que je modifie mon paramètre adresse ( – adresse 101) ?

A+

Non, laisse le paramètre à 1 ou ne le précise pas. Ton interface aura l’adresse 101 mais elle veut bien communiquer avec l’adresse 1
Donc ton interface USB/RS485 a l’adresse 101 et la passerelle a l’adresse 1.

1 « J'aime »

Essaie avec stopbits = 1

1 « J'aime »