CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

RS485 Modbus
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Warday



Joined: 21 May 2021
Posts: 11

View user's profile Send private message

RS485 Modbus
PostPosted: Mon Aug 23, 2021 1:59 pm     Reply with quote

Hi, I’m trying a simple Modbus communication using RS485. I have already used RS485 to communicate thru serial without problem. Now I want to implement Modbus protocol. I only required to read and edit 2 registers (one is position and the other is inclination).
I have modified ex_modbus_slave.c to do so. To read and modify register I’m using python and raspberry. Unfortunately it always say that there is no communication (Timeout error). I try to use Modbus Poll, and Modbus scan to read the registers but the communications always fail (Same error). What can I be doing wrong? I use 0x0A which is address 10.

pic code (CCS)
I only modify:
uncomment #define USE_WITH_PC 1
change pic to 30f4012.h
change rx tx pin
define enable pin for rs485
#define MODBUS_ADDRESS 0x0A
Thats all.

Code:


#define USE_WITH_PC 1

#if defined(__PCD__)
#include <30f4012.h>
#fuses PR,HS,NOWDT
#use delay(clock=20M)
#elif defined(__PCH__)
#include <30f4012.h>
#fuses HS, NOWDT
#use delay(clock=20M)
#else
#include <30f4012.h>
#fuses HS,NOWDT
#use delay(clock=20M)
#endif

#define MODBUS_TYPE MODBUS_TYPE_SLAVE
#define MODBUS_SERIAL_TYPE MODBUS_RTU     //use MODBUS_ASCII for ASCII mode
#define MODBUS_SERIAL_RX_BUFFER_SIZE 64
#define MODBUS_SERIAL_BAUD 9600

#ifndef USE_WITH_PC
#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_EXT
#if defined(__PCD__)
#define MODBUS_SERIAL_TX_PIN PIN_F3   // Data transmit pin
#define MODBUS_SERIAL_RX_PIN PIN_F2   // Data receive pin
//The following should be defined for RS485 communication
#define MODBUS_SERIAL_ENABLE_PIN   PIN_R4   // Controls DE pin for RS485
#define MODBUS_SERIAL_RX_ENABLE    PIN_R3   // Controls RE pin for RS485
#else
#define MODBUS_SERIAL_TX_PIN PIN_F3   // Data transmit pin
#define MODBUS_SERIAL_RX_PIN PIN_F2   // Data receive pin
//The following should be defined for RS485 communication
#define MODBUS_SERIAL_ENABLE_PIN   PIN_R4   // Controls DE pin for RS485
#define MODBUS_SERIAL_RX_ENABLE    PIN_R3   // Controls RE pin for RS485
#endif
#else
#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_RDA
#endif

#include <modbus.c>

#define MODBUS_ADDRESS 0x0A

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;

   setup_adc_ports(NO_ANALOGS);

   modbus_init();

Rule 10 same as ex_modbus_slave.c


Pycode


Code:

import minimalmodbus
instrument = minimalmodbus.Instrument('/dev/ttyUSB0', 10)
instrument.serial.port
instrument.serial.baudrate = 9600
instrument.serial.bytesize = 8
instrument.serial.timeout  = 0.2
instrument.mode = minimalmodbus.MODE_RTU   # rtu or ascii mode
instrument.clear_buffers_before_each_transaction = True
print(instrument)

register= instrument.read_register(0x01) 

print(register)


Thanks for the help.
Jerson



Joined: 31 Jul 2009
Posts: 125
Location: Bombay, India

View user's profile Send private message Visit poster's website

PostPosted: Mon Aug 23, 2021 8:04 pm     Reply with quote

Since you have already got a working modbus implementation on RS485, I would guess your problem is on the host Rasp Pi side. Try increasing the polling timeout and/or the time between polls to see which one it is that fixes the problem.
Ttelmah



Joined: 11 Mar 2010
Posts: 19544

View user's profile Send private message

PostPosted: Tue Aug 24, 2021 1:09 am     Reply with quote

You are selecting USE_WITH_PC. This is designed for when the PIC
system is being attached via RS232 to a PC, and it then has to handle the
RS485, using INT_EXT, not the UART. Is this what you are doing?. .

It requires hardware changes to the Modbus wiring (with the RX line
connected to the INT_EXT line).

I think you are simply setting the slave up wrong.....
temtronic



Joined: 01 Jul 2010
Posts: 9244
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Aug 24, 2021 6:05 am     Reply with quote

hmm... curious about this...
Quote:
'/dev/ttyUSB0', 10)

in your Python code,
I assume means the Pie is looking for a USB device on the serial port ? Or do you have a USB<.RS485 adapter on the USB port ? Or do you need to say ... '/dev/ttyRS485', 10) ?? or something else ??

You may need to explain what hardware actually connects electrons from PIC to PIE.
Jerson



Joined: 31 Jul 2009
Posts: 125
Location: Bombay, India

View user's profile Send private message Visit poster's website

PostPosted: Tue Aug 24, 2021 6:26 am     Reply with quote

On linux systems like the RaspPi /dev/ttyUSB0 usually signifies a USB serial port. The 10 possibly is a timeout value(I suspect)
Warday



Joined: 21 May 2021
Posts: 11

View user's profile Send private message

PostPosted: Tue Aug 24, 2021 7:25 am     Reply with quote

I have a RS482 to usb adapter and a HW-97 RS482 for the pic. Whit that I can convert normal serial communication to rs485. That works ok. Now I want to implement Modbus on that communication.

Jerson wrote:
Since you have already got a working modbus implementation on RS485, I would guess your problem is on the host Rasp Pi side. Try increasing the polling timeout and/or the time between polls to see which one it is that fixes the problem.

I have make RS485 work as a normal serial communication not Modbus.
Ttelmah wrote:
You are selecting USE_WITH_PC. This is designed for when the PIC
system is being attached via RS232 to a PC, and it then has to handle the
RS485, using INT_EXT, not the UART. Is this what you are doing?. .

It requires hardware changes to the Modbus wiring (with the RX line
connected to the INT_EXT line).

I think you are simply setting the slave up wrong.....

That can be the problem. I will check it out.
temtronic wrote:
hmm... curious about this...

'/dev/ttyUSB0', 10)
in your Python code,
I assume means the Pie is looking for a USB device on the serial port ? Or do you have a USB<.RS485 adapter on the USB port ? Or do you need to say ... '/dev/ttyRS485', 10) ?? or something else ??

you may need to explain what hardware actually connects electrons from PIC to PIE.


'/dev/ttyUSB0' is the rs482 to serial converter and the 10 is the device id. The python code works in decimal.
Thanks for the answers
temtronic



Joined: 01 Jul 2010
Posts: 9244
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Aug 24, 2021 7:40 am     Reply with quote

re: ...
Quote:
I have a RS482 to usb adapter and a HW-97 RS482 for the pic

I have to ask HOW do the adapters control the direction of RS-485 data ?

BTW I didn't find HW-97 to be an adapter...seems to be a gun and a highway.....sigh...good ol Google !

Maybe post a link to the adapters ?
Warday



Joined: 21 May 2021
Posts: 11

View user's profile Send private message

PostPosted: Tue Aug 24, 2021 8:15 am     Reply with quote

temtronic wrote:
re: ...I have a RS482 to usb adapter and a HW-97 RS482 for the pic

I have to ask HOW do the adapters control the direction of RS-485 data ?

BTW I didn't find HW-97 to be an adapter...seems to be a gun and a highway.....sigh...good ol Google !

Maybe post a link to the adapters ?


pic adapter
https://protosupplies.com/product/max485-ttl-to-rs-485-interface-module/
USB adapter
https://www.twinschip.com/USB_to_RS485_Converter_Adapter

As difference as serial, RS485 is half-duplex communication device. You can use is it with standard communication (printf("PWM= %d\r\n",PWM); to do so you only have to properly select DE RE state to indicate if you are transmitting or receiving. That’s works without problem. Now I want to implement Modbus protocol. Modbus library have already the RE DE configuration for RS485.
Warday



Joined: 21 May 2021
Posts: 11

View user's profile Send private message

PostPosted: Tue Aug 24, 2021 9:00 am     Reply with quote

Ttelmah wrote:
You are selecting USE_WITH_PC. This is designed for when the PIC
system is being attached via RS232 to a PC, and it then has to handle the
RS485, using INT_EXT, not the UART. Is this what you are doing?. .

It requires hardware changes to the Modbus wiring (with the RX line
connected to the INT_EXT line).

I think you are simply setting the slave up wrong.....

I made the next test. I change
#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_EXT
to MODBUS_INT_RDA to use UART. It fails.
I change conection and use INT0 (30f4012) with INT_EXT it fails.
Jerson



Joined: 31 Jul 2009
Posts: 125
Location: Bombay, India

View user's profile Send private message Visit poster's website

PostPosted: Tue Aug 24, 2021 9:29 am     Reply with quote

Seeing the adapters you are using, I assume the PIC side would be handled well by the library which will switch TX/RX direction as needed by the code.

On the Python side, you would always be in receive mode when using the USB-485 converter unless you try sending some data Py->PIC. That is when the USB converter will switch direction from Py->PIC, send the data, and then after a fixed internal delay fall back to receive mode again PIC->Py. This timeout along with the latency of your PIC would normally become the bottleneck for modbus. So, start high with timeout of 1000ms and work your way down.

The way I would check this is to use a serial monitor on the RaspPi, and let the PIC keep sending some known data patterns. Once you receive the data patterns clearly, you can then check the reverse direction.
Warday



Joined: 21 May 2021
Posts: 11

View user's profile Send private message

PostPosted: Tue Aug 24, 2021 12:53 pm     Reply with quote

Jerson wrote:
Seeing the adapters you are using, I assume the PIC side would be handled well by the library which will switch TX/RX direction as needed by the code.

On the Python side, you would always be in receive mode when using the USB-485 converter unless you try sending some data Py->PIC. That is when the USB converter will switch direction from Py->PIC, send the data, and then after a fixed internal delay fall back to receive mode again PIC->Py. This timeout along with the latency of your PIC would normally become the bottleneck for modbus. So, start high with timeout of 1000ms and work your way down.

The way I would check this is to use a serial monitor on the RaspPi, and let the PIC keep sending some known data patterns. Once you receive the data patterns clearly, you can then check the reverse direction.


Well i try ex_modbus_master.c and set it to work with pc. It seems to worked ok. I have problem with slave only.
Edit: Seems that the problem is on RX. The devise sends information but cand receive. (I make the master change register 3 to 0x1111 if it could read the coils and 0x2222 if it couldn’t. it set always 0x2222)

Ttelmah



Joined: 11 Mar 2010
Posts: 19544

View user's profile Send private message

PostPosted: Wed Aug 25, 2021 7:35 am     Reply with quote

As I have already pointed oot in another thread, 'USE_WITH_PC' means
the modbus will be setup to use INT_EXT to trigger the receive, not INT_RX.
Warday



Joined: 21 May 2021
Posts: 11

View user's profile Send private message

PostPosted: Thu Aug 26, 2021 2:57 pm     Reply with quote

Ttelmah wrote:
As I have already pointed oot in another thread, 'USE_WITH_PC' means
the modbus will be setup to use INT_EXT to trigger the receive, not INT_RX.


I already try that. I used INT_EXT and INT_RDA

Fixed. The problem whas that the default grup was EVEN and software default was NONE.

Sujesstions to do it yourself.
1º when trying the demo clean it and use your configuration
Example:

Code:


#include <30f4012.h>
#fuses HS,NOWDT
#use delay(clock=20M)

#define MODBUS_PROTOCOL  MODBUS_PROTOCOL_SERIAL
#define MODBUS_TYPE MODBUS_TYPE_SLAVE
#define MODBUS_SERIAL_TYPE MODBUS_RTU     //use MODBUS_ASCII for ASCII mode
#define MODBUS_SERIAL_RX_BUFFER_SIZE 64
#define MODBUS_SERIAL_BAUD 9600

#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_RDA

#define MODBUS_SERIAL_TX_PIN PIN_F3   // Data transmit pin
#define MODBUS_SERIAL_RX_PIN PIN_F2   // Data receive pin
//The following should be defined for RS485 communication
#define MODBUS_SERIAL_ENABLE_PIN   PIN_E4   // Controls DE pin for RS485
#define MODBUS_SERIAL_RX_ENABLE    PIN_E3   // Controls RE pin for RS485

#include <modbus.c>
#define MODBUS_ADDRESS 0xF7


In my case I use Timer 1 to control one pid so in the future I will have to change modbus.c default timer. I use UART so i use:

#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_RDA

Example code in python(Raspbian): I use inst to speak devise 247 (0xF7) and inst2 (0) to speak to all (you can only write register). All work perfect. Hope it helps others with the same problem. Thanks for all!


Code:

import minimalmodbus

inst = minimalmodbus.Instrument('/dev/ttyUSB0', 247 )
inst.serial.stopbits = 1
inst.serial.baudrate = 9600
inst.serial.bytesize = 8
inst.serial.timeout  = 0.2
inst.serial.parity = minimalmodbus.serial.PARITY_EVEN
inst.clear_buffers_before_each_transaction = True
inst2 = minimalmodbus.Instrument('/dev/ttyUSB0', 0, debug=True )
inst2.serial.stopbits = 1
inst2.serial.baudrate = 9600
inst2.serial.bytesize = 8
inst2.serial.timeout  = 0.2
inst2.serial.parity = minimalmodbus.serial.PARITY_EVEN
inst2.clear_buffers_before_each_transaction = True
# Registernumber, number of decimals
inst2.write_register(0x00, 1100, 0,6)
print("Old")
print(inst.read_register(0x00))
print(inst.read_register(0x01))
print(inst.read_register(0x02))
print(inst.read_register(0x03))
print(inst.read_register(0x04))
print(inst.read_register(0x05))
print(inst.read_register(0x06))
print(inst.read_register(0x07))

print("New")
inst.write_register(0x00, 1, 0,6)
inst.write_register(0x01, 2, 0,6)
inst.write_register(0x02, 3, 0,6)
inst.write_register(0x03, 4, 0,6)
inst.write_register(0x04, 5, 0,6)
inst.write_register(0x05, 6, 0,6)
inst.write_register(0x06, 7, 0,6)
inst.write_register(0x07, 8, 0,6)

print(inst.read_register(0x00))
print(inst.read_register(0x01))
print(inst.read_register(0x02))
print(inst.read_register(0x03))
print(inst.read_register(0x04))
print(inst.read_register(0x05))
print(inst.read_register(0x06))
print(inst.read_register(0x07))



Last edited by Warday on Fri Aug 27, 2021 9:38 am; edited 2 times in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19544

View user's profile Send private message

PostPosted: Fri Aug 27, 2021 12:50 am     Reply with quote

You are missing the point.
The RX signal has to go _both_ to INT_EXT, and the receive pin.
The INT_EXT is used to 'trigger' the start of the receive, but the data
still has to actually be received.
Warday



Joined: 21 May 2021
Posts: 11

View user's profile Send private message

PostPosted: Fri Aug 27, 2021 9:31 am     Reply with quote

Ttelmah wrote:
You are missing the point.
The RX signal has to go _both_ to INT_EXT, and the receive pin.
The INT_EXT is used to 'trigger' the start of the receive, but the data
still has to actually be received.


Hi. It’s depends in how you configure the device.
If you read the source code of the library you will find an interrupt selector that switch between INT_RDA, INT_RDA1, INT_RDA2, INT_RDA3, INT_INI or INT_INI0. If you set MODBUS_INT_EXT (Default) It will select INT_INI_, INT_INI0 depending in your devise. I change the default configuration to INT_RDA because I wanted to use UART. The communication works perfect with INT_RDA, RS485 and modbus protocol, and INT_INI0 is free to use (I use it to detect a dead end). As I sed, my problem was the default configuration.
Note that in previous post I sed that I could fix the problem and what was it.
Greetings !!!
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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