Introduction:
This manual aims to show how to create an ROV control system used in the 2021 regional competition. It uses network programming and serial communication to control the robot underwater and receiving data, all by connecting your computer to the control tube using an ethernet tether.
Overview:
The current design for the control system is having a computer onshore that sends signals to the underwater raspberry pi through a LAN tether cable and on the software side achieved through network programming. Upon receiving commands from the onshore computer the underwater raspberry pi would, through serial communication, pass on the commands to a microcontroller (in this case an Arduino Board).
What you need:
- Computer and external monitor
- Ethernet cable
- Raspberry pi
- Arduino
- Motors and ESCs
- USB camera
- Gamepad controller (not necessary)
Steps:
- Setting up developing environment on Mac and raspberry pi
- Detecting keyboard input
- Network programming
- Serial communication and Arduino
- Images to help illustrate everything
- Overall structure of the code
Setting up developing environment on Mac and raspberry pi:
First, make sure to install python since this would be the language of choice here. Install here and also make sure to install “pip”. Then install a text editor of your choice, mine is sublime. Then head over to your raspberry pi, find a micro SD card and install raspberry pi OS. Write the downloaded files to the micro SD card, remove it, and plug it into the raspberry pi. (No need to download raspberry pi OS if the SD card already has it.) Now on your raspberry pi install the Arduino C application using on your terminal sudo apt-get install arduino
. Now hover over to the application tab and you should see under electronics the Arduino C IDE.
Detecting keyboard input:
The plan for controlling the ROV is by taking keyboard input from the computer’s keyboard where for example, pressing “w” would move the ROV forward.
The library of choice for this would be pygame. Go into the terminal on your mac and type in pip install pygame
. After that open your code editor and create a new python file.
These 3 lines of code is the set up of pygame, first import pygame, then initialize pygame, then set a display. You can run this code on terminal by first going into the directory of your python file so if it was saved on your desktop, cd desktop
will get you in the right directory. Then proceed to run your file by python3 <filename>.py
.
The chunk of code here is a bit long but extremely easy to understand. Whenever there is a change in keyboard inputs, pygame creates an event object. We can then loop through individual events in the event objects by using the for loop for event in pygame.event.get():
. Then we can verify the events to see what we should do with them. For example, if event.key == pygame.K_UP:
the program would detect when the up key is pressed on the computer and would tell the robot to move up. Another important thing to note here is that there are 2 different types of events we are looking for in here, first is the key down if event.type == pygame.KEYDOWN:
, and second is the key down if event.type == pygame.UP:
. The purpose of these two differentiating events is to make sure the robot makes sense! For example, if you press the up button, the robot should not move up continuously. So if the program detects a key release, and the key released is the up arrow, the robot will stop moving up.
Network Programming:
Now that we have keyboard inputs all set up and with the correct logic to control the computer, it is time to be able to send the information to the raspberry pi. First, we would treat the onshore computer as a host and the raspberry pi underwater as the client. So on the onshore computer, we would bind it to an address, then the raspberry pi would be able to connect to it here:
As seen on line 10, we are trying to connect to the same address binded by the onshore computer with s.connect(). When that is successful the raspberry pi and your onshore computer is now on the same network, good! The rest of the code you see above will be explained next.
Disclaimer here, lots of things here still don't work well all the time. For example, the address needs to be dynamically set and the host sometimes does not accept the client connections all the time so I made some changes to the code but since its not conventionally written it would be a good idea to figure these out in the future.
Serial communication and Arduino:
Now the commands have been transferred from onshore to the raspberry pi underwater. The final step now is to forward the commands from the raspberry pi to a microcontroller, in this case, the Arduino board.
First, we need to set up a network serial communication between the raspberry pi and the Arduino. So in the raspberry pi, there should be a python file with this code in it:
The overall idea here through on line 6 is to connect the raspberry pi to the arduino. using serial.Serial(), inside you would have to pass the port id of where the arduino is connected on the raspberry, in this case /dev/ttyACM0, the baud rate and timeout which have conventional values you should use.
On the while loop, the raspberry pi will receive the message from the onshore computer on line 15, s.recv(1024). Then it will decode the message into utf-8 form and then writes it to the arduino on line 20, ser.write(msg.encode(“utf-8”)).
The final step before the motors start moving is the Arduino C code. Overall the code here is pretty straightforward, the only tricky part is reading the data until the “\n” which is where the message ends. So you would get messages like “back” , “left”, “right”. This is on line 30, “serial.ReadStringUntil(‘\n’)”. Rest of the code is just simple motor controls and logic flows.
Images to help illustrate the situation: (Underwater Control tube)
Overall structure of the code:
This is basically how the control system work. Github: https://github.com/DoggoOP/ROV
ROV_Arduino_Control.ino is on the arduino
rovtest.py is on the onshore computer
socketControl.py on the raspberry pi
The order of communications would be rovtest.py → socketControl.py → ROV_Arduino_Control.ino