© Liz Clark 2019
Liz ClarkPractical Tinker Boardhttps://doi.org/10.1007/978-1-4842-3826-4_11

11. Project 5: Build a Robot with a Streaming Camera Feed

Liz Clark1 
(1)
Boston, MA, USA
 

It’s been a long journey, but we’ve reached our final project in this book. The previous four projects focused on practical uses for the Tinker Board, but for the grand finale we’re going to stray a bit from the practical and build a simple robot that can be operated via a custom Bluetooth controller and will stream video.

Why a Robot?

A robot is the quintessential electronics project. Robots come in many varieties and can be very simple or incredibly complex. By now you’re well aware of the Tinker Board’s features, and once again the Internet connectivity, full operating system, and diverse IO options beyond GPIO make it a great platform for a robot with more features than your average beginner robot.

Robot Supplies

For the construction of the robot, we’ll be using two DC motors with wheels attached to a mini robot chassis. If you want to use a different motor type, such as gearbox motors, you can. The concept will be the same. For the chassis, there are countless options available on the market, and the one you choose really comes down to personal preference since its purpose is to hold the electronics and attach the motors. Different shapes, colors, or materials won’t affect the robot’s technical outcome.

To keep everything mobile, the Tinker Board will be powered by a USB battery bank, which will be mounted to whatever chassis you choose. You’ll need a high-capacity battery bank, especially with the Tinker Board’s amperage concerns. Luckily, these larger capacity battery banks are becoming more common and are also available in smaller sizes. Because of this you will probably get better power results with the original Tinker Board than the Tinker Board S, since the Tinker Board S needs 3A to boot.

Of course, something needs to control the motors, since hardware PWM is not available on the Tinker Board’s GPIO and is a necessary feature when it comes to controlling motors. As a result, we’ll be using another HAT, this time by Adafruit, specifically the Motor HAT. Additionally, we’ll use their Python library for the HAT, which will make coding the motors’ movement a lot more straightforward.

Adafruit was mentioned in the GPIO chapter as an option for procuring electronics supplies. In addition to selling standard electronics components, they’re also an open source hardware company in the United States that designs, manufactures, and supports a variety of boards produced in-house.

I2C

The HAT communicates with the Tinker Board through I2C (Inter-integrated Circuit, pronounced “I squared C”), which is a serial communication protocol that is very similar to SPI in that it allows for multiple integrated circuits to communicate with each other. However, I2C requires only two pins to communicate with multiple devices; by contrast, SPI requires four pins for each connected device and a dedicated IO pin from the master device for each connected device. I2C-connected devices are also a bit easier to manage and don’t require as much setup as SPI.

The HAT has onboard electronics, including PWM drivers, terminal connectors for motors, and a dedicated power input for the motors, which receive I2C communication that then control the motors and anything else attached to the pins, as shown in Figure 11-1.
../images/465130_1_En_11_Chapter/465130_1_En_11_Fig1_HTML.jpg
Figure 11-1

The Adafruit Motor HAT

Robot Extras

To give our robot some extra flair, we’re going to implement a camera into its design. We’ll use either a webcam or a camera module connected to the CSI connector on the Tinker Board, like the one we used in the Android chapter, to stream a video feed to a webpage on your network while we drive the robot around. We’ll be able to mount the camera to the front of the robot chassis and have it act almost like the robot’s eyes.

Speaking of driving around, we’ll need to control the robot, and this creates a great opportunity to build a custom controller that communicates via Bluetooth. To do that we’ll use an additional Adafruit development board that’s Arduino-compatible (meaning that you can code it using the Arduino IDE and Arduino code libraries), called the 32u4 Bluetooth Feather.

But if you don’t want to build a custom controller, you don’t have to. We’ll be controlling the robot with keyboard inputs, so our custom controller will be a macro keyboard in disguise. As a result, you can use the same wireless or Bluetooth keyboard you’ve been using the whole time with your Tinker Board.

This entire project will again take place in TinkerOS. So, let’s begin by booting into TinkerOS and setting up the Python library for the HAT.

Motor HAT Setup

Let’s begin the setup for the Motor HAT by following the steps outlined by Adafruit to install the Python library.1 First, we’ll need to change directories to the Home directory and install the dependencies, most of which should already be installed if you’ve been following along with the other chapters.

Navigate to a terminal and enter
sudo apt-get install build-essential python-dev python-smbus
Then, as we’ve done before, we’re going to clone into the GitHub repo with
git clone https://github.com/adafruit/Adafruit-Motor-HAT-Python-Library.git

After that finishes, change directories into the newly cloned folder with cd ~/Adafruit-Motor-HAT-Python-Library. Once in the folder, we have a Python setup script to run. In the terminal, type sudo python setup.py install.

After you’ve run the setup.py script, the library is ready to use. Adafruit provides some example code in the examples folder along with the Robot.py file, which has the main components of the library, as shown in Figure 11-2.
../images/465130_1_En_11_Chapter/465130_1_En_11_Fig2_HTML.jpg
Figure 11-2

The Robot.py library file

The main takeaway from Robot.py is that it has functions written to define the pulses for the motors for different speeds and directions. This means that when you write your own code with Robot.py imported, you can use simple commands like robot.direction(speed, time) , where you enter a direction parameter, speed parameter, and then how long you want your robot to do that action, and your robot is on the move.

As you can see in Figure 11-2, the files for this library have very detailed comments explaining what each line is doing, which you can read at your leisure if you need to clarify anything.

Connecting the Hardware

The software won’t do much, though, without the hardware connected. First, we’ll connect the two DC motors to the Motor HAT by plugging their power and ground wires into the terminal connectors on the HAT as shown in Figure 11-3.
../images/465130_1_En_11_Chapter/465130_1_En_11_Fig3_HTML.jpg
Figure 11-3

The motors connected to the terminal blocks on the Motor HAT. You’ll need a small screwdriver to tighten the terminal blocks.

Next, plug the HAT into the GPIO pins. This HAT fits over the stock heat sink, but just barely. For robots planned to rack up a lot of miles and as a result give off more heat, you may want to consider a riser header like the one we used in the last chapter for the EPD HAT. The final step is to connect the external battery power for the motors to the HAT, as shown in Figure 11-4. AA and AAA battery boxes that have wire connections for power and ground are sold for applications like this.
../images/465130_1_En_11_Chapter/465130_1_En_11_Fig4_HTML.jpg
Figure 11-4

The power terminal connector for the motors on the HAT

Running the Example Code

Once everything is connected to the Tinker Board, the demo code we’re going to try is RobotTest.py . It basically has a sequence of commands to make sure everything is hooked up properly by pulsing the motors at different PWM frequencies. Each sequence is on a timer without a loop, so the script runs through once and then stops.

To run it, while still in the examples folder, enter sudo python RobotTest.py into the terminal. Your motors should start spinning for a few seconds each at different speeds. If you run it with your robot fully assembled, you’ll also see that it’s going backward, forward, left, and right.

If we look at the code, by entering idle RobotTest.py into the terminal, we can see the syntax that’s making this script tick, or rather pulse. As you can see in Figure 11-5, the code begins by importing Robot and then setting up the motors with calls to the imported Robot.py file.
../images/465130_1_En_11_Chapter/465130_1_En_11_Fig5_HTML.jpg
Figure 11-5

The RobotTest.py file

Then we can see how the different motor movements are called using the same syntax that we discussed earlier: robot.direction(speed, time) . That’s basically the entire script. The Robot.py library file makes it very simple to program in motor movements. Let’s move on now to starting our robot project code.

Robot Project Python Code

When you’re beginning to write code for any project, it’s important to break the process down into the basic goals that you want to accomplish, as we did when planning the EPD project in Chapter 10. In its most basic form, we want our robot to be able to go forward, backward, left, and right and to stop. Each of these directions will be controlled with a button, which points us in the direction of using if statements; for example, “if this button is pressed, have the robot do this.”

To implement these controls, we’re going to use keyboard inputs. This way, you can either use your attached keyboard or build the upcoming custom Bluetooth controller, which will send the same keyboard commands. The camera portion of the project will be separate from the Python code. With everything planned, we can start writing our code.

In Python, you can have keyboard inputs affect code execution by using the readchar library . It’s installed using pip , so you’ll need to change directories to the Home folder and enter pip install readchar into the terminal to install.

After the installation, change directories back to the Motor HAT’s examples folder and open IDLE to create a new file. First, we’ll import our dependencies: time, Robot, and readchar. Robot is, of course, the Adafruit library file, which we will need to keep in the same folder as the project file, just as we experienced with the EPD project and the Waveshare dependencies. Those first three lines will look like this:
import time
import Robot
import readchar
Then, we’ll set up the needed items for the Robot library, just like the code we saw in RobotTest.py, with these lines:
LEFT_TRIM = 0
RIGHT_TRIM = 0
Robot = Robot.Robot(left_trim=LEFT_TRIM, right_trim=RIGHT_TRIM)
After that, we’ll go right into the loop. We’ll be setting everything up for readchar in the loop rather than outside it. The syntax for readchar is to first set up a variable that is equal to readchar.readkey() , so that we can plug in any of various keyboard inputs and have the readchar library know it should interpret that as keyboard input. We do that with this line:
key = readchar.readkey()
The keys that we’ll be using are W, A, S, D and B. The WASD keys were chosen since they’re traditionally used for movement controls in PC gaming. W controls forward movement, A for left, D for right and S for backward movement. B will be used for stopping, as B stands for brake. As discussed before, we’ll be using if statements to integrate our keyboard inputs with our motor movements. The syntax will be this:
if (key == 'w'):
       robot.forward(150)
       print('forward ')
       time.sleep(0.1)

To break that if statement down, if W is pressed, then the robot will move forward at 75% speed. The string forward will also be printed to the terminal for troubleshooting purposes and there will be a slight delay to keep everything running smoothly. Since the script is going to be waiting for keystrokes, the delay will avoid any lag or scenario of commands running into each other in an infinite loop. If the delay is set to be too long, however, you will experience a noticeable lag.

Note

An important point about the readchar library is that anything that you put in the (key == ' ') parentheses is case-sensitive. As result, if you want just a simple keystroke to be read, be sure to keep the enclosed letters lowercase.

Using exactly the same formatting, we’ll now create if statements for the other key inputs. But because we want to allow different inputs, the rest of the statements will be elif statements , Python’s syntax for else-if. The rest of the key inputs will look like this:
elif (key == 'a'):
         robot.left(150)
         print('left ')
         time.sleep(0.1)
elif (key == 's'):
         robot.backward(150)
         print('backward ')
         time.sleep(0.1)
elif (key == 'd'):
         robot.right(150)
         print('right ')
         time.sleep(0.1)
elif (key == 'b'):
         robot.stop()
         print('brake! ')
         time.sleep(0.1)
The only big difference among the different robot movements is that robot.stop() does not include a speed parameter, since it’s effectively taking away all speed. The entire script will look like this:
import time
import Robot
import readchar
LEFT_TRIM = 0
RIGHT_TRIM = 0
robot = Robot.Robot(left_trim=LEFT_TRIM, right_trim=RIGHT_TRIM)
while True:
      key = readchar.readkey()
      if (key == 'w'):
             robot.forward(150)
             print('forward ')
             time.sleep(0.1)
      elif (key == 'a'):
             robot.left(150)
             print('left ')
             time.sleep(0.1)
      elif (key == 's'):
             robot.backward(150)
             print('backward ')
             time.sleep(0.1)
      elif (key == 'd'):
             robot.right(150)
             print('right ')
             time.sleep(0.1)
      elif (key == 'b'):
             robot.stop()
             print('brake! ')
             time.sleep(0.1)
It’s a relatively short script, thanks to the Robot.py library. Now you can save this as roboTinker.py and test it via the terminal with sudo python roboTinker.py. Using your attached keyboard (wireless of course), you should be able to control the motors and see confirmation in the terminal that you’re sending the correct commands as shown in Figure 11-6.
../images/465130_1_En_11_Chapter/465130_1_En_11_Fig6_HTML.jpg
Figure 11-6

The confirmation strings that the roboTinker script has received the keyboard inputs for control

Configuring the Camera

We’re going to take a break from the Motor HAT for a moment and work on the camera portion of this project. We’ll be using a camera, either a USB webcam or a ribbon cable camera, as essentially a set of eyes for the robot to navigate with.

The camera feed will be streamed with a piece of software called MJPG-streamer, which allows you to receive a video feed from a device on your network, in this case the Tinker Board, via a browser. You’ll have to be on another device on the same network to receive the stream, but it should at least allow you to explore your home without leaving the couch.

Webcam vs. Ribbon Cable Camera

You can use MJPG-streamer with either a webcam or a camera module, which plugs into the MIPI connector on the Tinker Board as shown in Figure 11-7 and discussed as an Android example in Chapter 6.
../images/465130_1_En_11_Chapter/465130_1_En_11_Fig7_HTML.jpg
Figure 11-7

The CSI-cam connected to the Tinker Board

There are pros and cons for each camera choice. For the webcam, you’ll more than likely get better picture quality, and a USB connection is easier for hot-swapping peripherals; but it is much larger than a camera module, and you’ll have to manage the longer USB cable when assembling your robot. The housing for the webcam may also create issues with mounting the camera to the robot chassis.

The camera module is a much smaller form factor than a webcam, and you can either purchase an aftermarket case for mounting it or create your own using 3D printing or CNC. The ribbon cable can be swapped for different lengths to best suit your project, and plugging directly into the top of the Tinker Board can also help to keep things tidy. However, the camera module will have a lower picture quality than a webcam and often requires a well-lit area to have the best results. The MIPI connector is also finicky on both the camera module and the Tinker Board. Additionally, the camera module is highly sensitive to static shock and should only be handled in a grounded area. The connectors and ribbon cables are also very fragile, so the entire camera must be handled with care.

As you can see, the camera type you choose will come down to your goals for the robot and personal preference. Luckily, the same software can be used for either choice, so let’s move on to setting up MJPG-streamer.

Installing MJPG-streamer

MJPG-streamer is run through the terminal, so we won’t be using Python or any other programming language. We will need to install some dependency programs and drivers though. Navigate to the terminal and enter
sudo apt-get install subversion libjpeg-dev libjpeg62-turbo-dev imagemagick libv4l-dev uvcdynctrl

to install them.

After that we’ll use subversion, which we just installed, to download MJPG-streamer from the server location where it’s hosted. With the terminal, enter svn co https://svn.code.sf.net/p/mjpg-streamer/code/ to download the folder into the Home directory.

After downloading, change directories to the new folder using cd ~/code/mjpg-streamer. MJPG-streamer utilizes a make file to install, so while in the directory enter make followed by sudo make install into the terminal. Once the installation completes, you’re ready to try MJPG-streamer.

Running MJPG-streamer

To use MJPG-streamer, you of course need to connect your chosen camera device. This needs to be done while the Tinker Board is powered off, because during boot, the Tinker Board will detect that the camera is connected and create a video device under /dev; otherwise, your camera will not be recognized. Once your camera is connected, power up the Tinker Board and via the terminal change directories to the MJPG-streamer folder with cd ~/code/mjpg-streamer.

From the folder, we’ll run the MJPG-streamer program. There are a few configurable parts for MJPG-streamer. The first is calling MJPG-streamer, with ./mjpg-streamer. Next you select an input device and settings with -i "./input_uvc.so -y. Here the UVC video plug-in is initialized as the video input, and -y indicates that the YUYV video format will be used over MJPG.

The next few parameters are optional but have been shown to achieve smooth streaming results on the Tinker Board and avoid any errors.
  • -r sets the resolution; and since we’re streaming, a lower resolution will guarantee smooth video via the network.

  • 640×480 is an option that balances between image quality and streaming quality. Of course, you can use a resolution as high as your camera supports.

  • -f sets the frame rate, or FPS, for the video, and depending on your region and goals for the project this may vary. 30 FPS will create a very smooth picture.

  • Finally, -n blocks the initialization of the dynamic control features (dynctrls) in the Linux-UVC library. This will depend on your camera and its drivers, but you have a lower chance of throwing errors if you disable it.

Combined, the entire input portion will be listed as -i "./input_uvc.so -y -r 640x480 -f 30 -n".

Next is the output portion, basically how the video is being pushed to the stream on the network. It begins with -o, followed by "./output_http.so for streaming with the HTTP plug-in, followed by -w ./www" so that the files will be written to the web page for the stream rather than a subfolder, and as a result are not saved anywhere.

The full terminal command will be
./mjpg_streamer -i "input_uvc.so -y -r 640x480 -f 30 -n" -o "./output_http.so -w ./www"
If executed with zero errors, this will return the output shown in Figure 11-8 via the terminal and will begin streaming over the network.
../images/465130_1_En_11_Chapter/465130_1_En_11_Fig8_HTML.jpg
Figure 11-8

MJPG-streamer executed without errors via the terminal

On a device on your network, you can enter the following URL into a browser to see the stream: http://111.111.1.1:8080/?action=stream, where 111.111.1.1 will be your Tinker Board’s IP address, as shown in Figure 11-9. You can also view the stream on the Tinker Board in a browser with http://127.0.0.1:8080/?action=stream.
../images/465130_1_En_11_Chapter/465130_1_En_11_Fig9_HTML.jpg
Figure 11-9

The MJPG-streamer streamed live in a browser on the network. The camera feed seen here is from a ribbon cable camera module.

Start on Boot

Much as we needed to have our EPD project start up on boot, we’ll do the same thing with our robot so that we don’t have to worry about an HDMI connection interfering with our chassis. We’re going to target the same network folder, if-up.d, for MJPG-streamer, since it requires a network connection. MJPG-streamer is terminal-based, though, so how will we have it launch without typing into the terminal? We’re going to use a type of script called a Bash script. You can put anything that you would normally type into the terminal in a Bash script to have it run as an executable file.

For our roboTinker Python script, we’re going to launch it from a file called autostart , which is in the .config/lxsession/LXDE folder path. It contains other commands related to the GUI that need to begin on startup, but unlike the files located in if-up.d, they do not require a network connection and you don’t need to be root to access the folder and file.

Bash Script for MJPG-Streamer

To create our Bash script for MJPG-streamer, we’ll first need to create a new text file. To do this we’ll enter sudo nano start_streamer.sh into the terminal. This creates and enters into a text file called start_streamer.sh. In our blank text file, we’ll first enter our line to make it executable. This is similar to the line that we’ve entered at the top of our Python scripts previously. The technical term for this command is a shebang, because it begins with #!. The shebang syntax for a Bash script is #!/bin/bash.

Next, we’ll define our library path for MJPG-streamer with
export LD_LIBRARY_PATH=/home/linaro/mjpg-streamer/
Finally, our last line will be similar to what we put in the terminal once inside the /mjpg-streamer directory. We’ll put
/home/linaro/mjpg-streamer/mjpg_streamer -i "/home/linaro/mjpg-streamer/input_uvc.so -y -r 640x480 -f 30 -n" -o "/home/linaro/mjpg-streamer/output_http.so -w ./www"
The full file extensions are there for the program path and input and output plug-ins, since this won’t be running directly from the file directory as it would if we were executing it from the terminal. The final Bash script will look like this:
#!/bin/bash
export LD_LIBRARY_PATH=/home/linaro/mjpg-streamer/
/home/linaro/mjpg-streamer/mjpg_streamer -I "/home/linaro/mjpg-streamer/input_uvc.so -y -r 640x480 -f 30 -n" -o "/home/linaro/mjpg-streamer/output_http.so -w ./www"

Once you have that in the text file, save and exit the nano editor , which will bring you back to the terminal. Now, much as we’ve done with Python scripts, we’ll use chmod to make our Bash script executable. Enter sudo chmod +x start_streamer.sh into the terminal and then sudo ./start_streamer.sh to test. If all has gone well, MJPG-streamer should begin running.

Copying start_streamer.sh to if-up.d

After we’ve made start_streamer.sh an executable, we can move it to the if-up.d folder. Before we can do that, though, we need to remove the .sh file extension from the filename, because files with file extensions cannot run in the if-up.d folder. Rename the file to start_streamer via the GUI and then we can copy it over to the if-up.d folder.

To begin the copying process, just as we did with the EPD project, we need to enter the terminal as root using sudo su. Next, we’ll change directories to if-up.d with cd /etc/network/if-up.d. Finally, we’ll copy the start_streamer file with
cp -r /home/linaro/start_streamer /etc/network/if-up.d

Note that the file location for the file to be copied is listed first, followed by the target file location, which in this case is if-up.d.

Launching roboTinker.py with autostart

Previously with our EPD project, we copied our Python files into if-up.d so that they would run on startup once a network connection was established. However, since we’re using readchar for inputs in our roboTinker.py file, it needs to run in the terminal because readchar does not work when executed through IDLE. As a result, we’re going to use the command lxterminal inside the autostart executable to run roboTinker.py via a terminal window that will open upon startup and remain open to receive our readchar commands.

First, we’ll edit the autostart text file by entering sudo nano /home/linaro/.config/lxsession/LXDE/autostart into the terminal. You’ll see three lines that already exist in autostart. We’re going to insert our line for roboTinker.py with
@lxterminal -e sudo python /home/linaro/Adafruit-Motor-HAT-Python-Library/examples/roboTinker.py
into the third line space, as shown in Figure 11-10. This tells the script to open a terminal window and execute the roboTinker.py file. Then save the autostart file and return to the terminal. We’re now ready to reboot to test that both MJPG-streamer and roboTinker.py begin automatically.
../images/465130_1_En_11_Chapter/465130_1_En_11_Fig10_HTML.jpg
Figure 11-10

The edited autostart file

Bonus: Bluetooth Controller Coded with Arduino IDE

As a bonus project to accompany the robot, we can also build a custom controller as discussed earlier in this chapter. One of the great things about DIY electronics and maker projects is that they can have multiple components and involve as many different platforms as you want.

For our custom controller, we’re going to be using a 32u4 Bluetooth Feather development board by Adafruit, the same company that made the Motor HAT we’re using to control the motors for our robot. This board can be coded using the Arduino IDE, which is the official coding interface used with Arduino boards.

The 32u4 processor used on this Feather board can act as an HID device without a firmware switch when coded with the Arduino libraries for it. There is also a BLE Arduino library from Adafruit available, along with example code, that we’ll be able to utilize for this mini-project. We’ll just add some minor edits, specifically the GPIO pins and keycodes, to the example code and then be ready to use our controller.

The example code2 and Bluetooth Arduino library3 are both available via Adafruit’s GitHub or their Learn system web site with full instructions for setting up the Arduino IDE to use the board. The two lines we’ll need to edit are the arrays for both the IO pins utilized and keycodes; revise lines 112 and 113 to look like this:
int inputPins[5]     = { 5        , 6        , 9        , 10       , 11       };
int inputKeycodes[5] = { HID_KEY_B, HID_KEY_D, HID_KEY_W, HID_KEY_S, HID_KEY_A};

where both arrays are set to have five items. The order matters for both the digital pins and keycodes, where the first index in each array will be paired; meaning that digital pin 5 will send a keystroke for B, pin 6 will send D, and so on. This aspect of the code will all depend on how your circuit is set up.

Circuit

For the circuit, we’ll use five temporary push buttons, just as we did in the GPIO chapter. One side of each button will be grounded and the other side will be routed to its appropriate IO pin on the Feather board. We’ll be utilizing digital pins 5, 6, 9, 10 and 11 as shown in the circuit diagram in Figure 11-11.
../images/465130_1_En_11_Chapter/465130_1_En_11_Fig11_HTML.jpg
Figure 11-11

The circuit diagram for the BLE controller

The simplest and most accessible way to accomplish this project’s circuit is to use a breadboard. We can easily place our buttons and then use wire to route it to the Feather board that can also plug directly into the breadboard with male headers, as shown in Figure 11-12 with the circuit fully assembled.
../images/465130_1_En_11_Chapter/465130_1_En_11_Fig12_HTML.jpg
Figure 11-12

The breadboarded BLE controller. Notice that the buttons are arranged to mimic a keyboard layout with the brake button off to the side.

Since the Feather board can directly plug in a LiPo battery for power, the project can be fully wireless and resemble a controller’s shape while still living on a solderless breadboard. Of course, more experienced users can create a more polished and final version by soldering the circuit to some protoboard and creating a case, but this iteration will certainly get the job done.

Once your circuit is assembled, we can load up the code from the Arduino IDE to the board and connect our new controller via Bluetooth to the Tinker Board.

Connecting the Bluetooth Controller to the Tinker Board

With the BLE controller powered on, either through USB or the LiPo battery, navigate to the Bluetooth options in TinkerOS that are located at the bottom-right side of the task bar, as shown in Figure 11-13.
../images/465130_1_En_11_Chapter/465130_1_En_11_Fig13_HTML.jpg
Figure 11-13

The Bluetooth options in TinkerOS

Select Setup a New Device from the menu, which will bring you through a setup wizard for new BLE devices. You’ll be presented with a list of available BLE devices based on their MAC addresses. If you aren’t sure which MAC belongs to the Feather, luckily it will show-up with a keyboard icon since it has HID properties as shown in Figure 11-14.
../images/465130_1_En_11_Chapter/465130_1_En_11_Fig14_HTML.jpg
Figure 11-14

The available BLE devices. Notice the keyboard icon for our BLE controller. The MAC addresses have been blacked out for privacy.

After you select the device, it will take a moment to sync to the Tinker Board and then a message will pop-up to let you know it has successfully connected, as shown in Figure 11-15. You should now be able to control the roboTinker.py program via the terminal window.
../images/465130_1_En_11_Chapter/465130_1_En_11_Fig15_HTML.jpg
Figure 11-15

The BLE controller has been successfully paired to the Tinker Board!

Note

The BLE controller will automatically reconnect to TinkerOS after reboots and shutdowns, so you shouldn’t have to go through this process again unless you purposely disconnect it.

Robot Assembly

Now that all the software and hardware is ready, you can take your robot chassis of choice and mount the motors, Tinker Board with the Motor HAT, camera choice, and power banks onto it so that it will resemble the one pictured in Figure 11-16.
../images/465130_1_En_11_Chapter/465130_1_En_11_Fig16_HTML.jpg
Figure 11-16

A fully assembled Tinker Board robot. You can go for any aesthetic you want with your assembly. If you leave the zip ties uncut like the robot in the picture, it can appear to have little antennae.

The most important thing for this process is to ensure that everything is safely secured, both physically and electrically. To mount the Tinker Board, it’s recommended to use some stand-offs so that it isn’t making direct contact with any conductive surfaces, as shown in Figure 11-17. If you’re using a ribbon cable camera module, make sure that it’s mounted so that it will be kept safe from any static; again, these cameras can easily become damaged and as a result unusable.
../images/465130_1_En_11_Chapter/465130_1_En_11_Fig17_HTML.jpg
Figure 11-17

The Tinker Board mounted to a robot chassis with stand-offs

Wire management is also very important here, since you’ll want to keep your wire routing for all components neat and out of the way of any motors. Everything should be tightly secured, but not too tight; you want to avoid any strain that could cause damage over time. For the battery banks, especially the USB one used for the Tinker Board, you can use Velcro and zip ties to safely secure them and their accompanying cables.

Once everything is assembled on the chassis, you can power up the Tinker Board and Motor HAT, log in to the MJPG-stream on a browser, and begin to drive your robot around.

Final Thoughts

This project is probably the most impractical of the projects in this book; however, it’s assembled with a lot of practical components ranging from Bash scripts to hardware communicating over I2C and even a custom BLE controller. Hopefully this and all the previous chapters have given you the tools to not only get started with the Tinker Board, but truly explore it and use it confidently.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.218.196.182