Friday, October 27, 2017

Remote SOund Navigation And Ranging(SONAR) Application with Raspberry Pi 2 in the Local Network Area(LAN)

Hello everybody, today I am here with another post. I will construct a remote SONAR application using Raspberry Pi 2, servo motor and HC-SR04 ultrasonic range sensor. In order to understand this post better, please check the previous posts that I have already written.

1 - Controlling Servo Motor using Raspberry Pi, Python (RPi.GPIO) software based Pulse Width Modulation(PWM)
2 - Using HC-SR04 Ultrasonic Range Sensor with Raspberry Pi 2

What do we need?

1 - Raspberry Pi 2
2 - HC-SR04 Ultrasonic Range Sensor
3 - Micro Servo Motor
4 - 1x1kΩ and 1x2.2kΩ Resistors
5 - Bread Board
6 - Jumper Male to Female Wires
7 - Laptop(for remote communication)

We need all the components above. But, if you want to display the results on Raspberry Pi locally, then you don't need a Laptop. However, here I will use Laptop. Because, Raspberry Pi is a small board which is used for remote applications generally.

Here is the technical description.

1 - My laptop's config(It will be the client machine):

- IP Adress:192.168.1.106
- Communication port is 9000
- Operating System: Windows 10
- This will be the client machine

2 - My Raspberry Pi's config(It will be the server machine):

- IP Adress:192.168.1.108
- Communication port is 9000
- Operating System: Raspbian Jessie Lite
- This will be the server machine

What does SONAR means?

According to Wikipedia(Yeah, I know. Currently, it is forbidden in Turkey, But I am using VPN), SONAR(acronym for SOund Navigation And Ranging) is a technique that uses sound propagation (usually underwater, as in submarine navigation) to navigate, communicate with or detect objects on or under the surface of the water, such as other vessels. Two types of technology share the name "sonar": passive sonar is essentially listening for the sound made by vessels; active sonar is emitting pulses of sounds and listening for echoes.

In this post, I will detect the objects and their distances by using servo motor and HC-SR04. I will rotate the HC-SR04 sensor 180° around itself. It will detect the object as explained in the second post above. It will send the message to my Laptop by using TCP/IP(server-client model) protocol and I will display them on the PC.

I have already explained how to use servo motor and HC-SR04 ultrasonic range sensor with Raspberry Pi 2 in the posts that I shared above. So, I will not write the wiring procedures and the details again.

Server-Client Socket Communication

Raspberry Pi and the laptop will communicate over Internet by using sing TCP/IP(server-client model) protocol. Sockets can be configured to act as a server and listen for incoming messages, or connect to other applications as a client. After both ends of a TCP/IP socket are connected, communication is bi-directional.

Server Side

This sample program, based on the one in the standard library documentation, receives incoming messages and echos them back to the sender. It starts by creating a TCP/IP socket. Then bind() is used to associate the socket with the server address. In this case, the address will be 192.168.1.108, referring to the Raspberry Pi 2 server, and the port number can be chosen any number. For me, it was 9000. Calling listen() puts the socket into server mode, and accept() waits for an incoming connection. accept() returns an open connection between the server and client, along with the address of the client. The connection is actually a different socket on another port (assigned by the kernel). Data is read from the connection with recv() and transmitted with sendall().

import socket
import sys

# Check if the parameters are correctly called
if len(sys.argv) != 3:
    print("Not enough parameters!");
    print("Usage > python server.py  ");
    exit(1);

# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM);

# Bind the socket to the port
print("Connecting to " + sys.argv[1] + ":" + sys.argv[2]);
sock.bind((sys.argv[1], int(sys.argv[2])));

# Listen for the incoming connections
sock.listen(1);

while True:

    # Wait for a connection
    print("Waiting for a connection");
    connection, client_address = sock.accept();
 
    try:
 
        print("Connection from " + str(client_address));

        # Receive the data in small chunks and retransmit it
        while True:
  
            data = connection.recv(256);
            print("RECEIVED: " + data);
   
            if data:
   
  # TO DO: You can send different message
                print("SENT: " + data);
                connection.sendall(data);
    
            else:
   
                print('No more data from');
                break;
            
    finally:
        # Clean up the connection
        connection.close();

When communication with a client is finished, the connection needs to be cleaned up using close(). This example uses a try:finally block to ensure that close() is always called, even in the event of an error.

Client Side

The client program sets up its socket differently from the way a server does. Instead of binding to a port and listening, it uses connect() to attach the socket directly to the remote address. After the connection is established, data can be sent through the socket with sendall() and received with recv(), just as in the server.

import socket
import sys

# Check if the parameters are correctly called
if len(sys.argv) != 3:
    print("Not enough parameters!");
    print("Usage > python server.py  ");
    exit(1);

# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM);

# Connect the socket to the port where the server is listening
print("Connecting to " + sys.argv[1] + ":" + sys.argv[2]);
sock.connect((sys.argv[1], int(sys.argv[2])))

try:
    
    # Send data
    message = "This is the message. It will be repeated.";
    print("SENT: " + message);
    sock.sendall(message);

    data = sock.recv(256);
    print("RECEIVED: " + data);

finally:
    # Clean up the connection
    sock.close();

Basically, server-client communication is implemented like above. But, you should integrate these code with the your code.

Remote SONAR Application Interface

After detecting the objects and their distances by using servo motor and HC-SR04 ultrasonic range sensor, Raspberry Pi will send the data to the laptop over TCP/IP protocol. On the other side, the laptop will display the objects, their distances and the direction of the HC-SR04 sensor. You can see the following videos and (The Graphics Interchange Format)GIF image that shows the interface of the client side. Be careful! For this project we just need the components above. I have many Raspberry Pi Hats and sensors like GPS, GSM etc. I didn't want to remove them from my Raspberry Pi. So, don't worry about the videos.



As you see in the GIF image, red line shows the current direction of the HC-SR04 sensor. It is not omnidirectional. It can only rotate 180° around itself and I restricted the distance 200cm coming from HC-SR04. If it is more than 200cm, It doesn't send anything. The orange dots on the scene, shows the object detected by the sensor. Of course, you can improve the interface. It is just for prototype.

The interface is implemented in Python and OpenCV library is used. Servo motor was very cheap and now it is quite old. Because of that it is not soo precise, when it rotates. If you buy a decent one, it would be great. It is same for HC-SR04, I would like buy better one, instead of using this old one. But, they are good enough for prototyping of course. Just for testing the idea, it is enough. Maybe, in the future I can buy new and better sensors to get better, smooth and accurate results.


If you have any question, you can ask. I did not share the code. But, I explained the whole idea behind of this project. If you need, you should ask for it.

1 comment: