Hello guys!
I'm working on an arduino project that require bulletproof communication between few arduinos (up to 30 or more, up to 100m) in disruptive environment (like near frequency inverter). I have one master device, that is communicating with few slaves. The master can send information-data, to the slaves, or read info-data from them. In project each slave will have few pushbuttons and an display (7-segment or graphic display). When the pushbutton is pressed on slave, the information of that pushbutton has to be transmited to the master. Also master device can send information to the slaves, so slaves can change information on display. Display will show only numbers and maybe few signs. That's about it.
My main goals are:
- Bulletproof communication
- Real time response
- Low price
- No delays for main code
Real time in my case means up to 1sec to address all slaves and get response from them.
For the communication standard I choosed RS485, which is the best option for my project, I suppose, and have few advantages over CAN, SPI, Ethernet, I2C. On top of that I need a protocol for communication. There is a lot of libraries on the web for arduino that implement RS485 communication into arduino. I'm a little afraid, that these libraries aren't really bulletproof + many of them uses delay function that is not helpful at all for my main code. After some time investigating communication between arduinos I decided to stick with the ModBus protocol. Since ModBus is a little complicated for me and my knowledge I'm asking here for help.
I'm still at the begining phase of programming this. I have found a ModBus library for arduino, called SimpleModbus, that contains master and slave example code. The whole library project can be found here: SimpleModbus.
For my master device I choose Arduino Due, and for the slaves Arduino Leonardo. For RS485 transceiver I choose SN65HVD75D from Texas Instruments, which is working at 3.3V, just like DUE and Leonardo [datasheet].
Current configuration
For the beginning I'm trying to establish communication only between master and one slave device. I haven't connect all the pushbuttons and displays, because firstly I want succesfully establish communication betwen arduinos using ModBus protocol. The hardware is the easiest part of design. Just arduino board, few ICs, breadboard and some wires. The hardware part is working flawlessly (for now ).
So I have connected everything and now I'm stuck with programming. I will go trough most parts of the code and will try to explain what I do understand and what I do not. All the code and libraries are available here: SimpleModbus
MASTER: SimpleModbusMasterExample
#include <SimpleModbusMaster.h>
#define baud 9600
#define timeout 1000
#define polling 200 // the scan rate
// If the packets internal retry register matches
// the set retry count then communication is stopped
// on that packet. To re-enable the packet you must
// set the "connection" variable to true.
#define retry_count 5
// used to toggle the receive/transmit pin on the driver
#define TxEnablePin 2
Few lines of code that defines some parameters. Timeout is time in ms that defines how much is max. time for master to wait, till slave responds. If slave wouldn't respond, master would call next slave.
Polling defines how fast will master call slaves (but I don't know what exactly nr. 200 means).
Retry_count is counter, that defines max. nr. of unsuccessful tryes of calling one slave. If slave don't respond 5 times in row, the master will stop calling him.
TxEnablePin is just a digital output for /RE-DE pins on RS485 transmitter that defines direction (transmit or receive data).
// This is the easiest way to create new packets
// Add as many as you want. TOTAL_NO_OF_PACKETS
// is automatically updated.
enum
{
PACKET1,
PACKET2,
// leave this last entry
TOTAL_NO_OF_PACKETS
};
I'm not 100% sure what this is. I understand part that I can freely add or remove packets. I think this packets contains informations-data of what we want to send to the slave or what we want to read from the slave? Each packet can contain up to 256 bytes of information but serial buffer can contain only 128 bytes of information so this is limited to 128 bytes. But I'm not sure how to handle this packets.
// Create an array of Packets to be configured
Packet packets[TOTAL_NO_OF_PACKETS];
// Create a packetPointer to access each packet
// individually. This is not required you can access
// the array explicitly. E.g. packets[PACKET1].id = 2;
// This does become tedious though...
packetPointer packet1 = &packets[PACKET1];
packetPointer packet2 = &packets[PACKET2];
// The data from the PLC will be stored in the regs array
unsigned int regs[10];
Packet pack... is an array of packets. With line packets[1] = 0; I probably write a zero value to the PACKET2. I'm not sure if I'm correct?
packetPointer is just an pointer that points to the corresponding packet.
regs[10] array is, well I don't know what.
void setup()
{
// The modbus packet constructor function will initialize
// the individual packet with the assigned parameters. You can always do this
// explicitly by using struct pointers. The first parameter is the address of the
// packet in question. It is effectively the "this" parameter in Java that points to
// the address of the passed object. It has the following form:
// modbus_construct(packet, id, function, address, number of registers, register array)
// read 2 registers starting at address 0
modbus_construct(packet1, 2, READ_HOLDING_REGISTERS, 0, 2, regs);
// write the 10 registers to the PLC starting at address 2
modbus_construct(packet2, 2, PRESET_MULTIPLE_REGISTERS, 2, 10, regs);
// P.S. the register array entries above can be different arrays
// Initialize communication settings etc...
modbus_configure(baud, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS);
}
Not sure what this is, but if I'm correct, modbus_construct create an map that contains all the informations that will be send to slave, like slave ID, function (receive or transmit data to the slave), what data (packet) to send... I would appreciate if someone could explain this line.
modbus_configure configures modbus setting. Nothing complicated
void loop()
{
modbus_update();
// update the array with the counter data
regs[2] = packet1->requests;
regs[3] = packet1->successful_requests;
regs[4] = packet1->failed_requests;
regs[5] = packet1->exception_errors;
regs[6] = packet2->requests;
regs[7] = packet2->successful_requests;
regs[8] = packet2->failed_requests;
regs[9] = packet2->exception_errors;
}
The part that I don't understand at all.
What is modbus_update? What are next lines of code?
I couldn't fit whole post in one post, so the post continue in next post.