|
|
View previous topic :: View next topic |
Author |
Message |
salihonur
Joined: 21 Mar 2020 Posts: 22
|
Modbus Master/Slave Switch by parameter |
Posted: Thu Nov 26, 2020 4:06 pm |
|
|
Hi guys,
As you know the standard modbus library allows to switch master or slave via macro. But I need to switch it by a flag which will be controlled remotely and save into the eeprom. So I removed all MODBUS2_TYPE == xxxx statements successfully.
Modbus slave works very well. And the mcu sends a query to the slave node and the node reply. I have checked the interrupt and saw that the mcu receives. But there is a problem in the interrupt function below. The state doesn't jump to another state. I'm debugging with numbers to steps. It prints always 111. If I put debug_writeln(modbus2_serial_state); debugging function into each "if" statements, then it jumps to the another state.
Have you ever done similar project? How can I read the response of slave device properly?
Notes:
* MCU is PIC18F46K80
* Compiler version is 5.091.
* UART1 and INT_RDA are used with Modbus RTU
* Master and slave aren't allowed to run at same time
* I'm using modbus TCP/IP at same time. So I renamed library as modbus1 for TCP/IP and modbus2 for RTU.
* debug_writeln is my debugging function which includes printf with a soft-uart port
Code: | void incomming_modbus2_serial() {
char c;
c=fgetc(MODBUS2_SERIAL);
if (!modbus2_serial_new)
{
if(modbus2_serial_state == MODBUS2_GETADDY)
{
[b]debug_writeln("111");[/b]
modbus2_serial_crc.d = 0xFFFF;
modbus2_rx.address = c;
modbus2_serial_state++;
modbus2_rx.len = 0;
modbus2_rx.error=0;
}
else if(modbus2_serial_state == MODBUS2_GETFUNC)
{
[b]debug_writeln("222");[/b]
modbus2_rx.func = c;
modbus2_serial_state++;
}
else if(modbus2_serial_state == MODBUS2_GETDATA)
{
[b]debug_writeln("333");[/b]
if (modbus2_rx.len>=MODBUS2_SERIAL_RX_BUFFER_SIZE)
{
modbus2_rx.len=MODBUS2_SERIAL_RX_BUFFER_SIZE-1;
}
modbus2_rx.data[modbus2_rx.len]=c;
modbus2_rx.len++;
}
modbus2_enable_timeout(TRUE);
modbus2_calc_crc(c);
}
//#if (MODBUS2_TYPE == MODBUS2_TYPE_MASTER)
modbus2_serial_wait=MODBUS2_SERIAL_TIMEOUT;
//#endif
} |
_________________ Compiler v5.091+ Windows 10 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Nov 27, 2020 12:30 am |
|
|
Post the code for debug_writeln(). |
|
|
salihonur
Joined: 21 Mar 2020 Posts: 22
|
|
Posted: Fri Nov 27, 2020 11:19 am |
|
|
Hi,
Here is the debug file.
config file of the project
Code: |
#define DEBUG TRUE
#define PIN_DBG_TX PIN_B7
#define PIN_DBG_RX PIN_A6
|
Debug.h
Code: | /*
* File: Debug.h
* Author: SOZ
*
* Created on 06 Nisan 2019 Cumartesi, 01:23
*/
#ifndef DEBUG_H
#define DEBUG_H
typedef union{
char bytes[64];
}string;
#ifndef DEBUG_LED
#define DEBUG_LED FALSE
#endif
#ifndef DBG_BAUDRATE
#define DBG_BAUDRATE 115200
#endif
#ifndef PIN_DBG_TX
#define PIN_DBG_TX PIN_C6
#define PIN_DBG_RX PIN_C7
#endif
#include "Debug.c"
#endif /* DEBUG_H */
|
Debug.c
Code: |
/*
* File: Debug.c
* Author: SOZ
*
* Created on 06 Nisan 2019 Cumartesi, 01:23
*/
#ifndef DEBUG_C
#define DEBUG_C
#ifdef DEBUG
/*
Format ===================
The format takes the generic form %nt. n is optional and may be 1-9 to specify how many characters are to be outputted, or 01-09 to indicate leading zeros, or 1.1 to 9.9 for floating point and %w output. t is the type and may be one of the following:
c : Character
s : String or character
u : Unsigned int
d : Signed int
Lu : Long unsigned int
Ld : Long signed int
x : Hex int (lower case)
X : Hex int (upper case)
Lx : Hex long int (lower case)
LX : Hex long int (upper case)
f : Float with truncated decimal
g : Float with rounded decimal
e : Float in exponential format
w : Unsigned int with decimal place inserted. Specify two numbers for n. The first is a total field width. The second is the desired number of decimal places.
fprintf (stream, cstring, values...)
fputc(cdata, stream)
fputs (string, stream)
*/
#use rs232(baud=DBG_BAUDRATE, parity=N, xmit=PIN_DBG_TX, rcv=PIN_DBG_RX, bits=8, errors, stream=DEBUG_PORT)
void debug_write(int *p)
{
restart_wdt();
fprintf(DEBUG_PORT, p);
restart_wdt();
}
void debug_write(int32 num)
{
restart_wdt();
fprintf(DEBUG_PORT, "%lu", num);
restart_wdt();
}
void debug_write(float num)
{
restart_wdt();
fprintf(DEBUG_PORT, "%f", num);
restart_wdt();
}
void debug_write_ip(unsigned int32 ipDouble)
{
union
{
unsigned int8 v[4];
unsigned int32 d;
} ipUnion;
ipUnion.d = ipDouble;
for(int i=0; i<4; i++)
{
if(i != 0)
debug_write(".");
debug_write(ipUnion.v[i]);
}
}
void debug_writeln(int *p)
{
restart_wdt();
fprintf(DEBUG_PORT, p);
fprintf(DEBUG_PORT, "\r");
restart_wdt();
}
void debug_writeln(int32 num)
{
restart_wdt();
fprintf(DEBUG_PORT, "%lu", num);
fprintf(DEBUG_PORT, "\r");
restart_wdt();
}
void debug_writeln(float num)
{
restart_wdt();
fprintf(DEBUG_PORT, "%f", num);
fprintf(DEBUG_PORT, "\r");
restart_wdt();
}
void debug_bytes_in_hex(int *bytes, int16 size)
{
for(int16 i=0; i<size; i++)
{
if(i>0)
fprintf(DEBUG_PORT, " ");
fprintf(DEBUG_PORT, "%2X", bytes[i]);
restart_wdt();
}
}
#endif
#endif /* DEBUG_C */
|
_________________ Compiler v5.091+ Windows 10 |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Fri Nov 27, 2020 3:22 pm |
|
|
One problem I have is the fact you've got the WDT enabled. Typically for 'debug' purposes' WDT would NOT be enabled, and only enabled once the product was properly tested and ready for sale.
While I don't used MODbus, the 'library' should be 'stable' so I suspect the problem is in whatever code you've added.
Jay |
|
|
salihonur
Joined: 21 Mar 2020 Posts: 22
|
|
Posted: Fri Nov 27, 2020 3:44 pm |
|
|
temtronic wrote: | One problem I have is the fact you've got the WDT enabled. Typically for 'debug' purposes' WDT would NOT be enabled, and only enabled once the product was properly tested and ready for sale.
While I don't used MODbus, the 'library' should be 'stable' so I suspect the problem is in whatever code you've added.
Jay |
I have never had a problem with WDT. WDT isn't timeout yet. Actually this project has been working since 2014. I used to activate RTU Slave or TCP/IP via macro. But I needed to add master feature. First I splitted and renamed libraries for TCP/IP and RTU. Then I decided to activate modbus master automatically if the Modbus ID is set to 1, otherwise it will stay as a slave. I have no problem on RTU slave and TCP/IP. The problem only appears on master. _________________ Compiler v5.091+ Windows 10 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Nov 27, 2020 5:50 pm |
|
|
Your complaint is that it fails with the line in bold below. It doesn't
advance to the next state.
Quote: |
if(modbus2_serial_state == MODBUS2_GETADDY)
{
debug_writeln("111");
modbus2_serial_crc.d = 0xFFFF;
modbus2_rx.address = c;
modbus2_serial_state++;
modbus2_rx.len = 0;
modbus2_rx.error=0;
}
|
But if you replace the line in bold above with this, it works:
Quote: | debug_writeln(modbus2_serial_state); |
The only thing I can think of is this: You're using function over-loading.
What if it doesn't work correctly in your version ? What if there's a bug
in the compiler ? You might get problems.
Try it with unique function names for your debug routines.
Rename the routines as shown below in bold.
Quote: |
void debug_writeln_string(int *p)
{
restart_wdt();
fprintf(DEBUG_PORT, p);
fprintf(DEBUG_PORT, "\r");
restart_wdt();
}
void debug_writeln_int32(int32 num)
{
restart_wdt();
fprintf(DEBUG_PORT, "%lu", num);
fprintf(DEBUG_PORT, "\r");
restart_wdt();
}
void debug_writeln_float(float num)
{
restart_wdt();
fprintf(DEBUG_PORT, "%f", num);
fprintf(DEBUG_PORT, "\r");
restart_wdt();
} |
Then edit your isr code to use the appropriate one for each test.
Example:
Quote: |
if (!modbus2_serial_new)
{
if(modbus2_serial_state == MODBUS2_GETADDY)
{
debug_writeln_string("111");
modbus2_serial_crc.d = 0xFFFF;
modbus2_rx.address = c;
modbus2_serial_state++;
modbus2_rx.len = 0;
modbus2_rx.error=0;
}
else if(modbus2_serial_state == MODBUS2_GETFUNC)
{
debug_writeln_string("222");
modbus2_rx.func = c;
modbus2_serial_state++;
}
else if(modbus2_serial_state == MODBUS2_GETDATA)
{
debug_writeln_string("333");
if (modbus2_rx.len>=MODBUS2_SERIAL_RX_BUFFER_SIZE)
{
modbus2_rx.len=MODBUS2_SERIAL_RX_BUFFER_SIZE-1;
}
modbus2_rx.data[modbus2_rx.len]=c;
modbus2_rx.len++;
} |
|
|
|
salihonur
Joined: 21 Mar 2020 Posts: 22
|
|
Posted: Sat Nov 28, 2020 2:18 pm |
|
|
I guess I couldn't explain the problem very well. Normally I don't need to debug what is going on there. I put some debug prints to track where the problem is. INT_RDA works very well. I can see incoming data.
I discovered that modbus2_serial_state isn't increased even though the it enters to if(modbus2_serial_state == MODBUS2_GETADDY) state. I track the state number by printing numbers like 111, 222, 333. But I don't see any other numbers except 111. I captured with the regular printf. You can see that it isn't get into the next state if I don't print it in every all state below.
Note: Of course Modbus data is validated by crc function. But there is a problem before it. There isn't any data validation check at this step.
Modbus query of master and the response of slave
_________________ Compiler v5.091+ Windows 10 |
|
|
salihonur
Joined: 21 Mar 2020 Posts: 22
|
|
Posted: Sat Nov 28, 2020 2:44 pm |
|
|
Eureka!!!!
I found the problem. I had disabled the timer setting in the Modbus library to use my timer setting and interrupt function. My timeout setting is lower than library's setting. I multiplied GET_DATA_TIMEOUT by 10, then it started to read the slave very well.
_________________ Compiler v5.091+ Windows 10 |
|
|
|
|
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
|