This instructable details the process for building a Wi-Fi robot on the ZYBO platform. This project utilizes a real-time operating system for object detection, distance measurement, and responsive control. This guide will cover interfacing the ZYBO with peripherals, running custom firmware, and communicating via Java application. The following is a list of all the key components required for this project:
- 1 ZYBO Development Board
- 1 TL-WR802N Wireless Router
- 1 Shadow Chassis
- 2 65mm Wheels
- 2 140rpm Gearmotors
- 2 Wheel Encoders
- 1 HC-SR04 Ultrasonic Sensor
- 1 BSS138 Logic Level Converter
- 1 L293 H-Bridge Motor Driver
- 1 12V to 5V DC/DC Converter
- 1 2200mAh LiPo Battery
- 1 Ethernet Cable
- 1 USB Micro-B Cable
- 1 Female XT60 Connector
- 2 Male-to-Female Jumper Wires
- 30 Male-to-Male Jumper Wires
- 2 10kΩ Resistors
- 1 Breadboard
In addition, the following software must be installed on the target computer:
- Xilinx Vivado Design Suite 2018.2
- Digilent Adept 2.19.2
- FreeRTOS 10.1.1
- Java SE Development Kit 8.191
Step 1: Assemble Robot Chassis
Assemble the shadow chassis and attach the gearmotors and encoders to the bottom frame. The ZYBO, breadboard, and ultrasonic sensor can be mounted with the provided parts that can be 3D printed and fixed to the chassis using standoffs and double-sided tape.The battery should be mounted near the back of the robot and preferably between the top and bottom frames. Mount the router close to the ZYBO and the DC/DC converter close to the breadboard. Attach the wheels to gearmotors at the very end.
Step 2: Wire Electronics
Connect the input and output of the DC/DC converter to the two power rails on the breadboard respectively. These will serve as the 12V and 5V supplies for the system. Connect the ZYBO to the 5V rail as shown in the picture. Use a USB Micro-B supply cable to connect the router to the 5V rail as well. The XT60 cable should be attached to the 12V rail. Do not plug in the battery until the rest of the electronics are wired correctly. The ultrasonic sensor should be wired to the 5V rail. Create a 3.3V rail on the breadboard using pin 6 of Pmod port JC on the ZYBO. The high voltage input of the logic converter should be wired to the 5V rail while the low voltage input of the logic converter should be wired to the 3.3V rail. Wire the motor encoders to the 3.3V rail. Connect VCC1 of the motor driver to the 5V rail and connect VCC2 to the 12V rail. Tie all EN pins to 5V and ground all GND pins.
Connect the TRIG and ECHO pins of the ultrasonic sensor to HV1 and HV2 of the logic converter respectively. LV1 should be wired to JC4 and LV2 should be wired to JC3. Refer to the chart for Pmod pinouts. Connect the motors to the motor driver. Y1 should be connected to the positive terminal of the right motor and Y2 should be connected to the negative terminal of the right motor. Similarly, Y3 should be connected to the positive terminal of the left motor and Y4 should be connected to the negative terminal of the left motor. A1, A2, A3, and A4 should be mapped to JB2, JB1, JB4, and JB3 respectively. Refer to the schematic for pin numbers. Wire JC2 to the right encoder and JC1 to the left encoder. Ensure pull-up resistors are used to tie these signals to the 3.3V rail. Lastely, utilize the ethernet cable to connect the ZYBO to the router.
Step 3: Create Block Diagram in Vivado
Create a new RTL project in Vivado. Make sure to not specify any sources at this time. Search for "xc7z010clg400-1" and hit finish. Download encoder_driver.sv and ultrasonic_driver.sv. Place them in their own folders. Open the IP Packager under "Tools" and choose to package a specified directory. Paste the path to the folder containing the encoder driver and hit "Next". Click "package IP" and repeat the processes for the ultrasonic sensor driver. Afterwards, navigate to the repository manager under the IP subsection in the settings menu. Add the paths to the driver folders and hit apply to include them in the IP library.
Create a new block diagram and add the "ZYNQ7 Processing System". Double-click the block and import the ZYBO_zynq_def.xml file provided. Under "MIO Configuration", enable Timer 0 and GPIO MIO. hit "OK" to save the configuration. Add 3 "AXI GPIO" blocks and 4 "AXI Timer" blocks. Run block automation followed by connection automation for S_AXI. Double click the GPIO blocks to configure them. One block should be dual channel with a 4-bit input and a 4-bit output. Make these connections external and label them SW for input and LED for output. The second block should also be dual channel with 2 32-bit inputs. The last GPIO block will be a single 32-bit input. Make the pwm0 output from each timer block external. Label them PWM0, PWM1, PWM2, and PWM3.
Add the encoder driver to the block diagram and connect CLK to FCLK_CLK0. Connect OD0 and OD1 to the input channels of the second GPIO block. Make ENC external and rename ENC_0 to ENC. Add the ultrasonic sensor block and connect CLK to FCLK_CLK0. Make TRIG and ECHO external and rename TRIG_0 to TRIG and ECHO_0 to ECHO. Connect RF to the third GPIO block. Refer to the provided block diagram for reference.
Right click your block diagram file in the Sources pane and create an HDL wrapper. Be sure to allow user edits. Add the provided ZYBO_Master.xdc file as a constraint. Hit "Generate Bitstream" and take a coffee break.
Step 4: Setup Software Development Environment
Go under "File" to export hardware to the Vivado SDK. Make sure to include the bitstream. Import the RTOSDemo project inside the "CORTEX_A9_Zynq_ZC702". It will be located within the FreeRTOS installation directory. Create a new Board Support Package select the lwip202 library. Change the referenced BSP in the RTOSDemo project to the BSP you just created*.
*At the time of writing this Instructable, FreeRTOS seems to have a bug with referencing the correct BSP. To remedy this, create a new BSP with the same settings as the first. Change the referenced BSP to the new one and then change it back to the old one after it fails to build. FreeRTOS should now compile without errors. Feel free to delete the unused BSP.
Step 5: Modify the Demo Program
Create a new folder called "drivers" under the "src" directory of RTOSDemo. Copy the provided gpio.h. gpio.c, pwm.h, pwm.c, odometer.h, odometer.c, rangefinder.c, rangefinder.h, motor.h, and motor.c files into the "drivers" directory.
Open main.c and set mainSELECTED_APPLICATION to 2. Replace main_lwIP.c under "lwIP_Demo" with the updated version. BasicSocketCommandServer.c under "lwIP_Demo/apps/BasicSocketCommandServer" also has to be updated with a new version. Lastely, navigate to "FreeRTOSv10.1.1/FreeRTOS-Plus/Demo/Common/FreeRTOS_Plus_CLI_Demos" and replace Sample-CLI-commands.c with the provided version. Build the project and ensure everything compiles successfully.
Step 6: Flash Firmware to QSPI
Create a new Application Project called "FSBL" using the "Zynq FSBL" template. After compiling the FSBL project, create a boot image of the RTOSDemo project. Make sure "FSBL/Debug/FSBL.elf" is selected as the bootloader under "Boot image partitions". Manually add the path to this file if it is not listed.
Move the JP5 jumper on the ZYBO to "JTAG". Use a USB Micro-B cable to connect your computer to the ZYBO. Connect the battery and turn on the ZYBO. Run Adept to make sure the ZYBO is correctly identified by the computer. Click "Program Flash" in the Vivado SDK and provide the paths to the BOOT.bin file in RTOSDemo and the FSBL.elf file in FSBL. Make sure to select "Verify after flash" before hitting "Program". Watch the console to ensure the flashing operation completed successfully. Afterwards, power the ZYBO off and disconnect the USB cable. Move the JP5 jumper to "QSPI".
Step 7: Configure Wireless Access Point
With the battery still connected, connect to the router's Wi-Fi network. The default SSID and password should be on the bottom of the router. Afterwards, navigate to http://tplinkwifi.net and login using "admin" for the username and password. Run the quick setup wizard to configure the router in access point mode with DHCP enabled. Make sure to update the default username and password for the device as well. The router should automatically reboot into access point mode after you are finished.
Power on the ZYBO and connect to the router using the SSID you assigned. The router will most likely come up on either IP address 192.168.0.100 or 22.214.171.124. The ZYBO will be assigned whichever address the router doesn't have. To quickly determine the IP address of the router, you can run "ipconfig" from the command prompt in windows or "ifconfig" from the terminal in Linux or MacOS. If you are still connected to the router, you will see its IP address displayed next to your wireless interface. Use this information to determine the IP address of the ZYBO. To confirm the IP address of the ZYBO, you can either ping it from the command line or connect to it via telnet.
Step 8: Run Java Program
Download RobotClient.java and compile the file using the command "javac RobotClient.java" from the command line. Run the command "java RobotClient <ip_address>" where "ip_address" is the IP address of the ZYBO. The control GUI will popup if a successful connection is established between the computer and the ZYBO. After focusing the window, the robot should be controllable using the arrow keys on the keyboard. Press the escape button to end the session and disconnect from the robot.
The GUI will highlight the keys that are pressed and show the motor output in the top right. The distance meter on the left fills a bar every 2 meters up to a maximum of 10 meters.
Step 9: Calibrate Rangefinder
The switches onboard the ZYBO can be used to configure the onboard rangefinder. The minimum detection distance d is given as a function of the switch input i:
d = 50i + 250
The input can vary between 0 to 15 in integer steps. This translates to a distance range of 0.25 meters to 1 meter. At the minimum distance, the first LED will start to blink. The number of LEDs that are active is proportional to the proximity of the object.
Step 10: Accessibility
This robot is very easily accessible. Due to the simplicity of its control, it can be fully controlled with just one finger. To improve accessibility, support for additional input devices could be added. This could allow disabled uses to control the robot with a different part of their body.