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

Multidrop / Master+Slaves on RS485 or similar #26

Open
hippyau opened this issue Nov 15, 2021 · 17 comments
Open

Multidrop / Master+Slaves on RS485 or similar #26

hippyau opened this issue Nov 15, 2021 · 17 comments

Comments

@hippyau
Copy link

hippyau commented Nov 15, 2021

Is there any possibility of using this between 2 or more nodes in a small network, with simple addressing? Or any suggestions of a protocol that is light and can support more than 2 nodes?

@lexus2k
Copy link
Owner

lexus2k commented Nov 18, 2021

Hi,

Unfortunately, the full duplex version (tiny_fd) doesn't work out of the box with the RS485 physical channel, since RS485 is the half-duplex interface. Tinyproto implements only the ABM part of the HDLC protocol that can be used only with P2P connections. For your case NBM or ARM parts of HDLC must be implemented.

However, you can still write communication using tinyproto's hdlc_ll functions. The low level will provide you error checking and framing.

@michcfr
Copy link

michcfr commented Nov 21, 2021

Hello,
I got the same kind of question but with classical UART like in the figure below:
http://www.sampson-jeff.com/article/interface/as-mdd.gif
Can I address 1 master and multiple slaves?
thx

@lexus2k
Copy link
Owner

lexus2k commented Nov 22, 2021

Hi @michcfr ,

According to your picture there are 2 diodes blocking TX line for 2 slave devices. ABM mode is the mode that requires confirmation, so any node in the network must have the ability both to read and send data asynchronously. Your scheme doesn't allow that, thus tiny_fd cannot be used in your case.
So the best way with the current HDLC and hardware implementation is to use hdlc_ll API and to interpret the first byte of the buffer being sent at application protocol as an address field. On the slave devices, upon receiving the whole frame, you need just to check the first byte of the buffer to understand if the data are designated for a specific slave station.

изображение

PS. HDLC NBM and ARM modes have address fields, however in many HDLC implementations the field is not used and usually initialized to either 0xFF or 0x01/0x03. The tinyproto library initializes that field to 0xFF all the time.

@michcfr
Copy link

michcfr commented Nov 22, 2021

Hello Aleksei,
Thank you for your response.

The diodes are not blocking the TX line for the 2 slave devices. Diode exists just for electrical protection reasons only.
UART uses negative logic. So, if the Tx output is high the diode is reverse biased: it blocks. If Tx output is low the diode is forward biased: it is conducting. Consequently, any node have the ability to read and send data asynchronously. So I think tiny_fd can be used.

In the case of tiny_fd, can you please show me in the source code where I can get the address fields? I suppose this is also a fixed value of 0xFF?

@hippyau
Copy link
Author

hippyau commented Nov 22, 2021

The diodes are not blocking the TX line for the 2 slave devices. Diode exists just for electrical protection reasons only.

This is my understanding also.

In the case of tiny_fd, can you please show me in the source code where I can get the address fields? I suppose this is also a fixed value of 0xFF?

tiny_fd_int.h line 51: ​        ​uint8_t​ address;

I'd like to have simple arrangement and coordinate where the master polls the slave, and only the addressed slave responds.

@michcfr
Copy link

michcfr commented Nov 22, 2021

ok I see.
I have to do some test to see how it fits together.
For information, I plan to connect together many ESP32 throught the UART with a multi-master architecture: no master ESP32, so that any ESP32 can communicate with each other. I think this is ABM mode?
Can I add an extra field to put the source address, knowing that HDLC include only the destination address?
Another question: do you have any plan to adapt your software to Arduino ?

@lexus2k
Copy link
Owner

lexus2k commented Nov 24, 2021

Hi

The diodes are not blocking the TX line for the 2 slave devices

Oh, my bad. I was confused with the diagram.  Some of the hardware manufactures require pull-up resistors for the Tx-Rx line.  Absolutely agree with you

In the case of tiny_fd, can you please show me in the source code where I can get the address fields? I suppose this is also a fixed value of 0xFF?

You can check the file tiny_fd.c. Look for .address text.

I'd like to have a simple arrangement and coordinate where the master polls the slave, and only the addressed slave responds.

Good point, but that requires a different HDLC mode - not ABM, maybe NRM.

For information, I plan to connect together many ESP32 throught the UART with a multi-master architecture: no master ESP32, so that any ESP32 can communicate with each other. I think this is ABM mode?

ABM mode is usually invoked with async modes, when each station can send at any time, and there are no master and slave devices. Current implementation of the ABM HDLC mode can be used only in P2P connections. The user data is transferred in I-Frames, which need confirmation from the receiver, and there is only a single N(s) N(r) table in the current tinyproto implementation. For your case, the master needs separate N(s) N(r) tables and different frame pools for each slave station.
I'm thinking of P2M support, but I have no solution right now for you. I'm sorry.

Can I add an extra field to put the source address, knowing that HDLC includes only the destination address?

The address field in the HDLC is exactly for the same purpose - it should contain a slave address, whenever the master sends to and receives from the packet.

Another question: do you have any plans to adapt your software to Arduino ?

Is this question for me? The library can be used in Arduino IDE as is.

@michcfr
Copy link

michcfr commented Nov 24, 2021

Hello Aleksei,
About the diodes
=> don't worry, I was confused too at first time :-)

I'd like to have a simple arrangement....
=> It was not my question, but your response is interesting

ABM mode is usually invoked with async mode....
=> yes I need P2M support where each node needs separate N(s) N(r) tables and different frame pools. Can you please indicate part of the code that need to be changed?

thx

@lexus2k
Copy link
Owner

lexus2k commented Nov 25, 2021

Can you please indicate part of the code that need to be changed?

That's not so easy to update that code to work with multiple stations. I mean tiny_fd.c

@lexus2k
Copy link
Owner

lexus2k commented Nov 25, 2021

Here are the steps, which are required to reach the goal.

  1. Implement frame queue to keep as much frames on the master as required to support all slave.

For example, if you have window size (maximum number of unconfirmed frames) for each slave station equal to 4, then the master device must be able to keep 4 * N unconfirmed framed. If we're talking about the picture, then 4 * 2 = 8.
I'm working on this, and do not have ready solution yet.

This step also requires on the master side to have next_ns, confirm_ns, nr, last_ns counters for each slave station.
And I'm working on this.

  1. Make the master to be able address each slave separately

This step required API change, because you need somehow to inform the protocol that specific data is for specific slave station only. There are 3 ways to implement that:

  • Change current API (I don't like that, because it breaks the applications already using the tinyproto)
  • Add additional API, something like tiny_fd_set_slave_address(handle, address) (I don't like that also, because such API can be a headache in multi-threaded applications)
  • Add new API, something like int tiny_fd_send_packet(tiny_fd_handle_t handle, uint8_t address, const void *buf, int len);
  1. Make the slave devices to understand, if the received frame addressed to specific section

Actually this can be easily implemented, for example, by adding the address field to initialization data for tinyproto.

  1. Update the tinyproto implementation to use P/F HDLC bit correctly in NRM mode.

In current implementation P/F bit is always set to 0 for I-Frames, and is always set to 1 for S and U-Frames. Because the protocol actually fully asynchronous, i.e. each station can transmit at any time it wants. But that plays a bad role in your case, because of the collisions, when 2 slave devices want to send data at the same time.
So to solve this problem, the protocol should be significantly updated to use something like markers, and with specific timeouts, if some device doesn't respond.

@lexus2k
Copy link
Owner

lexus2k commented Dec 9, 2021

@michcfr

Let me know how it goes.

@lexus2k
Copy link
Owner

lexus2k commented Jan 21, 2022

Things to do to implement multiple devices support on a single serial interface:

  • Add API to tiny_fd with support for device address
  • Add callbacks to pass device address, that sent the frame
  • Add memory allocation for each slave peer station
  • Add special marker to pass it between peers to allow transmissions. (P/F bit can be used)

@lexus2k
Copy link
Owner

lexus2k commented Feb 5, 2022

Things to do to implement multiple devices support on a single serial interface:

  • Add API to tiny_fd with support for device address
  • Add callbacks to pass device address, which has sent the frame
  • Add special marker to pass it between peers to allow transmissions. (P/F bit can be used) (In progress)

@lexus2k
Copy link
Owner

lexus2k commented Feb 6, 2022

Things to do to implement multiple devices support on a single serial interface:

  • Add API to tiny_fd with support for device address
  • Add callbacks to pass device address, which has sent the frame

@lexus2k
Copy link
Owner

lexus2k commented Feb 7, 2022

Let me know if you want Multidrop feature to be implemented.

@hippyau
Copy link
Author

hippyau commented Feb 7, 2022 via email

@lexus2k
Copy link
Owner

lexus2k commented Feb 13, 2022

Basic implementation on NRM protocol (Multidrop support) is ready. There are new API's to use for NRM.

First of all tiny_fd_init() has new fields in init structure: on_read_cb, on_send_cb, peers_count, address, mode.

  • address must be set to TINY_FD_PRIMARY_ADDR for primary station and between 1 and 63 for secondary stations
  • mode must be set to TINY_FD_MODE_NRM for multidrop support.
  • peers_count must be 0 for secondary stations, and 2 for primary station in your case
  • on_read_cb is the same callback as on_frame_cb except it provides address of the peer that sent the frame
  • on_send_cb is the same callback as on_sent_cb except it provides address of the peer the frame is sent to
    Don't forget to allocate enough buffer size for the FD protocol

tiny_fd_register_peer must be used before sending something to remote client peers. This API tell the protocol the address of secondary station to talk to. Please, not that all registered secondary stations must be up to have primary station properly working.

Next new APIs tiny_fd_send_packet_to and tiny_fd_send_to accept also address of the peer station to send frame to.

Some old API's have changed, let me know if there are some issues with them.
The protocol is not tested completely, there are only a couple of unit tests for NRM mode right now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants