|
|
View previous topic :: View next topic |
Author |
Message |
td
Joined: 16 Apr 2015 Posts: 21 Location: India
|
modbus error with pic18f87k90 |
Posted: Tue Jul 28, 2015 11:50 pm |
|
|
hi,
when i interface sn75176 IC with pic18f4620, i can do modbus communication. we are using modbus.c file
but when i connect sn75176 with pic18f87k90, in modbus tester, it shows TIME OUT. (status not connected is showing)
i m using the same code for both pic. following the example code given in ccs
but i dont know why it is working in one controller and not in other.
my code is
Code: |
#include <18F87K90.h>
#device ICD=TRUE
#fuses NOWDT
#fuses MCLR
#fuses HSH
#fuses SOSC_DIG
#fuses NOIESO
#fuses NOBROWNOUT
#fuses NOPLLEN
#use delay (clock=20M)
#define MODBUS_TYPE MODBUS_TYPE_SLAVE
#define MODBUS_SERIAL_TYPE MODBUS_RTU
#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_RDA
#define MODBUS_SERIAL_BAUD 9600 //
#use rs232(baud=9600, UART1, bits=8, stop=1, parity=N, stream=MODBUS_SERIAL, errors)
#include "modbus.c"
#define MODBUS_ADDRESS 2 //Channel_No
#define MODBUS_SERIAL_ENABLE_PIN Pin_C5
int16 hold_regs [45] = {0};
int16 input_regs[] = {0};
int16 event_count = 0;
void main()
{
modbus_init();
while(1)
{
output_high(GSM_IND);
delay_ms( 1000 );
output_low(GSM_IND);
delay_ms( 1000 );
hold_regs[0]=1;
hold_regs[1]=2;
hold_regs[2]=3;
hold_regs[3]=4;
hold_regs[4]=5;
hold_regs[5]=6;
hold_regs[6]=7;
hold_regs[7]=8;
hold_regs[8]=9;
hold_regs[9]=10;
if(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_HOLDING_REGISTERS:
case FUNC_READ_INPUT_REGISTERS:
if(modbus_rx.data[0] || modbus_rx.data[2] ||
modbus_rx.data[1] >= 22 || modbus_rx.data[3]+modbus_rx.data[1] > 22)
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_REGISTER:
if(modbus_rx.data[0] || modbus_rx.data[1] >= 22)
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]));
hold_regs[modbus_rx.data[1]]=hold_regs[modbus_rx.data[1]]/256;
}
break;
case FUNC_WRITE_MULTIPLE_REGISTERS:
if(modbus_rx.data[0] || modbus_rx.data[2] ||
modbus_rx.data[1] >= 21 || modbus_rx.data[3]+modbus_rx.data[1] > 21)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
int i,j;
int8 k;
k=modbus_rx.data[1];
for(i=0,j=5; i < modbus_rx.data[4]/2; ++i,j+=2)
hold_regs[k+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++;
}
hold_regs[modbus_rx.data[1]]=hold_regs[modbus_rx.data[1]]/256;
break;
default: //We don't support the function, so return exception
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_FUNCTION);
}
}
}// modbus function ends
}}
|
the same working in 18f4620 after changing configuration bit.
in the above code, is there any mistake in configuration bit?
i m using uart 1. (PIN C7 and C6) and C5 as enable pin
i checked the above code with and without #device ICD=TRUE .
but the same result - TIME OUT.
please advise. |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
Re: modbus error with pic18f87k90 |
Posted: Wed Jul 29, 2015 1:46 am |
|
|
Code: |
...
#define MODBUS_TYPE MODBUS_TYPE_SLAVE
#define MODBUS_SERIAL_TYPE MODBUS_RTU
#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_RDA
#define MODBUS_SERIAL_BAUD 9600 //
// #use rs232(baud=9600, UART1, bits=8, stop=1, parity=N, stream=MODBUS_SERIAL, errors) // DO NOT define the serial port used by modbus. Modbus.c does that for you. MODBUS_INT_RDA selects UART1.
#define MODBUS_SERIAL_ENABLE_PIN Pin_C5 // This MUST go before the include of modbus.c. Putting it after will stop the enable working. This is probably the main problem.
#include "modbus.c"
// This is not used by modbus.c and so it can come after the include.
#define MODBUS_ADDRESS 2
...
|
|
|
|
td
Joined: 16 Apr 2015 Posts: 21 Location: India
|
|
Posted: Wed Jul 29, 2015 2:30 am |
|
|
i changed the code..
Code: |
#define MODBUS_TYPE MODBUS_TYPE_SLAVE
#define MODBUS_SERIAL_TYPE MODBUS_RTU
#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_RDA
#define MODBUS_SERIAL_BAUD 9600
#define MODBUS_SERIAL_ENABLE_PIN Pin_C5
#define MODBUS_ADDRESS 2
#include "modbus.c"
......
|
then also I'm getting TIMEOUT: status not connected. |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Wed Jul 29, 2015 3:02 am |
|
|
I'm no expert in fuses, but at a glance what you have looks okay.
However, this code waits two seconds in every loop:
Code: | output_high(GSM_IND);
delay_ms( 1000 );
output_low(GSM_IND);
delay_ms( 1000 );
|
That's going to cause a lot of problems, especially if the timeout time is shorter than two seconds.
What are your termination and bias? Have do you know if the slave doesn't receive, or if you are sure it does, does it try to send anything back? |
|
|
td
Joined: 16 Apr 2015 Posts: 21 Location: India
|
|
Posted: Wed Jul 29, 2015 3:20 am |
|
|
deleted delay_ms( 1000 ) . then also not connected.
termination resistor 120E, and bias is 10K. same hardware successfully communicate with PIC18f4620 and modbus.
i have connected leds in RX and Tx pin of PIC. so if anything receive or transmit, led will blink.
but in this case, led is off.
|
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Wed Jul 29, 2015 4:06 am |
|
|
Your code includes: Therefore it is being compiled for debug. I therefore assumed you were using a debugger to single step and breakpoint the code. That would allow you to tell you exactly what was working and what wasn't.
If you are trying to run this code standalone, which is what your most recent comment about LEDs suggests, then yes, of course, it won't work as its debug code, not release (standalone) code. |
|
|
td
Joined: 16 Apr 2015 Posts: 21 Location: India
|
|
Posted: Wed Jul 29, 2015 4:33 am |
|
|
Quote: | i checked the above code with and without #device ICD=TRUE .
but the same result - TIME OUT. |
we are not using debug option.
directly programing using pickit3.
But i dont know why the same code and hardware are working for one controller and not for other.
I checked the uart of pic18f87k90. It is working while connecting to hyperterminal by rs232. But while connecting modbus, TIMEOUT error...... |
|
|
td
Joined: 16 Apr 2015 Posts: 21 Location: India
|
solved |
Posted: Thu Jul 30, 2015 3:32 am |
|
|
now its working.......
thank you for your support....
for last 3 days it was showing TIMEOUT. but today, it is working. but some times.. it is showing timeout.
Quote: |
...
#define MODBUS_TYPE MODBUS_TYPE_SLAVE
#define MODBUS_SERIAL_TYPE MODBUS_RTU
#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_RDA
#define MODBUS_SERIAL_BAUD 9600 //
// #use rs232(baud=9600, UART1, bits=8, stop=1, parity=N, stream=MODBUS_SERIAL, errors) // DO NOT define the serial port used by modbus. Modbus.c does that for you. MODBUS_INT_RDA selects UART1.
#define MODBUS_SERIAL_ENABLE_PIN Pin_C5 // This MUST go before the include of modbus.c. Putting it after will stop the enable working. This is probably the main problem.
#include "modbus.c"
// This is not used by modbus.c and so it can come after the include.
#define MODBUS_ADDRESS 2
...
|
thank you... it may be the problem...'
but after correcting this also it was showing timeout for 1 day. but now its working... |
|
|
td
Joined: 16 Apr 2015 Posts: 21 Location: India
|
|
Posted: Sun Aug 02, 2015 10:51 pm |
|
|
again.... it is showing timeout error for last 2 days....
but when i connect another device having 18f4620 controller, modbus is working without any timeout. |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Mon Aug 03, 2015 2:26 am |
|
|
td wrote: | but when i connect another device having 18f4620 controller, modbus is working without any timeout. |
This shows you most likely still have a hardware problem, because it works when some hardware is connected, and doesn't if its not. You also had firmware problems. Some you have fixed, and you may still have some others. What is your circuit, both with and without the 18f4620? |
|
|
td
Joined: 16 Apr 2015 Posts: 21 Location: India
|
|
Posted: Mon Aug 03, 2015 5:26 am |
|
|
both circuit are similar. only difference microcontroller.
via optocoupler connected to sn75176 IC.
in code, we used
Code: |
case FUNC_READ_HOLDING_REGISTERS:
case FUNC_READ_INPUT_REGISTERS:
if(modbus_rx.data[0] || modbus_rx.data[2] ||
modbus_rx.data[1] >= 16000 || modbus_rx.data[3]+modbus_rx.data[1] > 16000)
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;
|
length of holding/input register here we choose as 16000. previously it was 21.
in modbus tester, we select the length above 127, it shows illegal response. in modbus.c driver file , we changed
Code: |
struct
{
unsigned int8 address; //
unsigned int8 len; //number of bytes in the message received
function func; //the function of the message received
exception error; //error recieved, if any
unsigned int16 data[MODBUS_SERIAL_RX_BUFFER_SIZE]; //data of the message received // changed int8 to 16
} modbus_rx;
|
|
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Mon Aug 03, 2015 9:10 am |
|
|
td wrote: |
Code: |
case FUNC_READ_HOLDING_REGISTERS:
case FUNC_READ_INPUT_REGISTERS:
if(modbus_rx.data[0] || modbus_rx.data[2] ||
modbus_rx.data[1] >= 16000 || modbus_rx.data[3]+modbus_rx.data[1] > 16000)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
|
|
This just isn't going to work. The example code can only work with 256 registers. It assumes the upper bytes of register numbers is assumed to be zero. It can be made to work with more, but it needs to be changed to do that.
Then there is the question of message size. You can't send to many registers in one message. I forget how many it is, but its dependant on message buffer lengths, and its a LOT less than 16000! I think maybe 16 or 32 registers in one message.
Also, Modbus only allows 10000 endpoint of any one kind: holding registers, coils, input registers etc. In fact it is possible to have more, the addressing will actually allow upto 65536 or each type, and some implementations allow it, but the original Modbus only allowed 10000. In general I can't see the need for so many. There are ways of using the registers to access large data sets, for example to use a pair as start address and counts to access larger memory spaces. However you do it, simply making the counts huge won't work.
This code won't work, and will cause strange, unexpected results.
Quote: |
Code: |
struct
{
unsigned int8 address; //
unsigned int8 len; //number of bytes in the message received
function func; //the function of the message received
exception error; //error recieved, if any
unsigned int16 data[MODBUS_SERIAL_RX_BUFFER_SIZE]; //data of the message received // changed int8 to 16
} modbus_rx;
|
|
What do you think this does? The data in the buffer is eight bit characters, making the buffer sixteen bit simply wastes memory, and may cause other problems. If you are thinking about changing the CCS supplied Modbus code, then you're doing something wrong, and need to think again.
Are you getting timeouts, or are you getting errors? Which is it? What is the actual problem? You say you have code for an that works, but it doesn't in the 18f87k90, but then you say you've changed the number of registers and messed about with modbus.c. So it isn't the "same code" at all, is it?
I'd start by getting a simple version to work. I might start, in fact and assuming that I knew than code really worked properly, by getting the 18f4620 code working on the 18f87k90. I'd make sure the hardware really was doing what I expected to, and that my modbus comms were rock solid reliable. Only then I might start changing the code to do other stuff. but either way, 16000 holding registers is probably not going to work. |
|
|
td
Joined: 16 Apr 2015 Posts: 21 Location: India
|
|
Posted: Wed Aug 05, 2015 12:45 am |
|
|
Quote: | Are you getting timeouts, or are you getting errors? Which is it? What is the actual problem? |
when i use 18f4620 with modbus register length 21, it was working perfect.
when i use the same hardware circuit with 18f87k90 and modbus register length 21, most of the time, we r getting timeout. but sometimes, it is working.
when it was working, i changed the modbus register lenth. it is working only up to 127.
in our project, we need atleast 2000-3000 locations (holding/input registers).thats why i extended the length of modbus register.
Quote: | What do you think this does? The data in the buffer is eight bit characters, making the buffer sixteen bit simply wastes memory, and may cause other problems. If you are thinking about changing the CCS supplied Modbus code, then you're doing something wrong, and need to think again. |
thank you for pointing out my mistakes.
is there any other way to extend the length of modbus registers? |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Wed Aug 05, 2015 2:34 am |
|
|
Look, two or three thousand registers, while still a lot, are much easier that sixteen thousand. I still think its too many to do directly as registers, and there's no way you can transfer that many at a time. You'll have to limit the number in a message to, say sixteen, as Modbus messages cannot be very long.
You need to have a look at the Modbus protocol documentation (Look on modbus.org) to understand how Modbus addressing works to increase to a few thousand registers. I've given you one suggestion as to how to implement more - think of it more as a serially driven (e.g. SPI or I2C) memory, and don't access the data directly, but through addressing and access registers.
You've not given any useful details of your circuits, and if it works some of the time then hardware is likely to be the problem, also your main loop, that has or calls the Modbus code, must loop round as fast as possible so that it can catch all incoming messages. Delays, even of a millisecond or so, may result in missed messages. In fact, better yet, don't use delays at all. You've not even told us what compiler version you are using. You've shown you don't know how to debug using the ICSP facilities (hardware debugging). So all in all, there's little more I can do. |
|
|
td
Joined: 16 Apr 2015 Posts: 21 Location: India
|
|
Posted: Wed Aug 05, 2015 4:31 am |
|
|
compiler version: 4.119
Our project is a data logger. We used rtc ds1302 to get the date and time. if any events occurs, the data with date and time will be saved in eeprom 24lc16. For each event, we need 10 locations in eeprom. (date&time - 7 locations itself).
At last for displaying the data saved in eeprom, we use modbus.ie, via modbus, we are displaying the saved data. For each event, we need 10 different registers. We need to save at least 200 events. |
|
|
|
|
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
|