Skip to content

Commit e12961c

Browse files
committed
Functional RTU on Arduino
1 parent c184529 commit e12961c

File tree

4 files changed

+102
-0
lines changed

4 files changed

+102
-0
lines changed

src/libmodbus/modbus-rtu-private.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
#if defined(_WIN32)
1717
#include <windows.h>
18+
#elif defined(ARDUINO)
19+
// nothing extra needed
1820
#else
1921
#include <termios.h>
2022
#endif
@@ -43,6 +45,10 @@ struct win32_ser {
4345
#endif /* _WIN32 */
4446

4547
typedef struct _modbus_rtu {
48+
#if defined(ARDUINO)
49+
unsigned long baud;
50+
uint16_t config;
51+
#else
4652
/* Device: "/dev/ttyS0", "/dev/ttyUSB0" or "/dev/tty.USA19*" on Mac OS X. */
4753
char *device;
4854
/* Bauds: 9600, 19200, 57600, 115200, etc */
@@ -68,6 +74,7 @@ typedef struct _modbus_rtu {
6874
int rts_delay;
6975
int onebyte_time;
7076
void (*set_rts) (modbus_t *ctx, int on);
77+
#endif
7178
#endif
7279
/* To handle many slaves on the same link */
7380
int confirmation_to_ignore;

src/libmodbus/modbus-rtu.cpp

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
#endif
1515
#include <assert.h>
1616

17+
#ifdef ARDUINO
18+
#include <RS485.h>
19+
#endif
20+
1721
#include "modbus-private.h"
1822

1923
#include "modbus-rtu.h"
@@ -147,6 +151,9 @@ static uint16_t crc16(uint8_t *buffer, uint16_t buffer_length)
147151

148152
static int _modbus_rtu_prepare_response_tid(const uint8_t *req, int *req_length)
149153
{
154+
#ifdef ARDUINO
155+
(void)req;
156+
#endif
150157
(*req_length) -= _MODBUS_RTU_CHECKSUM_LENGTH;
151158
/* No TID */
152159
return 0;
@@ -273,6 +280,16 @@ static ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_lengt
273280
modbus_rtu_t *ctx_rtu = ctx->backend_data;
274281
DWORD n_bytes = 0;
275282
return (WriteFile(ctx_rtu->w_ser.fd, req, req_length, &n_bytes, NULL)) ? (ssize_t)n_bytes : -1;
283+
#elif defined(ARDUINO)
284+
(void)ctx;
285+
286+
ssize_t size;
287+
288+
RS485.beginTransmission();
289+
size = RS485.write(req, req_length);
290+
RS485.endTransmission();
291+
292+
return size;
276293
#else
277294
#if HAVE_DECL_TIOCM_RTS
278295
modbus_rtu_t *ctx_rtu = ctx->backend_data;
@@ -304,7 +321,11 @@ static ssize_t _modbus_rtu_send(modbus_t *ctx, const uint8_t *req, int req_lengt
304321
static int _modbus_rtu_receive(modbus_t *ctx, uint8_t *req)
305322
{
306323
int rc;
324+
#ifdef ARDUINO
325+
modbus_rtu_t *ctx_rtu = (modbus_rtu_t*)ctx->backend_data;
326+
#else
307327
modbus_rtu_t *ctx_rtu = ctx->backend_data;
328+
#endif
308329

309330
if (ctx_rtu->confirmation_to_ignore) {
310331
_modbus_receive_msg(ctx, req, MSG_CONFIRMATION);
@@ -328,6 +349,10 @@ static ssize_t _modbus_rtu_recv(modbus_t *ctx, uint8_t *rsp, int rsp_length)
328349
{
329350
#if defined(_WIN32)
330351
return win32_ser_read(&((modbus_rtu_t *)ctx->backend_data)->w_ser, rsp, rsp_length);
352+
#elif defined(ARDUINO)
353+
(void)ctx;
354+
355+
return RS485.readBytes(rsp, rsp_length);
331356
#else
332357
return read(ctx->s, rsp, rsp_length);
333358
#endif
@@ -338,6 +363,9 @@ static int _modbus_rtu_flush(modbus_t *);
338363
static int _modbus_rtu_pre_check_confirmation(modbus_t *ctx, const uint8_t *req,
339364
const uint8_t *rsp, int rsp_length)
340365
{
366+
#ifdef ARDUINO
367+
(void)rsp_length;
368+
#endif
341369
/* Check responding slave is the slave we requested (except for broacast
342370
* request) */
343371
if (req[0] != rsp[0] && req[0] != MODBUS_BROADCAST_ADDRESS) {
@@ -398,18 +426,24 @@ static int _modbus_rtu_connect(modbus_t *ctx)
398426
{
399427
#if defined(_WIN32)
400428
DCB dcb;
429+
#elif defined(ARDUINO)
430+
// nothing extra needed
401431
#else
402432
struct termios tios;
403433
speed_t speed;
404434
int flags;
405435
#endif
436+
#ifdef ARDUINO
437+
modbus_rtu_t *ctx_rtu = (modbus_rtu_t*)ctx->backend_data;
438+
#else
406439
modbus_rtu_t *ctx_rtu = ctx->backend_data;
407440

408441
if (ctx->debug) {
409442
printf("Opening %s at %d bauds (%c, %d, %d)\n",
410443
ctx_rtu->device, ctx_rtu->baud, ctx_rtu->parity,
411444
ctx_rtu->data_bit, ctx_rtu->stop_bit);
412445
}
446+
#endif
413447

414448
#if defined(_WIN32)
415449
/* Some references here:
@@ -575,6 +609,9 @@ static int _modbus_rtu_connect(modbus_t *ctx)
575609
ctx_rtu->w_ser.fd = INVALID_HANDLE_VALUE;
576610
return -1;
577611
}
612+
#elif defined(ARDUINO)
613+
RS485.begin(ctx_rtu->baud, ctx_rtu->config);
614+
RS485.receive();
578615
#else
579616
/* The O_NOCTTY flag tells UNIX that this program doesn't want
580617
to be the "controlling terminal" for that port. If you
@@ -898,6 +935,7 @@ static int _modbus_rtu_connect(modbus_t *ctx)
898935
return 0;
899936
}
900937

938+
#ifndef ARDUINO
901939
int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode)
902940
{
903941
if (ctx == NULL) {
@@ -1103,11 +1141,16 @@ int modbus_rtu_set_rts_delay(modbus_t *ctx, int us)
11031141
return -1;
11041142
}
11051143
}
1144+
#endif
11061145

11071146
static void _modbus_rtu_close(modbus_t *ctx)
11081147
{
11091148
/* Restore line settings and close file descriptor in RTU mode */
1149+
#ifdef ARDUINO
1150+
modbus_rtu_t *ctx_rtu = (modbus_rtu_t*)ctx->backend_data;
1151+
#else
11101152
modbus_rtu_t *ctx_rtu = ctx->backend_data;
1153+
#endif
11111154

11121155
#if defined(_WIN32)
11131156
/* Revert settings */
@@ -1120,6 +1163,11 @@ static void _modbus_rtu_close(modbus_t *ctx)
11201163
fprintf(stderr, "ERROR Error while closing handle (LastError %d)\n",
11211164
(int)GetLastError());
11221165
}
1166+
#elif defined(ARDUINO)
1167+
(void)ctx_rtu;
1168+
1169+
RS485.noReceive();
1170+
RS485.end();
11231171
#else
11241172
if (ctx->s != -1) {
11251173
tcsetattr(ctx->s, TCSANOW, &ctx_rtu->old_tios);
@@ -1135,6 +1183,14 @@ static int _modbus_rtu_flush(modbus_t *ctx)
11351183
modbus_rtu_t *ctx_rtu = ctx->backend_data;
11361184
ctx_rtu->w_ser.n_bytes = 0;
11371185
return (PurgeComm(ctx_rtu->w_ser.fd, PURGE_RXCLEAR) == FALSE);
1186+
#elif defined(ARDUINO)
1187+
(void)ctx;
1188+
1189+
while (RS485.available()) {
1190+
RS485.read();
1191+
}
1192+
1193+
return 0;
11381194
#else
11391195
return tcflush(ctx->s, TCIOFLUSH);
11401196
#endif
@@ -1155,6 +1211,26 @@ static int _modbus_rtu_select(modbus_t *ctx, fd_set *rset,
11551211
if (s_rc < 0) {
11561212
return -1;
11571213
}
1214+
#elif defined(ARDUINO)
1215+
(void)ctx;
1216+
(void)rset;
1217+
1218+
unsigned long wait_time_millis = (tv == NULL) ? 0 : (tv->tv_sec * 1000) + (tv->tv_usec / 1000);
1219+
unsigned long start = millis();
1220+
1221+
do {
1222+
s_rc = RS485.available();
1223+
1224+
if (s_rc == length_to_read) {
1225+
break;
1226+
}
1227+
} while ((millis() - start) < wait_time_millis);
1228+
1229+
if (s_rc == 0) {
1230+
/* Timeout */
1231+
errno = ETIMEDOUT;
1232+
return -1;
1233+
}
11581234
#else
11591235
while ((s_rc = select(ctx->s+1, rset, NULL, NULL, tv)) == -1) {
11601236
if (errno == EINTR) {
@@ -1180,7 +1256,9 @@ static int _modbus_rtu_select(modbus_t *ctx, fd_set *rset,
11801256
}
11811257

11821258
static void _modbus_rtu_free(modbus_t *ctx) {
1259+
#ifndef ARDUINO
11831260
free(((modbus_rtu_t*)ctx->backend_data)->device);
1261+
#endif
11841262
free(ctx->backend_data);
11851263
free(ctx);
11861264
}
@@ -1207,13 +1285,18 @@ const modbus_backend_t _modbus_rtu_backend = {
12071285
_modbus_rtu_free
12081286
};
12091287

1288+
#ifdef ARDUINO
1289+
modbus_t* modbus_new_rtu(unsigned long baud, uint16_t config)
1290+
#else
12101291
modbus_t* modbus_new_rtu(const char *device,
12111292
int baud, char parity, int data_bit,
12121293
int stop_bit)
1294+
#endif
12131295
{
12141296
modbus_t *ctx;
12151297
modbus_rtu_t *ctx_rtu;
12161298

1299+
#ifndef ARDUINO
12171300
/* Check device argument */
12181301
if (device == NULL || *device == 0) {
12191302
fprintf(stderr, "The device string is empty\n");
@@ -1227,12 +1310,17 @@ modbus_t* modbus_new_rtu(const char *device,
12271310
errno = EINVAL;
12281311
return NULL;
12291312
}
1313+
#endif
12301314

12311315
ctx = (modbus_t *)malloc(sizeof(modbus_t));
12321316
_modbus_init_common(ctx);
12331317
ctx->backend = &_modbus_rtu_backend;
12341318
ctx->backend_data = (modbus_rtu_t *)malloc(sizeof(modbus_rtu_t));
12351319
ctx_rtu = (modbus_rtu_t *)ctx->backend_data;
1320+
#ifdef ARDUINO
1321+
ctx_rtu->baud = baud;
1322+
ctx_rtu->config = config;
1323+
#else
12361324
ctx_rtu->device = NULL;
12371325

12381326
/* Device name and \0 */
@@ -1267,6 +1355,7 @@ modbus_t* modbus_new_rtu(const char *device,
12671355

12681356
/* The delay before and after transmission when toggling the RTS pin */
12691357
ctx_rtu->rts_delay = ctx_rtu->onebyte_time;
1358+
#endif
12701359
#endif
12711360

12721361
ctx_rtu->confirmation_to_ignore = FALSE;

src/libmodbus/modbus-rtu.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ MODBUS_BEGIN_DECLS
1616
*/
1717
#define MODBUS_RTU_MAX_ADU_LENGTH 256
1818

19+
#ifdef ARDUINO
20+
MODBUS_API modbus_t* modbus_new_rtu(unsigned long baud, uint16_t config);
21+
#else
1922
MODBUS_API modbus_t* modbus_new_rtu(const char *device, int baud, char parity,
2023
int data_bit, int stop_bit);
2124

@@ -36,6 +39,7 @@ MODBUS_API int modbus_rtu_set_custom_rts(modbus_t *ctx, void (*set_rts) (modbus_
3639

3740
MODBUS_API int modbus_rtu_set_rts_delay(modbus_t *ctx, int us);
3841
MODBUS_API int modbus_rtu_get_rts_delay(modbus_t *ctx);
42+
#endif
3943

4044
MODBUS_END_DECLS
4145

src/libmodbus/modbus.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,9 +363,11 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
363363
}
364364
}
365365

366+
#ifndef ARDUINO
366367
/* Add a file descriptor to the set */
367368
FD_ZERO(&rset);
368369
FD_SET(ctx->s, &rset);
370+
#endif
369371

370372
/* We need to analyse the message step by step. At the first step, we want
371373
* to reach the function code because all packets contain this

0 commit comments

Comments
 (0)