0

I'd like to know if it's possible, and if so how to use the serial Rx pin in a shared way to read a push button?

I've seen people using it in sort of a dedicated way but my idea is to use it dynamically. Which means it would stay as a standard Rx pin, with a push button sharing it. So the question is, what would happen if the push button was pressed? Would it be possible to detect it from the Rx stream?

  • Just to make sure: Are you have a X-Y problem maybe? (meta.stackexchange.com/questions/66377/what-is-the-xy-problem). If your basic problem is "I don't have enough I/O pins on my ESP8266 to add a push-button", then the actual answer would be "add more I/O pins by adding a GPIO port expander over I2C or SPI", not "whack it onto the UART RX line and see if I can detect it" – Maximilian Gerhardt Jan 17 '18 at 19:51
  • Just get a WeMos D1 mini or similar. You get access to all 11 GPIO pins (except the SDIO pins of course, those are reserved for the flash memory) and a USB interface for easy programming. They're like $3.50 from China, so there's really no reason to use the ESP-01 in the first place. – tttapa Jan 17 '18 at 22:50
3

I have experimented with my NodeMCU (ESP8266-12F, but the core chip is the same ESP8266EX).

First, the theory: UART is a asynchronous serial protocol. It has a configuration which consits of the baud rate (bits per second), parity bit (enabled or not) and number of stop bits (between 1-2). A common configuration is "9600N1", meaning 9600 bits per second, no parity bit, 1 stop bit.

If you want to trasmit the bitstring 0101 0101 with no parity, 1 stop bit, the RX line voltage will be:

uart1

RX line idles in high state (for us: 3.3V). Transmission is started by the start bit, which means that the line is pulled LOW. Then, the bits are transmitted LSB to MSB, followed by parity (if enable) and the stop bits.

I wrote the sketch

#include <Arduino.h>

void setup() {
    //use 300 Baud, lol
    Serial.begin(300);
}

void loop() {
    if(Serial.available()) {
        char readChar = (char) Serial.read();
        Serial.println("Read char: " + String(readChar) + " hex " + String((int)readChar, HEX));
    }
}

When transmitting a normal "A" (binary: 0100 0001) over serial, it looks like this in a logic analyzer:

uart_1

When I connected a pulled-up button the RX line and press, the signal goes as

uart2

As one can see, the analyzer sees the pushing down of the button as a start bit, but the timing is way of. The line is pulled back to high much later. The time slot for the stop bit (which must be 1) was missed, so the logic analyzer displays "FRAMING ERROR". But the UART circuit inside the ESP8266 doesn't seem to care. It reads this as the transmission of a byte of the value "0x00".

Serial output: Read char: hex 0

So, in response to the question "what would happen the push button was pressed?" we can say: At this speed of 300 baud (lowest possible setting), the UART received a bogus transmission but still reads it as an incomming 0x00 byte. However, depending on the bouncing of the signal due to the button presses, other received byte values might well be possible. You could be able to de-bounce the button to make the signal more stable, timing wise.

Anyway, you should not make a push button act as a crude UART transmitter if it isn't the absolute last possible solution. Depending on your application, you might be able to use the solution from this question and switch the function of the TXD0 and RXD0 to GPIO (more info). If you know exactly when to expect a button push, switch the pins to GPIO mode before and poll the status of the button (or install an interrupt).

However, as a bottom line: If you have no idea when the button will be pushed, then you will be fundamentally unable to distinguish the cause of the RX line falling low at the time the transition happens. It could be the transmission of some actual data (maybe also the zero-byte), but it could have also been the button.

A I²C GPIO port expander like the MCP23017 (link) would make much more sense, especially if you already have an I2C bus. There are also SPI devices available for this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.