# On Raspberry PI, how do I pull down a GPIO pin and then read it immediately after?

My application is reading the wind speed and direction from a TX23U sensor. These are not designed to be interfaced with the PI, but with a proprietary weather station. However, someone figured out the communication protocol which can be found here.

The site describes the TX connection should be tied to high, and pulled low to signal the sensor to begin transmitting.

How though, could I pull the TX connection low and then read the data the sensor outputs through that same pin right after?

From what I understand, a GPIO pin's input/output function must be specified first. Is there a way to switch the functionality of the pin from output to input? Or is there another way of using two pins to perform this function which I am not seeing?

## migrated from electronics.stackexchange.comMar 24 '18 at 4:53

This question came from our site for electronics and electrical engineering professionals, students, and enthusiasts.

• Yes, by signaling it to change in code. The pins mode is not fixed per reboot, you can change it any time multiple times. – cde Mar 24 '18 at 5:16
• @cde There is some code available at github.com/ToninoTarsi/swpi/tree/master/TX23 . In the first file, RPi_TX23.c, I see "TX23_DATA_SET_OUTPUT_LOW;" and "TX23_DATA_SET_INPUT;" but these are not functions are they? What are they referring to? Where can I find the code these lines actually execute? – A.S. Mar 24 '18 at 5:27
• Somewhere in that git repo/ library. Those functions will call some lower level standard rpi functions to change the pin status. – cde Mar 24 '18 at 5:33
• I was able to find it, missed it the first two times. Ctrl+F works miracles... #define TX23_DATA_SET_OUTPUT_LOW bcm2835_gpio_write(RPI_GPIO_TX23_DATA, LOW);\ bcm2835_gpio_fsel(RPI_GPIO_TX23_DATA, BCM2835_GPIO_FSEL_OUTP) #define TX23_DATA_SET_INPUT bcm2835_gpio_fsel(RPI_GPIO_TX23_DATA, BCM2835_GPIO_FSEL_INPT);\ bcm2835_gpio_set_pud(RPI_GPIO_TX23_DATA, BCM2835_GPIO_PUD_OFF) – A.S. Mar 24 '18 at 5:40
• If you found a solution, then write your own answer, for benefits of all. In areadable format. I still can't see how current libraries can possibly handle bi-directional (with usual high-Z state) general-purpose I/O (input-output BTW). – Ale..chenski Mar 24 '18 at 6:00

Below is a schematic of the RPi GPIO circuit. As you can see, the input buffer is always reading the external state of the pin, so if you want to read the pin, as that shoe company likes to say, just do it.

All of the GPIO libraries such as pigpio(my personal favorite) and WiringPi have library functions to set the pin direction. If the GPIO data output register is set to 0 and you set the GPIO as an output, it will drive a 0 on the pin. Set it back to an input, and the resistor will pull the pin back up. In pigpio you use the set_mode function to set the I/O direction.

Looking at the protocol, after you pulse the pin low and it is pulled high, the TX23U pulls the pin low and then eventually sends a start of frame pattern followed by the data. There is a pigpio application called piscope that records the state of a GPIO pin that you could probably adapt to record the sensor data stream. It has the ability to trigger on edges in the data stream before starting to record. It can store the data in a file.

• Still unclear how to manage so-called "bi-directional" function, which OP needs. There must be some sort of "output enable" register (or bit) in addition to actual data to out put. Where is it? – Ale..chenski Mar 24 '18 at 5:36
• This is useful info. In order to read the sensor output signal correctly (getting the right low/high) does the GPIO pin need to be set as an input? Or can I maintain the pin set as an output, and just read the pin and still expect to read the correct value from the sensor? – A.S. Mar 24 '18 at 5:37
• If you leave it as an output, you will read the state that you are driving from the PI. Once you turn off the driver by setting it as an input, the sensor can then drive the pin and you can read your data. Use the abyz.me.uk/rpi/pigpio/python.html#set_mode to set the pin direction. – crj11 Mar 24 '18 at 5:40

Using python on the PI this is petty easy. I didn't test this code but check out this page as a reference https://sourceforge.net/p/raspberry-gpio-python/wiki/BasicUsage/

import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BOARD) # sets numbering system of GPIO pins
channel = MY_BOARD_PIN_ID

GPIO.setup(channel, GPIO.OUT, initial=GPIO.HIGH) # output high

# wait for a few ms

GPIO.output(channel, GPIO.LOW) # output low

# maybe wait for a few ms

GPIO.setup(channel, GPIO.IN) # change to input

# then some code where you read the input as many times as needed:
value = GPIO.input(channel)

# lastly
GPIO.cleanup()


All of the Pi GPIO libraries will be able to handle the basic signalling. In fact the signalling required is very similar to the popular DHT11/22 series of temperature and humidity sensors.

With the DHT11/22 there is a single data line. The data line is normally held high by a 5K pull-up resistor to Vcc (3V3 for the Pi). To request a reading the Pi pulls the data line low for a brief period (sets the GPIO mode to OUTPUT and writes 0) and then sets the GPIO to be an INPUT. The DHT11/22 then writes 0s and 1s to the data line to signal the 40 data bits which the Pi reads via the GPIO.

Any library which can handle the DHT11/DHT22 could be amended to handle the TX23U.

My pigpio library is well suited to this sort of application as it can accurately time GPIO inputs.

This looks similar to the 1-wire interface (although the protocol is different). You might find some of the programs to read these similar.

You can program a pin as output, then program as input within 20mSec - this is a lifetime for the Pi processor.