From 9a4286492fca5660fd86f384f5f38afd9e324ac2 Mon Sep 17 00:00:00 2001 From: rob tillaart Date: Sun, 5 Feb 2023 20:00:17 +0100 Subject: [PATCH] 0.2.4 RS485 --- .../RS485/.github/workflows/arduino-lint.yml | 2 +- .../.github/workflows/arduino_test_runner.yml | 2 +- .../RS485/.github/workflows/jsoncheck.yml | 2 +- libraries/RS485/ASCII_CONTROL.h | 3 +- libraries/RS485/CHANGELOG.md | 12 +- libraries/RS485/LICENSE | 2 +- libraries/RS485/MESSAGES.MD | 106 ++++++++++++++++++ libraries/RS485/README.md | 36 ++++-- libraries/RS485/RS485.cpp | 17 ++- libraries/RS485/RS485.h | 6 +- libraries/RS485/library.json | 2 +- libraries/RS485/library.properties | 2 +- libraries/RS485/test/unit_test_001.cpp | 5 +- 13 files changed, 163 insertions(+), 34 deletions(-) create mode 100644 libraries/RS485/MESSAGES.MD diff --git a/libraries/RS485/.github/workflows/arduino-lint.yml b/libraries/RS485/.github/workflows/arduino-lint.yml index b2ca058c..8a26f14a 100644 --- a/libraries/RS485/.github/workflows/arduino-lint.yml +++ b/libraries/RS485/.github/workflows/arduino-lint.yml @@ -6,7 +6,7 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: arduino/arduino-lint-action@v1 with: library-manager: update diff --git a/libraries/RS485/.github/workflows/arduino_test_runner.yml b/libraries/RS485/.github/workflows/arduino_test_runner.yml index 096b975b..fadfa904 100644 --- a/libraries/RS485/.github/workflows/arduino_test_runner.yml +++ b/libraries/RS485/.github/workflows/arduino_test_runner.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: ruby/setup-ruby@v1 with: ruby-version: 2.6 diff --git a/libraries/RS485/.github/workflows/jsoncheck.yml b/libraries/RS485/.github/workflows/jsoncheck.yml index 04603d08..37a11298 100644 --- a/libraries/RS485/.github/workflows/jsoncheck.yml +++ b/libraries/RS485/.github/workflows/jsoncheck.yml @@ -10,7 +10,7 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: json-syntax-check uses: limitusus/json-syntax-check@v1 with: diff --git a/libraries/RS485/ASCII_CONTROL.h b/libraries/RS485/ASCII_CONTROL.h index 0fca2e79..da21ca48 100644 --- a/libraries/RS485/ASCII_CONTROL.h +++ b/libraries/RS485/ASCII_CONTROL.h @@ -5,7 +5,7 @@ // DATE: 2020-08-26 // PURPOSE: ASCII control characters // URL: https://github.com/RobTillaart/RS485 -// + #define NUL 0x00 // NULL char #define SOH 0x01 // Start Of Header @@ -41,5 +41,6 @@ #define US 0x1F // Unit Separator #define DEL 0x7F // DELete + // -- END OF FILE -- diff --git a/libraries/RS485/CHANGELOG.md b/libraries/RS485/CHANGELOG.md index 7caf5afe..7e0ccc45 100644 --- a/libraries/RS485/CHANGELOG.md +++ b/libraries/RS485/CHANGELOG.md @@ -6,6 +6,13 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.2.4] - 2023-02-05 +- update readme.md +- added messages.md to give som ideas about handshakes/protocols. +- update GitHub actions +- update license 2023 + + ## [0.2.3] - 2022-11-23 - add changelog.md - add RP2040 to build-CI @@ -13,15 +20,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - update keywords.txt - minor edits - -## [0.2.2] - 2022-05-25 +## [0.2.2] - 2022-05-25 - rewrite blocking write(uint8_t \* array, length). - added write(char \* array, length). (convenience) ## [0.2.1] - 2022-05-24 - add setTXmode(), setRXmode(), getMode(). -## [0.2.0] - 2022-05-24 +## [0.2.0] - 2022-05-24 - first published version ---- diff --git a/libraries/RS485/LICENSE b/libraries/RS485/LICENSE index 4231b05c..562b0ffe 100644 --- a/libraries/RS485/LICENSE +++ b/libraries/RS485/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017-2022 Rob Tillaart +Copyright (c) 2017-2023 Rob Tillaart Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/libraries/RS485/MESSAGES.MD b/libraries/RS485/MESSAGES.MD new file mode 100644 index 00000000..1d380392 --- /dev/null +++ b/libraries/RS485/MESSAGES.MD @@ -0,0 +1,106 @@ + +# Messages + +Examples of command/answer protocols. +(to be elaborated) + +#### Guidelines + +- Keep protocols as simple as possible. +- be aware of implications of future expansion. + + +#### ASCII codes + +Possible useful char codes. + +| commando | value | meaning | +|:----------:|:-------:|:----------| +| SOH | 0x01 | start of header +| STX | 0x02 | start of text +| ETX | 0x03 | end of text +| EOT | 0x04 | end of transmission +| ACK | 0x06 | ACKnowledge +| NAK | 0x15 | Not Acknowledge +| CAN | 0x18 | CANcel + + + +---- + +## example 1 + +A minimal message protocol consisting of 1 byte commands + +command = (0x80 | 7 bits command) +answer = (0x00 | 7 bits answer)* + +All command are coded in a single byte with 0x80 bit set. +All answers bytes 0 or more (sender knows how many to expect, or a specific end char. + +requirement: +- All devices listen to a disjunct command set. + + + +## example 2 + +using a device id to send the command to. + + +command := + + SOH start of header, (attention new command) + deviceID to (is it for me?) + command (if so, exec command) + bytes expected (to generate the bytes) + +answer := + + bytes requested bytes (send them back) + + +## example 3 + +command and answer have same layout. +Uses device ID's to address specific device. + + SOH start of header 0x01 + deviceID to + deviceID sender + length length of message + message idem in ASCII + +optional extend with: + checksum optional + EOT optional (end of transmission) + + +## example 4 + +More complex package with multiple fields and crc per message. + + SOH start of header + deviceID to + deviceID sender + fields 0 or more + length length of field 1 + STX start of text + message idem + CHECKSUM idem, message only! + ETX end of text + length length of field 2 + STX start of text + message idem + CHECKSUM idem, message only! + ETX end of text + ... + EOT end of transmission + +---- + +## Future + +- binary protocols +- example code + diff --git a/libraries/RS485/README.md b/libraries/RS485/README.md index be80db6e..09825c01 100644 --- a/libraries/RS485/README.md +++ b/libraries/RS485/README.md @@ -8,7 +8,7 @@ # RS485 -Arduino library for RS485. +Arduino library for RS485 communication. ## Description @@ -18,7 +18,8 @@ The library implements the Stream interface so the user can use **print()** and **write()** calls just like one does with **Serial**. Preferably the library is to be used with a hardwareSerial as these -can buffer incoming characters in the background. +can buffer incoming characters in the background. +A software Serial that uses pin interrupts would also work quite well. The 0.2.0 version of the library has no (tested) protocol for multi-byte messages so the user must implement such on top of this class. @@ -26,6 +27,11 @@ messages so the user must implement such on top of this class. ## Interface +```cpp +#include "RS485.h" +``` + + #### Base - **RS485(Stream stream, uint8_t sendPin, uint8_t deviceID = 0)** constructor. @@ -34,7 +40,7 @@ The stream is typically Serial, and the baud rate, timeout etc. should be set via the Serial class. The sendPin is the pin that connects to the transmit/receive enable pins. The library sets the pinMode and defaults it to LOW (receiving mode). -- **void setMicrosPerByte(uint32_t baudRate)** set the delay per character needed. +- **void setMicrosPerByte(uint32_t baudRate)** set the delay per character needed. This gives the hardware enough time to flush the buffer. - **uint32_t getMicrosPerByte()** returns the current delay in micros used. - **void setTXmode()** explicitly set mode to transmitting / sending. @@ -58,7 +64,7 @@ All variations of **print()**, **println()** and **write()** can be used, the library calculates the time needed to set the RS485 chip in transmit mode. An important command from the stream interface is the **setTimeOut()** as -this allows reads on the RS485 bus that are limited +this allows reads on the RS485 bus that are limited. ## Operation @@ -74,7 +80,7 @@ resumes with listening. Do not forget to use one pull up (A line) and one pull down (B line) at only one end of the bus. -Values depend on the length of the cables, start with 1 KΩ. +Values depend on the length of the cables, start with 1 KΩ (kilo ohm) #### Wires @@ -100,12 +106,12 @@ To enable **yield()** uncomment the following line in **RS485.cpp** // #define RS485_YIELD_ENABLE 1 -or use this flag in the compile line option +or set this flag in the command line compile option. Note: the **yield()** calling version is substantial slower, depending on the baud rate. Use with care. -TODO: to be tested on ESP32 - RTOS . +TODO: to be tested on ESP32 - RTOS. #### Protocol design @@ -115,10 +121,12 @@ response of one module would trigger another module to also send a response. Of course these two responses interacted quite consistent but wrong. It took some time to find the cause and to redesign the protocol used. -Lesson learned was to spend more time designing the protocol. +Lesson learned was to spend more time designing the protocol up front. +And keep commands and responses 100% disjunct. An example of a simple byte protocol could use commands all with bit 7 set to 1, and all responses with bit 7 set to 0 (E.g ASCII). +Would allow 127 different 1 byte commands. #### Useful links @@ -130,18 +138,24 @@ bit 7 set to 1, and all responses with bit 7 set to 0 (E.g ASCII). ## Future -#### must +#### Must + - improve documentation -#### should +#### Should + - setUsPerByte() parameter does not feel 100% (investigate) -#### could +#### Could + - add **send()** and **receive()** for longer messages. - which handshake? - dynamic buffer size? - should this be a sort of message class / struct. fixed size? - add examples - add unit tests +- investigate yield() on ESP32/RTOS behaviour + +#### Wont diff --git a/libraries/RS485/RS485.cpp b/libraries/RS485/RS485.cpp index ea53ffe6..c12d83d1 100644 --- a/libraries/RS485/RS485.cpp +++ b/libraries/RS485/RS485.cpp @@ -2,7 +2,7 @@ // FILE: RS485.cpp // AUTHOR: Rob Tillaart // DATE: 30-okt-2017 -// VERSION: 0.2.3 +// VERSION: 0.2.4 // PURPOSE: Arduino library for RS485 modules (MAX485) // URL: https://github.com/RobTillaart/RS485 @@ -116,20 +116,21 @@ void RS485::setMicrosPerByte(uint32_t baudRate) // /////////////////////////////////////////////////////// // -// commando value meaning +// commando value meaning // // SOH 0x01 start of header // STX 0x02 start of text // ETX 0x03 end of text +// EOT 0x04 end of transmission // -// optional +// optional // ACK 0x06 ACKnowledge // NAK 0x15 Not Acknowledge // CAN 0x18 CANcel // /////////////////////////////////////////////////////// // -// A message has the following layout +// A message has the following layout // // SOH start of header // deviceID to @@ -142,7 +143,6 @@ void RS485::setMicrosPerByte(uint32_t baudRate) // EOT end of transmission // - void RS485::send(uint8_t receiverID, uint8_t msg[], uint8_t len) { uint8_t CHKSUM = 0; @@ -186,7 +186,7 @@ bool RS485::receive(uint8_t &senderID, uint8_t msg[], uint8_t &msglen) case 0: if (v == SOH) { - _bidx = 0; // start new packet + _bidx = 0; // start new packet state = 1; } break; @@ -223,7 +223,7 @@ bool RS485::receive(uint8_t &senderID, uint8_t msg[], uint8_t &msglen) state = 6; break; } - // error handling if v not ascii ? + // error handling if v not ASCII ? _buffer[_bidx++] = v; CHKSUM ^= v; length--; @@ -266,12 +266,11 @@ bool RS485::receive(uint8_t &senderID, uint8_t msg[], uint8_t &msglen) } - ////////////////////////////////////////////////// // // PRIVATE // -// -- END OF FILE -- +// -- END OF FILE -- diff --git a/libraries/RS485/RS485.h b/libraries/RS485/RS485.h index 4ca18028..0a0ad0bc 100644 --- a/libraries/RS485/RS485.h +++ b/libraries/RS485/RS485.h @@ -3,7 +3,7 @@ // FILE: RS485.h // AUTHOR: Rob Tillaart // DATE: 30-okt-2017 -// VERSION: 0.2.3 +// VERSION: 0.2.4 // PURPOSE: Arduino library for RS485 modules // URL: https://github.com/RobTillaart/RS485 @@ -11,7 +11,7 @@ #include "Arduino.h" #include "ASCII_CONTROL.h" -#define RS485_LIB_VERSION (F("0.2.3")) +#define RS485_LIB_VERSION (F("0.2.4")) class RS485 : public Stream @@ -66,5 +66,5 @@ private: }; -// -- END OF FILE -- +// -- END OF FILE -- diff --git a/libraries/RS485/library.json b/libraries/RS485/library.json index a27096b5..04e3e8eb 100644 --- a/libraries/RS485/library.json +++ b/libraries/RS485/library.json @@ -15,7 +15,7 @@ "type": "git", "url": "https://github.com/RobTillaart/RS485" }, - "version": "0.2.3", + "version": "0.2.4", "license": "MIT", "frameworks": "arduino", "platforms": "*", diff --git a/libraries/RS485/library.properties b/libraries/RS485/library.properties index f73795c6..94cb9fc0 100644 --- a/libraries/RS485/library.properties +++ b/libraries/RS485/library.properties @@ -1,5 +1,5 @@ name=RS485 -version=0.2.3 +version=0.2.4 author=Rob Tillaart maintainer=Rob Tillaart sentence=RS485 library for Arduino. diff --git a/libraries/RS485/test/unit_test_001.cpp b/libraries/RS485/test/unit_test_001.cpp index f5245b5f..7adb9821 100644 --- a/libraries/RS485/test/unit_test_001.cpp +++ b/libraries/RS485/test/unit_test_001.cpp @@ -41,6 +41,7 @@ unittest_setup() fprintf(stderr, "RS485_LIB_VERSION: %s\n", (char *) RS485_LIB_VERSION); } + unittest_teardown() { } @@ -99,4 +100,6 @@ unittest(test_communication_mode) unittest_main() -// -------- + +// -- END OF FILE -- +