[SORTED] Serial Half Duplex communication in 2 pins

Hi all! I want to ask you a question that I can't find the solution anywhere. For my proyect I need to communicate with two peripherals in serial half duplex. I found a library that configurate one of the digital pin of arduino to do this type of communication, but my problem is that I need to configurate two pins instead of one and this library let me configurate only one pin. If I call to the function twice, It configurate only the last pin that I configure.

Do anyone know how i can do this? I don't know if I have explained it good.

Thank you all

Post your code so we can see what you can see.

...R

This is the libray that I found:

#ifndef SoftwareSerialWithHalfDuplex_h
#define SoftwareSerialWithHalfDuplex_h

#include <inttypes.h>
#include <Stream.h>

/******************************************************************************
* Definitions
******************************************************************************/

#define _SS_MAX_RX_BUFF 64 // RX buffer size
#ifndef GCC_VERSION
#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#endif

class SoftwareSerialWithHalfDuplex : public Stream
{
private:
  // per object data
  uint8_t _receivePin;
  uint8_t _receiveBitMask;
  volatile uint8_t *_receivePortRegister;
  uint8_t _transmitPin;								//NS Added
  uint8_t _transmitBitMask;
  volatile uint8_t *_transmitPortRegister;
  
  uint16_t _rx_delay_centering;
  uint16_t _rx_delay_intrabit;
  uint16_t _rx_delay_stopbit;
  uint16_t _tx_delay;

  uint16_t _buffer_overflow:1;
  uint16_t _inverse_logic:1;
  uint16_t _full_duplex:1;							//NS Added

  // static data
  static char _receive_buffer[_SS_MAX_RX_BUFF]; 
  static volatile uint8_t _receive_buffer_tail;
  static volatile uint8_t _receive_buffer_head;
  static SoftwareSerialWithHalfDuplex *active_object;

  // private methods
  void recv();
  uint8_t rx_pin_read();
  void tx_pin_write(uint8_t pin_state);
  void setTX(uint8_t transmitPin);
  void setRX(uint8_t receivePin);

  // private static method for timing
  static inline void tunedDelay(uint16_t delay);

public:
  // public methods
  SoftwareSerialWithHalfDuplex(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic = false, bool full_duplex = true);
  ~SoftwareSerialWithHalfDuplex();
  void begin(long speed);
  bool listen();
  void end();
  bool isListening() { return this == active_object; }
  bool overflow() { bool ret = _buffer_overflow; _buffer_overflow = false; return ret; }
  int peek();

  virtual size_t write(uint8_t byte);
  virtual int read();
  virtual int available();
  virtual void flush();
  
  using Print::write;

  // public only for easy access by interrupt handlers
  static inline void handle_interrupt();
};

// Arduino 0012 workaround
#undef int
#undef char
#undef long
#undef byte
#undef float
#undef abs
#undef round

#endif

My code is this:

#include <SoftwareSerialWithHalfDuplex.h>
#define comPinMon 2
SoftwareSerialWithHalfDuplex puertoMon(comPinMon,comPinMon,false,false);

This code confugurate pin 2 to use in half duplex mode. I need to configurate two pins so try with this code:

#include <SoftwareSerialWithHalfDuplex.h>
#define comPinMon 2
#define comPinR 3
SoftwareSerialWithHalfDuplex puertoMon(comPinMon,comPinMon,false,false);
SoftwareSerialWithHalfDuplex puertoR(comPinR,comPinR,false,false);

But this code doesn’t work like I like becouse only configurate pin 3 to use in half duplex mode.
How can I do to cofigurate both pins?

thank you

The normal SoftwareSerial library can create two serial ports. It is however only possible to listen to one. Could you make the halfduplex at a higher level in the sketch ? Finish the communication and then switch to the other port. https://www.arduino.cc/en/Reference/SoftwareSerial

I confess I have forgotten exactly what half-duplex means. Is it that both Tx and Rx take place on the same wire by taking turns?

If so I suspect it would not be too difficult to modify my Yet Another Software Serial to do that.

How does the (current) receiver know when a Tx has finished and it can take its turn at replying.

...R

Yes, you are right with half-duplex. the transmitter send a message with the number of data bytes sent in its header, so when it send the message to the peripheral, it waits the peripheral reply. The peripheral knows when transmitter ends because it only read the number of data bytes that it read in the header.

You say that you want to communicate with two peripherals in half-duplex.

Can you control when those peripherals transmit so that you can be sure that only one of them transmits at any one time?

I think you would need to be able to do that to use SoftwareSerial.

My Yet Another Software Serial uses one of the External Interrupt pins and I reckon you should be able to make a second instance of it work with the other External interrupt.

You should be aware, however, that any approach to software serial uses up a lot of CPU cycles and is hard work for the Arduino.

What Arduino board are you using?

…R

As far as I know, there are still a TX and a RX wire in half duplex. In half duplex there however is no communication on both at the same time.

No, I can´t control when the preripherals transmit. Both peripherals are transmiting simultaneously. But if the Arduino take a little time to reply it doesn´t matter. Maybe if Arduino read through one of the pins and then read through the other one, it could work. But I need Arduino to do this operation fast becouse if peripherals don't receive any data in approximately 150ms , they block the transmission.

I'm ussing Arduino Uno

I have tried calling the half-duplex function to configurate both pins in the Loop function (when the first pin ends the code, it is called to configurate the second one) as a botched job but it seems that it doesn't work.

sterretje: No, in half-duplex there isn´t communication on both at the same time, but I have two different peripherals communicating with Arduino at the same time trough two diferent wires.

I think it will never work calling the half-duplex function in the Loop because when one pin is reading, the other one lose its messages.

I think other "solution" but I don't know if it is possible to implement with arduino, or if there is another better solution. The other "solution" is making diferent threads. When the Arduino receive a message, make a thread to reply this message and the main code still running.

is it possible to do this with Arduino like in C++?

I don´t know how to solve this problem with only one Arduino. Any proposal is welcomed.

alexmaralk: No, I can´t control when the preripherals transmit. Both peripherals are transmiting simultaneously. But if the Arduino take a little time to reply it doesn´t matter. Maybe if Arduino read through one of the pins and then read through the other one, it could work.

That won't work because while the Arduino is reading one pin data will be lost at the other pin.

You have not told us anything about the devices you want to communicate with. Links to their datasheets would be useful.

If it is the case that the device won't send anything until it has received a message from the Arduino you may be able to enforce flow control so that only one of them sends at one time - though you may lose one of the very first messages. Think of it this way

  • Suppose A and B send messages and you detect the message from A and then DON'T reply to A.
  • Instead you guess that B has also sent a message and you send a reply to B.
  • B will get that message and then will reply and you will receive the reply but do NOT respond.
  • At this point you reply to A (which hopefully has been waiting patiently) and when A gets the reply it will respond.
  • Then you reply to B
  • etc
  • etc

Of course this may fail gloriously if the devices use a timeout so that they don't wait forever for the Arduino to respond - and, to my mind, a timeout would be sensible.

AFAIK (but not tested) my Yet Another Software Serial should be capable of being duplicated to receive on two pins at the same time provided the baud rate is not too high.

...R

The devices I want to communicate with use ccTalk protocol. In this web you can found the specifications of this protocol: ccTalk Protocol . I'll try to do that you said to me. I hope I know how to do this haha. I'll write a post when I've tried to do this.

Thank you!

The link you posted seems to be about money machines. Please describe what your project is about - I don't wish to contribute to anything illegal or otherwise inappropriate.

The link you posted is just a bridge to a lot of other documents, Which is the relevant document to minimize my reading?

...R

Sorry, I think that with this document it's enough: ccTalk

alexmaralk: Sorry, I think that with this document it's enough: ccTalkccTalk

And what are you trying to make?

...R

Robin2: And what are you trying to make?

...R

I'm trying to replace two peripherics connected to a host. Arduino have to simulate like it was both peripherics.

ccTalk uses a bus; this means multiple devices connected on the same wire. Is your host using 2 wires for two peripherals (or 10 wires for 10 peripherals)? I doubt it but you need to tell us.

In case of multi-drop you can simulate both peripherals with one pin on the Arduino. As far as I understand the protocol, the host requests data from a slave. The slave responds with some data.

Exception will be a broadcast initiated by the host as all devices start replying; the Arduino can neatly do it correctly.

sterretje: ccTalk uses a bus; this means multiple devices connected on the same wire. Is your host using 2 wires for two peripherals (or 10 wires for 10 peripherals)? I doubt it but you need to tell us.

In case of multi-drop you can simulate both peripherals with one pin on the Arduino. As far as I understand the protocol, the host requests data from a slave. The slave responds with some data.

Exception will be a broadcast initiated by the host as all devices start replying; the Arduino can neatly do it correctly.

Yes, my host use 2 wires, one for one peripheral and the other one for 3 diferent peripherals but this isn't a problem, the problem is the 2 wires. Yes, in my case, Arduino is the differents slaves. Although I can connect all peripherals to the same wire, in my proyect I need to connect those in 2 different.

alexmaralk:
I’m trying to replace two peripherics connected to a host. Arduino have to simulate like it was both peripherics.

That sounds even more sinister - are you trying to trick some system so you can get money out of it. Tell us what the project is about.

…R

No, I'm not trying to trick anything. It's impossible to trick any system without open it, and if I have an opened system, what I'm going to trick? It's only for testing system without those peripherals