Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

This version can change Serial by user. #14

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 45 additions & 30 deletions Modbusino.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,17 @@ static uint16_t crc16(uint8_t *req, uint8_t req_length)
return (crc << 8 | crc >> 8);
}

ModbusinoSlave::ModbusinoSlave(uint8_t slave)
ModbusinoSlave::ModbusinoSlave() { }

void ModbusinoSlave::setup(uint8_t slave, long baud, HardwareSerial* port)
{
if (slave >= 0 & slave <= 247) {
_slave = slave;
}
}

void ModbusinoSlave::setup(long baud)
{
Serial.begin(baud);
_port = port;
if (baud >= 0) {
(*port).begin(baud);
}
}

static int check_integrity(uint8_t *msg, uint8_t msg_length)
Expand Down Expand Up @@ -93,14 +94,14 @@ static int build_response_basis(uint8_t slave, uint8_t function, uint8_t *rsp)
return _MODBUS_RTU_PRESET_RSP_LENGTH;
}

static void send_msg(uint8_t *msg, uint8_t msg_length)
static void send_msg(uint8_t *msg, uint8_t msg_length, Stream* _port)
{
uint16_t crc = crc16(msg, msg_length);

msg[msg_length++] = crc >> 8;
msg[msg_length++] = crc & 0x00FF;

Serial.write(msg, msg_length);
(*_port).write(msg, msg_length);
}

static uint8_t response_exception(uint8_t slave, uint8_t function,
Expand All @@ -116,19 +117,19 @@ static uint8_t response_exception(uint8_t slave, uint8_t function,
return rsp_length;
}

static void flush(void)
static void flush(Stream* _port)
{
uint8_t i = 0;

/* Wait a moment to receive the remaining garbage but avoid getting stuck
* because the line is saturated */
while (Serial.available() && i++ < 10) {
Serial.flush();
while ((*_port).available() && i++ < 10) {
(*_port).flush();
delay(3);
}
}

static int receive(uint8_t *req, uint8_t _slave)
static int receive(uint8_t *req, uint8_t _slave, Stream* _port)
{
uint8_t i;
uint8_t length_to_read;
Expand All @@ -148,9 +149,9 @@ static int receive(uint8_t *req, uint8_t _slave)
/* The timeout is defined to ~10 ms between each bytes. Precision is
not that important so I rather to avoid millis() to apply the KISS
principle (millis overflows after 50 days, etc) */
if (!Serial.available()) {
if (!(*_port).available()) {
i = 0;
while (!Serial.available()) {
while (!(*_port).available()) {
if (++i == 10) {
/* Too late, bye */
return -1 - MODBUS_INFORMATIVE_RX_TIMEOUT;
Expand All @@ -159,7 +160,7 @@ static int receive(uint8_t *req, uint8_t _slave)
}
}

req[req_index] = Serial.read();
req[req_index] = (*_port).read();

/* Moves the pointer to receive other data */
req_index++;
Expand All @@ -170,7 +171,7 @@ static int receive(uint8_t *req, uint8_t _slave)
if (length_to_read == 0) {
if (req[_MODBUS_RTU_SLAVE] != _slave
&& req[_MODBUS_RTU_SLAVE != MODBUS_BROADCAST_ADDRESS]) {
flush();
flush(_port);
return -1 - MODBUS_INFORMATIVE_NOT_FOR_US;
}

Expand All @@ -184,14 +185,14 @@ static int receive(uint8_t *req, uint8_t _slave)
length_to_read = 5;
} else {
/* Wait a moment to receive the remaining garbage */
flush();
flush(_port);
if (req[_MODBUS_RTU_SLAVE] == _slave
|| req[_MODBUS_RTU_SLAVE] == MODBUS_BROADCAST_ADDRESS) {
/* It's for me so send an exception (reuse req) */
uint8_t rsp_length = response_exception(
_slave, function, MODBUS_EXCEPTION_ILLEGAL_FUNCTION,
req);
send_msg(req, rsp_length);
send_msg(req, rsp_length, _port);
return -1 - MODBUS_EXCEPTION_ILLEGAL_FUNCTION;
}

Expand All @@ -207,14 +208,14 @@ static int receive(uint8_t *req, uint8_t _slave)

if ((req_index + length_to_read)
> _MODBUSINO_RTU_MAX_ADU_LENGTH) {
flush();
flush(_port);
if (req[_MODBUS_RTU_SLAVE] == _slave
|| req[_MODBUS_RTU_SLAVE] == MODBUS_BROADCAST_ADDRESS) {
/* It's for me so send an exception (reuse req) */
uint8_t rsp_length = response_exception(
_slave, function,
MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, req);
send_msg(req, rsp_length);
send_msg(req, rsp_length, _port);
return -1 - MODBUS_EXCEPTION_ILLEGAL_FUNCTION;
}
return -1;
Expand All @@ -230,9 +231,10 @@ static int receive(uint8_t *req, uint8_t _slave)
}


static void reply(uint16_t *tab_reg, uint16_t nb_reg, uint8_t *req,
uint8_t req_length, uint8_t _slave)
static uint32_t reply(uint16_t *tab_reg, uint16_t nb_reg, uint8_t *req,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change about return of reply should be in another PR

uint8_t req_length, uint8_t _slave, Stream* _port)
{
uint32_t backnum = 0;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't find the backnum term explicit.

uint8_t slave = req[_MODBUS_RTU_SLAVE];
uint8_t function = req[_MODBUS_RTU_FUNCTION];
uint16_t address =
Expand All @@ -243,12 +245,11 @@ static void reply(uint16_t *tab_reg, uint16_t nb_reg, uint8_t *req,
uint8_t rsp_length = 0;

if (slave != _slave && slave != MODBUS_BROADCAST_ADDRESS) {
return;
return backnum;
}

if (address + nb > nb_reg) {
rsp_length = response_exception(
slave, function, MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp);
rsp_length = response_exception(slave, function, MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp);
} else {
req_length -= _MODBUS_RTU_CHECKSUM_LENGTH;

Expand All @@ -262,6 +263,11 @@ static void reply(uint16_t *tab_reg, uint16_t nb_reg, uint8_t *req,
rsp[rsp_length++] = tab_reg[i] & 0xFF;
}
} else {

backnum = address;
backnum = backnum << 16;
backnum += nb;

uint16_t i, j;

for (i = address, j = 6; i < address + nb; i++, j += 2) {
Expand All @@ -277,18 +283,21 @@ static void reply(uint16_t *tab_reg, uint16_t nb_reg, uint8_t *req,
}
}

send_msg(rsp, rsp_length);
send_msg(rsp, rsp_length, _port);

return backnum;
}

int ModbusinoSlave::loop(uint16_t *tab_reg, uint16_t nb_reg)
{
int rc = 0;
uint8_t req[_MODBUSINO_RTU_MAX_ADU_LENGTH];
uint32_t b = 0;

if (Serial.available()) {
rc = receive(req, _slave);
if ((*_port).available()) {
rc = receive(req, _slave, _port);
if (rc > 0) {
reply(tab_reg, nb_reg, req, rc, _slave);
b = reply(tab_reg, nb_reg, req, rc, _slave, _port);
}
}

Expand All @@ -297,5 +306,11 @@ int ModbusinoSlave::loop(uint16_t *tab_reg, uint16_t nb_reg)
-1 if an undefined error has occured,
-2 for MODBUS_EXCEPTION_ILLEGAL_FUNCTION
etc */
return rc;
// if(rc > 0) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To remove.

// return b;
// } else {
// return 0;
// }
// return rc;
return b;
}
5 changes: 3 additions & 2 deletions Modbusino.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,12 @@

class ModbusinoSlave {
public:
ModbusinoSlave(uint8_t slave);
void setup(long baud);
ModbusinoSlave();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why you change the API here?

void setup(uint8_t slave, long baud, HardwareSerial* port);
int loop(uint16_t *tab_reg, uint16_t nb_reg);
private:
int _slave;
Stream* _port;
};

#endif
31 changes: 17 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Modbusino

Introduction
------------
This project fork from https://github.com/stephane/modbusino.

Modbusino is a ISC licensed library to handle Modbus requests on Arduino
(slave).
Expand All @@ -23,14 +24,16 @@ Example
```c
#include <Modbusino.h>

/* Initialize the slave with the ID 1 */
ModbusinoSlave modbusino_slave(1);
/* Initialize the slave */
ModbusinoSlave modbusino_slave;
/* Allocate a mapping of 10 values */
uint16_t tab_reg[10];

void setup() {
/* Set the slave address with the ID 1 */
/* The transfer speed is set to 115200 bauds */
modbusino_slave.setup(115200);
/* Set the serial port is Serial */
modbusino_slave.setup(1, 115200, &Serial);
}

void loop() {
Expand All @@ -39,17 +42,17 @@ void loop() {
/* Launch Modbus slave loop with:
- pointer to the mapping
- max values of mapping */
modbusino_slave.loop(tab_reg, 10);
}
```
uint32_t t = 0;

Contribute
----------
t = modbusino_slave.loop(tab_reg, 10);

uint16_t dlen = temp;
uint16_t addr = temp >> 16;

I want to keep this library very basic and small so if you want to contribute:
/* If the Modbus commend is 16(0x10):
- dlen: length of the regs that want write
- addr: index of the start address
Else, t always is 0*/

1. Check for open issues or open a fresh issue to start a discussion around a feature idea or a bug.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing of information about contributing!

2. Fork the [repository](https://github.com/stephane/modbusino/) on Github to start making your changes on another
branch.
3. Send a pull request (of your small and atomic changes).
4. Bug the maintainer if he's too busy to answer :)
}
```