Arduino Mega 2560 conflict between Servo.h, ModbusRtu.h and pinMode()

Hi guys this is my first post here, I have been looking around for asnwers but I gave up so I decided to start a new topic.

I have a HMI Display as a Master connected to an Arduino Mega as a Slave using Modbus RTU protocol and a RS485 transceiver.

I connected the pins as follows:
19 is connected to R in the transceiver
18 is connected to D in the transceiver
and the 22 is conected to DE/RE in the transceiver.

And that’s it I don’t have more pins connected to anything.

This is the code I am using

#include <ModbusRtu.h>
#include <Servo.h>
#define TXEN  22
Servo myservo;

uint16_t au16data[3];


Modbus slave(1,Serial1,TXEN);




void setup() 
{
  //input pins
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);
  pinMode(A3, INPUT);
  pinMode(A4, INPUT);
  pinMode(A5, INPUT);
  pinMode(A6, INPUT);
  pinMode(A7, INPUT);
  pinMode(A8, INPUT);
  pinMode(A9, INPUT);
  pinMode(A10, INPUT);
  pinMode(A11, INPUT);
  pinMode(A12, INPUT);
  pinMode(A13, INPUT);
  pinMode(A14, INPUT);
  pinMode(A15, INPUT);
  pinMode(4, INPUT);
  pinMode(13, INPUT);
  pinMode(36, INPUT);
  pinMode(37, INPUT);
  pinMode(38, INPUT);
  pinMode(39, INPUT);
  pinMode(40, INPUT);
  pinMode(41, INPUT);
  pinMode(42, INPUT);
  pinMode(43, INPUT);
  pinMode(47, INPUT);
  pinMode(48, INPUT);
  pinMode(49, INPUT);
  pinMode(50, INPUT);
  pinMode(51, INPUT);
  pinMode(52, INPUT);
  pinMode(53, INPUT);

  //output pins
  pinMode(2 OUTPUT);
  pinMode(3 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(44 OUTPUT);
  pinMode(45 OUTPUT);
  pinMode(46 OUTPUT);
  pinMode(14 OUTPUT);
  pinMode(15 OUTPUT);
  pinMode(16 OUTPUT);
  pinMode(17 OUTPUT);
  pinMode(20 OUTPUT);
  pinMode(21 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);
  Serial1.begin( 19200 ); // baud-rate at 19200
  slave.start();
  myservo.attach(2);

}


void loop() 
{
  slave.poll( au16data, 3);
  myservo.write(20); 
  

}

This is the link to the ModbusRtu.h library https://github.com/smarmengol/Modbus-Master-Slave-for-Arduino/blob/master/ModbusRtu.h

And this is the problem.
The communication with the HMI will work as long as:

1- I don’t use the Servo.h library at all.
2- I use the Servo.h library but I don’t set any single pin as an INPUT.
3- I use the Servo.h library, I don’t set any single pin as an INPUT, and I set few pins as OUTPUTs but not too many (The problem doesn’t seem to be related to specific pins).

Honestly, I am desperate, and I don’t know what’s going on, it’s so strange.

Please help, thank you.

You know that there is a built-in Modbus library have you tried that one ?
The Servo.h library has some pitfalls, for one thing it uses nearly all available 16-bit timers and can not work properly is interrupts are disabled at any given time, but i don't see how that could be an issue. There are also alternatives for Servo.h and actually it is not to difficult to just send a Pulse to a servo manually, though if you have multiple Servos you may need to pull some tricks to do this efficiently.

You know that there is a built-in Modbus library have you tried that one ?

I don't know how to make it work, I have been looking for examples using this library for an Arduino as a slave using Modbus RTU but I haven't been lucky so far.

The Servo.h library has some pitfalls, for one thing it uses nearly all available 16-bit timers and can not work properly is interrupts are disabled at any given time, but i don't see how that could be an issue.

I have been reading the library and I don't see the conflict either, as far as I understand it is using just Timer 5 but that's all. The weirdest thing is that the communication with the HMI and the Servo.h library work together as long as I don't set any pin as an input or set too many pins as outputs.

There are also alternatives for Servo.h and actually it is not to difficult to just send a Pulse to a servo manually

I am using just one servo, if you could guide me on how to create the pulse, I am planning on using 2 PWM's at the same time though.

Thank you for your reply

I am using just one servo, if you could guide me on how to create the pulse, I am planning on using 2 PWM’s at the same time though.

it is not hard to do, the minimum length for a pulse should be 544us (approx 0 degrees) and the maximum 2400us, (approx 180 degrees) the maximum frequency of a pulse should be 50hz which means that the next pulse should not start before 20ms have passed since the previous pulse. So something like

static uint32_t pulsestart = millis();  // global or static for the function
if (millis() - pulsestart < 20) return;
pulsestart = millis();
digitalWrite(SERVOPIN, HIGH);
delayMicroseconds(570 + 10 * degrees);
digitalWrite(SERVOPIN, LOW);

just multiplying the degrees by 10 is of course an approximation, you could use the map() function instead, and for the sake of accuracy you could turn interrupts off for the time of the pulse, but that will certainly interfere with the Modbus reception (at 38400 baud) and it is blocking in nature, though the rest of your processes will just continue in the background anyway.There are many things wrong with the Servo.h library, so it is a choice of evils.

Thank you so much.

Ok I am not using the Servo.h library anymore and the servo and the HMI display are working perfectly.

Now the problem is I need to use a PWM and as soon as I do use an “analogWrite” the communication with the display fails, any idea to get around this or finding the cause of this problem?

include <ModbusRtu.h>
define TXEN  22

uint16_t au16data[3];
uint32_t servodelay;
byte servopulse=0;
int servopos;
Modbus slave(1,Serial1,TXEN);

void setup() 
{
  
  //input pins
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);
  pinMode(A3, INPUT);
  pinMode(A4, INPUT);
  pinMode(A5, INPUT);
  pinMode(A6, INPUT);
  pinMode(A7, INPUT);
  pinMode(A8, INPUT);
  pinMode(A9, INPUT);
  pinMode(A10, INPUT);
  pinMode(A11, INPUT);
  pinMode(A12, INPUT);
  pinMode(A13, INPUT);
  pinMode(A14, INPUT);
  pinMode(A15, INPUT);
  pinMode(4, INPUT);
  pinMode(13, INPUT);
  pinMode(36, INPUT);
  pinMode(37, INPUT);
  pinMode(38, INPUT);
  pinMode(39, INPUT);
  pinMode(40, INPUT);
  pinMode(41, INPUT);
  pinMode(42, INPUT);
  pinMode(43, INPUT);
  pinMode(47, INPUT);
  pinMode(48, INPUT);
  pinMode(49, INPUT);
  pinMode(50, INPUT);
  pinMode(51, INPUT);
  pinMode(52, INPUT);
  pinMode(53, INPUT);

  //output pins
  pinMode(2, OUTPUT);
  pinMode(3, 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(44, OUTPUT);
  pinMode(45, OUTPUT);
  pinMode(46, OUTPUT);
  pinMode(14, OUTPUT);
  pinMode(15, OUTPUT);
  pinMode(16, OUTPUT);
  pinMode(17, OUTPUT);
  pinMode(20, OUTPUT);
  pinMode(21, 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);
  Serial1.begin( 19200 ); // baud-rate at 19200
  slave.start();



}

void loop() 
{
  digitalWrite(3,1);
  digitalWrite(5,1);
  //analogWrite(6,122);
  
  //servo signal//
  switch (servopulse)
  {
  
    case 0:
      servopos = map(analogRead(2), 0, 1023, 1000, 2000); 
      digitalWrite(2,1);
      servodelay=micros();
      servopulse=1;
    break;
    case 1:
      while(servodelay+servopos>micros())
      {
      }
      servopulse=2;
      digitalWrite(2,0);
  
    break;
    case 2:
      if(servodelay+19999<micros())
      {
        servopulse=0;
      }
    break;
  }
  //servo signal//
  
  
  slave.poll( au16data, 3);
  au16data[2]=au16data[1]; //testing comm

}

if(servodelay+19999<micros())I would really use millis() but that is a choice. the ‘latch’ doesn’t need to be very accurate, most Servos work with anything from 20ms to nearly 80ms (or even 100ms), and you should always calculate through ‘elapsed’ time, to prevent errors in the roll-over so

case 1:
      while(micros() - servodelay < servopos)
      {
      }

as an example.

I need to use a PWM and as soon as I do use an “analogWrite” the communication with the display fails,

have you tried all different PWM pins ? your Modbus library must be using a timer to keep track of the ‘latch’ in the modbus communication, but somehow not have restricted access to the timer. IOW it uses a timer that is otherwise used for PWM but doesn’t disable it for the pins. Try all the PWM pins individually, chances are it hasn’t used all timers.

Just to let you know guys, the problem was related with the Arduino IDE.

My codes using ModbusRtu.h don't work propertly on Arduino IDE version 1.8.12 but they work perfectly on 1.8.1.

I don't know why but this was the whole problem.