I have designed and installed a building management system that consists of a string of Arduino UNOs and MEGAs (all slaves) all controlled by a central Programmable Logic Controller (the master) over MODBUS RS485. It has generally been working well. The issue I am having is that the first serial port (Pin 0, 1) on the MEGA boards that drive the TTL-RS485 external transceiver board seems to only work occasionally and at random when powered up. This is a new problem that didn't exist when I first designed the system. When I say it "doesn't work" I mean that the MEGA is not responding to a request. If I cycle power on the MEGA enough, eventually it starts working and it stays working forever (essentially). If I switch the port to one of the other hardware ports on the MEGA, there are no issues. Has something changed in the MEGA firmware as this has seemed to occur later in the project? Here are some of the things I have tried:
- Tried multiple new boards, including a genuine Arduino board, same result
- Hard coded the MODBUS address in software, instead of reading from dip switches.
- I have done testing both on the bench and in the field with the same results
- Put an oscilloscope on the incoming RS485 request and the TTL signal going into the MEGA, all look healthy
- The issue does not appear to be the TTL-RS485 transceiver as switching the serial port on the MEGA solves the problem.
My feeling is that there is a software issue with the port. I have attached the code. Please let me know if anyone has any ideas. It's really important I can get this issue solved quickly. Thanks for your help!!
// Building Management System - Output Unit
// This includes code from the MODBUS library
#include <SimpleModbusSlave.h>
//////////////// registers of your slave ///////////////////
enum
{
// just add or remove registers and your good to go...
// The first register starts at address 0
Board_1,
Board_2,
Board_3,
HOLDING_REGS_SIZE // leave this one
// total number of registers for function 3 and 16 share the same register array
// i.e. the same address space
};
unsigned int holdingRegs[HOLDING_REGS_SIZE];
int Dip0 = 0;
int Dip1 = 0;
int Dip2 = 0;
int Dip3 = 0;
int Dip4 = 0;
int Modbus_Addr = 0;
word Board1_New = 0;
word Board2_New = 0;
word Board3_New = 0;
word Board1_Old = 0;
word Board2_Old = 0;
word Board3_Old = 0;
// End of declaring objects
void WriteOutput(word value, int start)
{
digitalWrite(start, HIGH && (bool)(value & 1));
digitalWrite(start+1, HIGH && (bool)(value & 2));
digitalWrite(start+2, HIGH && (bool)(value & 4));
digitalWrite(start+3, HIGH && (bool)(value & 8));
digitalWrite(start+4, HIGH && (bool)(value & 16));
digitalWrite(start+5, HIGH && (bool)(value & 32));
digitalWrite(start+6, HIGH && (bool)(value & 64));
digitalWrite(start+7, HIGH && (bool)(value & 128));
digitalWrite(start+8, HIGH && (bool)(value & 256));
digitalWrite(start+9, HIGH && (bool)(value & 512));
digitalWrite(start+10, HIGH && (bool)(value & 1024));
digitalWrite(start+11, HIGH && (bool)(value & 2048));
digitalWrite(start+12, HIGH && (bool)(value & 4096));
digitalWrite(start+13, HIGH && (bool)(value & 8192));
digitalWrite(start+14, HIGH && (bool)(value & 16384));
digitalWrite(start+15, HIGH && (bool)(value & 32768));
}
void setup() { // Put your setup code here, to run once:
pinMode(3,OUTPUT);
pinMode(4,OUTPUT);
pinMode(5,OUTPUT);
pinMode(6,OUTPUT);
pinMode(7,OUTPUT);
pinMode(8,OUTPUT);
pinMode(9,OUTPUT);
pinMode(10,OUTPUT);
pinMode(11,OUTPUT);
pinMode(12,OUTPUT);
pinMode(13,OUTPUT);
pinMode(14,OUTPUT);
pinMode(15,OUTPUT);
pinMode(16,OUTPUT);
pinMode(17,OUTPUT);
pinMode(18,OUTPUT);
pinMode(19,OUTPUT);
pinMode(20,OUTPUT);
pinMode(21,OUTPUT);
pinMode(22,OUTPUT);
pinMode(23,OUTPUT);
pinMode(24,OUTPUT);
pinMode(25,OUTPUT);
pinMode(26,OUTPUT);
pinMode(27,OUTPUT);
pinMode(28,OUTPUT);
pinMode(29,OUTPUT);
pinMode(30,OUTPUT);
pinMode(31,OUTPUT);
pinMode(32,OUTPUT);
pinMode(33,OUTPUT);
pinMode(34,OUTPUT);
pinMode(35,OUTPUT);
pinMode(36,OUTPUT);
pinMode(37,OUTPUT);
pinMode(38,OUTPUT);
pinMode(39,OUTPUT);
pinMode(40,OUTPUT);
pinMode(41,OUTPUT);
pinMode(42,OUTPUT);
pinMode(43,OUTPUT);
pinMode(44,OUTPUT);
pinMode(45,OUTPUT);
pinMode(46,OUTPUT);
pinMode(47,OUTPUT);
pinMode(48,OUTPUT);
pinMode(49,OUTPUT);
pinMode(50,OUTPUT);
pinMode(51,OUTPUT);
pinMode(52,OUTPUT);
pinMode(A0,INPUT_PULLUP);
pinMode(A1,INPUT_PULLUP);
pinMode(A2,INPUT_PULLUP);
pinMode(A3,INPUT_PULLUP);
pinMode(A4,INPUT_PULLUP);
//Assign the modbus device ID.
Dip0 = (int) !digitalRead(A0);
Dip1 = (int) !digitalRead(A1);
Dip2 = (int) !digitalRead(A2);
Dip3 = (int) !digitalRead(A3);
Dip4 = (int) !digitalRead(A4);
Modbus_Addr = Dip0*1+Dip1*2+Dip2*4+Dip3*8+Dip4*16;
modbus_configure(&Serial, 19200, SERIAL_8E1, Modbus_Addr, 2, HOLDING_REGS_SIZE, holdingRegs);
WriteOutput(65535, 5);
WriteOutput(65535, 21);
WriteOutput(65535, 37);
} // End of setup
void loop() { // Put your main code here, to run repeatedly:
Board1_New = holdingRegs[Board_1];
Board2_New = holdingRegs[Board_2];
Board3_New = holdingRegs[Board_3];
// Write Output to Board #1 if ouput status has changed
if (Board1_New != Board1_Old)
{
WriteOutput(Board1_New,5);
Board1_Old = Board1_New;
}
// Write Output to Board #2 if ouput status has changed
if (Board2_New != Board2_Old)
{
WriteOutput(Board2_New,21);
Board2_Old = Board2_New;
}
// Write Output to Board #3 if ouput status has changed
if (Board3_New != Board3_Old)
{
WriteOutput(Board3_New,37);
Board3_Old = Board3_New;
}
modbus_update();
} // End of loop