[Programmation] PIC32MZ MODBUS TCP communication - Page 2
Répondre à la discussion
Page 2 sur 3 PremièrePremière 2 DernièreDernière
Affichage des résultats 31 à 60 sur 67

PIC32MZ MODBUS TCP communication



  1. #31
    Jojo2504

    Re : PIC32MZ MODBUS TCP communication


    ------

    Justement je ne sais pas ou j'envoie de l'information dans le programme de l'harmony (demo: tcpip_tcp_client_server)

    C'est microchip qui a fait cette demo et je pense qu'elle doit pouvoir envoyer des caractères !! quand je connecte modbus poll j'obtiens cette trame et quand je lance wireshark j'observe aussi de la comm entre le pc et le pic mais je ne sais pas comment gérer cette comm et envoyer mes infos !

    -----

  2. #32
    Jojo2504

    Re : PIC32MZ MODBUS TCP communication

    Je pense que le programme transmet seulement la longueur de la trame:

    Code:
    static void SendCommandPrint(const void* cmdIoParam, const char* format, ...)
    {
        char tmpBuf[SYS_CMD_PRINT_BUFFER_SIZE];
        size_t len = 0;
        size_t padding = 0;
        va_list args;
        va_start( args, format );
    
        len = vsnprintf(tmpBuf, SYS_CMD_PRINT_BUFFER_SIZE, format, args);
    
        va_end( args );
    
    
        if (len > 0 && len < SYS_CMD_PRINT_BUFFER_SIZE)
        {
            tmpBuf[len] = '\0';
        
            if (len + printBuffPtr >= SYS_CMD_PRINT_BUFFER_SIZE)
            {
                printBuffPtr = 0;
            }
    
            strcpy(&printBuff[printBuffPtr], tmpBuf);
            SendCommandMessage(NULL, &printBuff[printBuffPtr]);
    
            padding = len % 4;
    
            if (padding > 0)
            {
                padding = 4 - padding;
            }
            printBuffPtr += len + padding;
        }
    }

  3. #33
    Jack
    Modérateur

    Re : PIC32MZ MODBUS TCP communication

    je pense qu'elle doit pouvoir envoyer des caractères !!
    Il faudrait partir sur des certitudes sinon on va faire du sur place.

  4. #34
    Jojo2504

    Re : PIC32MZ MODBUS TCP communication

    Oui c'est pour ça que je demande de l'aide je suis débutant en pic et je n'est jamais utilisé mplab harmony c'est une première pour moi et franchement le code est assez perturbant ... beaucoup de chose que je comprend qu'à moitié mais c'est surtout comment envoyer un caractère dans la trame qui est compliqué

  5. #35
    Jack
    Modérateur

    Re : PIC32MZ MODBUS TCP communication

    En fait, dans tout le code que tu nous as montré, je ne vois pas trop à quel endroit le protocole modbus est pris en compte. Tout ce qu'on voit, c'est de la gestion du protocole TCP/IP

  6. #36
    Jojo2504

    Re : PIC32MZ MODBUS TCP communication

    J'ai pas mis tt le code car il est trés long et contient plusieur fichier mais je pense que le protocole modbus est inclus dans la demo


    Code:
    void APP_Initialize(void) {
        /* Place the App state machine in its initial state. */
        appData.state = APP_STATE_INIT;
    
        appData.clientState = APP_TCPIP_WAIT_INIT;
        appData.serverState = APP_TCPIP_WAIT_INIT;
    
        APP_Commands_Init();
    }
    
    void _APP_ClientTasks() {
        switch (appData.clientState) {
            case APP_TCPIP_WAITING_FOR_COMMAND:
            {
                SYS_CMD_READY_TO_READ();
              if (APP_URL_Buffer[0] != '\0') {
                    TCPIP_DNS_RESULT result;
                    appData.port = TCPIP_HTTP_SERVER_PORT;
                    if (_APP_ParseUrl(APP_URL_Buffer, &appData.host, &appData.path, &appData.port)) {
                        SYS_CONSOLE_PRINT("Could not parse URL '%s'\r\n", APP_URL_Buffer);
                        APP_URL_Buffer[0] = '\0';
                        break;
                    }
                    result = TCPIP_DNS_Resolve(appData.host, DNS_TYPE_A);
                    if (result == DNS_RES_NAME_IS_IPADDRESS) {
                        IPV4_ADDR addr;
                        TCPIP_Helper_StringToIPAddress(appData.host, &addr);
                        appData.clientSocket = TCPIP_TCP_ClientOpen(IP_ADDRESS_TYPE_IPV4,
                                appData.port,
                                (IP_MULTI_ADDRESS*) & addr);
                        if (appData.clientSocket == INVALID_SOCKET) 
                        {
                            SYS_CONSOLE_MESSAGE("Could not start connection\r\n");
                            appData.clientState = APP_TCPIP_WAITING_FOR_COMMAND;
                        }
                        SYS_CONSOLE_MESSAGE("Starting connection\r\n");
                        appData.clientState = SYS_CONSOLE_EVENT_WRITE_COMPLETE;
                        appData.clientState = APP_TCPIP_WAIT_FOR_CONNECTION;
                        break;
                    }
                    if (result != DNS_RES_OK) {
                        SYS_CONSOLE_MESSAGE("Error in DNS aborting\r\n");
                        APP_URL_Buffer[0] = '\0';
                        break;
                    }
                    appData.clientState = APP_TCPIP_WAIT_ON_DNS;
                    APP_URL_Buffer[0] = '\0';
                }
            }
                break;
    
            case APP_TCPIP_WAIT_ON_DNS:
            {
                IPV4_ADDR addr;
                switch (_APP_PumpDNS(appData.host, &addr)) {
                    case -1:
                    {
                        // Some sort of error, already reported
                        appData.clientState = APP_TCPIP_WAITING_FOR_COMMAND;
                    }
                        break;
                    case 0:
                    {
                        // Still waiting
                    }
                        break;
                    case 1:
                    {
                        appData.clientSocket = TCPIP_TCP_ClientOpen(IP_ADDRESS_TYPE_IPV4,
                                appData.port,
                                (IP_MULTI_ADDRESS*) & addr);
                        if (appData.clientSocket == INVALID_SOCKET) {
                            SYS_CONSOLE_MESSAGE("Could not start connection\r\n");
                            appData.clientState = APP_TCPIP_WAITING_FOR_COMMAND;
                        }
                        SYS_CONSOLE_MESSAGE("Starting connection\r\n");
                        appData.clientState = APP_TCPIP_WAIT_FOR_CONNECTION;
                    }
                        break;
                }
            }
                break;
    
            case APP_TCPIP_WAIT_FOR_CONNECTION:
            {
                char buffer[MAX_URL_SIZE];
                if (!TCPIP_TCP_IsConnected(appData.clientSocket)) 
                {
                    break;
                }
                
                if (TCPIP_TCP_PutIsReady(appData.clientSocket) == 0) {
                    break;
                }
                sprintf(buffer, "GET /%s HTTP/1.1\r\n"
                        "Host: %s\r\n"
                        "Connection: close\r\n\r\n", appData.path, appData.host);
                SYS_CONSOLE_PRINT("%s\r\n", buffer);
                TCPIP_TCP_ArrayPut(appData.clientSocket, (uint8_t*) buffer, strlen(buffer) + 1);
                appData.clientState = APP_TCPIP_WAIT_FOR_RESPONSE;
            }
                break;
    
            case APP_TCPIP_WAIT_FOR_RESPONSE:           // for me: envoye des données
            {
                char buffer[80];
                memset(buffer, 0, sizeof (buffer));
                if (!TCPIP_TCP_IsConnected(appData.clientSocket)) {
                    SYS_CONSOLE_MESSAGE("\r\nConnection Closed\r\n");
                    appData.clientState = APP_TCPIP_WAITING_FOR_COMMAND;
                    break;
                }
                if (TCPIP_TCP_GetIsReady(appData.clientSocket)) {
                    TCPIP_TCP_ArrayGet(appData.clientSocket, (uint8_t*) buffer, sizeof (buffer) - 1);
                    SYS_CONSOLE_PRINT("%s", buffer);
                }
            }
                break;
            default:
                break;
        }
    }
    void _APP_ServerTasks() {
        switch (appData.serverState) {
            case APP_TCPIP_OPENING_SERVER:
            {
                SYS_CONSOLE_PRINT("Waiting for Client Connection on port: %d\r\n", SERVER_PORT);
                appData.serverSocket = TCPIP_TCP_ServerOpen(IP_ADDRESS_TYPE_IPV4, SERVER_PORT, 0);
                if (appData.serverSocket == INVALID_SOCKET) {
                    SYS_CONSOLE_MESSAGE("Couldn't open server socket\r\n");
                    break;
                }
                appData.serverState = APP_TCPIP_WAIT_FOR_CONNECTION;
            }
                break;
    
            case APP_TCPIP_WAIT_FOR_CONNECTION:
            {
                if (!TCPIP_TCP_IsConnected(appData.serverSocket)) {
                    return;
                } else {
                    // We got a connection
                    appData.serverState = APP_TCPIP_SERVING_CONNECTION;
                    SYS_CONSOLE_MESSAGE("Server Received a connection\r\n");
                }
            }
                break;
    
            case APP_TCPIP_SERVING_CONNECTION: //
            {
                if (!TCPIP_TCP_IsConnected(appData.serverSocket)) {
                    appData.serverState = APP_TCPIP_CLOSING_CONNECTION;
                    SYS_CONSOLE_MESSAGE("Connection was closed\r\n");
                    break;
                }
                int16_t wMaxGet, wMaxPut, wCurrentChunk;
                uint16_t w, w2;
                uint8_t AppBuffer[160];
                // Figure out how many bytes have been received and how many we can transmit.
                wMaxGet = TCPIP_TCP_GetIsReady(appData.serverSocket); // Get TCP RX FIFO byte count
                wMaxPut = TCPIP_TCP_PutIsReady(appData.serverSocket); // Get TCP TX FIFO free space
    
                // Make sure we don't take more bytes out of the RX FIFO than we can put into the TX FIFO
                if (wMaxPut < wMaxGet)
                    wMaxGet = wMaxPut;
    
                // Process all bytes that we can
                // This is implemented as a loop, processing up to sizeof(AppBuffer) bytes at a time.
                // This limits memory usage while maximizing performance.  Single byte Gets and Puts are a lot slower than multibyte GetArrays and PutArrays.
                wCurrentChunk = sizeof (AppBuffer);
                for (w = 0; w < wMaxGet; w += sizeof (AppBuffer)) {
                    // Make sure the last chunk, which will likely be smaller than sizeof(AppBuffer), is treated correctly.
                    if (w + sizeof (AppBuffer) > wMaxGet)
                        wCurrentChunk = wMaxGet - w;
    
                    // Transfer the data out of the TCP RX FIFO and into our local processing buffer.
                    TCPIP_TCP_ArrayGet(appData.serverSocket, AppBuffer, wCurrentChunk);
    
                    // Perform the "ToUpper" operation on each data byte
                    for (w2 = 0; w2 < wCurrentChunk; w2++) {
                        char i = AppBuffer[w2];
                        if (i >= 'a' && i <= 'z') {
                            i -= ('a' - 'A');
                            AppBuffer[w2] = i;
                        } else if (i == '\e') //escape
                        {
                            appData.serverState = APP_TCPIP_CLOSING_CONNECTION;
                            SYS_CONSOLE_MESSAGE("Connection was closed\r\n");
                        }
                    }
    
                    // Transfer the data out of our local processing buffer and into the TCP TX FIFO.
                    SYS_CONSOLE_PRINT("Server Sending %s\r\n", AppBuffer);
                    TCPIP_TCP_ArrayPut(appData.serverSocket, AppBuffer, wCurrentChunk);
    
                    // No need to perform any flush.  TCP data in TX FIFO will automatically transmit itself after it accumulates for a while.  If you want to decrease latency (at the expense of wasting network bandwidth on TCP overhead), perform and explicit flush via the TCPFlush() API.
                }
            }
                break;
            case APP_TCPIP_CLOSING_CONNECTION:
            {
                // Close the socket connection.
                TCPIP_TCP_Close(appData.serverSocket);
    
                appData.serverState = APP_TCPIP_OPENING_SERVER;
    
            }
                break;
            default:
                break;
        }
    }
    
    /******************************************************************************
      Function:
        void APP_Tasks ( void )
    
      Remarks:
        See prototype in app.h.
     */
    
    void APP_Tasks(void) {
        SYS_STATUS tcpipStat;
        const char *netName, *netBiosName;
        static IPV4_ADDR dwLastIP[2] = {
            {-1},
            {-1}
        };
        IPV4_ADDR ipAddr;
        TCPIP_NET_HANDLE netH;
        int i, nNets;
    
        switch (appData.clientState) {
            case APP_TCPIP_WAIT_INIT:
                tcpipStat = TCPIP_STACK_Status(sysObj.tcpip);
                if (tcpipStat < 0) { // some error occurred
                    SYS_CONSOLE_MESSAGE(" APP: TCP/IP stack initialization failed!\r\n");
                    appData.clientState = APP_TCPIP_ERROR;
                } else if (tcpipStat == SYS_STATUS_READY) {
                    // now that the stack is ready we can check the
                    // available interfaces
                    nNets = TCPIP_STACK_NumberOfNetworksGet();
                    for (i = 0; i < nNets; i++) {
    
                        netH = TCPIP_STACK_IndexToNet(i);
                        netName = TCPIP_STACK_NetNameGet(netH);
                        netBiosName = TCPIP_STACK_NetBIOSName(netH);
    
    #if defined(TCPIP_STACK_USE_NBNS)
                        SYS_CONSOLE_PRINT("    Interface %s on host %s - NBNS enabled\r\n", netName, netBiosName);
    #else
                        SYS_CONSOLE_PRINT("    Interface %s on host %s - NBNS disabled\r\n", netName, netBiosName);
    #endif  // defined(TCPIP_STACK_USE_NBNS)
    
                    }
                    appData.clientState = APP_TCPIP_WAIT_FOR_IP;
    
                }
                break;
    
    
            case APP_TCPIP_WAIT_FOR_IP:
    
                // if the IP address of an interface has changed
                // display the new value on the system console
                nNets = TCPIP_STACK_NumberOfNetworksGet();
    
                for (i = 0; i < nNets; i++) {
                    netH = TCPIP_STACK_IndexToNet(i);
                    ipAddr.Val = TCPIP_STACK_NetAddress(netH);
                    if (dwLastIP[i].Val != ipAddr.Val) {
                        dwLastIP[i].Val = ipAddr.Val;
    
                        SYS_CONSOLE_MESSAGE(TCPIP_STACK_NetNameGet(netH));
                        SYS_CONSOLE_MESSAGE(" IP Address: ");
                        SYS_CONSOLE_PRINT("%d.%d.%d.%d \r\n", ipAddr.v[0], ipAddr.v[1], ipAddr.v[2], ipAddr.v[3]);
                        if (ipAddr.v[0] != 0 && ipAddr.v[0] != 169) // Wait for a Valid IP
                        {
                            appData.clientState = APP_TCPIP_WAITING_FOR_COMMAND;
                            appData.serverState = APP_TCPIP_OPENING_SERVER;
                            SYS_CONSOLE_MESSAGE("Waiting for command type: openurl <url>\r\n");
                        }
                    }
                }
                break;
               
    /*if (buffer vide & buffer d'emission vide)
     {
     * Appel fonction write(....,'a');
     * }
     */
            case APP_TCPIP_ERROR:
                break;
    
            default:
                _APP_ClientTasks();
                _APP_ServerTasks();
                break;
        }
    }
    
    int32_t _APP_ParseUrl(char *uri, char **host, char **path, uint16_t * port) {
        char * pos;
        pos = strstr(uri, "//"); //Check to see if its a proper URL
    
        if (!pos) {
            return -1;
        }
        *host = pos + 2; // This is where the host should start
    
        pos = strchr(* host, ':');
    
        if (!pos) {
            pos = strchr(*host, '/');
            if (!pos) {
                *path = NULL;
            } else {
                *pos = '\0';
                *path = pos + 1;
            }
        } else {
            *pos = '\0';
            char * portc = pos + 1;
    
            pos = strchr(portc, '/');
            if (!pos) {
                *path = NULL;
            } else {
                *pos = '\0';
                *path = pos + 1;
            }
            *port = atoi(portc);
        }
        return 0;
    }
    
    int8_t _APP_PumpDNS(const char * hostname, IPV4_ADDR *ipv4Addr) {
        TCPIP_DNS_RESULT result = TCPIP_DNS_IsResolved(hostname, ipv4Addr);
        switch (result) {
            case DNS_RES_OK:
            {
                // We now have an IPv4 Address
                // Open a socket
                return 1;
            }
            case DNS_RES_PENDING:
                return 0;
            case DNS_RES_SERVER_TMO:
            case DNS_RES_NO_ENTRY:
            default:
                SYS_CONSOLE_MESSAGE("TCPIP_DNS_IsResolved returned failure\r\n");
                return -1;
        }
        // Should not be here!
        return -1;
    
    }
    
    /*******************************************************************************
     End of File
     */

  7. #37
    Jack
    Modérateur

    Re : PIC32MZ MODBUS TCP communication

    Je ne vois que du code gérant TCP/IP

  8. #38
    Jojo2504

    Re : PIC32MZ MODBUS TCP communication

    d'accord j'ai vu un autre post ou une pêrsonne montré c'est screens de son modbus tcp et effectivement je pense que tu as raison le code démo de harmony permet seulement d'avoir la pile tcp/ip et non le modbus ... Il a publié son wireshark et lui envoie réellement de l'info.

    Mais là je suis un peu perdu je ne sais pas comment réaliser le modbus tcp si tu as des doc d'aides ou des astuces pour que je ne parte pas de 0.

  9. #39
    Jojo2504

    Re : PIC32MZ MODBUS TCP communication

    J'ai trouvé 2 pdf qui explique comment faire je vais essayer de suivre leurs conseils !

  10. #40
    Jack
    Modérateur

    Re : PIC32MZ MODBUS TCP communication

    Si rien n'existe pour modbus, tu peux peut-être commencer par créer une socket TCP, constituer la trame qui te permet d'envoyer des données, puis l'envoyer à l'aide la fonction sendto que tu as montrée précédemment.

    Tu devrais voir tes données apparaître dans modbus slave.
    Dernière modification par Jack ; 22/05/2017 à 12h15.

  11. #41
    Johnplayer

    Re : PIC32MZ MODBUS TCP communication

    J'ai pris le code de la doc que je t'ai filé et j'ai ajouté une trame modbus en dur pour un test avec ModbusPal.
    Remplace juste l'IP du serveur par celle de ton PC sur lequel tourne ModbusPal.
    Dans ModbusPal, tu créé un serveur avec l'adresse modbus 1 et tu déclares des holding registers.

    Code:
    #include <p32xxxx.h>
    #include <plib.h>
    
    #define ModbusPort 502
    #define SERVER_IP 192.168.0.20
    
    char TrameRTU[252];
    int TrameRTU_len = 0;
    
    int main(void)
    {
      // Client
      SOCKET Sock;
      // Adresse Serveur
      struct sockaddr_in addr;
      int addrlen = sizeof(struct sockaddr_in);
      int len;
    
      SetupDefault_IP_MAC();
      MSTimerInit(36000000);
      InitStackMgr();
      TickInit();
      //create tcp client socket
      if( (Sock = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP )) == SOCKET_ERROR ) return -1;
      //bind to a unique local port
      addr.sin_port = ModbusPort;
      addr.sin_addr.S_un.S_addr = IP_ADDR_ANY;
      if( bind( Sock, (struct sockaddr*)&addr, addrlen ) == SOCKET_ERROR ) return -1;
      //create the server address
      addr.sin_port = SERVER_PORT;
      addr.sin_addr.S_un.S_addr = SERVER_IP;
      addrlen = sizeof(struct sockaddr);
      ClientConnected = FALSE;
    
      while(1)
      {
        // execute the stack process once every iteration of the main loop
        StackMgrProcess();
    
        // The connect process requires multiple messages to be
        // sent across the link, so we need to keep on trying until successful
        while( !ClientConnected )
          if( connect( Sock, (struct sockaddr*)&addr, addrlen ) == 0 )
            ClientConnected = TRUE;
    
        // Création d'une requête Modbus pour un test avec ModbusPal
        // On va écrire dans 2 holding registers
        TrameRTU[0] = 0x01; // Adresse modbus du serveur (UNIT_ID)
        TrameRTU[1] = 0x10; // Ecriture d'un ou plusieurs holding registers
        TrameRTU[2] = 0x00; // Adresse premier registre MSB (ex: 400007 donc 0x0006)
        TrameRTU[3] = 0x06; // Adresse premier registre LSB
        TrameRTU[4] = 0x00; // Nombre de registres à écrire MSB (ex: 2 registres 0x0002)
        TrameRTU[5] = 0x02; // Nombre de registres à écrire LSB
        TrameRTU[6] = 0x04; // Nombre d'octets de données que l'on va envoyé (2 registres donc 4 octets, 0x04)
        TrameRTU[7] = 0x12; // Valeur premier registre MSB (ex: 0x1234)
        TrameRTU[8] = 0x34; // Valeur premier registre LSB
        TrameRTU[9] = 0x56; // Valeur premier registre MSB (ex: 0x5678)
        TrameRTU[10] = 0x78; // Valeur premier registre LSB
        // Longueur total de la trame RTU
        TrameRTU_len = 11;
    
        //send the Modbus Request to server
        while( (len = send( Sock, TrameRTU, TrameRTU_len, 0 )) != TrameRTU_len )
        {
          if( len == SOCKET_ERROR )
          {
            closesocket( Sock);
            return(len);
          }
        }
        ...
        ...
        //Receive data from server
        len = recv( Sock, TrameRTU, sizeof(TrameRTU), 0 );
        if( len > 0 )
        {
          //process the data received in TrameRTU
          ...
          ...
        }
        else if( len < 0 ) //handle error condition
        {
          closesocket( Sock );
          Sock = INVALID_SOCK;
          ClientConnected = FALSE;
          return(len);
        }
        ...
        ...
      }
      ...
      ...
    }

  12. #42
    Jojo2504

    Re : PIC32MZ MODBUS TCP communication

    John avec quelle logiciel tu as écrit ton programme ? je suis avec mplab harmony et il n'a pas du tout apprécié le programme surtout au niveau des sockets.

    Jack merci ta technique fonctionne mais il faut que je créer une communication modbus tcp

    Il faudra donc que je créer 2 fonctions je pense:

    - Write holding register
    - Read holding register

    Est ce que vous savez si avec ces 2 fonctions je peux allumer une led et observer la trame sur modbus poll ?

  13. #43
    Jack
    Modérateur

    Re : PIC32MZ MODBUS TCP communication

    Jack merci ta technique fonctionne mais il faut que je créer une communication modbus tcp
    Je ne vois pas en quoi ce que je te recommande n'est pas une communication en modbus tcp.

    - Write holding register
    - Read holding register

    Est ce que vous savez si avec ces 2 fonctions je peux allumer une led
    En principe, pour commander une ou plusieurs sorties binaires, c'est plutôt les fonctions write single coil ou write multiple coils qu'il faut utiliser.

  14. #44
    Johnplayer

    Re : PIC32MZ MODBUS TCP communication

    J'ai juste repris le code de l'AN1108A à laquelle j'ai rajouté quelques lignes pour te montrer comment envoyer une requête modbus. Maintenant, je n'ai pas réinstallé le compilateur XC32 dans MPLAB, vu que je ne l'utilise pas. Le code vient d'une app note de microchip donc il doit y avoir une adaptation à faire pour qu'il fonctionne avec ton pic, ceci dit j'ai laissé les points de suspensions pour montrer qu'il y avait un peu de taf à faire.

    Et comme je te l'ai dit un peu avant, je n'ai jamais toucher au stack TCP/IP par contre je connais bien le Modbus. Je travaille en industrie, principalement sur des automates schneider et je me suis amusé à connecté un raspberry pi sur le réseau d'automate pour récupérer des infos et contrôler la ligne de production. Du coup, j'ai appris le modbus RTU puis le modbus TCP/IP. Mais en perl et en c++ sous linux...

    Donc je t'invite à travailler un peu le code, s'il y a des erreurs dont tu n'arrives pas à te débarrasser reviens vers nous on t'aideras à corriger ça. En attendant, je vais installer XC32 pour pouvoir mieux t'aider...

  15. #45
    Jack
    Modérateur

    Re : PIC32MZ MODBUS TCP communication

    Salut Johnplayer,

    j'ai l'impression que ton code correspond à du modbus RTU (sans CRC) transporté par du TCP/IP. Çà n'est pas à proprement parler du modbus TCP, mais un protocole "maison" qui est utilisé puisque l'ADU ne correspond pas complètement aux spécifications modbus TCP (ni RTU d'ailleurs).

    Avec modbus TCP, il faudrait que la trame (l'ADU) soit constituée du MBAP et du PDU .

  16. #46
    Johnplayer

    Re : PIC32MZ MODBUS TCP communication

    Exact, j'ai repris mon code perl pour voir comment j'avais fait la com. J'ai bien un header devant la trame RTU, autant pour moi .
    Le header est construit comme suit :
    - Transaction header = 0x0001
    - Protocol ID = 0x0000
    - Length = nombre d'octets de la trame RTU(2octets).

  17. #47
    Jack
    Modérateur

    Re : PIC32MZ MODBUS TCP communication

    C'est bien mieux

    Pour l'identificateur de transaction, on peut mettre ce qu'on veut si chaque nouvelle requête est émise après avoir obtenu la réponse de l'esclave (du serveur)

  18. #48
    Jack
    Modérateur

    Re : PIC32MZ MODBUS TCP communication

    Length = nombre d'octets de la trame RTU(2octets).
    Pourquoi RTU? Longueur de la trame tout simplement. RTU, c'est pour la liaison série.

  19. #49
    Jojo2504

    Re : PIC32MZ MODBUS TCP communication

    Mais du coup c'est un mode RTU non ?

    Dans mon projet, j'ai créer le tcp client server qui appelle des sockets.

    Maintenant je dois faire une communication Modbus TCP avec les fonctions suivantes:

    Code:
    TCP_SOCKET TCPIP_TCP_ServerOpen(IP_ADDRESS_TYPE addType,TCP_PORT localPort,IP_MULTI_ADDRESS* localAddress); //Ouverture du serveur
    
    TCP_SOCKET TCPIP_TCP_ClientOpen(IP_ADDRESS_TYPE addType,TCP_PORT remotePort,IP_MULTI_ADDRESS* remoteAddress);
    
    uint16_t TCPIP_TCP_ArrayPut(TCP_SOCKET hTCP,const uint8_t* Data,uint16_t Len); // Transmittion des données
    
    uint16_t TCPIP_TCP_ArrayGet(TCP_SOCKET hTCP,uint8_t* buffer,uint16_t count); // Réception des données
    
    uint16_t TCPIP_TCP_GetIsReady(TCP_SOCKET hTCP) // recevoir des données
    
    void TCPIP_TCP_Close(TCP_SOCKET hTCP);

  20. #50
    Bluedeep

    Re : PIC32MZ MODBUS TCP communication

    Citation Envoyé par Jojo2504 Voir le message
    Mais du coup c'est un mode RTU non ?
    Je commence à me demander si tu lis vraiment ce qu'on te répond.
    Comme déjà dit :

    RTU => liaison physique série, mode maître esclave
    TCP => liaison physique ethernet, mode client-serveur

  21. #51
    Jojo2504

    Re : PIC32MZ MODBUS TCP communication

    Je parlais du programme de John !

  22. #52
    Jojo2504

    Re : PIC32MZ MODBUS TCP communication

    Ah oui effectivement j'avais pas vu la réponse RTU pour longueur de trame désolée

  23. #53
    Jojo2504

    Re : PIC32MZ MODBUS TCP communication

    John j'ai une question !
    Quand tu écris cette fonction :

    socket( AF_INET, SOCK_STREAM, IPPROTO_TCP )

    C'est pour créer une socket client dans mon programme cette fonction se transformera en:

    TCP_SOCKET TCPIP_TCP_ClientOpen(IP_ADDRES S_TYPE addType, TCP_PORT remotePort, IP_MULTI_ADDRESS* remoteAddress)

    est ce que c'est juste ?

    Je n'arrive pas à organiser la structure du programme dans ma tête ..
    Dernière modification par Jojo2504 ; 23/05/2017 à 09h59.

  24. #54
    Johnplayer

    Re : PIC32MZ MODBUS TCP communication

    Quand je dis trame RTU, c'est un abus de langage.
    En TCP, on a : MBAP Header + PDU = ADU mais vu que j'ai travaillais pendant un moment en série, j'ai gardé dans mon esprit "header + message RTU sans CRC".
    Du coup, pour gérer le message on peu faire un truc dans le genre:
    (Attention, ce code est à revoir, je programme en c++ la majorité du temps donc la gestion des pointeurs ne conviendra pas sur MPLAB...)

    Code:
    // liste des FCode des 8 fonctions principalement utilisées
    #define ReadDiscreteOutputStatus 1
    #define ReadDiscreteInputStatus 2
    #define ReadOutputRegisters 3
    #define ReadInputRegisters 4
    #define ForceSingleCoil 5
    #define PresetSingleRegister 6
    #define ForceMultipleCoils 15
    #define PresetMultipleRegisters 16
    
    char ADU[256]; // max 1460 octets mais ça fait beaucoup pour un pic32^^
    char *PDU_Data = &ADU[8]; // pointeur sur le début de la partie data de la trame
    
    // init les champs transaction id et protocole id
    void initADU() 
    { 
      ADU[0] =  0x00;
      ADU[1] =  0x01;
      ADU[2] =  0x00;
      ADU[3] =  0x00;
    }
    
    // set la valeur du champs length avec longueur de la partie data
    void setDataLength(short data_length) 
    { 
      short tmp = data_length + 2; // on ajoute 2 octets (unit_id et fcode)
      ADU[4] = (char*)&tmp[1]; 
      ADU[5] = (char*)&tmp[0]; 
    }
    
    void setUNIT_ID(char unit_id) { ADU[6] = unit_id; }
    
    void setFCode(char fcode) { ADU[7] = fcode; }
    Pour mieux comprendre voici un lien : explications.

  25. #55
    Jojo2504

    Re : PIC32MZ MODBUS TCP communication

    Merci john !!

    Du coup la data commence à partir de ADU[8]

    et à quelle moment nous écrivons un 3 pour faire un read_out_put_registers ? sur l'octet ADU[4-5] comme dans l'exemple que tu as mis en lien ?

    La longueur de la Data correspond bien à : data_length + x (x est le nombre d'octets de data) c'est bien ça ?

    Et ensuite je créer une fonction pour la data !

    Par contre comment faire le lien entre le modbus et le client server ? car je n'ai pas de socket avec ton programme si ?

  26. #56
    Jack
    Modérateur

    Re : PIC32MZ MODBUS TCP communication

    Code:
      short tmp = data_length + 2; // on ajoute 2 octets (unit_id et fcode)
      ADU[4] = (char*)&tmp[1]; 
      ADU[5] = (char*)&tmp[0];
    A prendre avec toutes les précautions liées à l'endianness du processeur pour lequel ce code sera compilé.

  27. #57
    Jojo2504

    Re : PIC32MZ MODBUS TCP communication

    Qu'est ce que l'endiannes ?

  28. #58
    Johnplayer

    Re : PIC32MZ MODBUS TCP communication

    Bien vu pour l'endian, après un simple test suffit à assurer le coup.
    @Jojo2504 : l'endian c'est la façon dont les données sont mises en mémoire. Sur certains systèmes d'exploitation, le LSB sera en premier (little-endian) en mémoire et pour d'autres se sera le MSB(big-endian). Ce qui fait que mon code pourrait bien devenir:
    Code:
    short tmp = data_length + 2; // on ajoute 2 octets (unit_id et fcode)
      ADU[4] = (char*)&tmp[0];  // inversion des 2 octets qui compose le short
      ADU[5] = (char*)&tmp[1];
    Citation Envoyé par Jojo2504
    Du coup la data commence à partir de ADU[8]

    et à quelle moment nous écrivons un 3 pour faire un read_out_put_registers ? sur l'octet ADU[4-5] comme dans l'exemple que tu as mis en lien ?

    La longueur de la Data correspond bien à : data_length + x (x est le nombre d'octets de data) c'est bien ça ?
    Oui d'où le pointeur sur ADU[8].

    La fonction est faite :
    void setFCode( char fcode );
    #define ReadOutputRegisters 3
    Donc tu fais :
    setFCode( ReadOutputRegisters );

    Lenght = data_length(en octet) + 1 (octet pour UNIT_ID) + 1 (octet pour FCode), c'est écrit dans la fonction, lit les commentaires!
    data_length c'est le nombre d'octet qui compose ta requête, elle va donc varier suivant ce que tu veux faire...

  29. #59
    Jojo2504

    Re : PIC32MZ MODBUS TCP communication

    Tu penses que si je reprends ce programme je pourrais l'utiliser avec le code demo "tcpip_tcp_client_server" ? J'ai l'impression d'avoir 2 programme complétement indépendant ...

    Je suis tout à fait d'accord pour l'envoie des données mais je sais pas si cela va être compatible avec le code tcp ...

    Quen pensez vous ?

  30. #60
    Jojo2504

    Re : PIC32MZ MODBUS TCP communication

    Merci pour l'explication des endians ! j'ai compris !

Page 2 sur 3 PremièrePremière 2 DernièreDernière

Discussions similaires

  1. communication MODBUS RTU
    Par Samikerc dans le forum Électronique
    Réponses: 0
    Dernier message: 05/08/2014, 14h18
  2. communication modbus PIC16F877
    Par invitef57db61e dans le forum Électronique
    Réponses: 19
    Dernier message: 28/11/2012, 22h44
  3. la communication via Modbus
    Par invitef44aa575 dans le forum Électronique
    Réponses: 37
    Dernier message: 02/04/2012, 16h39
  4. Communication modbus sur Ethernet
    Par mayonaise dans le forum Internet - Réseau - Sécurité générale
    Réponses: 6
    Dernier message: 24/11/2011, 19h00
  5. Modbus Protocol Communication
    Par invitec782be84 dans le forum Électronique
    Réponses: 1
    Dernier message: 27/02/2008, 19h40
Découvrez nos comparatifs produits sur l'informatique et les technologies.