The first thing you do when you buy a Raspberry Pi is to access the terminal using SSH, with PuTTY for instance. This is a great when you have network connectivity, but what if you want to use your Pi without network access? You could connect using the micro USB port as a serial port, but then you can’t use that port for anything else. In this article I’ll walk you through a simple project to access a Raspberry Pi terminal over Bluetooth using your Android device or PC. You can create files, install packages, run scripts or do any of the things you normally do over SSH.
You can use the concepts in this tutorial to add Bluetooth connectivity for lots of different projects. Note that the Raspberry Pi 3 has built in Bluetooth functionality, but I only have version 2 so I’ll be using an external module
First here is a video showing the final result:
I’ll be using an HC-06 module as a Bluetooth transceiver. You can find it for less than $10 shipped on Amazon. This little guy will act as a Bluetooth slave device that sends and receives serial data. There are only 4 pins to hook up, your standard ground and Vcc (3.3V) and the Tx/Rx Serial pins. The HC-06 Tx pin goes the Rpi Rx pin and the same for the Rx pin as shown below. The Key and State pins are used on the HC-05, but you can leave them unconnected.
As an alternative to the HC-06 you could also use an HC-05 Bluetooth module. This lets you send a variety of serial commands to, for instance, change the UART baud rate. These features are nice but they do increase the complexity and aren’t really needed for what we are doing here. Whichever module you use the major steps in this tutorial should be pretty much the same.
The hardware was pretty simple, now let’s tackle software. I’ll go over the main parts and then post the entire script at the end.
We are going to be controlling the serial port using a Python script. If you haven’t already, install the Python Serial library just run
sudo apt-get install python-serial to install it.
Our Python script will have 2 main jobs:
- Read any serial data coming in from the Bluetooth module and send it to a terminal process
- Send any data coming out of the terminal to the Bluetooth module
Let’s make a small class to handle each of these tasks and we can tie them together in our main function. First the class to read serial data, we will call it
1 2 3 4 5 6 7 8 9 10 11 12 13
class SerialComm: def __init__(self): self.port = serial.Serial("/dev/ttyAMA0", baudrate=9600, timeout=1) def read_serial(self): res = self.port.read(50) if len(res): return res else: return None def send_serial(self, text): self.port.write(text)
The HC-06 only supports 9600 baud unfortunately, so we initialize the baud rate to a constant. The
read() function will return either after receiving the given number of characters or when the read function times out.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
class ShellWrapper: def __init__(self): self.ps = subprocess.Popen(['bash'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) def execute_command(self, command): self.ps.stdin.write(command + "\n") def get_output(self): timeout = False time_limit = .5 lines =  while not timeout: poll_result = select.select([self.ps.stdout, self.ps.stderr], , , time_limit) if len(poll_result): for p in poll_result: lines.append(p.readline()) else: timeout = True return lines
Next the ShellWrapper class. We are using pipes to talk to our shell (called Bash) process. A pipe is concept that allows processes to read or write data, just like you read and write data to a file, between processes. Linux processes come with three pipes on startup: stdout, stdin and stderr. If you aren’t familiar with the standard pipes check out the summary on wikipedia. We are going to be writing our commands into stdin and reading the output from stdout and stderr. The
execute_command method will write our commands and in
get_output> we use the select module to check whether stdout or stderr have any text available for us to read, if it does we add to a list that we later return. If no data is available to read we return an empty list.
1 2 3 4 5 6 7 8 9 10 11 12
def main(): shell = ShellWrapper() ble_comm = SerialComm() while True: out = ble_comm.read_serial() for ble_line in out: print(out) shell.execute_command(ble_line) shell_out = shell.get_output() for l in shell_out: print(l) ble_comm.send_serial(l)s
main function ties everything together. We create an instance of each of our classes from above and sit in a loop that:
- Checks if any serial data is available from the Bluetooth module
- Prints any data we receive to the console for reference/debugging
- Sends text from the serial to our shell
- Reads output from the shell and sends out the response over Bluetooth
Putting it All Together
Now that you have your hardware hooked up and your Python script is running on your Pi, you will need to connect to it using a Bluetooth terminal app. I used BlueTerm for Android. You should be able to find something similar for Windows or iOS. Once you open the app search for the HC-06 and connect to it. If there is an option to add line termination characters (usually either “\n ” or “\r\n”) you will get more consistent performance. You can now type any commands you want in your app and see the result. You can even create and edit files. Interactive terminal programs like Vim likely won’t work however. One final step you might want to do to actually use this in the field is to start your Python script when the Pi boots up. To do this just add a command to start the script in the
/etc/rc.local file. For example, adding the line:
and your script will start running when your Pi boots up.
You can get the full source code here.
Thanks for reading, if you liked this tutorial please Subscribe to see all future tutorials and reviews.