|
|
View previous topic :: View next topic |
Author |
Message |
Sid2286
Joined: 12 Aug 2010 Posts: 119
|
Modbus Communication |
Posted: Sun Feb 27, 2011 3:24 am |
|
|
Hi,
I'm trying to establish the modbus slave communication using the existing ex_modbus_slave.c
I connected the Tx pin of Rs232 connector to Pin B0 and Rx pin to Pin B1 of microcontroller.
I'm using the modbus scan software to read the values.
however, i'm not sure what other things I need to configure.
till now i have not been able to establish any communication.
Please help me.
Thanks
Sid |
|
|
Sid2286
Joined: 12 Aug 2010 Posts: 119
|
Connections with modbus |
Posted: Sun Feb 27, 2011 9:51 am |
|
|
I tried running the code making the following connections, the connections is in the link below
http://www.4freeimagehost.com/show.php?i=4d3b0503ee6d.jpg
and I connected the rs485-232 converter to the PC.
I tired viewing the output from the slave device using modbusview but it is coming timeout
the transmit data is as follows:-
[3A][30][31][30][33][30][30][34][30][30][30][34][30][37][43][0D][0A]
and the data I received is as follows:-
[B1][D6][F6][96][F6][F6][76][F6][F6][F6][76][F6][16][96][95][EB][00]
I'm using modbusview as my master and the settings are as follows:-
com:-8
baudrate:- 9600
databit:- 8
Parity:-N
stopbit:-1
Mode:- Binary/RTU
Master/Slave:- Master selected
My code is as follows:-
Code: |
#define USE_WITH_PC 1
#include <16f877A.h>
#device *=16
#fuses HS, NOWDT, NOLVP, NOBROWNOUT, NOPROTECT, PUT
#use delay(clock=40000000)
#define MODBUS_TYPE MODBUS_TYPE_SLAVE
#define MODBUS_SERIAL_RX_BUFFER_SIZE 64
#define MODBUS_SERIAL_BAUD 9600
#ifndef USE_WITH_PC
#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_EXT
#define MODBUS_SERIAL_TX_PIN PIN_B1 // Data transmit pin
#define MODBUS_SERIAL_RX_PIN PIN_B0 // Data receive pin
//The following should be defined for RS485 communication
#define MODBUS_SERIAL_ENABLE_PIN PIN_B2 // Controls DE pin for RS485
#define MODBUS_SERIAL_RX_ENABLE 0 // Controls RE pin for RS485
#else
#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_EXT
#endif
#include "modbus.c"
#define MODBUS_ADDRESS 0xF7
/*This function may come in handy for you since MODBUS uses MSB first.*/
int8 swap_bits(int8 c)
{
return ((c&1)?128:0)|((c&2)?64:0)|((c&4)?32:0)|((c&8)?16:0)|((c&16)?8:0)
|((c&32)?4:0)|((c&64)?2:0)|((c&128)?1:0);
}
void main()
{
int8 coils = 0b00000101;
int8 inputs = 0b00001001;
int16 hold_regs[] = {0x8800,0x7700,0x6600,0x5500,0x4400,0x3300,0x2200,0x1100};
int16 input_regs[] = {0x1100,0x2200,0x3300,0x4400,0x5500,0x6600,0x7700,0x8800};
int16 event_count = 0;
modbus_init();
while(TRUE)
{
while(!modbus_kbhit());
//check address against our address, 0 is broadcast
if((modbus_rx.address == MODBUS_ADDRESS) || modbus_rx.address == 0)
{
switch(modbus_rx.func)
{
case FUNC_READ_COILS: //read coils
case FUNC_READ_DISCRETE_INPUT: //read inputs
if(modbus_rx.data[0] || modbus_rx.data[2] ||
modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
int8 data;
if(modbus_rx.func == FUNC_READ_COILS)
data = coils>>(modbus_rx.data[1]); //move to the starting coil
else
data = inputs>>(modbus_rx.data[1]); //move to the starting input
data = data & (0xFF>>(8-modbus_rx.data[3])); //0 out values after quantity
if(modbus_rx.func == FUNC_READ_COILS)
modbus_read_discrete_input_rsp(MODBUS_ADDRESS, 0x01, &data);
else
modbus_read_discrete_input_rsp(MODBUS_ADDRESS, 0x01, &data);
event_count++;
}
break;
case FUNC_READ_HOLDING_REGISTERS:
case FUNC_READ_INPUT_REGISTERS:
if(modbus_rx.data[0] || modbus_rx.data[2] ||
modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
if(modbus_rx.func == FUNC_READ_HOLDING_REGISTERS)
modbus_read_holding_registers_rsp(MODBUS_ADDRESS,(modbus_rx.data[3]*2),hold_regs+modbus_rx.data[1]);
else
modbus_read_input_registers_rsp(MODBUS_ADDRESS,(modbus_rx.data[3]*2),input_regs+modbus_rx.data[1]);
event_count++;
}
break;
case FUNC_WRITE_SINGLE_COIL: //write coil
if(modbus_rx.data[0] || modbus_rx.data[3] || modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else if(modbus_rx.data[2] != 0xFF && modbus_rx.data[2] != 0x00)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_VALUE);
else
{
//coils are stored msb->lsb so we must use 7-address
if(modbus_rx.data[2] == 0xFF)
bit_set(coils,7-modbus_rx.data[1]);
else
bit_clear(coils,7-modbus_rx.data[1]);
modbus_write_single_coil_rsp(MODBUS_ADDRESS,modbus_rx.data[1],((int16)(modbus_rx.data[2]))<<8);
event_count++;
}
break;
case FUNC_WRITE_SINGLE_REGISTER:
if(modbus_rx.data[0] || modbus_rx.data[1] >= 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
//the registers are stored in little endian format
hold_regs[modbus_rx.data[1]] = make16(modbus_rx.data[3],modbus_rx.data[2]);
modbus_write_single_register_rsp(MODBUS_ADDRESS,
make16(modbus_rx.data[0],modbus_rx.data[1]),
make16(modbus_rx.data[2],modbus_rx.data[3]));
}
break;
case FUNC_WRITE_MULTIPLE_COILS:
if(modbus_rx.data[0] || modbus_rx.data[2] ||
modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
int i,j;
modbus_rx.data[5] = swap_bits(modbus_rx.data[5]);
for(i=modbus_rx.data[1],j=0; i < modbus_rx.data[1]+modbus_rx.data[3]; ++i,++j)
{
if(bit_test(modbus_rx.data[5],j))
bit_set(coils,7-i);
else
bit_clear(coils,7-i);
}
modbus_write_multiple_coils_rsp(MODBUS_ADDRESS,
make16(modbus_rx.data[0],modbus_rx.data[1]),
make16(modbus_rx.data[2],modbus_rx.data[3]));
event_count++;
}
break;
case FUNC_WRITE_MULTIPLE_REGISTERS:
if(modbus_rx.data[0] || modbus_rx.data[2] ||
modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
int i,j;
for(i=0,j=5; i < modbus_rx.data[4]/2; ++i,j+=2)
hold_regs[i] = make16(modbus_rx.data[j+1],modbus_rx.data[j]);
modbus_write_multiple_registers_rsp(MODBUS_ADDRESS,
make16(modbus_rx.data[0],modbus_rx.data[1]),
make16(modbus_rx.data[2],modbus_rx.data[3]));
event_count++;
}
break;
default: //We don't support the function, so return exception
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_FUNCTION);
}
}
}
}
|
looking forward for some help...I'm out of ideas now..
please help
thanks
Sid |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Mon Feb 28, 2011 9:51 am |
|
|
Quote: | the transmit data is as follows:
[3A][30][31][30][33][30][30][34][30][30][30][34][30][37][43][0D][0A] |
It's no valid MODBUS RTU data. |
|
|
Sid2286
Joined: 12 Aug 2010 Posts: 119
|
|
Posted: Mon Feb 28, 2011 10:06 am |
|
|
How do I know what is the transmitted data? I tried to understand the code but it was quite difficult.
Please help. How should I proceed? |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Mon Feb 28, 2011 4:45 pm |
|
|
Quote: | How do I know what is the transmitted data? I tried to understand the code but it was quite difficult. |
You have MODBUSVIEW setup to ASCII instead of RTU and a default address of 01 decimal instead of 0xF7. This can never work. Read MOSBUSVIEW help thoroughly and try to understand the configuration settings. |
|
|
Sid2286
Joined: 12 Aug 2010 Posts: 119
|
|
Posted: Tue Mar 01, 2011 12:07 am |
|
|
thanks FvM,
It was my mistake not to set it into RTU mode.
Now that I have done the configuration I got the following results:-
Transmitted data:-
[01][03][00][F6][00][64][A4][13]
Received Data:-
[7F][7E][13][37][B7][76]
and still it is poll out error.
I did some modification in the code
Code: |
int8 coils = 0b00000101;
int8 inputs = 0b00001001;
int16 hold_regs[] = {0x8800,0x7700,0x6600};
int16 input_regs[] = {0x1100,0x2200,0x3300,0x4400}; |
and
Code: |
if(modbus_rx.func == FUNC_READ_COILS)
//Bugfix modbus_read_discrete_input_rsp(MODBUS_ADDRESS, 0x01, &data);
modbus_read_coils_rsp(MODBUS_ADDRESS, 0x01, &data); |
according to the forum link
http://www.ccsinfo.com/forum/viewtopic.php?p=98454
and changed the address to #define MODBUS_ADDRESS 123
but still no success..I'm trying very hard to find out the solution.
Please help me.
thanks
Sid |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Tue Mar 01, 2011 12:19 am |
|
|
You are still sending to MODBUS address 01, it's the first byte in the telegram. I also wonder, where the received data come from, the slave won't respond. What's the RS485 adapter at the master side, does is set the bus idle level correctly? |
|
|
Sid2286
Joined: 12 Aug 2010 Posts: 119
|
|
Posted: Tue Mar 01, 2011 12:28 am |
|
|
I have connected an adapter (Rs-485 to 232) between PC and slave device.
I'm not able to change anything at the master end.
My connections are according to the link I provided
http://www.4freeimagehost.com/show.php?i=4d3b0503ee6d.jpg
What should I do next??? |
|
|
Sid2286
Joined: 12 Aug 2010 Posts: 119
|
|
Posted: Tue Mar 01, 2011 1:26 am |
|
|
I made the following changes
Code: |
#define MODBUS_ADDRESS 0xF7 |
and the data transmitted was
[F7][03][00][00][00][40][50][AC]
ans received was
[04][7E][FF][FF][7F][5F][A7]
I have a little finding...I don't know if that will work...
the Led of the adapter for tx is blinking after every poll, however Led for receiving at the adapter on continuously.
so I removed the pull up resistor at the rx end. but still no change.
Ideally but the leds should be blinking.
Now I don't know if its the programming error or the connection error.
Please help
Thanks
Sid |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Tue Mar 01, 2011 12:24 pm |
|
|
The TX data is O.K.now, the RX data simply garbage. Most likely nothing, that has been send out by the slave.
Check your RS485 adapter, if it has the required pull-up/pull_down resistors at the bus terminals. |
|
|
Sid2286
Joined: 12 Aug 2010 Posts: 119
|
|
Posted: Tue Mar 01, 2011 8:52 pm |
|
|
Thanks FvM,
I will check the adapter connections (most likely guess they are ok) however can you please confirm if my connection from transceiver to PIC is ok?
And also please tell me if there are any bugs with existing ex_modbus_slave.c file.
Thanks,
sid |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Wed Mar 02, 2011 1:56 am |
|
|
I think, there must be a RS485 hardware problem, because you're apparently receiving garbage characters, that haven't been send by the slave. Particularly, the slave won't send permanently. You should be able to check in addition, if the slave is sending anything.
The connection is correct as far as I see, but I'm using a different setup (PIC24 UART with hardware transmitter enable), so I didn't check the correct operation of the respective RS485 related parts of the MODBUS driver.
I think to remember, that I had corrected minor errors in a previous version of the MODBUS slave example, but I don't know, what it was. |
|
|
Sid2286
Joined: 12 Aug 2010 Posts: 119
|
|
Posted: Wed Mar 02, 2011 3:15 am |
|
|
Thanks FvM,
I will search the forum to find out bugs if any :(
I need to find out some way to establish this communication.
hope I come across something.
thanks,
Sid |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Wed Mar 02, 2011 8:49 am |
|
|
I can't retrieve a bug now. I think, you should care for the other points first. |
|
|
Sid2286
Joined: 12 Aug 2010 Posts: 119
|
|
Posted: Wed Mar 02, 2011 9:26 am |
|
|
I had a card which has 8051 microcontroller on it, which uses modbus protocol. I connected the adapter to it and it was perfectly working fine. So i can conclude that the adapter is ok! So I'm left with nothing but to find out the software bug :-(
Please FvM, help me! I appreciate the effort you've taken till now.
Thanks for your time. Please do something!
Regards,
sid |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|