Marcelo Schmitt

Connecting PC and Raspberry Pi through a USB port

This post should serve as a guide to configure Raspbian in order to obtain an interactive terminal capable of executing commands on a Raspberry Pi that is connected to the computer through a USB port.

Warning: This is an old post with potentially outdated information. Read with caution.

We will explore two ways to connect a PC to a Raspberry Pi:

The first one is to connect PC and Raspberry Pi Zero through a micro-USB cable, configure Raspian to treat this connection as an ethernet connection and finally use SSH.

The second way is to use a USB-UART converter, configure Raspian to transmit a console through the GPIO pins of serial communication, and finally use GNU/screen to connect to the tty port associated with the board.

This guide was developed by performing tests with Raspberry Pi Zero and Raspberry Pi 3B along with Raspbian Stretch. The computer operating system I used was Debian 10 Buster.

Connection method 1 - Using a USB cable

For this connection, you only need a micro-USB cable to connect a USB port from the computer to a USB port on the Raspberry.

On your computer, mount the file system of the microSD card on which you installed Raspbian. Go to the root of the boot partition of the mounted file system. There are three things to do there:

  1. At the end of the config.txt file, insert a new line containing dtoverlay=dwc2.
    echo dtoverlay=dwc2 >> config.txt
    
  2. Open the cmdline.txt file. Be careful that the parameters in this file are single-spaced (ie, line breaks are not used). Insert modules-load=dwc2,g_ether after rootwait. If you wish to enable both ethernet and serial connections on the Raspberry, change g_ether to g_cdc.
  3. Create an empty file called ssh with no extension.
    > ssh
    

Go to the root of the rootfs partition of the SD and add static IP settings for the USB network interface.

echo -e "allow-hotplug usb0 \niface usb0 inet static \naddress=192.168.10.254 \nnetmask 255.255.255.0" | sudo tee -a /etc/network/interfaces

The end of the file should look like this:

allow-hotplug usb0
iface usb0 inet static
        address 192.168.10.254
        netmask 255.255.255.0

Once these steps are complete, the file system can be unmounted and the microSD card is ready to be inserted into the Raspberry Pi. The next Raspbian boot process may take a little longer after the changes are made (up to 90 seconds).

Before connecting the Raspberry Pi to the computer, let’s first list the available network interfaces. This will help us identify which network interface the Pi will be associated with.

sudo ifconfig
List of network interfaces shown by `ifconfig`.
Figure 1. List of network interfaces shown by ifconfig.

We can see that there are three available network interfaces: enp2s0f0, lo, wlp3s0.

Connect the Raspberry Pi to the computer using a USB cable.

Raspberry Pi and PC connected with a micro-USB cable.
Figure 2. Raspberry Pi and PC connected with a micro-USB cable.

Note that for the Raspberry Pi Zero it is advantageous to use the micro USB port that has “USB” written next to it. By connecting to this port it is possible to power and transmit data to the Raspberry Pi simultaneously.

Ensuring PC and Raspberry Pi are on the same network

Now we must make sure that our computer and Raspberry are on the same network. For this we will list the network interfaces again.

ifconfig
List of network interfaces shown by `ifconfig` after connecting the
   Raspberry Pi.
Figure 3. List of network interfaces shown by ifconfig after connecting the Raspberry Pi.

Now that the Raspberry Pi is connected you can see that one more network interface has been created, enp0s29u1u1i1. We can see that it is active (UP) and that the IP associated with the computer on this interface is 192.168.10.200 (inet 192.168.10.200). This is the desirable state in which PC and Raspberry Pi are on the same network. If the IP address is not on the same network (192.168.10) or if no value is displayed for inet, it will be necessary to configure the new network interface to assign a new IP address to the PC. In Debian Buster this can be done in at least two ways:

By editing the network interface settings under ‘Network Connections’.

Editing network configurations through NetworkManager GUI.
Figure 4. Editing network configurations through NetworkManager GUI.

It is important to set the IP addressing method to manual and assign an IP address to the computer that belongs to the same network that you defined in the /etc/network/interfaces file of the Raspbian file system. In this post I defined that the Pi would belong to the network address 192.168.10 (Class C IP address) so the IP address of the computer must start with 192.168.10 and its ID must be a number between 0 and 255. For this example, I chose the machine address within the network to be 200.

Another way to configure the network interface is by manually editing the file /etc/NetworkManager/system-connections/<interface>.nmconnection.

sudo vim /etc/NetworkManager/system-connections/<interface>.nmconnection

I leave here an image with the content of my network interface configuration file for connecting to Raspberry. Note that the connection id “USB-pi”, the defined IP address, and the addressing method appear.

Changing network configurations through a config file.
Figure 5. Changing network configurations through a config file.

If the network interface doesn’t appear with ifconfig or if you are not sure about the configuration associated with the network interface, you can try to get some information with dmesg.

sudo dmesg | grep cdc

Connecting with SSH

Having configured the Raspbian and linux network interfaces running on the PC, it should be possible to connect to the Raspberry Pi using ssh. The more traditional way of doing this is using the IP address of the device and the user to connect with.

ssh <user>@<IP address>

For example:

ssh pi@192.168.10.254

If you have avahi-daemon installed you can also connect by entering the hostname of your Raspberry Pi. For example:

ssh pi@raspberrypi.local

Connection method 2 - Using a USB-UART Converter

For this connection you will need some female-female jumpers (wires) and a USB-UART converter capable of operating at TTL 3.3V (I will discuss more details later). As some of the settings are the same for USB-ethernet and serial-UART connection cases, I could just point out some of the steps above but I’ll rewrite them here for convenience and organization.

On your computer, mount the file system of the microSD card on which you installed Raspbian. Navigate to the root of the boot partition of the mounted file system. There are three things to do here:

  1. At the end of the config.txt file, insert a new line containing dtoverlay=dwc2.
    echo dtoverlay=dwc2 >> config.txt
    

    Also make sure there is a line containing enable_uart=1 in that file. If it does not exist or has the value 0, set it to 1.

  2. Open the cmdline.txt file. Be careful that the parameters in this file are single-spaced (ie, line breaks are not used). Insert modules-load=dwc2,g_serial after rootwait. If you wish to enable both ethernet and serial connections on the Raspberry, change g_serial to g_cdc.

Once these steps are complete, the file system can be unmounted and the microSD card is ready to be inserted into the Raspberry Pi. The next Raspbian boot process may take a little longer after the changes are made (up to 90 seconds).

Just to make the final settings you will need to connect a keyboard and monitor to the Raspberry Pi to execute some commands.

Turn on the Raspberry Pi and log in with your username.

  1. Enable the Raspberry Pi to provide an interactive console over serial by editing the settings with raspi-config.
    sudo raspi-config
    

    Go to Interfacing Options.

raspi-config tool main screen.
Figure 6. raspi-config tool main screen.

Select Serial and choose “Yes” to enable console over serial.

raspi-config interfacing options.
Figure 7. raspi-config interfacing options.
  1. To use the standard serial module, you must also tell the Raspberry Pi to pass the serial console to it.
    sudo systemctl enable getty@ttyAMA0.service
    

Physical Connection

Since the serial communication GPIO pins on the Raspberry Pi operate at a TTL logic level of 3.3V, using a USB-UART or USB-TTL converter whose voltages on the RX and TX pins are greater than 3.3V can damage the Raspberry Pi’s UART controller! So make sure your converter works at TTL 3.3V by reading the datasheet or using a multimeter (the voltage between the GND and RX/TX pins must not exceed 3.6V).

In my experiment I used a USB-UART converter with a WCH CH340G IC that has a jumper allowing to select which logic level the RX and TX pins should operate.

A USB-UART converter.
Figure 8. A USB-UART converter.

In this module, shorting the VCC and 3V3 pins ensures that the TTL logic level 1 will be 3.3V.

Note: Short circuiting the VCC and 5V pins will make the module use TTL 5V which is used to communicate with various Arduino models. This is especially useful for programming some Arduino Pro-Mini models.

The GND, RX, TX pins of the USB-UART converter must be connected with the GND, TX, RX pins of the Raspberry Pi respectively. The physical setup will look like this:

Raspberry Pi and PC connected with a USB-UART converter.
Figure 9. Raspberry Pi and PC connected with a USB-UART converter.

Accessing the shell

After connecting PC and Raspberry you can run lsusb command on your computer to check if a new USB device is recognized by the system.

`lsusb` command shows the USB-serial adapter pluged in.
Figure 10. lsusb command shows the USB-serial adapter pluged in.

Right on the first line we can see that a USB-Serial adapter has been identified.

Use dmesg to quickly find out which tty port your Raspberry Pi is associated with.

sudo dmesg | grep tty
`dmesg` shows the tty associated with the serial adapter.
Figure 11. dmesg shows the tty associated with the serial adapter.

In my case, it is on the ttyUSB0 port.

To get a terminal with a shell from the tty file we can use GNU/screen. You can get it from the website or from the apt package manager.

sudo apt install screen

With screen installed, just start it informing the file that should be used.

screen <arquivo tty> [baud rate]

For example:

screen /dev/ttyUSB0

If you’re denied access to serial devices, try add your user to the dialout group with sudo usermod -aG dialout $USER. Reboot the computer for this change to take effect.

You will see the screen start a new session where the version of Raspbian running on the Raspberry Pi will appear, the tty file created in it to support serial communication, and a login prompt. If you get no shell within a few seconds, try pressing enter a few times and GNU/scree will guess the correct baud rate.

Connected to the Raspberry Pi with screen.
Figure 12. Connected to the Raspberry Pi with screen.

You may also look for the actual baud rate in the cmdline.txt file and pass it to screen:

screen /dev/ttyUSB0 115200

You are now logged into a shell on Raspberry and can run any command from there.

To exit the screen press Ctrl-a \ (Ctrl + a followed by \).

Is there a way to use a male-to-male USB cable?

I tried to make the connection using a male-to-male USB cable connecting a USB port on the computer to another USB port on the Raspberry Pi 3. According to the literature, the USB ports on the Raspberry Pi 3 are OTG (On-The-Go) host and, it seems that a USB device operating in host mode can only communicate with USB devices operating in device mode and vice versa. The reason for this would be because the host device is responsible for initiating all communications while the peripheral device only responds to requests from the host. As the USB ports of computers normally operate as a host, it is conceivable that both ports try to initiate some communication but neither of them waits to be notified asynchronously to respond to a request.

Maybe it would be possible to work around this situation using a USBNET cable (eg https://www.amazon.com/Belkin-Transfer-Cable-Windows-F4U060/dp/B0093HCIQ0 ), but I didn’t want to invest time and money in this.

References

Next, I list a series of pages I looked at when writing this post. They may be useful for troubleshooting.

Description of available connection modules available for Raspbian

https://gist.github.com/gbaman/50b6cca61dd1c3f88f41

USB-ethernet connection

https://www.thepolyglotdeveloper.com/2016/06/connect-raspberry-pi-zero-usb-cable-ssh/

https://gist.github.com/gbaman/975e2db164b3ca2b51ae11e45e8fd40a

https://www.youtube.com/watch?v=MJ084wtjiWM

Network Interface Settings in Debian

https://wiki.debian.org/NetworkConfiguration

Debug USB OTG g_serial gadget

https://raspberrypi.stackexchange.com/questions/67907/debugging-usb-otg-serial-on-the-pi-zero-w

https://github.com/raspberrypi/linux/pull/1239

GPIO-UART connection

http://www.embeddedforu.com/embedded-linux/how-to-connect-raspberry-pi-uart-to-a-computer/

https://www.raspberrypi.org/documentation/configuration/uart.md

https://www.instructables.com/id/Read-and-write-from-serial-port-with-Raspberry-Pi/

https://elinux.org/RPi_Serial_Connection

Raspberry Pi pinout scheme

https://www.raspberrypi.org/documentation/usage/gpio/README.md

https://pinout.xyz/#

Connecting to a serial port with GNU/screen

https://unix.stackexchange.com/questions/22545/how-to-connect-to-a-serial-port-as-simple-as-using-ssh

https://askubuntu.com/questions/40959/how-do-i-connect-to-tty-com-dev-ttyusb0

Raspberry Pi USB Ports

https://www.raspberrypi.org/documentation/hardware/raspberrypi/usb/README.md

https://www.raspberrypi.org/forums/viewtopic.php?t=223573

USBNET

https://www.raspberrypi.org/forums/viewtopic.php?f=36&t=131042

http://www.linux-usb.org/usbnet/