RCM 3900 modbus

Hello everyone,

I’m new in using the material Rabbit.
I have a RCM3900 and I want to read the records of a datalogger. I connected with an RS485 link to my card.
So I used the library and function modbus_master.lib MBM_ReadRegs.

#class auto
#use Modbus_Master.lib
void main (void)
{
int A,Regs_Value[50];

A = MBM_ReadRegs( 7, &Regs_Value[0], 0xC552, 2);

printf("%d, %d,
", Regs_Value[0], Regs_Value[1]);
while (1) ;
}

But I have two errors:_initMBMpacket and MBM_senbd_ADU

I do not understand why … If anyone can help me or give me a quick example of reading 485.

Thank you all.

My understanding is that these are two functions which you need to supply which will depend on the hardware interface you are using. I do notice that in the 10.66 library the call to _initMBMpacket has been #if 0’d out so may not be necessary.

You could look at the modbus_slave_tcp.lib and the modbus_slave__xxx.lib libraries for some examples of code for sending modbus packets to base your code on.

The 10.66 compiler only has a BL4S1xx.LIB but the DC 10.60 compiler has BL26xx and LP35xx libs.

Hope some of this points you in the right direction.

Regards,
Peter

Hello and Thanks Peter…

…but I did not understand. I have no BL4S1, LP35xx…
I just have a Rabbit 3000 with RCM 3900. I use the RS485 to connect the RCM3900 my datalogger. And I must read in my datalogger various measures …

Help me please.
Thanks

I was suggesting that you look at these examples and use them to base your code on. They show how to the RS485 interface on the various boards (bl2600 and lp3500) and should be a good place to start from.

I’m just starting to implement similar code for the BL5s220 and then my own custom Rabbit board and I’ll let you know how I get on.
Regards,
Peter

Try downloading the modbus module from http://www.digi.com/support/productdetl.jsp?pid=4978&osvid=0&s=565&tp=10&tp2=0 and have a look at the samples provided with it. There is an example of an implementation of the MBM_Send_ADU function in the modbus_serial_master.c file in the samples directory.

Regards,
Peter

Ok thank you very much,
I’ll see it right away.

Good day

Thank you, I already see more clearly. But I still can not read a register.
I think my connection does not do this because MB_SUCCESS = 0.

I took the program MODBUS_MASTER_SERIAL.C and I adapted it: C PORT RS785 …
My slave is configured with a stop bit and no parity bit and 9600 baud. I already paid for 9600 but the other two parameters I do not know how.

Thank you

Looking in RS232.LIB 1 stop bit and no parity seem to be the default settings when the port is opened.

Have you modified ser485Tx/ser485Rx to set the pin controlling the rs485 direction correctly?

Regards,
Peter

Again, thank you Peter

It’s ok for parity and stop bit! : D
Could you give me an example configuration for ser485Tx/ser485Rx?
I think after that my program will be good.

looking at the schematic for the RCM3900 development board, you need to be switching PD7 to change the RS485 direction. The samples\rcm39xx.lib file has the correct functions to use so just delete the ones in your modbus_serial_master.c and make sure to #use the lib.

Regards,
Peter

Hello,
Exact PD7 must be enabled. I looked in the library to set TCM39xx.lib ser485Txet ser485Rx. But I still can not, I’m sorry, it’s really complicated. Can you tell me where is my mistake?

#define Mesure
#define MODBUS_DEBUG_PRINT 0
#define CINBUFSIZE 15
#define COUTBUFSIZE 15
#define MODBUS_PORT C
#define _RS485 485
#define SERIAL_PORT_MODE _RS485
#use modbus_master.lib

void brdInit (void);
int MBM_Send_ADU ( char *Packet, int ByteCount );
int MBM_Rcv_Resp ( char * Packet );
void serInit ( void );
void ser485Tx(void);
void ser485Rx(void);

main ()
{ int i,a, RegsValue[50];
serInit();
i = MBM_ReadRegs ( 7, &RegsValue[0], 0xC552, 4 ); // read reg 0
a =MB_SUCCESS;
if (a==0)
printf(“Connexion NON OK”);
else printf(“Connexion OK”);
printf("%d, %d,
", RegsValue[1], RegsValue[2]);
while (1);
}

void brdInit (void)
{
WrPortI(PCFR, &PCFRShadow, PCFRShadow&0xEA); //clear bit 4,2,0 to normal function
//bits 5,3,1 normally inputs
WrPortI(PDDDR, &PDDDRShadow, 0x8b); //set bits 7,3,1,0 to output, rest inputs
}
void serInit ( void )
{ serCopen (9600 ); // open the serial port
}

void ser485Tx(void)
{
#asm
ld a,(PDDRShadow) ;get copy of shadow reg
set 7,a ;set bit 7
ioi ld (PDDR),a ;set PD7 high
ld (PDDRShadow),a ;update shadow reg
#endasm
}

void ser485Rx(void)
{
#asm
ld a,(PDDRShadow) ;get copy of shadow reg
res 7,a ;clear bit 7
ioi ld (PDDR),a ;set PF5 low
ld (PDDRShadow),a ;update shadow reg
#endasm
}

I think the problem comes from this part of the program because I copied and arranged functions MBM_Send_ADU and MBM_Rcv_Resp for my port C.
Thank you

Have you tried:

#define Mesure
#define MODBUS_DEBUG_PRINT 0
#define CINBUFSIZE 15
#define COUTBUFSIZE 15
#define MODBUS_PORT C
#define _RS485 485
#define SERIAL_PORT_MODE _RS485
#use modbus_master.lib
#use “rcm39xx.lib”

int MBM_Send_ADU ( char *Packet, int ByteCount );
int MBM_Rcv_Resp ( char * Packet );
void serInit ( void );

main ()
{ int i,a, RegsValue[50];
serInit();
i = MBM_ReadRegs ( 7, &RegsValue[0], 0xC552, 4 ); // read reg 0
a =MB_SUCCESS;
if (a==0)
printf(“Connexion NON OK”);
else printf(“Connexion OK”);
printf("%d, %d,
", RegsValue[1], RegsValue[2]);
while (1);
}

void serInit ( void )
{ serCopen (9600 ); // open the serial port
}

This should pull in the required functions from the lib and make sure all the ports etc are configured.

Regards,
Peter

Thank you but it does not work.
I really do not understand, I begin to drop … : /
Here is my program and some explanations:
Slave address: 07
Baud Rate: 9600
Data Length: 8
Stop Bit: 1
Parity: No Parity
half duplex

Program:

#define Mesure
#define MODBUS_DEBUG_PRINT 0 // define to 1 to print transactions
#define CINBUFSIZE 15
#define COUTBUFSIZE 15
#define MODBUS_PORT C

#define _RS485 485
#define SERIAL_PORT_MODE _RS485
#use modbus_master.lib

void brdInit (void);
int MBM_Send_ADU ( char *Packet, int ByteCount );
int MBM_Rcv_Resp ( char * Packet );
void serInit ( void );
void ser485Tx(void);
void ser485Rx(void);

main ()
{ int i,a, RegsValue[50];
serInit();
ser485Tx();
i = MBM_ReadRegs ( 7, &RegsValue[0], 0xC558, 4 ); // read reg 0
ser485Rx();
a =MB_SUCCESS;
if (a==0)
printf("Connexion NON OK,
“);
else printf(“Connexion OK”);
printf(”%d, %d,
", RegsValue[0], RegsValue[1]);
while (1);
}

/****************************************************
/****************************************************/

void brdInit (void)
{
WrPortI(PCFR, &PCFRShadow, PCFRShadow&0xEA); //clear bit 4,2,0 to normal function
WrPortI(PCDR, &PCDRShadow, PCDRShadow|0x15); //bits 5,3,1 normally inputs
WrPortI(PDDDR, &PDDDRShadow, 0x8b); //set bits 7,3,1,0 to output, rest inputs
}
void serInit ( void )
{ serCopen (9600 ); // open the serial port
}

void ser485Tx( void )
{
#asm
push ip ;save off IP state
ipset 1 ;set interrupt priority to level 1
ld a,(PDDRShadow) ;get copy of shadow reg
set 7,a ;set bit 7
ioi ld (PDDR),a ;set PD7 high
ld (PDDRShadow),a ;update shadow reg
pop ip ;restore IP to the previous state
#endasm
}

void ser485Rx( void )
{
#asm
push ip ;save off IP state
ipset 1 ;set interrupt priority to level 1
ld a,(PDDRShadow) ;get copy of shadow reg
res 7,a ;clear bit 7
ioi ld (PDDR),a ;set PF5 low
ld (PDDRShadow),a ;update shadow reg
pop ip ;restore IP to the previous state
#endasm
}

/* START FUNCTION DESCRIPTION ********************************************
MBM_Send_ADU
END DESCRIPTION **********************************************************/

int MBM_Send_ADU ( char *Packet, int ByteCount )
{ auto unsigned CRCvalue;
auto unsigned long Endtime;
int i;

// insert CRC
CRCvalue = MODBUS_CRC ( Packet, ByteCount );
Packet[ByteCount+1] = CRCvalue; // store low byte
Packet[ByteCount] = CRCvalue>>8; // store high byte
ByteCount+=2; // adjust for CRC

#ifdef MODBUS_DEBUG_PRINT & 1
printf ( “Tx:” );
for ( i=0; i

Really thank you Peter, and sorry to be so bad

If you have acces to an oscilloscope or an RS485 adapter for your PC I would recommend trying to see what is being transmitted and received on the serial port lines.

Also try setting MODBUS_DEBUG_PRINT to 1 and seeing what status info is displayed.

Regards,
Peter

When I put MODBUS_DEBUG_PRINT to 1, nothing is written. Just 'Connection NOT OK and two random values​​.

I think MBM_Send_ADU MBM_Rcv_Resp and do not execute my program … I think the error is there, but how to fix …

Peter, you did not write a program??

Thank you.

I’m in the middle of writing some test code for modbus but it is for DC10.66 and the BL5S220 board.

by the way this:

a =MB_SUCCESS;
if (a==0)
printf("Connexion NON OK,
“);
else printf(“Connexion OK”);
printf(”%d, %d,
", RegsValue[0], RegsValue[1]);

Will always give “Connexion NON OK” as a is simply set to 0 and checked (MB_SUCCESS = 0)

You should be testing i

You should see at least a “TX: nn nn nn” message with the modbus data you are sending when MODBUS_DEBUG_PRINT is 1

Regards,
Peter

Ok ok, good luck with your code. : D

When I print i i = -1.
How do I know if the connection between the slave and the RCM3900 is good?
And more, I have no message like "TX: nn nn nn"when MODBUS_DEBUG_PRINT is 1!!!

-1 is MBM_INVALID_PARAMETER which looking at the code in modbus_master.lib should only happen for an invalid number of registers which is not the case here.

Have you tried #defining MODBUS_DEBUG and single stepping through the call to MBM_ReadRegs?

Regards,
Peter

I want to say that if I enter a slave address that does not exist … the execution does not change. The same values ​​are displayed and no error occurs …

I’m completely lost