MichaelJonker / HardwareSerialRS485

Arduino Software for RS485 support with collision detection and message handling capabilities
MIT License
107 stars 29 forks source link

Simple usage #3

Closed ekarlso closed 8 years ago

ekarlso commented 8 years ago

Any examples on simple usage?

MichaelJonker commented 8 years ago

Hi, thanks for looking at this code. Yes there are examples. If you install this library under the Arduino IDE, these examples become available under the ide menu (file->examples->HardareSerial_RS485) The examples are further described in the project Wiki (https://github.com/MichaelJonker/HardwareSerialRS485/wiki)

The most complete example is RS485CommandResponse. At first sight it might seem not quite simple, but it is a demo sketch capable of demonstrating the multi-client/multi-server communication mode. Of course, to exploit this multi/multi mode you will need several arduino boards with a RS485 interface connected together as described on the Wiki pages.

However, with a minimum of configuration, it will run out of the box and can be used for a simple host to arduino RS485-based communication to start with. This is also described in the Wiki pages.

The demo sketch is also simple to adapt. In the RS485CommandResponse.ino file around line 388 you will see else if(canRemove(messageParser,"Echo:")) { myApplicationControl.startMessage(); thePrinter.print(messageParser); myApplicationControl.endMessage(); }

You can easily insert blocks of code like this one to add new commands.

It is not quite clear from your request what kind of examples of simple usage you would expect, but I hope that this is of some help. In order to help you further, maybe you can explain what kind of application you would like to implement. What hardware you have available, what you have tried out already, etc. Maybe we can come up with some more appropriate examples.

Regards Michael Jonker

JeroenVanHoye commented 3 years ago

Hi Michael,

I came across your code while i was searching for ways to create an MQTT serial RS485 to ethernet gateway. With multiple slaves able to publish messages, I need to be sure that messages are not interrupted. But i also find the example rather complex. Isn't there a way to narrow the main loop down to "RS485.Print(....)" and let the library take care of the retransmission if a collision is detected?

Looking forward hearing from you.

Kind regards, Jeroen

MichaelJonker commented 3 years ago

Beste Jeroen, (Ik vermoed dat je Nederlands spreekt, of Vlaams wellicht).

But for the sake of general interest, I will answer in English.

Thanks for your interest in my software library. Though it has been a while I worked with this software, I will try to answer you.

It is not clear what example code you looked at as there are two. The example RS485_USB (RS485_USB.ino) is probably the simplest and closest to your need. It is a bidirectional gateway between USB and RS458. There is some extra logic in there that you possibly do not need:

As far as the RS485 library is concerned: Reading from RS485 is shown in line 207 to 211. In this example, the bytes read from RS485 (object Serial1) are blindly forwarded to Serial (which is the USB port here). There is no message detection and filtering in here, and the process reading from the USB port will sees all RS485 traffic. Sending messages onto RS485, is shown in line 195 to 200. The sequence start with opening a transaction with startTransaction(), then building the message using one or more calls to print(), and then closing the transaction with endTransaction().

            Serial1.startTransaction( minimumBusIdleTime );
            Serial1.print( … );
            …
            Serial1.print( … );
            returnCode = Serial1.endTransaction();

The message is eligible to be output on the RS485 bus after the first call to print(). The library first checks whether there was any activity on the RS485 bus and it ensures that the bus was idle for a duration equal to time needed to send minimumBusIdleTime bytes. Hence for minimumBusIdleTime=0 the software will not wait and start sending immediately, in case it is 1, the software will make sure that the bus was idle for the duration to send one byte. (A technical detail: the software knows when the last byte was send even if this was prior to the print call, so it will not necessarily need to wait before it starts sending data).

If despite this collision avoidance mechanism there is still a collision, the software will take care of the message retransmission (after waiting for the predefined idle time). Important, to be able to detect collisions, the RS485 interface chip should allow to read while write, i.e. the software should be able to reads back what it is sending to ensures that it matches. Also important, message retransmission will only works transparently if the internal buffer of the Serial object is large enough (The internal buffer size can be parametrized through an instance parameter of the HarwareSerialRS485 template class, but I am getting into too much detail here).

If you build up your message with multiple calls to print, make sure that this is faster than the actual sending of the data over RS485, such that there will be no ‘blanks’ in the data transmission, which could be interpreted as bus idle. Also, if possible, limit your messages to sizes shorter than the internal buffer size.

Finally, EndTransaction() will waits for the full transmission to be completed. If needed (and while possible given length and internal buffer size) messages are transparently retransmitted in case of a collision. The EndTransaction() function also gives a return code to inform whether the message was correctly transmitted or not. If there was a collision and the message could not be retransmitted transparently, then the message can be retransmitted from the user code if desired. Not that the failure to transparently retransmit may only occur in case there are messages longer than the internal buffer size.

Hope this gives you some hints and better insight. If you need more info, let me know.

Doei, Michael