Half-Duplex uart over single gpio pin - problems....

smartinick
Posts: 1
Joined: Sun Nov 04, 2018 9:30 am

Half-Duplex uart over single gpio pin - problems....

Postby smartinick » Sun Nov 04, 2018 10:04 am

Hi community!

i have connected uart2 of my esp32 to a device running a "uart-bus" over just one wire.
programming in Arduino/PlattformIO i've used uart2 via Hardwareserial which uses esp32-hal-uart from arduino-esp32 sdk.

using two gpio pins (apparently one for rx, one for tx... :D) works fine, as long as 2 external parts are used (a diode and a resistor between rx & tx). i can read packets from the bus, send packets and get responses from the other devices on the bus. this solution works stable since some months.

the bus has one "master" device that sends packets on a regular basis and between those packets other devices can send data. so the esp32 can send data in that silence-period of the master, it can send data to slaves and get's responses from those devices as well.

so the uart/bus is half duplex - listen (most) of the time and when a special formed packet from the master was received esp32 can send it's own packet to the bus.

now i tried to use only one gpio pin for rx and tx, as i've looked into the esp32-hal-uart i saw there's attach/detach-rx/tx methods.
so the 1st try was to make 2 functions, one for switch to rx-mode, the other to switch to tx-mode.

i've #defined a serialgpio pin and 2 other "spare" rx & tx pins.
the serialgpio is connected to the bus, the spare pins are unconnected.

now if i use

Code: Select all

HardwareSerial myser(2);
myser.begin(115200, SERIAL_8N1, serialgpio, sparetxgpio);
to init the uart2, i can receive/read data from the bus.

when switching from rx to tx, i've tested to versions, both not working:
version 1:

Code: Select all

myser.end();
myser.begin(115200, SERIAL_8N1, sparerxgpio, uartgpio);
then i send some stuffusing myser.write
and after issuing the myser.write, i call the method to switch from tx to rx mode, which is:

Code: Select all

myser.flush(); //<- i suppose this waits until the queued data in tx-buffer is sent?
myser.end();
myser.begin(115200, SERIAL_8N1, serialgpio, sparetxgpio);
but this does not work, logic analyser on the bus shows now data from esp32.
next step was to add a "waitTX" method to hardwareserial & esp32-hal-uart that is a stripped-down copy of the flush method:

Code: Select all

void uartWaitTX(uart_t* uart) {
    if(uart == NULL) {        return;    }
    UART_MUTEX_LOCK();
    while(uart->dev->status.txfifo_cnt);
    UART_MUTEX_UNLOCK();
}
then i called .waittx instead of .flush, no change, nothing sent.

the only idea i have for that version 1 is that the flush/waittx do not wait until the fifo is empty, immediately return and therefore i switch to rx-mode to early. (and logic-analyzer shows that nothing is sent on sparetx pin as well, but myser.end/begin will clear the buffers at some point.

Version 2 was to skip all the overhead of myser.end/begin and just remap the pins using the switchmatrix:
(excuse the small differences in naming to above code, i typed the above as pseudo code but not i copied the methods ;) )

Code: Select all

void switch2RX() {
  //wait until send is done
    MySerial.waitTX(); //no difference if i use flush here...
  //detach TX from SerialGPIO and attach it to SerialSpareTX
      pinMatrixOutDetach(UART_TXD_IDX(UARTINDEX), false, false);
      pinMode(SerialSpareTX, OUTPUT);
      pinMatrixOutAttach(SerialSpareTX, UART_TXD_IDX(UARTINDEX), false, false);
  //detach RX from SerialSpareRX and attach it to SerialGPIO
    pinMatrixInDetach(UART_RXD_IDX(UARTINDEX), false, false);
      pinMode(SerialGPIO, INPUT);
      pinMatrixInAttach(SerialGPIO, UART_RXD_IDX(UARTINDEX), false);
  }

  void switch2TX() {
    MySerial.flush(); //added this for testing, but makes no difference with or without it (or with waittx instead)
  //detach RX from SerialGPIO and attach it to SerialSpareRX
      pinMatrixInDetach(UART_RXD_IDX(UARTINDEX), false, false);
      pinMode(SerialSpareRX, INPUT);
      pinMatrixInAttach(SerialSpareRX, UART_RXD_IDX(UARTINDEX), false); 
  //detach TX from SerialSpareTX and attach it to SerialGPIO
      pinMatrixOutDetach(UART_TXD_IDX(UARTINDEX), false, false);
      pinMode(SerialGPIO, OUTPUT);
      pinMatrixOutAttach(SerialGPIO, UART_TXD_IDX(UARTINDEX), false, false);
  }
i've put those 2 methods together from attach7detach rx/tx functions in esp32-hal-uart

now that code actually also sends data - but on the sparetx pin, not on the serialgpio.
and it off course receive-part works on the serialgpio.

so for this version 2, the changes i make via the switch-matrix do not work... :(

i've read a lot in the issues on github for arduino-esp32 with keyword uart, there have been quite some bugs, but they all seem fixed and checking it with my arduino-esp32 copy i already use the latest version.
from those issues i've also tested some ideas they had during fixing the issues, but it did not help me with my problem...

and now i'm running out of ideas....

So... i'm happy for any link, hint or idea how to solve that.
in the end this project should make it onto a really small pcb, so if i can save some externel parts/gpios/traces this would really help... :D

Thanks & Best Regards, Martin.

Hu-Hu.
Posts: 1
Joined: Mon Nov 18, 2019 1:51 pm

Re: Half-Duplex uart over single gpio pin - problems....

Postby Hu-Hu. » Mon Nov 18, 2019 1:56 pm

more than one year has passed, NO solution at all??? :(

zliudr
Posts: 357
Joined: Thu Oct 03, 2019 5:15 am

Re: Half-Duplex uart over single gpio pin - problems....

Postby zliudr » Tue Nov 19, 2019 7:46 pm

I wonder if OP has tried to use esp-idf directly instead of the arduino esp32. I don't have what OP has to test with esp-idf.

michcfr
Posts: 30
Joined: Mon Jan 29, 2018 5:55 pm

Re: Half-Duplex uart over single gpio pin - problems....

Postby michcfr » Sat Oct 23, 2021 9:51 pm

Hello,
Any solution?

Who is online

Users browsing this forum: No registered users and 117 guests