MODBUS RTU implementation on PK S5D9

Hi all,

I'm  facing issue with porting modbus library into renesas platform .

I have seen post on forum but found not so useful .

Appreciate if someone can share their experience working with rs485 terminal of  S5D9.

Many Thanks

  • Hi Alex,

    It seems like there's only few discussions on this topic. If you could still wait for this, maybe someone can share their experience about modbus rtu later. Thank you.

    JB
    RenesasRulz Forum Moderator

    https://renesasrulz.com/
    https://academy.renesas.com/
    https://en-us.knowledgebase.renesas.com/

  • In reply to JB:

    I have put together a quick demo for Mobbus RTU using freemodbus (https://www.embedded-solutions.at/en/freemodbus/) on the S5D9-PK board, it doesn’t use RS-485 as I don’t actually have any RS-485 hardware and there is no RS-485 transceiver on the S5D9-PK board, so it just outputs to a USB to serial convertor at 3.3V from J10 on the S5D9-PK board :-

     

    J6 is set to 2-3, and JP3 is 3-5 on J9, and JP4 is 4-6 on J9.

     

    The USB to serial convertor is connected to my PC, then use modpoll.exe from here :-

     

    https://www.modbusdriver.com/modpoll.html

     

    as the modbus master.

     

    The command line for modpoll I used :-

    modpoll.exe -m rtu -a 10 -r 1000 -c 4 -t 3 -b 38400 -d 8 -p even COM3

    and the output from modpoll :-

     

     

    S5D9_PK_freemodbus_rtu_SSP_1_7_5.zip

  • In reply to Jeremy:

    Hi Jeremy

    AS I dont have serial to USB converter with me at the momentso  I need to ask...Can "write to single" and "multiple register" be done with this ?

    Is this converter are you refering here ?

     But its a male converter 

    shall I go for this female header converter ?

  • In reply to Kirti:

    You would need to look at the specifications for freemodbus to see if it meets your requirements:-

  • In reply to Jeremy:

    [deleted]
  • In reply to Kirti:

    If the USB to serial convertor you provided the link to ( uk.farnell.com/.../2147356 ) meets your requirements, then use that one.

  • In reply to Jeremy:

    Hi Jeremy ,

    There is RE pin on J10, what is the functin of RE pin on J10 ...where should this pin be connected ..Is it to make it work as RS485 ?

     

    Thanks

  • In reply to Kirti:

    If you were using an RS-485 transceiver, the RE pin on J10 could be connected to the RE pin on the RS-485 transceiver, if required.
  • In reply to Jeremy:

    Hi Jeremy,

    I quite managed to send adc values to input register.

    I am struggling for below

    1.Though read adc API and modbus called in while loop ,Read of adc channels gets executed  only once and modbus routine keeps on executing and first register address is always read as ''0"(attached image for ref),its actually a nonzero value.

    2.As mentioned here It  supports read hoding register,write single register,write multiple register(0x04,0x06,0x10respectively )so to read holding register I changed "function code" from 3 to 4,changed Uart channel to 4 in thread object and sent comm prompt command as 

    -m rtu -a 10 -r 1000 -c10 -t 4  -b 38400 -d 8 -p even COM4

    the code in demo.c is 

    if( MB_ENOERR != ( eStatus = eMBInit( MB_RTU, 0x0A, 4, 38400, MB_PAR_EVEN ) ) )
    {
    printf("modbus not initialized : %d\n",eStatus);/* Can not initialize. Add error handling code here. */
    }

     

    so callback funcion eMBErrorCode eMBRegHoldingCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs, eMBRegisterMode eMode ) is expected to execute,here it doesnot happen so.

    3.while write to single register command is sent same thing as explained in 2.happens

    does it require some other tool or command for write to register?

    thread_entry function :

    while (1)
    {
    g_adc0.p_api->read(g_adc0.p_ctrl, ADC_REG_CHANNEL_0, &adc_data[0]);
    printf("read channel 0 : %d\n",adc_data[0]);

    g_adc0.p_api->read(g_adc0.p_ctrl, ADC_REG_CHANNEL_1, &adc_data[1]);
    printf("read channel 1 : %d \n",adc_data[1]);

    g_adc0.p_api->read(g_adc0.p_ctrl, ADC_REG_CHANNEL_2, &adc_data[2]);
    printf("read channel 2 : %d\n",adc_data[2]);

    g_adc0.p_api->read(g_adc0.p_ctrl, ADC_REG_CHANNEL_3, &adc_data[3]);
    printf("read channel 3 : %d\n",adc_data[3]);

    g_adc0.p_api->read(g_adc0.p_ctrl, ADC_REG_CHANNEL_4, &adc_data[4]);
    printf("read channel 4 : %d\n",adc_data[4]);

    g_adc0.p_api->read(g_adc0.p_ctrl, ADC_REG_CHANNEL_5, &adc_data[5]);
    printf("read channel 5 : %d\n",adc_data[5]);

    status = g_adc0.p_api->read(g_adc0.p_ctrl, ADC_REG_CHANNEL_6, &adc_data[6]);
    printf("read channel 6 : %d\n",adc_data[6]);

    vTaskMODBUS();

    tx_thread_sleep (1);
    }

    S5D9 connected to computer with USB to serial converter (just rx,tx no RE)

    After debugging in demo.c ,Stucckk....

    I m missing something ?CRC ? ...guide please

     

  • In reply to Kirti:

    vTaskMODBUS(); is a big loop, once you enter that function it won't return.

    The holding registers in the demo are defined as :-

     

    #define REG_HOLDING_START               ( 1 )
    #define REG_HOLDING_NREGS               ( 32 )

     

    so -r 1000 is not a valid holding register in the demo setup.

  • In reply to Jeremy:

    Hi Jeremy,

    I changed the code in demo.c file as

    void
    vTaskMODBUS( void )
    {
    const UCHAR ucSlaveID[] = { 0xAA, 0xBB, 0xCC };
    eMBErrorCode eStatus;

    for( ;; )
    {
     if( MB_ENOERR != ( eStatus = eMBInit( MB_RTU, 0x0A, 4, 9600, MB_PAR_EVEN ) ) )
     {
     printf("modbus not initialized : %d\n",eStatus);/* Can not initialize. Add error handling code here. */
     }
     else
    {
     if( MB_ENOERR != ( eStatus = eMBSetSlaveID( 0x34, TRUE, ucSlaveID, 4 ) ) )
    {
      printf("modbus setid : %d\n",eStatus); /* Can not set slave id. Check arguments */
    }
    /* else if(MB_ENOERR != ( eStatus = eMBInit( MB_RTU, 0x0A, 4, 9600, MB_PAR_EVEN)))   
    {
     printf("modbus not initialized for holding register : %d\n",eStatus);
    }
    */ else if( MB_ENOERR != ( eStatus = eMBEnable( ) ) )
    {
     printf("protocol stack : %d\n",eStatus); /* Enable failed. */
    }
    else
    {
     usRegHoldingBuf[0] = 1;
    do
    {

    ( void )eMBPoll( );
    g_adc0.p_api->read(g_adc0.p_ctrl, ADC_REG_CHANNEL_0, &adc_data[0]);

    g_adc0.p_api->read(g_adc0.p_ctrl, ADC_REG_CHANNEL_1, &adc_data[1]);

    g_adc0.p_api->read(g_adc0.p_ctrl, ADC_REG_CHANNEL_2, &adc_data[2]);

    g_adc0.p_api->read(g_adc0.p_ctrl, ADC_REG_CHANNEL_3, &adc_data[3]);

    g_adc0.p_api->read(g_adc0.p_ctrl, ADC_REG_CHANNEL_4, &adc_data[4]);

    g_adc0.p_api->read(g_adc0.p_ctrl, ADC_REG_CHANNEL_5, &adc_data[5]);

    g_adc0.p_api->read(g_adc0.p_ctrl, ADC_REG_CHANNEL_6, &adc_data[6]);

    usRegInputBuf[0]++;
    }
    while( usRegHoldingBuf[0] );
    }
    ( void )eMBDisable( );
    ( void )eMBClose( );
    }

    }
    }

     sent command in command prompt as  "-m rtu -a 10 -r 1 -c10 -t 4  -b 9600 -d 8 -p even COM4 "

    i am getting an error in big function   eMBInit() as 3(i.e port layer error)

    so I changed the g_uart0 channel to 4, getting this on comm prompt 

      

    1.AM I Missing some key part of code ?

    2.I can see mbcrc.c file has crc function,using this how can CRC be received in case of write to register?

     

    many thanks in advance

     

  • In reply to Kirti:

    If you change to SCI channel used in the call to eMBInit() you will also have to change it in the configuration of the Synergy project

    and in the pin configuration of the project :-

     

     

    Please look at the freemodus code and documentation for operation of the freemodbus.

  • In reply to Jeremy:

    Ok so this is the channel in eMBInit( MB_RTU, 0x0A, 3, 9600, MB_PAR_EVEN) 

    I am trying to understand which part of code sends the "function code" as modbus format is 

    start,slave id,function code,addresshi byte,address lo byte,crc lo,crc hi.

    here callback function for  read holding register (0x03) is invoked when I send command as  

    -m rtu -a 10 -r 1000 -c64 -t 4  -b 38400 -d 8 -p even COM4

    1.for each frame where can I get crc hi and crc lo byte ?

    2.As 0x06 is write to signle register function code  to update the register values I am sending command :

    -m rtu -a 10 -r 1000 -c64 -t 6  -b 38400 -d 8 -p even COM4

    but in modpoll thats a invalid data type ..

    same happens for 0x10(16 decimal ) write to multiple register function code hence i sent command as 

    -m rtu -a 10 -r 1000 -c64 -t 16  -b 38400 -d 8 -p even COM4

    Can you guide on how to update register values so that function eMBException
    eMBFuncWriteHoldingRegister() will be invoked .

    I might be misunderstood here,please correct

    Thanks

     

  • In reply to Kirti:

    As per the modpoll usage in the documentation :-
    modpoll.exe -m rtu -a 10 -r 1 -t 4 -b 38400 -d 8 -p even COM3 16

    will cause the function eMBFuncWriteMultipleHoldingRegister() to be called
  • In reply to Jeremy:

    Thanks Jeremy..you are a hero..

    so for single register write command: 

    -m rtu -a 10 -r 1000  -t 4  -b 9600 -d 8 -p even COM4  6 

    1.once I send this command I got as "written 1 reference ": how do i ensure which  reference is updated 

    2.command for single regster(6) is sent ,so function eMBFuncWriteHoldingRegister() is expected to call but eMBFuncWriteMultipleHoldingRegister() exception is called which is for 16 command.

    I verified by putting printf statement in eMBFuncWriteMultipleHoldingRegister() function ..I got the ucMBframe[0](function code ) as 16 when -m rtu -a 10 -r 1000  -t 4  -b 9600 -d 8 -p even COM4  6      is entered (apologies if the command is infront of me but misunderstood)