EODBox Documentation Release 1.0

Bailey Winter, Jason Gallant

May 26, 2016

Contents

1 How Does It Work?? 3 1.1 Utilizing Programmable Real-Time Units (PRUs)...... 3 1.2 Device Details and Specifications...... 4 1.3 Run Modes and Data Storage...... 8

2 How Do I Make My Own?? 11 2.1 Getting Started...... 11 2.2 Modifying the BeagleBone for Communication...... 12 2.3 External Storage...... 12 2.4 Modifying the PRU Memory...... 14 2.5 Enable the Real-Time Clock...... 15

3 Indices and tables 17

i ii EODBox Documentation, Release 1.0

Weakly electric fish are capable of both emitting and detecting electric signals called electric organ discharges (EODs). Current methods of recording EODs use multiple pieces of equipment that are fragile, expensive and inconvenient to transport, and rely on commercial software to record and analyze data. The goal of this project was to create a low cost and portable alternative to current research equipment. We created a device that we beleive circumvents these limitations, based the BeagleBone Black Rev C (BBB). The BBB uses a Texas Instruments AM335x 1GHz ARM© Cortex-A8, a reduced instruction computing microprocessor that is capable of running two billion instructions per second. This is powerful processor for its size and is capable of running a full operating system. Our goal was to create a device with a user interface that allows for an adjustable, high- speed sampling rate, a designated run time, adjustable gain, flexible storage, and two ‘run modes’: a raw data recording a mode where EODs are automatically extracted. The device can be broken up into two units: a microcontroller that supplies power and processes the data, and a shield that amplifies and digitizes the signal.

Contents 1 EODBox Documentation, Release 1.0

2 Contents CHAPTER 1

How Does It Work??

1.1 Utilizing Programmable Real-Time Units (PRUs)

The BBB runs a Debian Linux operating system which is not preemptive and cannot interrupt a kernel code once it begins executing. This causes an issue, as it does not allow for data collection in real time if the software is run on the main processor. To overcome this issue I had to make use of the processor’s programmable real time units (PRU). The PRUs operate as shown: First, a device overlay must be created and applied that configures and enables the GPIO pins. Then two different codes need to be written. The PRU code (Fishy.p) instructs the PRU on how to operate. This code is compiled in to a PRU program binary which can be interpreted by the PRU. The Linux host program (Fishy_v1.c) loads the PRU program binary to the PRU. The host program also communicates between the PRU and the Linux host. It is responsible for receiving and sending interrupts to and from the PRU. The PRU code is written in the assembly language and instructs the PRU to write the digitized data to a memory buffer. The buffer is only large enough to hold four seconds of data when the highest sampling rate is selected. Originally, the PRU code was written so that the program would end once the buffer was full; however, it is necessary to record more than four seconds of data. The program has been modified to create a circular buffer, so when the memory buffer is filled, the PRU returns to the beginning of the buffer and overwrites the previous data. As mentioned earlier, the Linux host program transfers the PRU binary and acts as a communication bridge between the PRU and the Linux host. When the memory buffer was finite, the host program only loaded the PRU binary to the PRU and a separate program was written to retrieve the data from the memory. Now that the memory buffer is circular and data analysis is required to occur in real time, the host code had to be altered to both read and analyze the data in the memory buffer as it was being written. In order to read the memory buffer, the buffer needs to be broken into segments that are read through individually. The current memory address is denoted as the variable “tail”, the beginning of the buffer segment is denoted as the variable “last_read_result” and the end of the segment is denoted as the variable “read_result”. By breaking the buffer into segments two situations can occur: 1. read_result > last_read_result

In this situation the process is quite simple. A “for loop” iterates from last_read_result to read_result. With each iteration, the value stored in the memory address at tail is read and tail_position, position of the tail in the memory

3 EODBox Documentation, Release 1.0 buffer, is moved two bytes. Once the end of the loop is reached last_read_result is set to read_result and the two are compared again. If the comparison reveals the same situation, the process is repeated. 2. read_result < last_read_result

In this situation arises when read_result reaches the end of the memory buffer and loops back around, but last_read_result has reached the end yet. In this situation a two part copy needs to be made. First the difference between the end of the buffer and last_read_result is calculated. A “for loop” iterates through these end point in the same manner as described in Situation 1. The program then iterates through another for loop that starts at the start of the buffer and ends at read_result.

1.2 Device Details and Specifications

The shield that attaches to the BBB contains the entire circuit that is responsible for amplifying and digitizing the signal. This circuit is based on the Backyard Brains Muscle SpikerBox and has been modified for the purposes of this project. The circuit can be broken down into several subunits that perform individual functions.

1.2.1 Power Supply

The first subunit of this circuit is the power supply unit, which creates a constant supply of the voltage supply divided by two.

This unit is largely unchanged from the original design. Additional decoupling capacitors, C1 and C12, have been added and preexisting ones, C2 and C13 have been reconfigured. C1 and C12 stabilize the supply voltage, VCC, by removing any high frequency oscillations from the signal. C2 and C13 do the same for VCC/2. The LED is used as a visual cue to tell the user when the shield is being powered. The constant VCC/2 output from the op-amp is

4 Chapter 1. How Does It Work?? EODBox Documentation, Release 1.0 accomplished using a negative feedback amplifier circuit. Connecting the output of the amplifier to the inverting input should result in an output that follows closely to the non-inverting input. As the non-inverting input voltage input increases, the output voltage increases with accordance to the differential gain. Because the output voltage is fed back into the inverting input of the op-amp, the difference between the inputs will decrease causing the output voltage to decrease. Over time this stabilizes to output a voltage nearly equal to the non-inverting input voltage, but still low enough that the difference between the two inputs can generate the output voltage.

Note: Currently, the entire shield is powered by the 3.3 V output from the BBB. The BBB itself is powered by a laptop via a microUSB, limiting where and how the device can be used. The board can be modified in the future to provide power through a battery.

1.2.2 Real Time Clock (RTC)

The second subunit is the real time clock (RTC) circuit. The BBB does not have an onboard RTC circuit, making it incapable of keeping the date and time. The filenames depend on the date and time an experiment is performed making it necessary to add a separate RTC circuit to the board itself.

The RTC chip is supplied with 5V from the BBB, with C11 as a decoupling capacitor, from the BBB to enable it to communicate with the microcontroller. An additional 3 V coin-cell battery is used to allow the RTC to retain the date and time when it is not being powered by the BBB. A quartz crystal regulates the electronic frequency oscillator. This keeps the oscillator at a very precise frequency, resulting in a highly accurate clock. RTC_SCL and RTC_SDA connect to input pins on the BBB and are the communication lines between the RTC circuit and the microcontroller. In some designs, there are 2.2 kΩ resistors between RTC_SCL and the supply voltage, and RTC_SDA and the supply voltage. Removing these resistors makes the BBB to use internal pullup resistors, forcing the BBB to communicate at 3.3 V instead of 5 V thus preventing the BBB from damage.

1.2.3 Amplifier

The next subunit is the circuitry which takes in and amplifies the EODs. This subunit will be broken down into sections and described individually. The first subsection is where the signal is input into the circuit.

1.2. Device Details and Specifications 5 EODBox Documentation, Release 1.0

The signal is inputted into the circuit through an XLR connector and consists of a positive input, negative input, and ground. The positive and negative inputs are connected to the non-inverting and inverting inputs of the differential op-amp respectively. This op-amp outputs the difference between the non-inverting and inverting inputs with a gain of one. The circuit contains two stages of amplification. The first stage amplifies the signal before filtration occurs to reduce the amount of noise that is amplified. The signal is then amplified further to achieve the desired amount of amplification.

The user can control the amount of gain in each stage using a dip switch to select gains of 1X, 10X, or 100X. The first three switches alter the gain of the first stage, and the last three alter the gain of the second stage. Only one switch from each group should be in the “ON” position to obtain the designated gains. If more than one switch in each region is in the “ON” position, resistors would be put in parallel, altering the amount of gain. The total amount of gain is calculated by multiplying the gain of stage one with the gain of stage two. This results in a gain range of 1X to 10,000X. The filtering stage is a single order low-pass filter with a cut-off frequency of 55 kHz. The dB amplitude of the signal will begin to noticeably decay around when the frequency of the signal passes 10 kHz. The EODs being studied are around 1 kHz, making this design suitable for the project’s purposes. The amplification and filtering stages are comprised of inverting amplifiers, meaning the signal experiences a 180° phase shift every time it passes through an op-amp. Additionally, an offset voltage, VCC/2, is applied to each op-amp essentially shifting the zero line from 0 V to VCC/2. This is required because the analog to digital converter is not capable of reading negative voltages, and would therefore not see the negative deflections of the waveforms.

6 Chapter 1. How Does It Work?? EODBox Documentation, Release 1.0

1.2.4 Analog to Digital Conversion

After the signal has been amplified and filtered, it is passed to the analog to digital converter (ADC) where it is digitized and sent to the BBB to be processed. The wiring for the ADC is shown below.

The ADS7883 is capable of sampling up to 1 Msps and as low as 100 ksps. As previously discussed, the sampling rate, can be altered in the software. This added flexibility allows the user to determine how detailed the digitized waveform will be. If the user only wants a preview of the waveform, a lower sampling rate can be chosen so as to not waste memory space.

1.2.5 Speaker Output

The final unit of the circuit is a speaker output. The output from the final stage of amplification is first fed through a 10 kΩ potentiometer. The potentiometer is a variable resistor that can be physically adjusted by the user to control the amplitude of the sound. This op-amp does not need an offset voltage as the speaker is an analog device. The speaker is useful for determining if the experimental set-up is correct. If the probe is close enough to the fish, the EODs will make a clicking sound on the speakers.

1.2. Device Details and Specifications 7 EODBox Documentation, Release 1.0

1.3 Run Modes and Data Storage

Even though the entire memory buffer is read, what information is stored depends on the operational mode chosen by the user. There are two different run modes: Run Mode 0, which collects raw data, and Run Mode 1, which collects only EODs. The data is saved to a .EOD file whose format changes depending on the selected operation mode. Both operation modes contain the same header at the beginning of a file. The header includes a description of the file itself and the metadata, which contains information on both the subject and experimental set-up. After the header, the actual data values are written to the file. If Run Mode 0 is chosen, the data will consist of a continuous string of data values. If Run Mode 1 is chosen, the timestamp will be printed followed by the corresponding EOD values. Unlike in Run Mode 0, each timestamp and EOD is printed on a new line. All data besides the header is saved as hexadecimal values to reduce file size. Details on Run Mode 1 When Run Mode 1 is selected, an additional file is created. Unlike the .EOD file, this file is not permanent. The file contains only the separate EODs which are written as space-separated values. This file is used to create a pop-up window that graphs the EODs using gnuplot. The separate EOD traces are overlaid, allowing the user to get a preview of the waveforms that are being recorded or determine if there are issues with the set-up. This file is then deleted at the end of the program to conserve memory space. In Run Mode 0 every data point that is read is saved to a file; however, if Run Mode 1 is chosen only the EODs should be saved. The program determines and EOD has occurred if a threshold has been reached. The threshold is calculated based on standard deviation, which is normally calculated using on the equation:

Unfortunately using this method to calculate standard deviation in not possible. The program is written in the C programming language and a datatype of “int” is assigned to both the value of the sample and the value of the mean. The highest value of an “int” datatype is +2147483647. An amplitude of 0 V corresponds to a value of 2048 when digitized. If a constant 0 V is fed to the analog to digital converter, at a maximum sampling rate of 1 Msps the sum of the sample values will exceed the maximum value in a little over one second. Because of this, the threshold must be calculated using an exponential moving mean and standard deviation using the equations below.

The closer the value of (1 – 훼) is to 1, the larger the impact the previous values have and the less impact each new sample has on the mean or variance. For this program, 훼 was chosen to have a value of 0.000001, so that samples that deviate greatly from the zero line, like the values that make up EODs, do not alter the mean significantly, keeping the mean constant. The same idea is applied to the variance. This approach causes a time delay before the mean reaches a constant value, requiring a mean to be established before checking for EODs. At the beginning of the code, the program pauses to allow a sufficient amount of data points to be available before calculating an initial mean. The initial mean is calculated by summing the first one thousand data points and dividing by the same number of data

8 Chapter 1. How Does It Work?? EODBox Documentation, Release 1.0 points. Once the initial mean has been calculated, the buffer is reread from the beginning and analyzed for EODs. An EOD is detected by comparing the value of the current data point to the threshold. If the value is greater than or equal to the threshold, then the deviation from the mean is considered significant and an EOD has occurred. If an EOD is detected, a timestamp, indicating when the EOD occurred, and a 2 ms time window of data is recorded with the peak amplitude of the EOD centered in the window. When writing the data to the file, similar situations occur as described when reading the data from the memory and are handled in the same manner.

1.3. Run Modes and Data Storage 9 EODBox Documentation, Release 1.0

10 Chapter 1. How Does It Work?? CHAPTER 2

How Do I Make My Own??

2.1 Getting Started

Before connecting the BeagleBone, go to https://beagleboard.org/getting-started and download the drivers for your computer. The BeagleBone Black will come with a USB to microUSB that can be used to both power and communicate with the BeagleBone. Using the microUSB ssh into the BeagleBone through PuTTy or another SSH client. The IP address for logging in over the microUSB is 192.168.7.2 and is standard for each BeagleBone. The BeagleBone is also accessible over Ethernet and WiFi; however, the IP address will be unique to each BeagleBone when using these methods and that will be discussed later. The login window for PuTTy is shown below.

Sessions can be saved after entering the IP address by entering a name in the “Saved Sessions” box and clicking on the “Save” button. Doing this will not only save the IP address information, but any settings that you have altered under the categories listed on the left. Log in to the BeagleBone as “root”. Once you have logged in, the BeagleBone will ask for a password. By default there is none and hit “Enter” to continue. Now you are within the BeagleBone’s Debian Linux system. Additionally, it is useful to easily transfer and navigate the files stored on the BeagleBone. The file system can be navigated using Linux commands; however, it is not as easy to transfer the files between the BeagleBone and your computer from the command line. For this reason, a SFTP client is recommended. A list of applications for both Windows and OS X is in Appendix A. The login is similar to when using PuTTy.

11 EODBox Documentation, Release 1.0

2.2 Modifying the BeagleBone for Communication

The BeagleBone must be modified to enable communication with the shield in order to function properly. Follow these steps to do so: 1. Enable the pins and slots. To do so, enter the following commands into the command line:

export SLOTS=/sys/devices/bone_capemgr.*/slots export PINS=/sys/devices/debug/pinctrl/44e10800.pinmux/pins

Note: the “*” indicates that this value differs depending on which version of Linux your BeagleBone has. To have this value automatically filled out for you, hit tab when typing the “bone_capemgr.*” portion of the command. 2. To enable these on startup the ,profile file needs to be edited. To do this enter the command: nano ~/.profile

And copy the following configuration: ~/.profile: executed by Bourne-compatible login shells.

if [ "$BASH" ]; then if [-f ~/.bashrc ]; then .~/.bashrc fi fi mesg n export SLOTS=/sys/devices/bone_capemgr.9/slots export PINS=/sys/devices/debug/pinctrl/44e10800.pinmux/pins

3. Save and close the file 4. The HDMI needs to be disabled in order to access the PRUs, disable HDMI by the following commands: sudo mkdir /mnt/vfat sudo mount /dev/mmcblk0p1 /mnt/vfat

5. Edit the uEnv.txt Configuration File by the following: cd /mnt/vfat nano uEnv.txt

The unedited file will have a “#” before the optargs= line. Delete the (#) symbol to disable the HDMI: ##Disable HDMI optargs=capemgr.disable_partno=BB-BONELT-HDMI,BB-BONELT-HDMIN

Note: Warning! There are similar lines also in this configuration file (labeled by the “##Disable HDMI/eMMC”), Uncommenting this line will disable the eMMC as well and the BeagleBone will not boot. This can be corrected by flashing the BeagleBone using an SD card and instructions on how to do this are included in Appendix B.

2.3 External Storage

The BeagleBone has limited storage, but has the capability of using SD card for additional storage space. A script that includes the necessary commands to format the SD card is already written; however, they are also included in the event the script is not available.

12 Chapter 2. How Do I Make My Own?? EODBox Documentation, Release 1.0

1. Insert a new micro-SD card into the slot on the BeagleBone while it is running. You can see it by entering the command: mount -l /dev/mmcblk1p1 on /media/*file location* type vfat ...

2. This will automatically mount the SD card to /media/file location with type vfat. You can check if there is any data on the card by using the following command:

cd /media/*file location* ls -l

3. Next the SD card will be formatted as an ext4 file system. Be careful to select the correct device. In this instance the device is mmcblk1p1 and it may be different when you go through these steps. If there is data on the SD card, it will be erased by these steps:

~/media/*file location*# cd/ umount /dev/mmcblk1p1 mkfx.ext4 /dev/mmcblk1p1

4. Next a mount point will be created for the card, in this case /media/store (note: the mount point does not have to be /media/store; however, the script specifies this location. If you want a different location you will need to edit the script to reflect this change.), and the card will be mounted at this point: cd / mkdir /media/store mount -t ext4 /dev/mmcblk1p1 /media/store cd /media/store mount -l

Note: The –t provided to the mount command indicates the file type. If omitted, “mount” will try to auto-detect the file system type.

5. The available capacity can be checked using the command: df -k

6. Now, the BeagleBone needs to modified to automatically mount the SD card when the BeagleBone boots. This process cannot be automated. You have to mount the device using its UUID (universally unique identifier). Type the following command to find the UUID: blkid/dev/mmcblk1p1

7. Write down the UUID number. In order to mount the SD card automatically the /etc/fstab file needs to be edited. Type the following command: nano/etc/fstab

8. At the end of the file add the following line: UUID=”UUID number” /media/store ext4 defaults,nofail,user,auto 0 0

Note: The options listed in the line are: Defaults: Use default settings nofail: Mount the device when present but ignore if absent user: The user gives permission to mount the file system

2.3. External Storage 13 EODBox Documentation, Release 1.0

auto: The card will be mounted on start-up, or if the user types mount -a Be very careful when editing fstab, particularly this line as it can cause the BeagleBone to not reboot properly or preventing it from booting at all. Where there is separation, two spaces should be present, or an error will occur.

2.4 Modifying the PRU Memory

1. The PRU memory needs to be modified to the size specified in the code. First the device tree overlay needs to be loaded to the slots. Compile EBB-PRU-ADC.dts. Enter the following command: echo EBB-PRU-ADC > $SLOTS

2. The UIO driver must be removed in order to be able to modify the memory. Remove the UIO driver: rmmod uio_pruss

3. Then modify the memory size: modprobe uio_pruss extram_pool_sz=0x7a1200

This sets the memory size to 8,000,000 bytes. 4. The memory must be modified each time the BeagleBone boots up. This process can be automated using a script and creating a service to run the script. The script will include the previous commands. The finished script is shown below: #!/bin/bash echo EBB-PRU-ADC > /sys/devices/bone_capemgr.*/slots rmmod uio_pruss modprobe uio_pruss extram_pool_sz=0x7a1200

Note: Make sure that in whatever source code editor that the script is written in, the EOL is set to Unix/OSX.

5. The script needs to be made executable before it can run. To make it executable enter the following command: chmod a+x .sh

This will make the file executable by all users.

6. Move the script to the /usr/bin directory: mv .sh /usr/bin/

7. Next a systemd service must be created that initiates the script on startup. A systemd service is a file that encodes information about a process controlled by systemd. Create the service by typing: nano /lib/system/.service

And enter the following: [Unit] Description = load device tree and modify memory After= syslog.target [Service]

14 Chapter 2. How Do I Make My Own?? EODBox Documentation, Release 1.0

Type = simple ExecStart = /usr/bin/.sh [Install] WantedBy = multi-user.target

Note: The “[Unit]” section contains the description and start dependencies. The “[Service]” section contains the information about the service and the process it supervises. With the type set to “simple” the process configured in “ExecStart” is the main process of the service. The “[Install]” section is used to define the behavior or a unit if it is enabled or disabled. Enabling a unit marks it to be automatically started at boot.

8. A symbolic link must be created to let the device know the location of the service: cd /etc/systemd/sytem ln /lb/systemd/.service .service

9. Make systemd reload the configuration file. Start the service immediately to see if the service is functioning correctly and enable the unit files specified in the command line: systemctl daemon-reload systemctl start .service systemctl enable .service

Now the service is enabled and will execute the script on startup.

2.5 Enable the Real-Time Clock

1. First declare the Real Time Clock to the kernel: echo ds1307 > /sys/class/i2c-adapter/i2c-1/new_device

2. Check if the Real Time Clock has been loaded to address 68: i2cdetect -y -r 1

If the Real Time Clock has not loaded, then the result should look like this

2.5. Enable the Real-Time Clock 15 EODBox Documentation, Release 1.0

It is also possible that “UU” will appear at address 68. If this is the case a driver is possibly loaded to that address. Remove the driver: echo 0x68 /sys/class/i2c-adapter/i2c-1/delete_device rmmod ds1307

The driver is now unloaded. Repeat the commands from above. If the driver has loaded correctly “68” will appear at address 68. 3. To set the time, first connect an Ethernet cord to the BeagleBone. To get the current UTC time and push that time to the RTC enter the command: ntpdate -b -s -u pool.ntp.org hwclock -w -f /dev/rtc1

4. To have the RTC enabled and read from on startup, add these lines to the beginning of the script that modifies the PRU memory: echo ds1307 0x68 > /syds/class/i2c-adapter-i2c-1/new_device hwclock -s -f /dev/rtc1 hwclock -w

16 Chapter 2. How Do I Make My Own?? CHAPTER 3

Indices and tables

• genindex • modindex • search

17