close-circle
Close

#buildinstructions for hardware: elephant deter devices

A project log for Elephant AI

a system to prevent human-elephant conflict by detecting elephants using machine vision, and warning humans and/or repelling elephants

Neil K. Sheridan 09/24/2017 at 18:510 Comments

INTRODUCTION

The elephant detection component of the system will communicate with these using Bluetooth (100m supposed range). We can go ahead and power them using the same solar/lead acid battery component that we use for the elephant detection components, or if they are isolated (e.g. >5m away) we will have to give them their own solar/lead acid battery components. At present if they receive a message having a deter=yes they will go ahead and play audio files of bee sounds. It will be a pseudo-random choice of bee audio file, to prevent elephant habituation to a single bee sound.

For these the primary parts are:

1. JustBoom Amp Zero pHAT for the Raspberry Pi Zero (£24)

2. Raspberry Pi Zero W with Soldered Header (£14) 

of course you can solder them on yourself, which would mean a cost of £9 + headers e.g. £1

3. micro SD card with operating system installed. I've used 16GB with NOOBS pre-installed (£9.99)

4. Power supply e.g. solar and lead acid battery 

5. Speakers x2; it's flexible e.g. old hifi speakers, old external laptop/PC speakers, etc. I'm using two waterproof 5V 4Ohm speakers from ebay (£11 each)


ATTACHING THE AMP ZERO TO THE PI ZERO W

First we need to attach the amp zero HAT to the pi zero! This is really easy and you just need a tiny phillips screwdriver to do it. There are 4x metal spacers (well they look like nuts really), and 8x metal bolts. There's a full guide here https://www.justboom.co/start/set-up-justboom-amp-zero-phat-and-case/ but I will summarise the instructions too:

1. Put you SD card into the pi zero card reader slot!


2. Fit your nuts/spacers and secure them to the pi zero with bolts


3.  Gently attach the Amp Zero female header to the Pi Zero male header. Push down to do this.


Here's the Amp Zero prior to attachment. You can see the female header at the back. And the 4x speaker outputs + 3.5mm jack at the front.


4. Screw in your last 4x nuts to the holes in amp zero - so securing the two devices together

5. The Amp Zero power usage configurations (for different speakers) are here: https://www.justboom.co/technical-guides/amp-boards-power-specifications/ remember that the Pi Zero is back powered from the Amp Zero (so you don't need to power it)

6. For testing, I'm using a 24 Volt 3.75 Amp 90 Watt Power Supply. You can go ahead and connect your keyboard, mouse, and monitor to the Pi Zero now. And your power supply! Then we are ready for the next stage. Remember that Pi Zero has a mini HDMI socket. So you'll need a mini HDMI to HDMI adaptor. It also has micro USB sockets for keyboard/mouse, so you'll need adaptors.

7. I think it's best to put the setup (pi zero + amp zero) into a box at this stage! After you've connected the keyboard, mouse, power, and the mini HDMI, it kind of keeps getting dragged about by the cables. Mine fell on the floor several times. And I ended up handling it so much it was destroyed -by ESD (i.e. static discharge)  I think :-( I

TESTING AND SETTING UP SOFTWARE, ADDING SPEAKERS

[not completed section yet.......]

8. Now we need to configure Raspian OS to use the Amp Zero for sound output.  First open the config.txt  file with the command on your raspberry pi:

sudo nano /boot/config.txt

Now scroll down the file until you reach the line:

dtparam=audio=on

You should comment this out with #, so you will have:  

#dtparam=audio=on

 Now, go ahead and add these new config instructions:

dtparam=audio=off
dtoverlay=i2s-mmap
dtoverlay=justboom-dac


 *Check the Just Boom website to confirm these config commands are correct! https://www.justboom.co/software/configure-justboom-with-raspbian/

9.

Now we need some speakers! You can decide on which speaker to use according to the power requirements you are able to fulfil, and what you can get cheaply! 

You can buy waterproof speakers, or you can water-proof some yourself! You can even build your own speaker cabinet if you want! I just purchased some cheap waterproof speakers from ebay for £11 each. My speakers are 5V 4Ohm 'Weatherproof Communication Extension Speaker B185' .

First of all I cut off the 3.5mm jack that came on the end of the speaker input cables, and stripped the wires to attach to the speaker output terminals on the Amp Zero. 

Then I attached the wires to the speaker output terminals of the Amp Zero. There are four output blocks. From the left: outputs 1 and 2 for the first speaker, outputs 3 and 4 for the second speaker. The -ve output is first, then the +ve output, same again for the second speaker. See image below:

10. 

Now we can get to playing the bee sounds and/or tiger sounds/other sounds!

I downloaded wav files from freesound.org. The audio files here are licensed under Creative Commons Attribution 3.0 Unported (CC BY 3.0)  https://creativecommons.org/licenses/by/3.0/

So the bee sounds I used are:

bees1.wav http://freesound.org/people/Benboncan/sounds/73370/ attributed to user: http://freesound.org/people/Benboncan/ | licensed under https://creativecommons.org/licenses/by/3.0/

It might be a great idea to record sounds of local bees that are known to the elephants, and use these instead for your system! The same with local tigers, and perhaps local people shouting too!

I've gone ahead and saved these to a directory called deter_elephants

The bee sounds/scare_sounds are played using aplay - a linux command line player for the ALSA soundcard driver (http://manpages.ubuntu.com/manpages/trusty/man1/aplay.1.html)

The following code can be used to play them:

import time
import random
import os
scare_sounds = ['aplay bees1.wav', 'aplay bees2.wav', 'aplay bees3.wav']
i = 0
while i < 4:
    i = i+1
    to_play = random.choice(scare_sounds)
    print(to_play) #debug
    os.system(to_play)
    time.sleep(1)

We import time, random and os. We execute aplay use os.system(aplay filename). The command to execute on command line (i.e. "aplay") and the file to pass to aplay (e.g. "bees1.wav") are all stored in the scare_sounds list. 

So random.choice will pseudo-randomly pick a list item and put it into to_play variable (e.g. "aplay bees3.wav") and then os.system will execute this.

The while loop is set to run while i is less than 4. You can adjust this to how long you want to continue playing the scare_sounds. It depends on the length of your scare_sound audio files and how long you think it will take to deter the elephants! So that needs some field research to determine!

So we've got that python code saved as scare_sounds.py into deter_elephants directory, and the bee%.wav files saved into the deter_elephants directory! Now we can go ahead and run it!

Here are the sounds of the bees after we run that code!

COMMUNICATING WITH THE DETER DEVICE VIA BLUETOOTH

11. We can use the PyBluez library https://github.com/karulis/pybluez "python extension module allowing access to system Bluetooth resources [free license update details] and http://www.bluez.org/about/ Bluez "official linux bluetooth protocol stack" to do this [unknown license update details]. Or we can use python sockets which support Bluetooth instead (for python 3.3.x that is).

Let me say in advance! Now is the time to pair your deter device with the detection device so they can communicate via Bluetooth! It's easy in the GUI. Just head to the Bluetooth icon on the top right of screen for your deter device and select add device (the other device i.e. detection device should be set via its Bluetooth GUI menu to discoverable when you do this). 

First, make sure serial profile is loaded:

sudo sdptool add SP

We can have two scenarios:

A. Deter device constantly acts as server, waiting for a deter=yes message from the detection devices. The detection device acts as client. Here we can't report back to the deter devices if we performed a deter successfully or not.

B. Deter devices acts as server. Detection device acts as client. Once the deter device has received a deter=yes message, it will run its scare code, then it will switch to client. The detection device switched to server after it sent the deter=yes message, and will now be listening for a confirmation message back from the deter device!

Regardless of scenario deployed, we need to get a MAC address for the Bluetooth adaptor on the respective devices.

We can use the following command to get the MAC address:

hciconfig

And we should get back something like  43:43:A1:12:1F:AC (which is what I got). You shouldn't get something like AA:AA:AA:AA:AA:AA. That is not good!

Ok, so we are going to use the second scenario, since we want the deter device to report back to the detection device if it performed a deter. First, let's do the test code for using native python sockets. It's similar to our code for communicating between the detection devices using Ethernet!

First for the server, so this is what the deter device is running:

import socket
hostMACAddress = '00:1f:e1:dd:09:3d' 
# The MAC address of a Bluetooth adapter on the server. 
# Which we got using hciconfig
port = 9 
# anything that isn't in use
backlog = 1
size = 1024
s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM)
s.bind((hostMACAddress,port))
s.listen(backlog)
try:
    client, address = s.accept()
    while 1:
        data = client.recv(size)
        if data:
            print(data)
            client.send(data)
        # echo back to client that we got the data
except:    
    print("Closing socket")    
    client.close()
    s.close()
if data == "yes_audio":
    deter = 1
# if the data sent from the client (detection device) was "yes_audio" we
# set deter to 1

 Secondly for the client (detection device):

import socket
message = "yes_audio"
serverMACAddress = '00:1f:e1:dd:08:3d'
port = 9
s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM)
s.connect((serverMACAddress,port))
while 1:
    s.send(bytes(message, 'UTF-8'))
s.close() 

 Now we switch the detection device to the server:

import socket
hostMACAddress = '00:1f:e1:dd:08:3d' 
# The MAC address of a Bluetooth adapter on the server. Which we got using hciconfig
port = 9 
# anything that isn't in use
backlog = 1
size = 1024
s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM)
s.bind((hostMACAddress,port))
s.listen(backlog)
try:
    client, address = s.accept()
    while 1:
        data = client.recv(size)
        if data:
            print(data)
            client.send(data)
except:    
    print("Closing socket")    
    client.close()
    s.close()
if data == "done":
    deter_done = 1
else:
        deter_done = 0
# so if the data we got back from the deter device was "done" we know it did the deter, else we can assume it failed

Now we switch the deter device to client, so it can send the "done" message to the server (detection device):

import socket
message = "done"
serverMACAddress = '00:1f:e1:dd:08:3d'
port = 9
s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM)
s.connect((serverMACAddress,port))
while 1:
    s.send(bytes(message, 'UTF-8'))
s.close() 

Now, let's do test code for doing this with  PyBluez instead. This is best for doing device discovery and Bluetooth service advertisements, and if you don't have python 3.3.x.

First for the server, so this is what the deter device is running:

import bluetooth
hostMACAddress = '00:1f:e1:dd:08:3d' 
port = 9
backlog = 1
size = 1024
s = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
s.bind((hostMACAddress, port))
s.listen(backlog)
try:
    client, clientInfo = s.accept()
    while 1:
        data = client.recv(size)
        if data:
            print(data)
            client.send(data) 
        # echo back to client so it knows we got the data
except:    
    print("Closing socket")
    client.close()
    s.close()
if data == "yes_audio":
    deter = 1
# if the data sent from the client (detection device) was "yes_audio" we
# set deter to 1

 Secondly for the client (detection device):

import bluetooth
message = "yes_audio"
serverMACAddress = '00:1f:e1:dd:08:3d'
port = 9
s = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
s.connect((serverMACAddress, port))
while 1:
    s.send(message)
sock.close()

 Ok, so I won't do the others, it's just the same thing, but with a different way of setting the sockets.

[video]

12. What kind of data is the detection device going to be sending?

Well it was intended to send a JSON file as a string. We looked at making these files for each detection alert in this log https://hackaday.io/project/20448-elephant-ai/log/67563-messaging-formats-example-of-json-alert-message-file . So in this scenario, the deter device is going to parse that string for:

"deter" : {
    "deterdone" : "no",
    "deteraudio" : "no",
    "deterphysical" : "no"

And if it gets deteraudio as having "yes" after the ":" then it can go ahead and run the code in part 10. Then the server (deter device) will send a modified JSON back to the client as a string with the deterdone "no" changed to "yes".

Now we do need two of these things! We need the detection device to send data telling the deter device to perform the deter (i.e. play scare_sounds), and we do need the deter device to send data to the detection device it has run this code for the time we've specified. It's important for the detection device to know if deter has occurred, since this information is required by the system users. But do we need to bother with sending entire JSON messages back and forth? I'm not sure there's any point! 

So we can just work like this:

- Deter device (server) listens on socket

- Detection device (client) sends data "yes_audio" to deter device (server) if elephant spotted and wants a deter done

- Deter device (server) runs the code to randomly play the audio files. Then once loop completes, it sends data "yes_done" back to detection device (client). If something went wrong it would send data back "no" to detection device (client)

Which is a lot easier!

13 Here we go with code to both receive the message from the detection device, play the sounds of bees, and send a message back. Then wait again for a message!

# DETER DEVICE
# this is test code for getting a message via bluetooth from the detection device, and
# going ahead and playing scare sounds
import socket
import time
import os
import random
hostMACaddress = 'xxx'
port = 9
backlog = 1
size = 1024
s = socket.socket(socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM)
s.bind((hostMACaddress, port))
s.listen(backlog)
print("We are waiting for a message from the detection device to arrive via bluetooth!")
try:
    client, address = s.accept()
    data = client.recv(size)
    if data:
        print(data)
        client.send(data)
        #echo back
except:
    print("closing the socket")
    client.close()
    s.close()
message = str(data)
#convert the data received to a string
print(message)
if message == "b'yes_audio'":
    print("play scare sounds now")
    time.sleep(3)
    scare_sounds = ['aplay bees1.wav', 'aplay bees2.wav', aplay bees3.wav']
    i = 0
    while i <10:
        i = i+1
        to_play = random.choice(scare_sounds)
        print(to_play)
        os.system(to_play)
print("Finished scare. Now can message detection device, and await another message from it")

 Ok, let's go ahead and see that in action with this video. Warning! Don't play this when you're near to a beehive!!

14. 

Now we need our code to run on startup! So when the Pi Zero comprising the deter device has power and boots, we execute our python code!

We need to edit /etc/rc.local

So edit with command:

sudo nano /etc/rc.local

Then add the following:

python /home/pi/deter_elephants/deter_device_code.py &

 The ampersand (&) will allow the command to run in a separate process, so raspberry pi booting  can continue with the process running.

15. 

Now all the hardware and software is completed, we can put our elephant deter devices into a waterproof housing.

We need to drill holes into the housing for +ve and -ve power wires from the solar charging circuit/battery. And we need to drill holes for the four speaker output cables from the Amp Zero.

I mounted my speakers on the top of the housing by drilling 4 other holes and using nuts and bolts!

There are many different solutions to housings and speakers!

Discussions