Modbus connection does not work

Good day. I am using the following code. When i run the code and connect the arduino to the remote. It does not work. i looked into the serial monitor and noticed the program did not start. Can someone maybe assist?

#include <SPI.h>
#include <Ethernet.h>       // Ethernet library v2 is required
#include <ModbusEthernet.h>
#include <MPU6050_tockn.h>
#include <Wire.h>

MPU6050 mpu6050(Wire);

const uint16_t REG1 = 57344;               // Heading Hreg Offset
const uint16_t REG2 = 57346;               // Trigger Hreg Offset
const uint16_t REG3 = 57348;               // Dirtection Hreg Offset
const uint16_t REG4 = 57350;               // Speed Hreg Offset
float float3 = 0;
int OldAngle = 0;
int NewAngle = 0;
// Set IP for VibGuard                           //
//***********************************************//
IPAddress remote(10, 196, 214, 219);
//***********************************************//

const int32_t showDelay = 1000;   // Show result every n'th mellisecond

// Enter a MAC address and IP address for your controller below.
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xEE
};
//***********************************************//
// Set IMU IP                                    //
IPAddress ip(10, 196, 214, 220); // The IP address will be dependent on your local network:
//***********************************************//


ModbusEthernet mb;               // Declare ModbusTCP instance

void setup() {
  Serial.begin(115200);     // Open serial communications and wait for port to open
  //#if defined(AVR_LEONARDO)
  //while (!Serial) {}        // wait for serial port to connect. Needed for Leonardo only
  //#endif
  Ethernet.init(10);         // SS pin
  Ethernet.begin(mac, ip);  // start the Ethernet connection
  delay(1000);              // give the Ethernet shield a second to initialize
  mb.client();              // Act as Modbus TCP server

  
  Wire.begin();
  mpu6050.begin();
  mpu6050.calcGyroOffsets(true);
}

uint16_t res1 = 0;       //Heading
uint16_t res2 = 1;       //Trigger
uint16_t res3 = 0;       //Direction
uint16_t res4 = 0;       //speed
uint32_t showLast = 0; int mult = 0;

void loop() {

  if (mb.isConnected(remote)) {   // Check if connection to Modbus Slave is established

    mpu6050.update();

    float float2 = float(mpu6050.getAngleZ() * -1);
    int   Angle = (uint16_t) float2;

    float float4 = float(mpu6050.getGyroZ());
    int   AccZ = (uint16_t) float4;

    mpu6050.calcGyroOffsets(true);


    //Heading Multiplier

    mult = float2 / 360;
    if (mult < 0) {
      mult = mult * -1;
    }

    if (float2 > 0)
    {
      float3 = float2 - (mult * 360);
    }

    if ((float2 < 0) && (float2 > (-1 * 360)))
    {
      float3 = float2 - (mult * 360) + 360;
    }

    if ((float2 < 0) && (float2 < -(1 * 360)))
    {
      float3 = ((((float2 + (mult * 360)) * -1) - 360) * -1);
    }



    NewAngle = float3;
    uint16_t res1 = float3;       //Heading
    uint16_t res4 = float4;       //Speed

    mb.writeHreg(remote, REG1, &res1);  // Initiate Read Hreg from Modbus Slav


    //Direction

    if ( float4 > 1) {

      mb.writeHreg(remote, REG3, &res2);


    }
    if ( float4 < -1) {

      mb.writeHreg(remote, REG3, &res3);


    }


    // if (OldAngle = NewAngle){
    //  mult = 0;
    // }




    Trigger
    if(mult >= 2){
     mb.writeHreg(remote, REG2, &res2 );

     }

     if(mult < 2){
     mb.writeHreg(remote, REG2, &res3 );

     }
    Sprrd GyroZ
    mb.writeHreg(remote, REG4, &res4);


    Serial.print(mult);
    Serial.print("    ");
    Serial.print(float2);
    Serial.print("    ");
    Serial.print(float3);
    Serial.print("    ");
    Serial.print(float4);
    Serial.print("    ");
    Serial.println(res4);




  } else {
    mb.connect(remote);           // Try to connect if not connected
  }

  mb.task();                      // Common local Modbus task
  delay(100);
  if (millis() - showLast > showDelay) { // Display register value every 5 seconds (with default settings)
    showLast = millis();

  }


}

I am using a Waveshare 10D Imu sensor with a W5100 ethernet shield and arduino nano. If i remove or // the if (mb isConnected(remote)) and the else mb.connect(remote) at the bottom then the program start. I have also Serial.println and noticed the error is on the modbus side. Dont know what is the cause or how to resolve.

Thank you

`

Please enclose the full code inside the "CODE" tag, otherwise it's almost unreadable for us.
Edit you first post, then select all (and only) the code lines and press the upper "<CODE/>" button then save.

1 Like

Thank you, i have done it.

Good.

Now, you said you "noticed the program did not start" and commenting out the bottom "if()" it starts. Well, first of all "start" usually means the "setup()" function/phase, and from your description it isn't clear if something goes wrong on the setup or not.
But as you say it seems to be ok when removing the if() condition (besides, without a connection it does almost nothing, so actually it isn't exactly "ok"...), we can assume the problem is in the "mb.isConnected(remote)" never returning "true". If it is "false", the following "else" tries to establish the connection, but if isConnected never returns true it can only mean the modbus connection can't be established for some reason, either software (e.g. bad library? Bad library usage? Missing Ethernet connection? Something else?) or hardware (e.g. faulty W5100 shield -that's not that rare...-? A bad cable?). Just as an example, are you sure the program locks after setup() instead of just never entering the first if()? Or the if() works but it somewhat locks when calling "mpu6050.update()"? Or any other?

But first of all I advise you to give the code a better form to make it more easy to read, starting from the indentation (press Ctrl-T and the IDE will do it for you) and avoiding useless empty lines between statements (to make it more "compact", and if you need to separate some blocks use just a single empty line).
Second, to make some better debugging put more "Serial.print()" all over the code, to make sure what a call returns, and if a block of code (e.g. inside the "if()"s) is being executed, so you can track everything down with Serial monitor.

For instance:

...
void setup() {
  Serial.begin(115200);     // Open serial communications and wait for port to open
  Serial.println("Starting...");
 
  Ethernet.init(10);         // SS pin
  Ethernet.begin(mac, ip);  // start the Ethernet connection
  delay(1000);              // give the Ethernet shield a second to initialize
  mb.client();              // Act as Modbus TCP server
 
  Wire.begin();
  mpu6050.begin();
  mpu6050.calcGyroOffsets(true);

  Serial.println("READY");
}

Then:

void loop() {

  if (mb.isConnected(remote)) {   // Check if connection to Modbus Slave is established
    Serial.println("CONNECTED!");
    mpu6050.update();
    Serial.println("MPU updated.");

    float float2 = float(mpu6050.getAngleZ() * -1);
    Serial.print("float2=");Serial.println(float2);
    int   Angle = (uint16_t) float2;
    //and so on ...
...

Apply the changes to your code, make some tests, and post here the results (together with the "new" code and its serial outputs)

Hi Docdoc,

Thank you for the assistance.

I noticed the SS pin was not connected. Only on the SPI side everything was connected. It was a matter of a wiring issue. Your assistance helped me diagnose the issue easier.

Ok, good! :sunglasses:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.