Giter VIP home page Giter VIP logo

modbusrtuslave's People

Contributors

cmb27 avatar coburnw avatar gerrygralton avatar hcd-bdltd avatar parthkalgaonkar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

modbusrtuslave's Issues

USB Serial initialization

Great library, all very clear for a simple application. However I've ran into a problem attempting to read/write modbus over serial over usb. I am using a Pro Micro clone. At the PC end I am using qmodmaster.
I can't quite track it down and I was hoping you could shed some light on it.
I have cut down your ModbusRTUSlaveExample.h code so that it just writes a couple of values to the Input Registers and to the Holding Registers, also the one coil is connected to the internal led.
I am not using software serial as i want to use the hardware usb serial. e.g.
ModbusRTUSlave modbus(Serial);

It all works perfectly providing i adopt the following magic spell-

  1. Plug in arduino to USB port on PC
  2. Open serial port monitor in Arduino IDE
  3. Close serial port monitor
  4. Connect with qmodmaster
  5. Poll the registers. All works and the coils work too.

If I miss steps 2 and 3 then the qmodmaster will connect to the port and I can see the tx/rx leds blink once, but attempting to read or write results in a timeout (even if I extend the timeout period to 1second)
I have tried different serial speeds and configurations with the modbus.begin statement to no avail. I also tried putting in a Serial.begin statement which didn't help either.
Any ideas please?

Thanks

Cannot be used with ESP32

I tried this library with ESP32 and found it to be incompatible with ESP32. Can you fix it to be compatible with ESP 32?

Where to assign or write the Modbus Addresses

Hello Hope your doing well I request you please tell me how do i assign or write address in the program to my slave ardiuno controller whether it is holding address, input register, input status or coil status please support me for the same

Exception response codes

What Exception response codes have you defined?
They do not appear conforming to the Modbus spec.
The library sourcecode uses magic values, but that keeps them unexplained.

Connection problem rasberry pi pico

Hi Chris,

I recently tried to integrate this library for the Raspberry Pi Pico (RP2040) to facilitate Modbus communication. However, despite my best efforts, I've encountered timeout errors, seems like I never receive an answer on the line.

In light of your expertise in this domain, I sended an invitation to my repository. Would you be available to spare a moment and have a quick look at the code I've developed?

Your assistance would be greatly appreciated.

Thank you for considering my request.

register addressing

From the code and sample, it appears that all uses of register addresses start at zero and end at { numCoils, numDiscreteInputs, numHoldingRegisters, numInputRegisters }
This is not common practice on Modbus.
How did you envision this?

Now there isn't any checking on valid/invalid addresses, and not the proper exception frame can be send when master uses out-of-range addresses.

Document Code

Add comments to library code.
Possibly use doxygen.

Parity isn't working

Hello,

Nice lib you've made, I really like it.
I had some issues trying to communicate in 8E1. I constantly had CRC errors on my debug Modbus RTU console.
I've figure out that the config was in fact not 8E1 but 8N1 (as by default). I've had a look at the code and couldn't find where the parity check is done or written. Is it done somewhere else ? I only had a look in the begin method.
Could you resolve this ?

I'm sorry I couldn't get directly into your code and try resolve.

Regards,
Maxim

Function pointers are not validated

Class contains 6 function pointers. These pointers aren't zeroed, nor tested before calling.

Strange things will happen when e.g. no coils are configured and master performs a Modbus Read Coils.

Example Program(s)

Rename example program.
Possibly make variants of example program, demonstrating customization.

Driver control

What pins are used for transmit enable and receive enable?
Also what are the UNO pins for TX RX?

Slave to master write problem

Hi Chris,

I have been working on simple modbus communication but, I haven't succeeded yet. I need your help.

I want to write boolean value from slave and read it from master.
I have two Arduino nano and two TTL rs485 converter.

Both Arduino pin connection;
R0 to RX(D0)
DI to TX(D1)
DE and RE to D2
A to A
B to B

Where is problem? Could you help me?

Slave code

#include "NewPing.h"
#include <ModbusRTUSlave.h>

#define TRIGGER_PIN 9
#define ECHO_PIN 10
#define MAX_DISTANCE 400
#define TRESHOLD_DISTINCE 30 //100

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
float duration, distance;

#define SERIAL_BAUD 38400
#define SERIAL_CONFIG SERIAL_8N1
#define SLAVE_ID 1 
#define TXEN	2


ModbusRTUSlave slave(Serial, TXEN);
bool discreteInputs[1];
bool oldStatus = false;
bool newStatus = false;

void setup() {
  discreteInputs[0] = false;
  Serial.begin( SERIAL_BAUD, SERIAL_8E1 ); // 19200 baud, 8-bits, even, 1-bit stop
  slave.configureCoils(discreteInputs, 1);
  slave.begin(SLAVE_ID, SERIAL_BAUD, SERIAL_8E1);
}

void loop() {
  
  distance = sonar.ping_cm();
  
  Serial.print("DIST ");
  // Send results to Serial Monitor
  distance = distance == 0? 400 : distance;
  if (distance >= 400 || distance <= 2) {
    Serial.print("- |");
  } else {
    Serial.print(distance);
    Serial.print(" | ");
  }

  if (distance < TRESHOLD_DISTINCE) {
    Serial.print(" PARK F | ");
    newStatus = true;
  } else {
    Serial.print(" PARK E | ");
    newStatus = false;
  }

  if (oldStatus != newStatus) {
    oldStatus = newStatus;
    discreteInputs[0] = newStatus;
  }
  
  slave.poll();

  Serial.println();
  delay(1000);
}

Master code

#include <ModbusRTUMaster.h>

#define SERIAL_BAUD 38400
#define SERIAL_CONFIG SERIAL_8N1
#define TXEN	2

ModbusRTUMaster modbus(Serial, TXEN);
bool discreteInputs[1];

void setup() {
  Serial.begin(SERIAL_BAUD);
  modbus.begin(SERIAL_BAUD);
}


void loop() { 
  modbus.readCoils(1, 0, discreteInputs, 1);
  uint8_t reesponse = modbus.getExceptionResponse();
  Serial.print( reesponse );
  Serial.print(" |");
  Serial.print(discreteInputs[0]);
  Serial.print(" |");
  Serial.println();
  delay(1000);
}

Best regards,
Seref

Unexpected slave response if large request received

If a master node sends a request for more than the number of available registers, this library seems to send a very unexpected response. It just returns a very large, never ending stream of data. Using the code below, with 4 declared input registers, if 5 or more registers are requested by the master the error occurs.

#include <ModbusRTUSlave.h>

#define de PB15
#define re PB14

HardwareSerial rs485_serial(PC7, PC6);
ModbusRTUSlave modbus(rs485_serial, de);

const uint16_t numInputRegisters = 4;
uint16_t inputRegisters [numInputRegisters] = {0};

void setup() {
  pinMode(re, OUTPUT);
  pinMode(de, OUTPUT);
  rs485_serial.begin(19200, SERIAL_8E1);

  modbus.begin(1, 19200, SERIAL_8E1);
  modbus.configureInputRegisters(inputRegisters, numInputRegisters);

  inputRegisters[0] = (uint16_t) 100;
  inputRegisters[1] = (uint16_t) 34;
}

void loop() {
  modbus.poll(); 
}

How to can send 32 bit float

Thank for your useful library
But how i can send and read 32 bit float?
I try send from MCU two 16 bit and config modbus read in 32 bit float but it not working.
Sorry cause my dummy, thanks

How do I know which ModBus register was written lastly?

First of all: Thank you for providing such a great ModBus-RTU library!

My issue:
I would like to get to know in my code, when a register was written in order to respond to the new "parameter" (in my case) due to the fact that the Arduino serves as a data translator between different protocols.
Is there already a possibility to get to know the register type as well as the register ID?

(I used Version 1 where it was possible, but I would like to upgrade to the newest version of the library)

Compile problem with ARM based boards like RP2040 and STM32

There seems to be a compile problem with data types for some ARM based boards like RP2040 and STM32.

The example below is Arduino 2 using ModbusRTUSlave Arduino library V1.0.5 for example file Coils_HardwareSerial.ino for board Raspberry Pi Pico using the Arduino Mbed OS RP2040 Boards core:

C:\Users\xxxx\AppData\Local\Temp\.arduinoIDE-unsaved202364-14620-1k0o4kz.tzqx\Coils_HardwareSerial\Coils_HardwareSerial.ino: In function 'void setup()':
C:\Users\xxxx\AppData\Local\Temp\.arduinoIDE-unsaved202364-14620-1k0o4kz.tzqx\Coils_HardwareSerial\Coils_HardwareSerial.ino:80:54: error: invalid conversion from 'char (*)(unsigned int)' to 'ModbusRTUSlave::BoolRead {aka signed char (*)(short unsigned int)}' [-fpermissive]
   modbus.configureCoils(numCoils, coilRead, coilWrite);
                                                      ^
In file included from C:\Users\xxxx\AppData\Local\Temp\.arduinoIDE-unsaved202364-14620-1k0o4kz.tzqx\Coils_HardwareSerial\Coils_HardwareSerial.ino:28:0:
c:\proj\Arduino\libraries\ModbusRTUSlave\src/ModbusRTUSlave.h:15:10: note:   initializing argument 2 of 'void ModbusRTUSlave::configureCoils(uint16_t, ModbusRTUSlave::BoolRead, ModbusRTUSlave::BoolWrite)'
     void configureCoils(uint16_t numCoils, BoolRead coilRead, BoolWrite coilWrite);
          ^~~~~~~~~~~~~~
C:\Users\xxxx\AppData\Local\Temp\.arduinoIDE-unsaved202364-14620-1k0o4kz.tzqx\Coils_HardwareSerial\Coils_HardwareSerial.ino:80:54: error: invalid conversion from 'boolean (*)(unsigned int, boolean) {aka bool (*)(unsigned int, bool)}' to 'ModbusRTUSlave::BoolWrite {aka bool (*)(short unsigned int, bool)}' [-fpermissive]
   modbus.configureCoils(numCoils, coilRead, coilWrite);
                                                      ^
In file included from C:\Users\xxxx\AppData\Local\Temp\.arduinoIDE-unsaved202364-14620-1k0o4kz.tzqx\Coils_HardwareSerial\Coils_HardwareSerial.ino:28:0:
c:\proj\Arduino\libraries\ModbusRTUSlave\src/ModbusRTUSlave.h:15:10: note:   initializing argument 3 of 'void ModbusRTUSlave::configureCoils(uint16_t, ModbusRTUSlave::BoolRead, ModbusRTUSlave::BoolWrite)'
     void configureCoils(uint16_t numCoils, BoolRead coilRead, BoolWrite coilWrite);
          ^~~~~~~~~~~~~~

exit status 1

Compilation error: invalid conversion from 'char (*)(unsigned int)' to 'ModbusRTUSlave::BoolRead {aka signed char (*)(short unsigned int)}' [-fpermissive]

Similar compile problems also for STM32. Would be good to support the newer ARM based processors as AVR has supply chain issues and is old/expensive technology.

Library used on Arduino MEGA 2560 - no reply from the slave

Hello,

I try to use the library on an arduino Mega 2560 @ 16MHz.

Here ist the example file modified for my application.

Changes:

  • I use RX0 for communication and PE4 for direction control.
  • Speed is 9600.
#include "Arduino.h"
/*
  ModbusRTUSlaveExample

  This example demonstrates how to setup and use the ModbusRTUSlave library.
  It is intended to be used with a second board running ModbusRTUMasterExample from the ModbusRTUMaster library.

  Circuit:
  - A pushbutton switch from pin 2 to GND
  - A pushbutton switch from pin 3 to GND
  - A LED from pin 5 to GND with a 330 ohm series resistor
  - A LED from pin 6 to GND with a 330 ohm series resistor
  - A LED from pin 7 to GND with a 330 ohm series resistor
  - A LED from pin 8 to GND with a 330 ohm series resistor
  - The center pin of a potentiometer to pin A0, and the outside pins of the potentiometer to 5V and GND
  - The center pin of a potentiometer to pin A0, and the outside pins of the potentiometer to 5V and GND

  !!! If your board's logic voltage is 3.3V, use 3.3V instead of 5V; if in doubt use the IOREF pin !!!

  - Pin 10 to pin 11 of the master/client board
  - Pin 11 to pin 10 of the master/client board
  - GND to GND of the master/client board

  A schematic and illustration of the circuit is in the extras folder of the ModbusRTUSlave library.

  - Pin 13 is set up as the driver enable pin. This pin will be HIGH whenever the board is transmitting.

  Created: 2023-07-22
  By: C. M. Bulliner
  Modified: 2023-07-29
  By: C. M. Bulliner

*/

#include <SoftwareSerial.h>
#include <ModbusRTUSlave.h>

const byte ledPins[4] = {47, 46, 45, 43};
const byte buttonPins[2] = {15, 14};
const byte potPins[2] = {A0, A1};

const uint8_t rxPin = 0;
const uint8_t txPin = 1;
const uint8_t dePin = 2;

SoftwareSerial mySerial(rxPin, txPin);
ModbusRTUSlave modbus(mySerial, dePin); // serial port, driver enable pin for rs-485 (optional)

bool coils[2];
bool discreteInputs[2];
uint16_t holdingRegisters[2];
uint16_t inputRegisters[2];

void setup() {
  pinMode(ledPins[0], OUTPUT);
  pinMode(ledPins[1], OUTPUT);
  pinMode(ledPins[2], OUTPUT);
  pinMode(ledPins[3], OUTPUT);
  pinMode(buttonPins[0], INPUT_PULLUP);
  pinMode(buttonPins[1], INPUT_PULLUP);
  pinMode(potPins[0], INPUT);
  pinMode(potPins[1], INPUT);

  modbus.configureCoils(coils, 2);                       // bool array of coil values, number of coils
  modbus.configureDiscreteInputs(discreteInputs, 2);     // bool array of discrete input values, number of discrete inputs
  modbus.configureHoldingRegisters(holdingRegisters, 2); // unsigned 16 bit integer array of holding register values, number of holding registers
  modbus.configureInputRegisters(inputRegisters, 2);     // unsigned 16 bit integer array of input register values, number of input registers
  modbus.begin(1, 9600);                                // slave id, baud rate, config (optional)
}

void loop() {
  discreteInputs[0] = !digitalRead(buttonPins[0]);
  discreteInputs[1] = !digitalRead(buttonPins[1]);
  inputRegisters[0] = map(analogRead(potPins[0]), 0, 1023, 0, 255);
  inputRegisters[1] = map(analogRead(potPins[1]), 0, 1023, 0, 255);

  modbus.poll();

  digitalWrite(ledPins[0], coils[0]);
  digitalWrite(ledPins[1], coils[1]);
  analogWrite(ledPins[2], holdingRegisters[0]);
  analogWrite(ledPins[3], holdingRegisters[1]);
}

From a Modbus terminal program I generate a modbus message to write a single coil (0) to value 1.

2023-12-01 19_46_01-New Issue · CMB27_ModbusRTUSlave – Mozilla Firefox

This is sent from the PC to the Arduino 2560 via a USB --> RS485 adapter.

On the Board the RS485 is decoded to TTL using a MAX487.

At the output of this converter the signal is fed directly into (physical) PIN 2 = Arduino PIN 0.

Here is a Scope measurement directly on the processor pin:

DS1Z_QuickPrint3

What is the result:

  • The sketch can be compiled successfully
  • After resetting the board the sketch sets the direction pin correctly to receive (low = RX enable)

2023-12-01 20_03_14-MAX487 Datasheet and Product Info _ Analog Devices – Mozilla Firefox

DS1Z_QuickPrint4

Therefore I conclude, that the library is initializing correctly. When I select another (wrong) pin in the sketch, the dirctional pin stays on high (there is a 10k pullup resistor).

But then ... nothing happens. No response is being generated on TX0, The direction is not changed on the directional pin. The board is not reacting at all.

Questions:

  • Is the library working with the 2560? I did not find anything in the documentation.
  • Could there be a timing problem due to the Mega 2560 instead of the Arduino uno?
  • Is there any debugging mode foreseen, to show the stus of the Modbus slave to any output pin?
  • What else could I try?

Regards

Alexander

2 byte holding register need fast 100ms

hi sir

Pico board used receive data from plc id 01 t0 06
recive interval -100ms

Modbus library support minimum 300ms duration working

how to read data 100ms speed?

example your code

#include <ModbusRTUSlave.h>

ModbusRTUSlave modbus(Serial1, 255); // serial port, driver enable pin for rs-485
uint16_t holdingRegisters[2];

union {
  uint16_t bytes[2];
  float x;
} Float_data_1;

void setup() {
  modbus.configureHoldingRegisters(holdingRegisters, 2); // unsigned 16 bit integer array of holding register values, number of holding registers
  modbus.begin(1, 9600);
  Serial.begin(9600);
}

void loop() {
  modbus.poll();

// Split holdingRegisters[0] and holdingRegisters[1]
Float_data_1.bytes[0] = holdingRegisters[1];
Float_data_1.bytes[1] = holdingRegisters[0];

Serial.println(Float_data_1.x); // Print the float value

}

例子错误

invalid conversion from 'char (*)(word)' {aka 'char (*)(unsigned int)'} to 'ModbusRTUSlave::BoolRead' {aka 'signed char (*)(short unsigned int)'} [-fpermissive]

image

how to use float 32 bit

hir sir

****read unsigned holding register working fine below codeusing Pico rp2040

how to read 32bit float value ?

please help me

#include <ModbusRTUSlave.h>
ModbusRTUSlave modbus(Serial1, 255); // serial port, driver enable pin for rs-485
uint16_t holdingRegisters[2];

void setup() {

modbus.configureHoldingRegisters(holdingRegisters, 2); // unsigned 16 bit integer array of holding register values, number of holding registers
modbus.begin(1, 9600);
}

void loop() {

modbus.poll();
Serial.println(holdingRegisters[0]);
delay(100);
}

QModBus Invalid CRC

Hi, I am trying found a ideal RTU modbus library. Now, I am trying an example, on Arduino Mega 2560 ( Later on ESP32 ). As a master is a PC with QModBus. Between PC and Ardino is a converter with Tx En. On any ask from a PC, I get some data, but always with CRC Error.


#include <ModbusRTUSlave.h>


const byte buttonPins[2] = {2, 3};
const byte ledPins[4] = {5, 6, 7, 8};


//HardwareSerial RS485(1);
ModbusRTUSlave modbus( Serial1 , 13 ); // serial port, driver enable pin for rs-485


bool coils[2];
bool discreteInputs[2];
uint16_t holdingRegisters[2];
uint16_t inputRegisters[2];

void setup() {

  Serial1.begin( 9600 );
  
  pinMode(buttonPins[0], INPUT_PULLUP);
  pinMode(buttonPins[1], INPUT_PULLUP);
  pinMode(ledPins[0], OUTPUT);
  pinMode(ledPins[1], OUTPUT);
  pinMode(ledPins[2], OUTPUT);
  pinMode(ledPins[3], OUTPUT);

  modbus.configureCoils(coils, 2);                       // bool array of coil values, number of coils
  modbus.configureDiscreteInputs(discreteInputs, 2);     // bool array of discrete input values, number of discrete inputs
  modbus.configureHoldingRegisters(holdingRegisters, 2); // unsigned 16 bit integer array of holding register values, number of holding registers
  modbus.configureInputRegisters(inputRegisters, 2);     // unsigned 16 bit integer array of input register values, number of input registers

  modbus.begin( 1 , 9600);
}

void loop() {
  inputRegisters[0] = 500;
  inputRegisters[1] = 550;
  discreteInputs[0] = !digitalRead(buttonPins[0]);
  discreteInputs[1] = !digitalRead(buttonPins[1]);

  modbus.poll();

  analogWrite(ledPins[0], holdingRegisters[0]);
  analogWrite(ledPins[1], holdingRegisters[1]);
  digitalWrite(ledPins[2], coils[0]);
  digitalWrite(ledPins[3], coils[1]);
}

crc_err

Arduino UNO R4 Minima - was able to receive values, but not send them

Hi Chris,

it has to do something with Stream library - flush returns before write is completed I guess.
With enable pin I had to insert additional delay when going to low with pin.
I implemented a while loop with chartimeout variable in case flush ends too early.
I tested it with my UNO Rev4 minima only and DFRobot RS485 shield (BTW shield in auto mode it works perfectly without any changes to library)

void ModbusRTUSlave::_writeResponse(uint8_t len) {
  unsigned long startTime = 0;  
  if (_buf[0] != 0) {
    uint16_t crc = _crc(len);
    _buf[len] = lowByte(crc);
    _buf[len + 1] = highByte(crc);
    if (_dePin != NO_DE_PIN) digitalWrite(_dePin, HIGH);
    startTime = micros();
    _serial->write(_buf, len + 2);
    _serial->flush();
    while (micros() - startTime < (_charTimeout * (len + 2)));
    if (_dePin != NO_DE_PIN) digitalWrite(_dePin, LOW);
    while(_serial->available()) {
      _serial->read();
    }
  }
}

Regards,
Michal

Read Input registers request returning exception code 2

I kept getting exception code 2 on reading input registers despite everything else working out. finally on inspection of the library code I found the culprit on line 185 of ModbusRTUSlave.cpp. The line reads
else if (quantity > _numDiscreteInputs || startAddress > (_numInputRegisters - quantity)) _exceptionResponse(2);

how ever changing it to
else if (quantity > _numInputRegisters || startAddress > (_numInputRegisters - quantity)) _exceptionResponse(2);

fixed the issue for me and the library is working perfectly now.

`_numDiscreteRegisters` used instead of `_numInputRegisters`

There's an error on Line 190 in ModbusRTUSlave.cpp inside the _processReadInputRegisters() function. It currently reads:

else if (quantity > _numDiscreteInputs || startAddress > (_numInputRegisters - quantity)) _exceptionResponse(2);

and it should read:

else if (quantity > _numInputRegisters || startAddress > (_numInputRegisters - quantity)) _exceptionResponse(2);

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.