andresarmento / modbus-arduino

A library that allows your Arduino to communicate via Modbus protocol, acting as a slave (master in development). Supports serial (RS-232, RS-485) and IP via Ethernet (Modbus IP).
BSD 3-Clause "New" or "Revised" License
453 stars 267 forks source link

Read/Write Multiple Coils/Inputs Bug Fixed ( 8 bit bug) #21

Open samiralavi opened 7 years ago

blddk commented 7 years ago

I posted the same on #22

There still seems to be some kind of problem with multiple items. The first two return their status correct, both for coils and inputs. Input registers seems to work fine.

Coils and inputs returns their status at high.

samiralavi commented 7 years ago

Actually I am using this in my project and up to now, they work fine. But I think there are some problems with parsing modbus packet which I am working on to improve.

blddk commented 7 years ago

Have you tried to add more than two inputs and outputs?

Right now I am looking at using 4 outputs and 4 inputs, all outputs work, but only the first two return their status correctly. But the output does switch on and off correct.

With the inputs only the first two return their status correct, and the rest always looks as they are on.

mb.Coil(DO2_COIL, false);

even this still makes them return as being true.

samiralavi commented 7 years ago

Mmm... Actually I have to view my code and I will answer you today.

On Apr 29, 2017 11:53 AM, "blddk" notifications@github.com wrote:

Have you tried to add more than two inputs and outputs?

Right now I am looking at using 4 outputs and 4 inputs, all outputs work, but only the first two return their status correctly. But the output does switch on and off correct.

With the inputs only the first two return their status correct, and the rest always looks as they are on.

mb.Coil(DO2_COIL, false);

even this still makes them return as being true.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/andresarmento/modbus-arduino/pull/21#issuecomment-298152790, or mute the thread https://github.com/notifications/unsubscribe-auth/ADofzgYkQ45GejmLO3NzZMhNloxUcpUXks5r0uVkgaJpZM4KYVRe .

blddk commented 7 years ago

Let me know if you need more info or anything. I am using the ModbusIP, and using the Universal Robots controller to control it.

Been trying for quite a while to figure out what is going on, but having some problems understanding what is going on, and what is going wrong.

samiralavi commented 7 years ago

Excuse me for the delay! I have added my code :

include

include

include

const int PINMUX1 = 7; const int PINMUX2 = 6; const int PINMUX3 = 5;

//Modbus Registers Offsets (0-9999) const int DI1 = 4001; const int DI2 = 4002; const int DI3 = 4003; const int DI4 = 4004; const int DI5 = 4005; const int DI6 = 4006; const int DI7 = 4007; const int DI8 = 4008;

const int DIPIN = 8;

const int COIL1 = 4009; const int COIL2 = 4010; const int COIL3 = 4011; const int COIL4 = 4012; const int COIL5 = 4013; const int COIL6 = 4014; const int COIL7 = 4015; const int COIL8 = 4016; const int COIL9 = 4017; const int COIL10 = 4018;

const int PINCOIL1 = A0; const int PINCOIL2 = A1; const int PINCOIL3 = A2; const int PINCOIL4 = A3; const int PINCOIL5 = A4; const int PINCOIL6 = A5; const int PINCOIL7 = 4; const int PINCOIL8 = 3; const int PINCOIL9 = 1; const int PINCOIL10 = 0;

//ModbusIP object ModbusIP mb;

void setup() { wdt_enable(WDTO_2S); // The media access control (ethernet hardware) address for the shield byte mac[] = { 0xB4, 0x68, 0xA8, 0x72, 0x4B, 0x3F};

//Config Modbus IP mb.config(mac);

//Set MUX pins output pinMode(PINMUX1, OUTPUT); pinMode(PINMUX2, OUTPUT); pinMode(PINMUX3, OUTPUT);

//Set coil pins output pinMode(PINCOIL1, OUTPUT); pinMode(PINCOIL2, OUTPUT); pinMode(PINCOIL3, OUTPUT); pinMode(PINCOIL4, OUTPUT); pinMode(PINCOIL5, OUTPUT); pinMode(PINCOIL6, OUTPUT); pinMode(PINCOIL7, OUTPUT); pinMode(PINCOIL8, OUTPUT); pinMode(PINCOIL9, OUTPUT); pinMode(PINCOIL10, OUTPUT); //Set DI pin input pinMode(DIPIN, INPUT);

// Add Digital Input registers - Use addIsts() for digital inputs mb.addIsts(DI1, false); mb.addIsts(DI2, false); mb.addIsts(DI3, false); mb.addIsts(DI4, false); mb.addIsts(DI5, false); mb.addIsts(DI6, false); mb.addIsts(DI7, false); mb.addIsts(DI8, false);

// Add coils to mb - Use addCoil() for digital outputs mb.addCoil(COIL1, false); mb.addCoil(COIL2, false); mb.addCoil(COIL3, false); mb.addCoil(COIL4, false); mb.addCoil(COIL5, false); mb.addCoil(COIL6, false); mb.addCoil(COIL7, false); mb.addCoil(COIL8, false); mb.addCoil(COIL9, false); mb.addCoil(COIL10, false);

}

void loop() { // Ethernet.maintain(); //Call once inside loop() - all magic here mb.task();

//Attach coils registers to pins digitalWrite(PINCOIL1, mb.Coil(COIL1)); digitalWrite(PINCOIL2, mb.Coil(COIL2)); digitalWrite(PINCOIL3, mb.Coil(COIL3)); digitalWrite(PINCOIL4, mb.Coil(COIL4)); digitalWrite(PINCOIL5, mb.Coil(COIL5)); digitalWrite(PINCOIL6, mb.Coil(COIL6)); digitalWrite(PINCOIL7, mb.Coil(COIL7)); digitalWrite(PINCOIL8, mb.Coil(COIL8)); digitalWrite(PINCOIL9, mb.Coil(COIL9)); digitalWrite(PINCOIL10, mb.Coil(COIL10));

//Attach digital input registers to pins digitalWrite(PINMUX3, LOW); digitalWrite(PINMUX2, LOW); digitalWrite(PINMUX1, LOW); mb.task(); mb.Ists(DI4, digitalRead(DIPIN));

digitalWrite(PINMUX3, HIGH); digitalWrite(PINMUX2, LOW); digitalWrite(PINMUX1, LOW); mb.task(); mb.Ists(DI2, digitalRead(DIPIN));

digitalWrite(PINMUX3, LOW); digitalWrite(PINMUX2, HIGH); digitalWrite(PINMUX1, LOW); mb.task(); mb.Ists(DI1, digitalRead(DIPIN));

digitalWrite(PINMUX3, HIGH); digitalWrite(PINMUX2, HIGH); digitalWrite(PINMUX1, LOW); mb.task(); mb.Ists(DI3, digitalRead(DIPIN));

digitalWrite(PINMUX3, LOW); digitalWrite(PINMUX2, LOW); digitalWrite(PINMUX1, HIGH); mb.task(); mb.Ists(DI5, digitalRead(DIPIN));

digitalWrite(PINMUX3, HIGH); digitalWrite(PINMUX2, LOW); digitalWrite(PINMUX1, HIGH); mb.task(); mb.Ists(DI8, digitalRead(DIPIN));

digitalWrite(PINMUX3, LOW); digitalWrite(PINMUX2, HIGH); digitalWrite(PINMUX1, HIGH); mb.task(); mb.Ists(DI7, digitalRead(DIPIN));

digitalWrite(PINMUX3, HIGH); digitalWrite(PINMUX2, HIGH); digitalWrite(PINMUX1, HIGH); mb.task(); mb.Ists(DI6, digitalRead(DIPIN)); }

blddk commented 7 years ago

I see you calling mb.task() a lot, are there any reason for that? The code says to only call it once

Den 1. maj 2017 8.38 AM skrev "Seyed Amir Alavi" notifications@github.com:

Excuse me for the delay! I have added my code :

include

include

include

const int PINMUX1 = 7; const int PINMUX2 = 6; const int PINMUX3 = 5;

//Modbus Registers Offsets (0-9999) const int DI1 = 4001; const int DI2 = 4002; const int DI3 = 4003; const int DI4 = 4004; const int DI5 = 4005; const int DI6 = 4006; const int DI7 = 4007; const int DI8 = 4008;

const int DIPIN = 8;

const int COIL1 = 4009; const int COIL2 = 4010; const int COIL3 = 4011; const int COIL4 = 4012; const int COIL5 = 4013; const int COIL6 = 4014; const int COIL7 = 4015; const int COIL8 = 4016; const int COIL9 = 4017; const int COIL10 = 4018;

const int PINCOIL1 = A0; const int PINCOIL2 = A1; const int PINCOIL3 = A2; const int PINCOIL4 = A3; const int PINCOIL5 = A4; const int PINCOIL6 = A5; const int PINCOIL7 = 4; const int PINCOIL8 = 3; const int PINCOIL9 = 1; const int PINCOIL10 = 0;

//ModbusIP object ModbusIP mb;

void setup() { wdt_enable(WDTO_2S); // The media access control (ethernet hardware) address for the shield byte mac[] = { 0xB4, 0x68, 0xA8, 0x72, 0x4B, 0x3F};

//Config Modbus IP mb.config(mac);

//Set MUX pins output pinMode(PINMUX1, OUTPUT); pinMode(PINMUX2, OUTPUT); pinMode(PINMUX3, OUTPUT);

//Set coil pins output pinMode(PINCOIL1, OUTPUT); pinMode(PINCOIL2, OUTPUT); pinMode(PINCOIL3, OUTPUT); pinMode(PINCOIL4, OUTPUT); pinMode(PINCOIL5, OUTPUT); pinMode(PINCOIL6, OUTPUT); pinMode(PINCOIL7, OUTPUT); pinMode(PINCOIL8, OUTPUT); pinMode(PINCOIL9, OUTPUT); pinMode(PINCOIL10, OUTPUT); //Set DI pin input pinMode(DIPIN, INPUT);

// Add Digital Input registers - Use addIsts() for digital inputs mb.addIsts(DI1, false); mb.addIsts(DI2, false); mb.addIsts(DI3, false); mb.addIsts(DI4, false); mb.addIsts(DI5, false); mb.addIsts(DI6, false); mb.addIsts(DI7, false); mb.addIsts(DI8, false);

// Add coils to mb - Use addCoil() for digital outputs mb.addCoil(COIL1, false); mb.addCoil(COIL2, false); mb.addCoil(COIL3, false); mb.addCoil(COIL4, false); mb.addCoil(COIL5, false); mb.addCoil(COIL6, false); mb.addCoil(COIL7, false); mb.addCoil(COIL8, false); mb.addCoil(COIL9, false); mb.addCoil(COIL10, false);

}

void loop() { // Ethernet.maintain(); //Call once inside loop() - all magic here mb.task();

//Attach coils registers to pins digitalWrite(PINCOIL1, mb.Coil(COIL1)); digitalWrite(PINCOIL2, mb.Coil(COIL2)); digitalWrite(PINCOIL3, mb.Coil(COIL3)); digitalWrite(PINCOIL4, mb.Coil(COIL4)); digitalWrite(PINCOIL5, mb.Coil(COIL5)); digitalWrite(PINCOIL6, mb.Coil(COIL6)); digitalWrite(PINCOIL7, mb.Coil(COIL7)); digitalWrite(PINCOIL8, mb.Coil(COIL8)); digitalWrite(PINCOIL9, mb.Coil(COIL9)); digitalWrite(PINCOIL10, mb.Coil(COIL10));

//Attach digital input registers to pins digitalWrite(PINMUX3, LOW); digitalWrite(PINMUX2, LOW); digitalWrite(PINMUX1, LOW); mb.task(); mb.Ists(DI4, digitalRead(DIPIN));

digitalWrite(PINMUX3, HIGH); digitalWrite(PINMUX2, LOW); digitalWrite(PINMUX1, LOW); mb.task(); mb.Ists(DI2, digitalRead(DIPIN));

digitalWrite(PINMUX3, LOW); digitalWrite(PINMUX2, HIGH); digitalWrite(PINMUX1, LOW); mb.task(); mb.Ists(DI1, digitalRead(DIPIN));

digitalWrite(PINMUX3, HIGH); digitalWrite(PINMUX2, HIGH); digitalWrite(PINMUX1, LOW); mb.task(); mb.Ists(DI3, digitalRead(DIPIN));

digitalWrite(PINMUX3, LOW); digitalWrite(PINMUX2, LOW); digitalWrite(PINMUX1, HIGH); mb.task(); mb.Ists(DI5, digitalRead(DIPIN));

digitalWrite(PINMUX3, HIGH); digitalWrite(PINMUX2, LOW); digitalWrite(PINMUX1, HIGH); mb.task(); mb.Ists(DI8, digitalRead(DIPIN));

digitalWrite(PINMUX3, LOW); digitalWrite(PINMUX2, HIGH); digitalWrite(PINMUX1, HIGH); mb.task(); mb.Ists(DI7, digitalRead(DIPIN));

digitalWrite(PINMUX3, HIGH); digitalWrite(PINMUX2, HIGH); digitalWrite(PINMUX1, HIGH); mb.task(); mb.Ists(DI6, digitalRead(DIPIN)); }

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/andresarmento/modbus-arduino/pull/21#issuecomment-298294255, or mute the thread https://github.com/notifications/unsubscribe-auth/AAhOZhwH_bl-i6zCyjbzaCyIJUyf6Z0Xks5r1X3vgaJpZM4KYVRe .

samiralavi commented 7 years ago

Yes. I use UIP and if the delay between the subsequent task() calling gets higher than a threshold, I have experienced that the connection will be dropped in a long run.

blddk commented 7 years ago

Okay, I tried to use that too, but it was very slow at replying. With my arduino ethernet I got 8ms reply time, with the other I got over 150ms, and that is too slow for the controller to accept.

blddk commented 7 years ago

I just tried your code, it returns the wrong status for everything for me, all coils active on initial connect, and all inputs active, and nothing changing to the inputs, so I went back to looking at my own code.

The signal for MODBUS_1 and MODBUS_2 are correct, and the signal for MODBUS_5 and MODBUS_6 are correct. But in the code they are all connected to the same pin, so they should return the same status.

udklip

#define TCP_KEEP_ALIVE

#include <SPI.h>
#include <Ethernet.h>
#include <Modbus.h>
#include <ModbusIP.h>

//Modbus Registers Offsets (0-9999)

// Define outputs
const int DO0_PIN = 4;
const int DO0_COIL = 0;
const int DO1_COIL = 1;
const int DO2_COIL = 2;
const int DO3_COIL = 3;

// Define inputs
const int DI0_PIN = 8;
const int DI0_ISTS = 0;
const int DI1_ISTS = 1;
const int DI2_ISTS = 2;
const int DI3_ISTS = 3;

//ModbusIP object
ModbusIP mb;

void setup()
{
  // The media access control (ethernet hardware) address for the shield
  byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

  // The IP address for the shield
  byte ip[] = { 192, 168, 1, 12 };

  //Config Modbus IP
  mb.config(mac, ip);

  pinMode(DO0_PIN, OUTPUT);

  pinMode(DI0_PIN, INPUT_PULLUP);

  // Add output to register - Use addCoil() for digital outputs
  mb.addCoil(DO0_COIL, false);
  mb.addCoil(DO1_COIL, false);
  mb.addCoil(DO2_COIL, false);
  mb.addCoil(DO3_COIL, false);

  // Add inputs to register - Use addIsts() for digital inputs
  mb.addIsts(DI0_ISTS, false);
  mb.addIsts(DI1_ISTS, false);
  mb.addIsts(DI2_ISTS, false);
  mb.addIsts(DI3_ISTS, false);

  // Set startup values
  mb.Ists(DI0_ISTS, false);
  mb.Ists(DI1_ISTS, false);
  mb.Ists(DI2_ISTS, false);
  mb.Ists(DI3_ISTS, false);

  mb.Coil(DO0_COIL, false);
  mb.Coil(DO1_COIL, false);
  mb.Coil(DO2_COIL, false);
  mb.Coil(DO3_COIL, false);
}

void loop()
{
  //Call once inside loop() - all magic here
  mb.task();

  //Attach inputs to register
  mb.Ists(DI0_ISTS, digitalRead(DI0_PIN));
  mb.Ists(DI1_ISTS, digitalRead(DI0_PIN));
  mb.Ists(DI2_ISTS, digitalRead(DI0_PIN));
  mb.Ists(DI3_ISTS, digitalRead(DI0_PIN));

  // Attach outputs to register
  digitalWrite(DO0_PIN, mb.Coil(DO0_COIL));
  digitalWrite(DO0_PIN, mb.Coil(DO1_COIL));
  digitalWrite(DO0_PIN, mb.Coil(DO2_COIL));
  digitalWrite(DO0_PIN, mb.Coil(DO3_COIL));
}
blddk commented 7 years ago

Looks like it is related to the number I give them.

0 and 1 works, everything else returns high.

samiralavi commented 7 years ago

I will send you my lib. May be my git repo is not update.

On May 1, 2017 6:52 PM, "blddk" notifications@github.com wrote:

Looks like it is related to the number I give them.

0 and 1 works, everything else returns high.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/andresarmento/modbus-arduino/pull/21#issuecomment-298341721, or mute the thread https://github.com/notifications/unsubscribe-auth/ADofzjcU92Rl6p3RbZCQkpWAqaDcHRaSks5r1eqTgaJpZM4KYVRe .

blddk commented 7 years ago

I hope it is jut something like that, this is giving me grey hair :D

samiralavi commented 7 years ago

Be sure I have made it work! Don't worry.

On May 1, 2017 8:05 PM, "blddk" notifications@github.com wrote:

I hope it is jut something like that, this is giving me grey hair :D

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/andresarmento/modbus-arduino/pull/21#issuecomment-298356087, or mute the thread https://github.com/notifications/unsubscribe-auth/ADofziQS18_Eqtsn574wHOBFoM46P5FMks5r1fupgaJpZM4KYVRe .

samiralavi commented 7 years ago

I have updated my branch.

samiralavi commented 7 years ago

Also note to a thing, this library only supports a single type of register in every request.

blddk commented 7 years ago

I just tried to upload with your newest changes (Change back to Ethernet.h though) it is still showing the wrong status for the MODBUS_3 and MODBUS_4 output, and MODBUS_7 and MODBUS_8 input.

I did same test with a MOXA ioLogic E1212 same setup works fine with that.

Do you know how to use wireshark? I have tried to use that to see what is going on, but I have no idea how to set it up properly and how to analyze the packages.

samiralavi commented 7 years ago

Have you tested with CAS modbus scanner? It is free. Search google.

On May 3, 2017 10:13 PM, "blddk" notifications@github.com wrote:

I just tried to upload with your newest changes (Change back to Ethernet.h though) it is still showing the wrong status for the MODBUS_3 and MODBUS_4 output, and MODBUS_7 and MODBUS_8 input.

I did same test with a MOXA ioLogic E1212 same setup works fine with that.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/andresarmento/modbus-arduino/pull/21#issuecomment-298983675, or mute the thread https://github.com/notifications/unsubscribe-auth/ADofznfMu93vJ9XDG5WsAcu5Knj2N1Hoks5r2LzXgaJpZM4KYVRe .

blddk commented 7 years ago

This is for the moxa module

[20:01:45] <= Response: FF 01 01 00 
[20:01:44] => Poll: FF 01 00 00 00 04 

This is my arduino

[20:02:27] <= Response: FF 01 01 00 
[20:02:27] => Poll: FF 01 00 00 00 04 

CAS Modbus Scanner is saying the same is returned, but the robot controller is getting them as two different.

What the robot controller seems to think it gets, is like this [20:05:02] <= Response: FF 01 01 0C for the outputs when reading their status the first time

blddk commented 7 years ago

Okay, this is strange... I just found what I was looking for in wireshark, the moxa module responds with FF 01 01 00 my arduino responds with FF 01 01 02 but that is not what CAS Modbus Scanner says.

blddk commented 7 years ago

Nevermind... that was me failing at wireshark...

Both the Moxa and my arduino returns the same reply, but for some reason, the robot understands the same message different when it comes from my arduino... No idea how that is possible.

samiralavi commented 7 years ago

The robot scanner you have used may have configuration mismatch. Nice to know you are a step closer.

On May 4, 2017 12:46 AM, "blddk" notifications@github.com wrote:

Nevermind... that was me failing at wireshark...

Both the Moxa and my arduino returns the same reply, but for some reason, the robot understands the same message different when it comes from my arduino... No idea how that is possible.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/andresarmento/modbus-arduino/pull/21#issuecomment-299022668, or mute the thread https://github.com/notifications/unsubscribe-auth/ADofzvyNlHuFCbRMcEXhtFdaOsbwiP5cks5r2OCTgaJpZM4KYVRe .

carlosinv commented 6 years ago

Puede por favor ayudarme con el ModbusIP_ESP8266AT? Modbus_WiFi. El Problema es que se cierra la conexión luego de enviado el primer paquete y recibida la respuesta. Luego en la siguiente encuesta sale por TimeOut del ModbusScanner.

Este problema lo he resuelto con Modbus_Ethernet habilitando el #define TCP_KEEP_ALIVE. Esta posibilidad no la tengo en WiFi. ¿Como puedo dejar abierta la conexión Permanentemente???

Muchas gracias

carlosinv commented 6 years ago

Can you please help me with the ModbusIP_ESP8266AT? Modbus_WiFi. The problem is that the connection is closed after sending the first packet and the received the first response. Then in the following request exit by TimeOut of the ModbusScanner.

This problem, I was resolved with Modbus_Ethernet by enabling the #define TCP_KEEP_ALIVE. This possibility I do not have in the header's WiFi. How can I allow the permanent connection?

thank you very much