From 76dea1532ce2bcf21a5a167e21b4e0ba4eeaa51a Mon Sep 17 00:00:00 2001 From: Marcelo Aquino Date: Thu, 20 Oct 2016 17:05:13 -0200 Subject: [PATCH] RPi: Add support for RS485 transport Remove serial print from MyTransportRS485.cpp to increase speed. --- MyConfig.h | 13 +++++++ MySensors.h | 7 +++- configure | 38 ++++++++++++++++--- core/MyTransportRS485.cpp | 19 +++++++--- drivers/Linux/SerialPort.cpp | 5 ++- .../GatewaySerialRS485/GatewaySerialRS485.ino | 9 ++++- .../MotionSensorRS485/MotionSensorRS485.ino | 11 +++++- keywords.txt | 1 + 8 files changed, 85 insertions(+), 18 deletions(-) diff --git a/MyConfig.h b/MyConfig.h index 1fc059d..ff8ba70 100644 --- a/MyConfig.h +++ b/MyConfig.h @@ -440,6 +440,18 @@ #define MY_RS485_MAX_MESSAGE_LENGTH 40 #endif +/** + * @def MY_RS485_DE_PIN + * @brief RS485 driver enable pin. + */ +//#define MY_RS485_DE_PIN 2 + +/** + * @def MY_RS485_HWSERIAL + * @brief Enable this if RS485 is connected to a hardware serial port. + */ +//#define MY_RS485_HWSERIAL Serial1 + /********************************** * NRF24L01P Driver Defaults ***********************************/ @@ -839,6 +851,7 @@ #define MY_SIGNING_REQUEST_SIGNATURES #define MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL #define MY_SIGNING_NODE_WHITELISTING {{.nodeId = GATEWAY_ADDRESS,.serial = {0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01}}} +#define MY_RS485_HWSERIAL #define MY_IS_RFM69HW #define MY_PARENT_NODE_IS_STATIC #define MY_REGISTRATION_CONTROLLER diff --git a/MySensors.h b/MySensors.h index 8824e8d..1e6414d 100644 --- a/MySensors.h +++ b/MySensors.h @@ -287,7 +287,12 @@ #include "drivers/RF24/RF24.cpp" #include "core/MyTransportNRF24.cpp" #elif defined(MY_RS485) - #include "drivers/AltSoftSerial/AltSoftSerial.cpp" + #if !defined(MY_RS485_HWSERIAL) + #if defined(__linux__) + #error You must specify MY_RS485_HWSERIAL for RS485 transport + #endif + #include "drivers/AltSoftSerial/AltSoftSerial.cpp" + #endif #include "core/MyTransportRS485.cpp" #elif defined(MY_RADIO_RFM69) #include "drivers/RFM69/RFM69.cpp" diff --git a/configure b/configure index 570edde..6d987af 100755 --- a/configure +++ b/configure @@ -27,8 +27,9 @@ Installation options: MySensors options: --my-debug=[enable|disable] Enables or disables MySensors core debugging. [enable] --my-config-file= Config file path. [/etc/mysensors.dat] - --my-gateway=[none|ethernet|serial|mqtt] + --my-gateway=[ethernet|serial|mqtt] Gateway type, set to none to disable gateway feature. [ethernet] + --my-node-id= Disable gateway feature and run as a node with given id. --my-controller-url-address= Controller or MQTT broker url. --my-controller-ip-address= @@ -47,13 +48,20 @@ MySensors options: MQTT publish topic prefix. --my-mqtt-subscribe-topic-prefix= MQTT subscribe topic prefix. - --my-radio=[none|nrf24] Radio type, set to none to disable radio feature. [rf24] + --my-transport=[none|nrf24|rs485] + Transport type, set to none to disable transport feature. [nrf24] --my-rf24-channel=<0-125> RF channel for the sensor net, 0-125. [76] --my-rf24-pa-level=[RF24_PA_MAX|RF24_PA_LOW] RF24 PA level. [RF24_PA_MAX] --my-rf24-irq-pin= Pin number connected to nRF24L01 IRQ pin. --my-rx-message-buffer-size= Buffer size for incoming messages when using rf24 interrupts. [20] + --my-rs485-serial-port= + RS485 serial port. You must provide a port. + --my-rs485-baudrate= RS485 baudrate. [9600] + --my-rs485-de-pin= Pin number connected to RS485 driver enable pin. + --my-rs485-max-msg-length= + The maximum message length used for RS485. --my-leds-err-pin= Error LED pin. --my-leds-rx-pin= Receive LED pin. --my-leds-tx-pin= Transmit LED pin. @@ -196,7 +204,7 @@ function gcc_cpu_flags { # Default values debug=enable gateway_type=ethernet -radio_type=nrf24 +transport_type=nrf24 params="SOC CXXFLAGS LDFLAGS PREFIX CXX GATEWAY_DIR INIT_SYSTEM" @@ -237,11 +245,15 @@ for opt do --my-gateway=*) gateway_type=${optarg} ;; + --my-node-id=*) + gateway_type="none"; + CXXFLAGS="-DMY_NODE_ID=${optarg} $CXXFLAGS" + ;; --my-config-file=*) CXXFLAGS="-DMY_LINUX_CONFIG_FILE=\\\"${optarg}\\\" $CXXFLAGS" ;; - --my-radio=*) - radio_type=${optarg} + --my-transport=*) + transport_type=${optarg} ;; --my-serial-port=*) CXXFLAGS="-DMY_LINUX_SERIAL_PORT=\\\"${optarg}\\\" $CXXFLAGS" @@ -289,6 +301,18 @@ for opt do --my-rx-message-buffer-size=*) CXXFLAGS="-DMY_RX_MESSAGE_BUFFER_SIZE=${optarg} $CXXFLAGS" ;; + --my-rs485-serial-port=*) + CXXFLAGS="-DMY_RS485_HWSERIAL=\\\"${optarg}\\\" $CXXFLAGS" + ;; + --my-rs485-baudrate=*) + CXXFLAGS="-DMY_RS485_BAUD_RATE=${optarg} $CXXFLAGS" + ;; + --my-rs485-de-pin=*) + CXXFLAGS="-DMY_RS485_DE_PIN=${optarg} $CXXFLAGS" + ;; + --my-rs485-max-msg-length=*) + CXXFLAGS="-DMY_RS485_MAX_MESSAGE_LENGTH=${optarg} $CXXFLAGS" + ;; --my-leds-err-pin=*) CXXFLAGS="-DMY_DEFAULT_ERR_LED_PIN=${optarg} $CXXFLAGS" ;; @@ -344,8 +368,10 @@ elif [[ ${gateway_type} == "mqtt" ]]; then CXXFLAGS="-DMY_GATEWAY_LINUX -DMY_GATEWAY_MQTT_CLIENT $CXXFLAGS" fi -if [[ ${radio_type} == "nrf24" ]]; then +if [[ ${transport_type} == "nrf24" ]]; then CXXFLAGS="-DMY_RADIO_NRF24 $CXXFLAGS" +elif [[ ${transport_type} == "rs485" ]]; then + CXXFLAGS="-DMY_RS485 $CXXFLAGS" fi LDFLAGS="-pthread $LDFLAGS" diff --git a/core/MyTransportRS485.cpp b/core/MyTransportRS485.cpp index a7990ae..780301a 100644 --- a/core/MyTransportRS485.cpp +++ b/core/MyTransportRS485.cpp @@ -61,6 +61,9 @@ #include "MyTransport.h" +#ifdef __linux__ + #include "SerialPort.h" +#endif #if defined(MY_RS485_DE_PIN) #define assertDE() hwDigitalWrite(MY_RS485_DE_PIN, HIGH); delayMicroseconds(5) @@ -87,8 +90,14 @@ unsigned char _recSender; unsigned char _recCS; unsigned char _recCalcCS; -AltSoftSerial _dev; +#if defined(__linux__) +SerialPort _dev = SerialPort(MY_RS485_HWSERIAL); +#elif defined(MY_RS485_HWSERIAL) +HardwareSerial& _dev = MY_RS485_HWSERIAL; +#else +AltSoftSerial _dev; +#endif unsigned char _nodeId; char _data[MY_RS485_MAX_MESSAGE_LENGTH]; @@ -160,10 +169,6 @@ bool _serialProcess() if ((_recSender == _nodeId) || (_recStation != _nodeId && _recStation != BROADCAST_ADDRESS)) { - _dev.print(" wrongid: "); - _dev.print(_recStation); - _dev.print(" - "); - _dev.println(_nodeId); _serialReset(); break; } @@ -302,7 +307,9 @@ bool transportSend(uint8_t to, const void* data, uint8_t len) _dev.flush(); delayMicroseconds((20000000UL/9600)+1); #endif - #endif + #elif defined(__linux__) + _dev.flush(); + #endif #endif hwDigitalWrite(MY_RS485_DE_PIN, LOW); #endif diff --git a/drivers/Linux/SerialPort.cpp b/drivers/Linux/SerialPort.cpp index b1145cc..0c9f1bb 100644 --- a/drivers/Linux/SerialPort.cpp +++ b/drivers/Linux/SerialPort.cpp @@ -235,7 +235,10 @@ int SerialPort::peek() void SerialPort::flush() { - tcflush(sd, TCIFLUSH); + // Waits until all output written to sd has been transmitted + if (tcdrain(sd) < 0) { + logError("Couldn't flush serial: %s\n", strerror(errno)); + } } void SerialPort::end() diff --git a/examples/GatewaySerialRS485/GatewaySerialRS485.ino b/examples/GatewaySerialRS485/GatewaySerialRS485.ino index 03c8996..2db67c9 100644 --- a/examples/GatewaySerialRS485/GatewaySerialRS485.ino +++ b/examples/GatewaySerialRS485/GatewaySerialRS485.ino @@ -32,8 +32,10 @@ * - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly * - ERR (red) - fast blink on error during transmission error or recieve crc error * - * The gateway uses AltSoftSerial to handle two serial links - * on one Arduino. Use the following pins for RS485 link + * If your Arduino board has additional serial ports + * you can use to connect the RS485 module. + * Otherwise, the gateway uses AltSoftSerial to handle two serial + * links on one Arduino. Use the following pins for RS485 link * * Board Transmit Receive PWM Unusable * ----- -------- ------- ------------ @@ -60,6 +62,9 @@ // Set RS485 baud rate to use #define MY_RS485_BAUD_RATE 9600 +// Enable this if RS485 is connected to a hardware serial port +//#define MY_RS485_HWSERIAL Serial1 + // Enable serial gateway #define MY_GATEWAY_SERIAL diff --git a/examples/MotionSensorRS485/MotionSensorRS485.ino b/examples/MotionSensorRS485/MotionSensorRS485.ino index 7af76d2..e034ab4 100644 --- a/examples/MotionSensorRS485/MotionSensorRS485.ino +++ b/examples/MotionSensorRS485/MotionSensorRS485.ino @@ -27,8 +27,10 @@ * Motion Sensor example using HC-SR501 * http://www.mysensors.org/build/motion * - * The transport uses AltSoftSerial to handle two serial links - * on one Arduino. Use the following pins for RS485 link + * If your Arduino board has additional serial ports + * you can use to connect the RS485 module. + * Otherwise, the transport uses AltSoftSerial to handle two serial + * links on one Arduino. Use the following pins for RS485 link * * Board Transmit Receive PWM Unusable * ----- -------- ------- ------------ @@ -43,6 +45,8 @@ * */ +// Enable debug prints to serial monitor +#define MY_DEBUG // Enable RS485 transport layer #define MY_RS485 @@ -53,6 +57,9 @@ // Set RS485 baud rate to use #define MY_RS485_BAUD_RATE 9600 +// Enable this if RS485 is connected to a hardware serial port +//#define MY_RS485_HWSERIAL Serial1 + #include unsigned long SLEEP_TIME = 120000; // Sleep time between reports (in milliseconds) diff --git a/keywords.txt b/keywords.txt index 1e4617b..6f31461 100644 --- a/keywords.txt +++ b/keywords.txt @@ -114,6 +114,7 @@ MY_W5100_SPI_EN LITERAL1 MY_RS485 LITERAL1 MY_RS485_BAUD_RATE LITERAL1 MY_RS485_MAX_MESSAGE_LENGTH LITERAL1 +MY_RS485_HWSERIAL LITERAL1 MY_INCLUSION_BUTTON_EXTERNAL_PULLUP LITERAL1 MY_W5100_SPI_EN LITERAL1 MY_MQTT_SUBSCRIBE_TOPIC_PREFIX LITERAL1