-1

I have only one pin available and I'd need to use it both for a digitalRead and for sending serial messages (assigning it the Tx role within a SoftwareSerial). I can alternate these two operations, but I don't seem to succeed. I could be interested in other pairs as well (digitalRead+Rx, digitalWrite+Tx and digitalWrite+Rx) and I hope that understanding one will solve them all, but for now I'd be happy to get the first one working. My first naive attempt would be something like:

 #include <SoftwareSerial.h>

SoftwareSerial swSerial(7,6);
int val;

void setup() {

  pinMode(6, INPUT_PULLUP);
  
}

void loop() {

  val = digitalRead(6);

  delay(2000);

  swSerial.begin(19200);
  swSerial.print("myData");
  swSerial.end();

  delay(2000);
  
}

But I've made other experiments, for example with a digitalWrite, hoping that combining two forms of output would be feasible, but again no way. I know I can alternate a pin role between output and input as long as common digital read/write operations are involved, but SoftwareSerial appears to be less flexible. It seems to me it refuses to work as soon as the pin is declared/used for common digital purposes. Is there a way to accomplish my goal?

I guess that similar requirements and fixes (make a pin role more flexible) led to the Software Serial with Half Duplex library, but I'd refrain from adopting it because I feel it is overcomplicated and seems like overkill for my purpose, moreover it doesn't seem actively supported.

To avoid a XY problem, my very initial need (I may have further ones, requiring the different pairs mentioned at the beginning) would be to check whether this pin is floating or connected to something (I can chose between Vcc or Gnd, setting up the pull-up or an external pull-down accordingly) and to send back some information (obviously this is useful if the pin is actually connected, but I have no reason not to send data anyway) alternating the tasks a few times per second at least.

lesath82
  • 101
  • 4
  • why do you have only one pin available? – jsotola Sep 06 '22 at 00:01
  • Check out my answer to your previous post of this question. – Gil Sep 06 '22 at 00:53
  • @jsotola it's an hardware-driven requirement – lesath82 Sep 06 '22 at 06:01
  • Before trying to write the software, invent the method how the external hardware can differentiate between both purposes. For example, if you want to read a digital value, the external hardware drives the wire. How do you control it to release the wire so that the Arduino can drive the wire? And, how do you control the hardware driven by TX that only during sending it shall read the value on the wire, and not during the time the Arduino reads the other device? Please [edit] your question and add this important information. – the busybee Sep 06 '22 at 06:06
  • @Gil What are you talking about? I'd guess there is a similar question I couldn't find when posting mine (it would be nice to have a link to it) and you assumed I asked twice hiding my identity, which is somewhat disrespectful (considering that I have a decent profile on other SE) – lesath82 Sep 06 '22 at 06:08
  • @thebusybee Suppose I have my pin with pull-up enabled. My idea is to have the external hardware to have a stronger pull-down, so that I can recognize it being attached finding my pin driven to LOW. Yet the external hardware stays ready to ready my data – lesath82 Sep 06 '22 at 06:12
  • OK. But this LOW would be interpreted as a start bit (and depending on the duration of the LOW and the used baud rate as additional data bits) on the TX line. How do you prevent this? – the busybee Sep 06 '22 at 06:37
  • If I did the opposite? My pin waiting on LOW, the external one driving it to HIGH, then I swap my pin to serial and start transmission Or maybe I could set SoftwareSerial to work with inverse_logic (I'm not sure if this means a low idle too) – lesath82 Sep 06 '22 at 06:44
  • From your comments it seems to me, that you only have one external hardware connected to the pin, but you want to first check for its presence before sending data to it. Is that correct, or do you have multiple different hardware connected to that pin? – chrisl Sep 06 '22 at 12:30
  • @chrisl Correct, only one external hardware! Arduino needs to know when this is connected, while it (when connected) needs to receive data from the Arduino. I have no problem sending data in any case (obviously it will be received only when there is connection) but Arduino needs to know when the external hardware is present. Checking if the information is correctly received wouldn't harm, but it's not necessary. – lesath82 Sep 06 '22 at 12:39
  • 1
    Is it hardware that you build/program yourself or hardware that will give an answer if you send it fitting data? Normally one would just use a simple handshaken meaning that your Arduino send a simple command and listens for the answer. If no answer is received there is nothing connected and you can try again later. Would that fit for you? – chrisl Sep 06 '22 at 12:48
  • Yes, definitely! It's even more than needed! I will probably have a chance to drive the choice of the external hardware, it may be another Arduino. That was the idea behind the Serial with Half Duplex possible solution. I may need to be able to repeat the same principle more than once (n pins, brought in separate locations, each one having the need to sense if ITS hardware is connected). And I'd feel more comfortable with a robust solution, not an almost experimental library that hardly I'd be able to debug... – lesath82 Sep 06 '22 at 13:01
  • I still don't understand why the question is downvoted... – lesath82 Sep 08 '22 at 15:07

1 Answers1

2

First of all, for using the Software Serial you need to set your tx and rx pins to OUTPUT, that what the library does under the hood.

What you may try to do is to set a millis timer (forget about delay(), never ever use it) and change pin mode to INPUT once every 200ms let's say. And after your measurements put it back to output as soon as you can.

200ms delay is normally ok for some readings like button click. If you can read the value more rare do it (for example you may read some sensor value only once per hour). Here is an example:

    #include <SoftwareSerial.h>

SoftwareSerial swSerial(7,6);
int val;

byte timer = 200; // Read value every 200ms
uint32_t prevTime = 0;

void setup() {

    // Don't change pin mode here
    swSerial.begin(19200);
  
}

void loop() {

    if (millis() - prevTime > timer) {
        // you could try swSerial.flush(); here...
        prevTime = millis(); // reset timer
        pinMode(6, INPUT_PULLUP); // changing pin mode and reading value
        val = digitalRead(6);
        pinMode(6, OUTPUT); // changing pin mode back
    }

    swSerial.print("myData");
    // swSerial.end(); // I don't think you need this line;

}

It may be a solution from a programming point of view. But another task is to organize an electric multiplexing for 2 different devices on the same pin as was mentioned by @the busybee

  • I'll try this straight away! – lesath82 Sep 06 '22 at 19:53
  • It works! Thank you! Let me ask you this: are you sure that tx AND rx need pins set to output? It seems to me that the setRX method (line 282 here: https://github.com/arduino/ArduinoCore-avr/blob/master/libraries/SoftwareSerial/src/SoftwareSerial.cpp) called by the constructor sets the rx pin as input, as one would guess. If I wanted to alternate digital read and swSerial read, cannot I leave the pin mode untouched? (apart from pull-ups). I didn't succeed at my first attempt, but I had only a few minutes left and I may have mistaken something else. – lesath82 Sep 07 '22 at 23:00
  • As I thought, I just had to debug the code, now it works also alternating digital and serial readings, no need to change the pin's destination: the rx pin has to be input. Thank you! – lesath82 Sep 08 '22 at 15:06
  • You're right, Rx (receiver) is INPUT, but Tx (tranceiver) is OUTPUT. You can leave th Rx pin untouched, and change only the mode of Tx pin. BUT!!! You need to be sure that the value you're reading is not from the Serial. You will need serial.flush, some timing or even maybe some physical solution on diods and transistors. It depends on your exact task and conditions. – GZstudio GZstudio Sep 08 '22 at 19:54