BirdNET-Pi Bencheng

From Sensors in Schools
Jump to navigation Jump to search

Introduction

For help just search for mediawiki formatting

Configuration of Raspberry Pi

To include photo - just click on Upload file on the left Upload file / image Then copy file name and place here using following format...


  • Step 1: Download the Raspberry Pi Imager

Download link: https://www.raspberrypi.com/software/

  • Step 2: Insert the sim card into the adapter and plug it into the computer.
  • Step 3: Choose Raspberry Pi OS Lite(64-bit) as the Operating System.


  • Step 4: Choose storage space

(If nothing is available it’s because the sim wasn’t recognized. Unplug it and insert again.)

  • Step 5: Advanced Options

Click the gear icon at the right bottom of the interface.

  - Step 5.1 Set username and password
   
  Here we set the username and password of the Raspberry Pi. They will be used in later steps so remember to take notes of them lest you forget.
  
  - Step 5.2 Configure wireless LAN
   This is where you specify the WIFI that is going to be connected to Raspberry Pi. These specifications can be altered later.

(Note that you must choose the Wireless LAN country to be the country you are currently in.)


  - Step 5.3 Set locale settings
   Choose the right time zone and set the Keyboard layout as “us”.
  • Step 6: Once the above steps are finished, click “write” on the right of the interface.

The writing and verification process takes a few minutes.

  • Step 7:

Unplug the adapter, pull out the sim card and gently place it into the Raspberry Pi board;

Then connect the keyboard and monitor to the Raspberry Pi;

Turn on the monitor and then plug in the power cable.

When the starting process is over, you will be able to see the interface shown below:

Insert Picture Later

Now the Raspberry Pi computer is ready to use!

Extracting Data from MPPT

tar -xvf arduino-1.8.19-linuxarm.tar.xz
The first thing to do is using crontab
The password of Raspberry Pi has been changed to techschool.

In this section, we'll go through the procedure of reading data from MPPT.

What is MPPT

MPPT stands for Maximum Power Point Tracking, which is a technique used in photovoltaic (solar) systems to optimize the power output from solar panels or arrays. MPPT is particularly important in situations where the amount of available solar energy varies, such as when clouds pass over the panels or when the angle of sunlight changes throughout the day.

Solar panels have what's known as a "maximum power point," which is the voltage and current combination that results in the highest power output from the panel. However, this point can shift based on factors like temperature, shading, and the angle of the sunlight. MPPT algorithms and controllers continuously adjust the electrical load on the solar panel to keep it operating at or near this maximum power point, thus maximizing the energy harvest from the available sunlight.

Here's how MPPT works:

  • Measuring Inputs: MPPT systems constantly monitor the output voltage and current of the solar panel or array.
  • Calculating Power: By multiplying the output voltage and current, the system calculates the instantaneous power being produced by the panel.
  • Adjusting Load: The MPPT algorithm compares the calculated power to previous readings and adjusts the electrical load on the panel. It does this by varying the voltage at which the solar panel operates, typically by adjusting a DC-DC converter. This process is done in a way that tries to keep the panel's output at or close to its maximum power point.
  • Optimizing Harvest: By dynamically adjusting the load, the MPPT system allows the solar panel to operate at its optimal voltage and current levels, even as external conditions change. This maximizes the power output of the panel and, consequently, the amount of energy harvested from the sunlight.

MPPT technology is widely used in solar power systems, from small off-grid setups to large-scale solar farms. It increases the efficiency of energy conversion and ensures that as much energy as possible is extracted from the available sunlight, leading to greater overall system efficiency and improved energy production.

Connect MPPT to the battery and Raspberry Pi

At the bottom left of the MPPT, you will be able to see two wires under the label BATT. You should carefully connect the red wire and black wire to the positive and negative of the battery respectively. Then, use VE. Direct to USB interface to connect the MPPT to the Raspberry Pi.


  • Find the port to read data from.

Since we have connected the MPPT to Raspberry Pi through a USB portal, we can use the following command to find the address of the USB portal:


As is shown in the above image, there's a USB portal "/dev/ttyUSB0" at the right bottom of the interface in the red frame. This is where we shall extract reading from the MPPT.

After this step is finished, we are all set to read in data from MPPT.

Extract and Process Data

In this section, we shall write a Python program to extract, process and save the readings from MPPT.

  • The data that needs to be extracted.

https://www.victronenergy.com/upload/documents/VE.Direct-Protocol-3.33.pdf

We can view all the units used by the serial interface from the VEDirect Protocol. However, in this project, we are only interested in the below quantities/states:

1. Main voltage (V)

2. Panel voltage (VPV)

3. Panel power (PPV)

4. Load current (IL)

5. Load output state (LOAD)

6. Yield total (H19)

7. Yield today (H20)

8. Maximum power today(H21)

9. Yield yesterday (H22)

10. Maximum power yesterday (H23)

11. Error code (ERR)

12. State of operation (CS)

13. Firmware version (FW)

14. Product ID (PID)

15. Serial number (SER#)

16. Day sequence number (HSDS)

17. Tracker operation mode (MPPT)

  • Read the state of the MPPT and Smart Shunt at the same time.

Use the below code:

#!venv/bin/python

#import serial
import datetime
from vedirect import VEDirect

# Make sure you specify the ports correctly.
port_0 = '/dev/ttyUSB0'
port_1 = '/dev/ttyUSB1'

ve_0 = VEDirect(port_0,60,'')
data_0 = ve_0.read_data_single()

# Because sometimes it fails to read data from the smart shunt, we need to try multiple times until it works.
ve_1 = VEDirect(port_1,60,'')
flag=0
while(flag==0):
    try:
        data_1 = ve_1.read_data_single()
        flag=1
    except:
        print("Fail!")


datasave_0,datasave_1="","" # These two strings are used to store information from the MPPT and the smart shunt.

# The below two lists store the values that need to be read from the MPPT and the smart shunt.
ls_0=['V','VPV','PPV','IL','LOAD','H19','H20','H21','H22','H23','ERR','CS','FW','PID','SER#','HSDS','MPPT']
ls_1=['H1','H2','H3','H4','H5','H6','H7','H8','H9','H10','H11','H12','H15','H16','H17','H18']

# The below section adds time stamps to the strings so we know the precise time the data is acquired. 
now = datetime.datetime.now()
date_stamp = now.strftime("%Y-%m-%d %H:%M:%S")
data_save_0=date_stamp+'\n'
data_save_1=data_save_0

# A simple typesetting would make the data more presentable.
for i in range(len(ls_0)):
    length=len(ls_0[i])+len(str(data_0[ls_0[i]]))
    data_save_0=data_save_0+ls_0[i]+ " : " + str(data_0[ls_0[i]]) + " "*(20-length)
    if (i+1)%5==0:
        data_save_0=data_save_0+"\n"
    else:
        data_save_0=data_save_0+"|    "

for i in range(len(ls_1)):
    length=len(ls_1[i])+len(str(data_1[ls_1[i]]))
    data_save_1=data_save_1+ls_1[i]+ " : " + str(data_1[ls_1[i]]) + " "*(20-length)
    if (i+1)%5==0:
        data_save_1=data_save_1+"\n"
    else:
        data_save_1=data_save_1+"|    "
data_save_0=data_save_0+"\n\n"
data_save_1=data_save_1+"\n\n"

# Use the below code to write the strings into the '.txt' files. Remember to replace the file path and file name.
open('/home/pi/MPPT/mppt_data_new.txt','w').close()
f=open('/home/pi/MPPT/mppt_data_new.txt','a')
f.write(data_save_0)
f.close

open('/home/pi/MPPT/shunt_data_new.txt','w').close()
f=open('/home/pi/MPPT/shunt_data_new.txt','a')
f.write(data_save_1)
f.close

Secure Shell

A Raspberry Pi is a small, affordable, single-board computer. We can configure and interact with it if we connect it to a keyboard and monitor.


However, it's usually more convenient to access the Raspberry Pi from a remote PC. To this end, we need to use a secure shell(SSH) to connect the Raspberry Pi and the remote PC.

Enabling SSH on the Raspberry Pi

  • Type the command sudo raspi-config in the terminal and the following interface will appear:
  • Choose 3 Interface Options and press enter.
  • Select SSH (Secure Shell) and then select Enable SSH.
  • Now the SSH has been enabled.

Connect the PC to Raspberry Pi

  • Have accomplished the above steps, go back to the main configuration interface.
  • Set up WIFI connections.
  • Open the terminal on another computer.
  • Connect this computer to the same network(WiFi).
  • Type the following command in the terminal then press enter.
ssh <name of your Raspberry Pi>@<IP address of your Raspberry Pi>

The name of Raspberry Pi is set by you and you can find the IP address by typing ifconfig in the terminal of Raspberry Pi computer and reading after WAN0.

  • Type in the password of the Raspberry Pi computer.
  • Now the SSH has been done and you can access the Raspberry Pi computer from another computer.
  • After you've finished your operations, type exit in the terminal and end SSH.

Use VE. Direct Bluetooth Smart Dongle to Configure and Monitor the Components

Basics about VE.Direct Bluetooth Smart Dongle

A VE.Direct Bluetooth Smart Dongle is a device used to monitor and control Victron Energy products, such as solar charge controllers, inverters, and battery monitors, via Bluetooth communication. Victron Energy is a company that specialises in energy systems for mobile and off-grid use, and their products are commonly used in recreational vehicles, boats, and off-grid solar power systems.

The main functions include Bluetooth connectivity, monitoring, configuration, data logging, and remote control. Insert a picture here.

Key Parameters

  • Battery voltage
  • Max charge current
  • Absorption voltage
  • Float voltage
  • Equalization voltage

Extract and Visualize Data from Database

DB Browser for SQLite

DB Browser for SQLite is an open-source graphical user interface (GUI) tool that allows users to manage and interact with SQLite databases. This software provides a user-friendly interface for performing tasks such as creating, editing, and deleting tables, indexes, views, and triggers within SQLite databases. It enables users to run SQL queries against their databases, view and modify data, and perform various database management operations without needing to use the command-line interface.

Step 1: Download DB Browser for SQLite Download link: https://sqlitebrowser.org/dl/

Step 2: Familiarize with the interface of the DB Browser for SQLite

  • Open the bird.db file in the database, and then the below interface will be shown.
  • As is shown above, the database contains two parts: Tables and Indices.
  • Click on the Browse Data highlighted in the red box and the following interface will show.


  • Demonstrated above are the contents of the table "detections".
  • Each row is a record of one bird detection while each column contains distinct information of the records such as Date, Time, name of the Species, etc.

Structured Query Language

Step 3: Learning the basics of SQL SQL, which stands for Structured Query Language, is a domain-specific programming language used for managing and manipulating relational databases. Here is a link for a brief tutorial for SQL language: https://www.w3schools.com/sql/default.asp

Step 4: Understand some relevant Python libraries

  • sqlite3 is a library in Python that provides a simple and convenient way to work with SQLite databases, which are self-contained, serverless, and file-based databases.
  • If you haven't installed this library, type the below command in the terminal for installation.
pip3 install sqlite3
  • Now, you can easily write SQL inquiries in Python to extract data from .db files.

Analysing the Detections of Bird Calls

Once the data regarding bird detections are stored in the database, we can use SQL to extract information from it and do some basic analysis. Here are a few examples:

1. Find out the proportion of detections for different species.

  • The proportions of detections give us a general idea of the abundance of different bird species which is crucial information regarding local ecology. Here we'll find the 15 bird species with the most detections and plot their proportions in a pie chart.
  • The code for it is shown below:
import sqlite3
import plotly.graph_objects as go

conn = sqlite3.connect('./birds.db')
# Create a cursor
cursor = conn.cursor()


# Execute a CREATE TABLE query
create_table_query = '''
CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY,
    username TEXT,
    email TEXT
)
'''
cursor.execute(create_table_query)

# Commit changes and close the connection


# Query data
select_query = 'SELECT DISTINCT Com_Name FROM detections;'
cursor.execute(select_query)
rows = cursor.fetchall()


# Find out the number of detections of each species.
query='SELECT COUNT(File_Name) FROM detections WHERE Com_Name = \''

new_row=[] # Records the name of the species and the number of detections.
count=0    # Records the total number of records.

for i in range(len(rows)):
    new_row.append([rows[i][0],0])
    new_query=query+rows[i][0]+'\';'
    cursor.execute(new_query)
    res = cursor.fetchall()
    new_row[i][1]=res[0][0]
    count+=res[0][0]

for i in range(len(rows)-1):
    for j in range(i+1,len(rows)):
        if new_row[i][1]<new_row[j][1]:
            inter=new_row[i]
            new_row[i]=new_row[j]
            new_row[j]=inter

#print(new_row)
labels=[]
values=[]
partial_sum=0
for i in range(15):
    labels.append(new_row[i][0])
    values.append(new_row[i][1]/count*100)
    partial_sum+=new_row[i][1]
labels.append('All Other Species Combined')
values.append((count-partial_sum)/count*100)

# Create a pie chart using Plotly Express
fig = go.Figure(data=[go.Pie(labels=labels, values=values,sort=False)])
fig.update_layout(
    title=dict(text="Proportion of Detections", font=dict(size=30), automargin=True, yref='paper')
)
# Show the chart
fig.show()

conn.commit()
conn.close()
  • The pie chart will be shown on a webpage:
  • If you click on one of the legends to remove certain species from the pie chart, the proportions of the remaining species will be automatically calculated.

For example, we can remove the species Noisy Miner from the pie chart by clicking on the legend.

The new pie chart doesn't include Noisy Miner and the proportions of other species are recalculated.


2. Analyse the hourly behaviour pattern of a bird species.

  • Sometimes, we want to find out when certain bird species are active and when they are dormant.
  • To achieve this, we can sort all the detections of these bird species by hour and generate a bar chart.
  • The code for this purpose is shown below:
import sqlite3
import pandas as pd
#import plotly.graph_objects as go
import plotly.express as px

# Specify the location of the '.db' file that contains the information.
conn = sqlite3.connect('./birds.db')
# Create a cursor
cursor = conn.cursor()


# Execute a CREATE TABLE query
create_table_query = '''
CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY,
    username TEXT,
    email TEXT
)
'''
cursor.execute(create_table_query)

# Commit changes and close the connection


# The users will type in the name of species they want to inquire about.  
species_name=input("Please type in the name of bird species:")

# The corresponding SQL inquiry command is specifies below.
select_query = 'SELECT * FROM detections WHERE Com_Name = \''+species_name+'\';'

cursor.execute(select_query)
rows = cursor.fetchall()

Total=len(rows)
Hour=[] # Hour stores how many records are there for each hour in a day and we initiate it to be a zero vector (1*24).
labels=[]

for i in range(24):
    Hour.append(0)
    if i==0:
        labels.append('12am')
    elif i<=11:
        labels.append(str(i)+'am')
    elif i==12:
        labels.append('12pm')
    else:
        labels.append(str(i-12)+'pm')

# Here we go through all the records of bird species the user typed in 
# and count how many are there for each hour.

for i in range(Total):
    hour=(ord(rows[i][1][0])-ord('0'))*10+ord(rows[i][1][1])-ord('0')
    Hour[hour]+=1

data={'Hours In A Day':labels,
      'Number of Detections':Hour}

df = pd.DataFrame(data)

fig = px.bar(df, x='Hours In A Day', y='Number of Detections')

# You can modify the below command to generate a different layout.
# For more information, see  https://plotly.com/python/reference/layout/.
fig.update_layout(
    title={
        'text': "Hourly Analysis for "+ species_name,
        'y':0.95,
        'x':0.5,
        'xanchor': 'center',
        'yanchor': 'top',
        'font' : dict(size=30)
        },
    title_font_color='purple',
    font_color="black"
)

fig.show() # Show the graph drawn.

# Here we close the inquiry.
conn.commit()
conn.close()
  • The above code lets users type in the name of the species they want to inquire about.
  • Here we demonstrate the bar charts corresponding to Rainbow Lorikeet and Galah respectively.

3. Analyse the monthly behaviour pattern of a bird species.

  • Similarly, we can also analyse the seasonal pattern of detections for bird species.
  • The modified code is shown below:
import sqlite3
import pandas as pd
#import plotly.graph_objects as go
import plotly.express as px

# Specify the location of the '.db' file that contains the information.
conn = sqlite3.connect('./birds.db') 
# Create a cursor
cursor = conn.cursor()


# Execute a CREATE TABLE query
create_table_query = '''
CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY,
    username TEXT,
    email TEXT
)
'''
cursor.execute(create_table_query)

# Commit changes and close the connection


# The users will type in the name of species they want to inquire about.  
species_name=input("Please type in the name of bird species:") 

# The corresponding SQL inquiry command is specifies below.
select_query = 'SELECT * FROM detections WHERE Com_Name = \''+species_name+'\';'

cursor.execute(select_query)
rows = cursor.fetchall()


Total=len(rows)
Month=[] # Month stores how many records are there for each month and we initiate it to be a zero vector.
labels=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
for i in range(1,13):
    Month.append(0)

# Here we go through all the records of bird species the user typed in 
# and count how many are there for each month.

for i in range(Total):
    month=(ord(rows[i][0][5])-ord('0'))*10+ord(rows[i][0][6])-ord('0')
    Month[month]+=1

data={'Months In A Year':labels,
      'Number of Detections':Month}

df = pd.DataFrame(data)

fig = px.bar(df, x='Months In A Year', y='Number of Detections')

# You can modify the below command to generate a different layout.
# For more information, see  https://plotly.com/python/reference/layout/.

fig.update_layout(
    title={
        'text': "Seasonal Analysis for "+ species_name,
        'y':0.95,
        'x':0.5,
        'xanchor': 'center',
        'yanchor': 'top',
        'font' : dict(size=30)
        },
    title_font_color='purple',
    font_color="black"
)

fig.show() # Show the graph drawn.

# Here we close the inquiry.
conn.commit()
conn.close()
  • Shown below are the two charts corresponding to Australian Magpie and Little Raven respectively.

Uploading files to Dropbox

  • Dropbox is a cloud-based file hosting and synchronization service that allows individuals and organizations to store, access, and share files and folders online.
  • In this project, we can upload our files to Dropbox so we can easily access them from a distant computer.
  • First, we need to create an APP and generate a token.
  • Take note of the token as it's the key component of the uploading process.
  • Type the following command in the terminal, it should open the Crontab interface.
  • Specify when do you want the code executed, the full file path, and the file name.
  • Note: If you need any help deciding how to specify the time, check section 11.3.

Extracting all the new records from the day before

  • Normally, we would like an update on the new bird calls recorded every day.
  • As discussed in the above subsection, we can use Crontab to schedule the uploading.
  • However, there's one thing we need to keep in mind: It takes time for BirdNET-Pi to identify the bird species.
  • Instead of uploading the records immediately after 00:00, we should schedule the uploading time to be at least 30 minutes past midnight.
  • The code shown below will extract the new records exclusively from the day before that day.
#!venv/bin/python

import datetime
import sqlite3
import datetime

# This functions decides whether Y is a leap year.
def isleap(Y): 
    if(Y%4!=0):
        return False
    elif(Y%100!=0):
        return True
    elif(Y%400!=0):
        return False
    else:
        return True

# This function will return the date of the day before the day the code is executed.    
def date_minus(former):
    year=1000*(ord(former[0])-ord('0'))+100*(ord(former[1])-ord('0'))+10*(ord(former[2])-ord('0'))+(ord(former[3])-ord('0'))
    month=10*(ord(former[5])-ord('0'))+(ord(former[6])-ord('0'))
    day=10*(ord(former[8])-ord('0'))+(ord(former[9])-ord('0'))

    M=[31,28,31,30,31,30,31,31,30,31,30,31] # M stores how many days are there in each month.
    if(isleap(year)):
        M[1]+=1 # If this is a leap year, then February has 29 days.

    if(day>1): # Usual date. Example: 2022-08-19->2022-08-18
        day-=1 
    elif(day==1 and month==1): # First day of the year. Example: 2014-01-01 -> 2013-12-31
        year-=1
        month,day=12,31
    elif(day==1 and month!=1): # First day of the month excluding January. Example: 2012-03-01-> 2012-02-29
        month-=1
        day=M[month-1]

    new_date=str(year)+'-'+str(month).zfill(2)+'-'+str(day).zfill(2) # Formatting the new date. 
    return new_date

now = datetime.datetime.now()

current_date = now.strftime("%Y-%m-%d")
target_date=date_minus(current_date)

conn = sqlite3.connect('/home/pi/MPPT/B.db')
cursor = conn.cursor()

select_query = 'SELECT * FROM detections WHERE date = ?'

# Only records from the day before will be extracted. 
cursor.execute(select_query,(target_date,))
rows = cursor.fetchall()

Total = len(rows)

for i in range(Total):
    data_save = data_save +rows[i][3] + '\n'

conn.close()

# All the former records in 'B.txt' will be deleted 
# so we won't transmit the same records agian and again.
open('/home/pi/MPPT/B.txt','w').close() 
f=open('/home/pi/MPPT/B.txt','a')
f.write(data_save)
f.close

Adding an SSD to improve performance

  • USB 3.0

USB 3.0 ports, also known as SuperSpeed USB ports, are considered unique due to their significantly improved data transfer speeds and enhanced capabilities compared to previous USB standards. One of the most salient features is its faster data transfer speed.

Tip: You can quickly identify a USB 3.0 port by remembering this: The USB 3.0 port is blue.

  • Kington A400S Series

Due to the large volume of data involved, we need to attach an SSD(Solid-State Drive) to the Raspberry Pi. It is a type of data storage device used in computers and other electronic devices. In this project, we chose the SA400S37/480G model.

The product specifications can be found in the link below:

https://www.scorptec.com.au/product/hard-drives-&-ssds/solid-state-drives-(ssd)/71426-sa400s37-480g?gclid=Cj0KCQjw0bunBhD9ARIsAAZl0E3uxry4rd_yIg2gIJG1NaU3FaXsMTMprgEl4MVEWMaWSeJv-Mz61i0aAiQxEALw_wcB

  • Configuring the SSD

Step 1: Download the Raspberry Pi imager software: https://downloads.raspberrypi.org/imager/imager_latest.exe

Step 2: Connect the SSD enclosure to your PC, then run the imager software.

Step 3: Select "Raspberry Pi OS (Other)". Then choose "Raspberry Pi OS (64-bit)".

Step 4: Click Write and wait for it to download, flash and verify. If everything clicks, you will see the interface shown below:

Step 5: Unplug the SSD drive, set up the Raspberry Pi 4, and plug in the SSD to one of the blue USB3 ports. Important: Always remember to remove the microSD card from the Raspberry Pi. The Pi needs to boot from the SSD inserted in the USB 3.0 port If you forgot to do so, the new Kingston SSD won't take effect and you are left with the microSD card.

Step 6: Connect your Raspberry Pi to the Internet and open a terminal.

Step 7: Run sudo apt update then sudo apt upgrade in the terminal. This will do a full update of do a full update of all software.

Step 8: Open up a new terminal and run lsusb -t. You should see Driver=uas among the results.

Step 9: Check TRIM: Run the code sudo fstrim -v /. If you see the below message in the red box, then the TRIM isn't enabled for the drive and you need to enable it.

Step 10: Run the command lsblk -D. Have a look for the 'sda' drive, and the two columns 'DISC-GRAN' and 'DISC-MAX'. If both of these are NOT zero, then your drive is capable of TRIM.

Step 11: If both the column "DISC-GRAN" and "DISC-MAX" under the 'sda' drive is zero as shown below:

One possible cause is you didn't remove the microSD card from the Raspberry Pi as mentioned in Step 5. Shut down Raspberry Pi, remove the microSD card and reboot.

Step 12: Enable TRIM support: run the command sudo su. Until you close this terminal, everything from now on will be run as "super user" (admin). The command prompt should have also changed to show "root@raspberrypi".

Step 13: Copy and paste the following command to the terminal and run it: find /sys/ -name provisioning_mode -exec grep -H . {} + | sort.

Step 14: At the end of the result, there should be "provisioning_mode". It's likely to be set to "full", but we need it set to "unmap". If yours shows "unmap" already, you can skip this next step.

Step 15: Run the following command: echo unmap > /sys/devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-1/2-1:1.0/host0/target0:0:0/0:0:0:0/scsi_disk/0:0:0:0/provisioning_mode.

Step 16: After running the above command, run the "find" command in step 13 again. You should see the "provisioning_mode" has been changed to "unmap".

Step 17: Run the command sudo fstrim -v / again and you should see the below message:

Step 18: If you get a similar output, then TRIM is working on the drive. However, when you reboot the Pi, it will revert back. To set the TRIM setting permanently, there are a few more steps we need to do.

Step 19: Run the command lsusb in the terminal. This will list all attached USB devices. Find the one associated with the SSD.(For me it's the first one in the red box.)

Step 20: Take note of the two codes separated by a colon (:) after "ID", they will be important to later steps.

Step 21: Run the following command mousepad /etc/udev/rules.d/10-trim.rules in the terminal. A text editor shown below should pop up.

Step 22: Copy and paste this line into the empty text file: ACTION=="add|change", ATTRS{idVendor}=="174c", ATTRS{idProduct}=="1153", SUBSYSTEM=="scsi_disk", ATTR{provisioning_mode}="unmap"

Step 23: Replace "idVendor" and "idProduct" in the above line with the two codes we took note of in Step 20 respectively. They should both have a length of 4. Close the mousepad and save the file.

Step 24: This code will enable TRIM by changing the provisioning mode to "unmap", just like we did manually earlier. Now we just need to schedule the TRIM process to be run periodically. Type sudo systemctl enable fstrim.timer into the terminal. This will enable a weekly timer, which is the preferred way to TRIM SSDs on Linux distributions (as opposed to continuous TRIM).

Step 25: At the end, we can type the command sudo curl https://raw.githubusercontent.com/TheRemote/PiBenchmarks/master/Storage.sh | sudo bash. This will give your drive a performance score, and if you fill in the prompts at the end, it will be published publicly on pibenchmarks.com.

Configure the UR41 Router from Milesight

When you receive a new router, you need to configure it.

There are two ways of doing that: Wired Access and Wireless Access.

As the model we use in this project is UR41, which lacks a Wi-Fi Antenna, the Wireless Access approach isn't viable.

Here we used Raspberry Pi to configure the router via the Wired Access approach:

Step 1: Find an Ethernet cable and connect the router to the Raspberry Pi.

Step 2: Open up Raspberry Pi and set the IP Address, Username and Password using the default setting. (You can find them in the Quick Start Guide.)

Step 3: Open a browser type the default IP address in the Address bar and press enter. The following interface should show up.

  • If you can't open the interface and see things like "can't open the site." or "192.168.1.1 refused to connect.". One possible reason is there's a fault with the ethernet cable, replace it and try again.

Step 4: Enter the username and password then press enter. You'll see the following interface.

Congratulations! The configuration is completed.

Port Forwarding

A Brief Introduction

Port forwarding is a networking technique that allows data packets to be sent from one network device to another through a specific port number on a router or firewall. This process is essential for enabling communication between devices on a local network (LAN) and devices on an external network, such as the internet.

Here's a breakdown of how port forwarding works:

1. Network Devices: In a typical home or office network, you have multiple devices connected, such as computers, smartphones, smart TVs, or web servers. Each of these devices may have services or applications that need to communicate with external networks.

2. Local IP Addresses: Every device on your local network has a local IP address, which is used for communication within the network. These addresses are typically assigned by your router using DHCP (Dynamic Host Configuration Protocol).

3. Ports: Ports are like doorways on a network device. They allow different services or applications to run on the same device without interfering with each other. Ports are numbered, and specific applications often use well-known port numbers (e.g., HTTP uses port 80, HTTPS uses port 443, etc.).

4. External IP Address: Your home or office network typically has a single external IP address, which is used to identify your network on the internet. This address is assigned by your internet service provider (ISP).

5. Router or Firewall: Your router or firewall acts as a gateway between your local network and the internet. It has the ability to forward incoming data packets from the internet to the appropriate device on your local network.

Here's how port forwarding comes into play:

  • Let's say you have a web server on your local network with a local IP address of 192.168.1.100, and it's configured to listen on port 80 for incoming web requests.
  • When someone from the internet wants to access your web server, they use your external IP address (provided by your ISP).
  • The incoming web request arrives at your router, but the router doesn't know which device on your local network should receive the request because multiple devices are connected.
  • This is where port forwarding comes in. You configure your router to forward incoming requests on a specific port (e.g., port 80) to the local IP address of your web server (192.168.1.100) on the same port.
  • Now, when someone accesses your external IP address on port 80, the router forwards the request to your web server, which can then respond to the request.

In summary, port forwarding allows you to direct incoming network traffic to a specific device and port on your local network. It's commonly used for hosting web servers, gaming servers, remote access to devices, and various other applications that require external access. However, it should be set up carefully and securely to prevent unauthorized access to your network.

Setting up port forwarding for UR41

Step 1: Log in to the GUI as described in the last section then click on Network.

Step 2: Click on Firewall below the Network

Step 3: Click on Port Mapping on the top bar.

Step 4: Now you will see the below interface.

You will need to fill out the parameters shown above. Their meanings are listed in the help section listed in the help section as shown below.

Teamviewer

  • Teamviewer is a popular remote access and remote control software solution that allows users to connect to and control computers or mobile devices from anywhere in the world over the internet. This software can be used as an alternative solution to Secure Shell when it comes to remote control.
  • One advantage of Teamviewer is it doesn't require the devices to be connected to the same LAN. We can easily control the remote device as long as they both have Internet connections.
  • The first step is to download the Teamviewer of suitable versions to both the main computer and the client computer (In our case it's Raspberry Pi).
  • Then add the Raspberry Pi to the list of All devices. The system will send you a confirmation email.

(Be patient as the email can take 10 minutes to arrive.)

  • As we are using the free version of the Teamviewer, the file transfer isn't supported. If it were, we could potentially directly transfer code and data between the Raspberry Pi computer and your remote computer.

Common Issues and Debugging

This section describes some issues we encountered in this project and what we did to solve them.

Crontab Won't Run the Code

  • If you have written a piece of code and would like it to be executed periodically, you can utilize crontab to schedule it for you.
  • However, sometimes you find that even if you have already scheduled the tasks in the crontab, the code simply wasn't executed.
  • More confusingly, you actually can execute the code by typing the following command in the terminal.
python3 Example.py


  • One possible cause is you didn't specify the file path in a clear way.
  • As is shown in the screenshot below, the full file path is written as the abbreviated version:./<some_file>.<some_extension>
  • Such file path can't be recognized by crontab and that's the reason why your code wasn't executed.
  • Make sure all the file paths in your code are written out fully as shown below:
  • After you fix this issue, Crontab should be able to execute your code correctly.

Can't Access MileSight Login Interface

  • When configuring the UR41 router, connect the router to the Raspberry Pi computer through an ethernet cable and type the IP address in the search bar.
  • It's possible that you can't open the login interface shown below after typing the IP address, and instead see things like "can't open the site" or "192.168.1.1 refused to connect"
  • The issue may lie in the Ethernet cable. Replace the cable and try again.

The Teamviewer Won't Work

  • Teamviewer provides an easy way for remote control. However, sometimes you may have trouble connecting to the remote device. When this happens, you might see the following interface:

Insert a picture here.

  • There are several possible reasons behind it and we will briefly go through them.
  • Firstly, if you are using the free version of the Teamviewer, the upper limit of your device is three. This means if you are trying to connect to the 4th device, your connection may simply be blocked with no reminder.
  • Secondly, it may be because other applications are running and taking up space in the CPU.
  • Do the following and see what applications are running and whether they are occupying too much space.

Insert a picture here

  • This shows that the BirdNET-Pi is running and taking up a lot of space. This may be the reason why the Teamviewer fails to connect.
  • Disable BirdNET-Pi for the time being and try again.

Insert a picture here.

Additional Tips and Tricks

To make life easier, we compiled the following "cheat sheet" to help you simplify things a bit.

Using the "find" command to locate files

1. Find a specific file under the folder

  • Sometimes, we may want to find whether a file exists under a folder and what exactly the file path is. This is where the find command comes in handy.
  • Given that we want to look for the Python code file birds.py, and we believe it's somewhere under the folder /home, we can type the following command:
find /home -name "birds.py"
  • Shown in the screenshot below is the file path of birds.py.


  • Now let's try to locate another file mammals.py (which doesn't exist) by typing the following command:
find /home -name "mammals.py"
  • As nothing is returned, we know that mammals.py doesn't exist under this folder.

2. Find all files with certain extensions under the folder

  • The find command can also be used to find all files with certain extensions under a folder.
  • Given we want to find out all the .txt files and their file paths under the folder /home/pi/MPPT, we can type the following command:
find /home/pi/MPPT -name "*.txt"
  • Now we have a full list of .txt files and their file paths under the folder.

Copy files from Raspberry Pi to a USB

When dealing with a Raspberry Pi computer without GUI, copying files from the computer to the USB is not straightforward. But it can be done.

  • Step 1: Plug the USB into the Raspberry Pi


  • Step 2: Type the following command to find out the unique ID of the USB and take note of the name before sda1:
ls -l /dev/disk/by-uuid/
  • Step 3: Create a mount point by typing the following command:
sudo mkdir /media/usb

This step creates a directory that will enable you to view the content of the USB. (You don't have to name it /usb.)

As is shown above, the file already exists. This is because, before the demonstration, this step has been done. If you are doing it the first time, don't skip this step.

  • Step 4: Type the following command to ensure the Pi user owns the folder:
sudo chown -R pi:pi /media/usb
  • Step 5: Now you can mount the drive using the following command:
sudo mount /dev/sda1 /media/usb -o uid=pi,gid=pi
  • Step 6: Open the folder "/media/usb" and then type "ls". Now we can view the contents of the USB.
  • Step 7: Copy the files from Raspberry Pi to the USB

Let's say we want to copy the file "birds.py" with the file path "/home/pi/MPPT/birds.py" to USB, we can use the following command:

cp /home/pi/MPPT/birds.py /media/usb

Type the command "ls" again and we can confirm that "birds.py" has been copied to the USB.

  • Step 8: Before we unplug the USB, we need to unmount it first. Type the following command:
sudo umount /media/usb

Type "ls", and we can no longer view the contents of the USB as it has been unmounted.

  • Step 9: Now the USB can be safely unplugged.

Using Crontab to Schedule Events

Crontab is a time-based job scheduler in Unix-like operating systems. It allows you to schedule tasks or commands to run automatically at specific intervals or times. These scheduled tasks are often referred to as "cron jobs."

  • Let's say you wrote a piece of Python code and you named it birds.py.
  • After some editing, you want it to be executed every hour.
  • Type the following command in the terminal and then press enter.
  • Now you should see the interface shown below:
  • Given that the file path of birds.py is /home/pi/MPPT/birds.py, and you want the code to be executed at the beginning of each hour, type the following line at the end of the file
  • Press ctrl + x to exit.
  • Press Y and then enter.
  • You'll see the following line in the terminal:
  • After accomplishing the above steps, birds.py should be executed at the beginning of every hour.

Extra Notes

1. If you have different ideas about when the code should be executed, consult the following website to find out how to specify the demands:

https://crontab.guru/


2. If crontab won't execute your code, check your file path and file name and make sure they are correct. If the problem remains, check the debugging section above for reference.

Using Only Keyboard to Switch Tab

  • To save time, we can directly use the keyboard to switch the tabs.
  • Initially the tab of Wikipedia is selected.
  • To move to tab selection, press Ctrl + Tab.
  • Now the tab of Raspberry Pi is selected.

Taking a Delayed Screenshot Using Scrot

  • For a Raspberry Pi computer with a GUI system, it's easy to take a screenshot with a delay.
  • The delay of a few seconds enables you to adjust the screen to be just what you want it to be. We need to install the application scrot to achieve this.
  • To install scrot, type the following command in the terminal:
sudo apt-get install scrot
  • Now type the following command in the terminal to take a screenshot with a delay of 5 seconds:
scrot -d 5
  • Use this 5 seconds to adjust the screen so it's exactly how you want it to be captured.
  • The screenshot is shown below:
  • In case 5 seconds aren't enough, you can adjust the parameter num in the following command.(To be 10 for example.)
scrot -u -d num