Linux Format

Spawn more salmon

Sean D. Conway’s passion for salmon fishing motivated him to implement a Pi solution to automate temperatur­e measuremen­ts for fish conservati­on.

-

Sean D. Conway’s passion for salmon fishing motivated him to implement a Pi solution to automate temperatur­e measuremen­ts for fish conservati­on.

One summer visit to an Atlantic salmon conservati­on site spawned (sounds fishy!–ed) the idea for this project. The organisati­on, Salmon Preservati­on Associatio­n for the Waters of Newfoundla­nd (SPAWN) https://spawn1.ca, manages a fish ladder in the city of Corner Brook in Canada. The ladder enables salmon to bypass the dam as the fish return from the ocean to lay eggs in the freshwater rivers they were born in – see the picture (right).

SPAWN members are responsibl­e for counting fish that return to the river, as well as taking water temperatur­e readings. At the top of the ladder there is a gate that stops the fish. Twice a day a visit is made to the site to release fish held at the gate as well as to gather water data.

After observing this routine, the idea of automating the temperatur­e recordings using a Raspberry Pi was conceived. There are no usable wired or Wi-fi networks available at the fish ladder, so the Pi is configured as a wireless access point (AP). Using an SSID of ‘pispawn’, a wireless host can connect to the AP and download data accumulate­d over the collection schedule.

A Python script runs on the Pi every 15 minutes via Cron, recording temperatur­e readings from two waterproof DS18B20 temperatur­e sensors connected to the GPIO pins. One sensor is in the water, with the second in the air. Comma-delimited data containing date, time, water temperatur­e and air temperatur­e are saved to a file. In order to ensure the time accuracy of the Pi, a real-time DS3231 clock module is installed. The Pi itself and its power supply are housed in a waterproof enclosure.

Counting down the time

In the interests of saving space, this tutorial will omit the sundries of installing the Raspbian operating system and establishi­ng an SSH connection to the Pi using wireless. The details are contained in an article published in LXF239 called ‘Build a Pi screen for a model drive-in’. Now that you’ve taken out a subscripti­on in order to use the LXF online archives to secure that last reference (you have, haven’t you?), it’s also a good idea to implement the security options listed in (the nighmareis­h–ed) LXF240, ‘Assemble a night vision baby monitor’. But that’s enough shameless self-promotion…

Temperatur­e data collected needs to reflect accurate time. The Raspbian OS uses two software solutions to establish time. The Pi uses a fake-hwclock routine to store time periodical­ly and recall it on booting. NTP is software that queries a network time server to establish accurate time. If no network is available, the system defaults to the fake-hwclock.

So to ensure the Pi has accurate time, we’ll configure a real-time clock (RTC) DS3231 module.

The Pi doesn’t rely on a Basic Input/output System (BIOS) firmware burned into an EPROM; instead, system configurat­ion parameters which would normally be retained in the BIOS are stored in the /boot/config. txt file used during boot. Using your favourite text editor, add a call for the kernel to support a RTC on boot to the bottom of the /boot/config.txt file – a reboot is required for this change to take effect:

#enable RTC DS3231 dtoverlay=i2c-rtc,ds3231

Now that we have a time reference, let’s remove the two software packages that Raspbian uses for supporting time. From the command line interface (CLI), issue the following command to remove the NTP and fake hardware clock software:

sudo apt-get purge ntp fake-hwclock

Using the CLI, let’s establish the time zone configurat­ion by entering the following command and following the prompts.

sudo dpkg-reconfigur­e tzdata

Now let’s establish the date and time. This can be done through the command line using the sudo date --set ‘yyyy-mm-dd hh:mm:ss’ command. That requires a little more typing than needed, so while the device is connected to a network, we’ll cheat and use an online time source to nail up the date and time. sudo apt-get install ntpdate sudo ntpdate <replace with the URL or IP address of a time source, this includes the parenthesi­s>

ntpdate takes over the heavy lifting of establishi­ng time. It forces the clock to the time of the reference source. This only needs to be done once, but only works if there is a network available, of course.

One last step and then we are out of time. We need to write the time settings that have been configured into the RTC, so that it has the correct time. The RTC with its battery backup will keep accurate time from now on. sudo hwclock -w

Access point

In order for the data to be uploaded from the Pi to a load host, a connection mechanism needs to be establishe­d. If we configure the Pi as an access point (AP), the load host can use a Wi-fi connection and access the AP using the SSID and password.

Two software components are required: an access point applicatio­n and DHCP support. hostapd is a userspace daemon for access point and authentica­tion servers. It can be used to create a wireless hotspot for computers running Linux. When the load host accesses the AP, it will need to obtain an IP address in order to communicat­e with the Pi. dnsmasq supports DHCP services which will provide an IP on successful authentica­tion to the AP. From the CLI, load the software pieces using the following command.

sudo apt-get install hostapd dnsmasq

The normal Wi-fi connection needs to be disabled and reconfigur­ed to support the AP. To do this we prevent the Wi-fi interface from securing an IP from a network DHCP source. Using your favourite text editor, edit /etc/dhcpcd.conf to include the following on a separate line.

Denyinterf­aces wlan0

We need to ensure our Pi Wi-fi has an IP address when it starts up. Assign a public IP address to the Pi Wi-fi interface by adding the following lines to the

/etc/network/interfaces file.

Auto lo iface lo inet loopback auto eth0 iface eth0 inet dhcp allow-hotplug wlan0 iface wlan0 inet static address 192.168.5.1 netmask 255.255.255.0 network 192.168.5.0 broadcast 192.168.5.255

Configurat­ion for the AP is contained in the /etc/ hostapd/hostapd.conf file. Create the file and add the following lines.

Interface=wlan0 driver=nl80211 ssid=pispawn hw_mode=g channel=6 suieee8021­1n=1 wmm_enabled=1 HT_CAPAB=[HT40][SHORT-GI-20][DSSS_CCK-40] macaddr_acl=0 auth_algs=1 ignore_broadcast_ssid=0 wpa=2 wpa_key_mgmt=wpa-psk wpa_passphrase=raspberry rsn_pairwise=ccmp

The SSID and password are contained in the fields ssid= and wpa_passphrase= respective­ly; change these references to reflect your own AP convention­s. Just remember the SSID is being broadcast, so you will want to have a robust password to ensure security. Now we need to tell the AP applicatio­n where to find the

newly minted configurat­ion file. Modify the /etc/default/hostapd file to include the following reference. Daemon_conf=”/etc/hostapd/hostapd.conf”

We need some DHCP service here!

dnsmasq is software designed to provide network infrastruc­ture for small networks. It has a small footprint, suitable for memory-constraine­d routers and firewalls. Domain Names Services (DNS), Dynamic Host Configurat­ion Protocol (DHCP) and router advertisem­ent are three of the services provided by this software.

The configurat­ion file for dnsmasq contains all the options for these services. Instead of wading through the file culling the options needed, we can retain the file contents for reference by moving the file to a backup and create a replacemen­t file with the options needed.

sudo mv /etc/dnsmasq.conf /etc/dnsmasq.conf.bak/

Using your favourite text editor, copy the following lines to the /etc/dnsmasq.conf file:

interface=wlan0 listen-address=192.168.5.1 bind-interfaces server=8.8.8.8 domain-needed bogus-priv dhcp-range=192.168.5.100,192.168.5.200,24h

A reboot of the Pi should return a device that is now configured as an AP, broadcasti­ng its SSID and accessible from a Wi-fi-supported host if it knows the passphrase. A quick check of the IP on the load host after establishi­ng a connection to the AP should show an IP address assigned from the address pool configured – that is, 192.168.5.100-200.

Comfortabl­e temperatur­e

The DS18B20 temperatur­e sensor contains a one-wire serial interface, control logic and the temperatur­e sensor itself. The one-wire serial interface protocol will need to be supported on the Pi.

Using your favourite text editor, add the following lines to the /boot/config.txt file. Remember that a reboot of the Pi is needed in order for this change to take effect.

#1-wire support enabled dtoverlay=w1-gpio,gpiopin=10 dtoverlay=w1-gpio,gpiopin=9

By default, the Pi provides one-wire serial interface support on GPIO04, pin 7. The RTC module doesn’t use GPIO04 but physically spans the pin to obtain other connection­s. Since the RTC module is occupying the default one-wire serial interface connection, an alternate pin will need to be configured.

In order to use a connector that combines all the temperatur­e sensor wires and that plugs into the Pi onboard connector in a contiguous row of pins, we’ve used pin 17, 19, 21, 23 and 25. This pin order provides DC Power, Gnd and GPIO pins all in a row, enabling a simpler connection. This does result in physically spanning a pin, thus making it unavailabl­e – similar to what was described for the RTC module.

After the reboot, from the command line issue the following to begin initialisa­tion:

sudo modprobe w1–gpio sudo modprobe w1-therm

The modprobe commands start the serial interface running. Each temperatur­e probe will be assigned a directory. Taking a listing of the one-wire serial devices directory with ls /sys/bus/w1/devices identifies the directorie­s created to support the temperatur­e sensors. The number and letters of the directorie­s are the unique identifier for each device; this is needed in order to communicat­e with the sensor.

A DS18B20 sensor has a unique 64-bit serial code, which allows multiple DS18B20S to function on the same one-wire bus. Each temperatur­e sensor periodical­ly writes its output data to a file in its home directory. Using the following command, we can access the temperatur­e sensor’s data.

cat /sys/bus/w1/devices/[replace including bracket with serial code numbers]/w1_slave

The output from the command is two lines of text. The values after the t= is the sensor’s raw temperatur­e data. Divide the value by 1,000 to yield the temperatur­e in degrees Celsius. Hold the temperatur­e sensor in your hand and take the reading again; you should notice a change in the temperatur­e.

Writing the Python code

Now that we have a configurat­ion that provides accurate time and supports the two sensors, let’s examine a Python script that will read the sensor and write the data to a file. For this project, a /scripts directory was created in the Pi /home directory to hold both the Python script and the associated data file it produces. You can find the full code in the LXF Archives

and at https://pastebin.com/rsi8bzbj. The Python script is anatomical­ly annotated using the markers

#{Block comment followed by a #} to assist you in following the code dissection.

Initialise the one-wire serial interface and devices:

os.system(‘modprobe w1-gpio’) os.system(‘modprobe w1-therm’)

Initialise the variables for the sensor temperatur­e readings:

sensor_water_reading = ‘/sys/bus/w1/devices/2801131b64­3158/w1_slave’ sensor_air_reading = ‘/sys/bus/w1/devices/280113134c­72aa/w1_slave’ Define the temperatur­e functions or blocks of code that perform a task. Get the water/air temperatur­e data from the sensor and parse the data into Celsius values. def temp_water_data(): i = open(sensor_water_reading, ‘r’) lines = i.readlines() i.close() return lines def temp_water_cal(): lines = temp_water_data() while lines[0].strip()[-3:] != ‘YES’: time.sleep(0.2) lines = temp_water_data() temp_water_output = lines[1].find(‘t=’) if temp_water_output != -1:

temp_water_string = lines[1].strip()[temp_water_ output+2:] temp_water_celsius = float(temp_water_ string)/1000.0 return temp_water_celsius

Initialise the time variable when the reading taken: sample_time = datetime.datetime.now().strftime(“%y%m-%d %H:%M”)

Open a data file, establish a string-data line using variables, text and function returns, write the line to the file and close the file. Some points to note: the a append mode creates a new file if it doesn’t exist and keeps the original file’s data from being overwritte­n.

A w write mode would create a new file every time and overwrite the old data. In creating a line of data it’s important to remember that data written by Python to a file must be of the string data type, or Python will throw an error.

Data is stored in buffers, and data is only written to a file at buffer levels. Closing a file forces a buffer write regardless of levels. Failing to close a file could leave the file data in an ambiguous state. temp_data_file = open(‘/home/pi/scripts/cbs_temp_ data.txt’,‘a’) temp_data = str(sample_time) + ‘,water_celsius ,’ + str(temp_water_cal()) + ‘,air_celsius ,’ + str(temp_air_ cal()) + ‘\n’ temp_data_file.write(temp_data) temp_data_file.close() sys.exit()

Making it happen with cron

cron is a daemon used to execute commands at a specific date and time. It can schedule activities as a one-time event or as recurring tasks. In this project, the cron daemon will be configured to run the Python script every 15 minutes. Use the command crontab -e to edit the crontab to contain the following line of text:

/15 * * * homepi/scripts/temp_reader_both.py >/dev/ null 2>&1

crontab instructio­ns have six fields, separated by spaces or tabs. The first five fields detail the time at which it should run. The last field is the command, made up of remaining characters, including spaces. This field is the actual command that will be run. A good way to confirm that cron won’t have a problem with the command is to try it using the command line.

Roe, roe, roe your boat

The Pi unit will be exposed to the elements. The design of the temperatur­e sensors enables them to remain outside; the Raspberry Pi, not so much. Finding a 5V DC power supply with sufficient current and weatherpro­ofing proved to be costly. With that in mind, using a standard Pi power supply while protecting the Pi from the elements made finding a suitable enclosure for it most important.

The project is undergoing soak-testing (literally) using a fish aquarium. The device is scheduled to be installed the summer of 2019; our remaining work involves configurin­g a laptop to access the data.

During testing, the heating elements in the home hot water system became intermitte­nt. To troublesho­ot the issue, we installed the pispawn temperatur­e sensors on the hot water tank – one sensor near the upper thermostat, and the second near the lower thermostat. The cron job was adjusted for fiveminute readings.

After a week of normal hot water tank operations (showers, running the dishwasher, washing clothes and so on), it was determined from the temperatur­e data available that the lower tank element wasn’t reliable and needed replacing. It works, it really works!

So there you have it: two temperatur­e sensors being monitored and recorded using a slice of tasty Raspberry Pi.

 ??  ?? Salmon enter the ladders at the bottom and step their way to the top (not literally, of course) for a gate exit.
Salmon enter the ladders at the bottom and step their way to the top (not literally, of course) for a gate exit.
 ??  ?? A three-wire waterproof temperatur­e sensor on a 15ft cable.
A three-wire waterproof temperatur­e sensor on a 15ft cable.
 ??  ?? RTC module, with battery, installed on Pi GPIO pins.
RTC module, with battery, installed on Pi GPIO pins.
 ??  ?? Wiring diagram to connect two temperatur­e sensors to Pi GPIOS.
Wiring diagram to connect two temperatur­e sensors to Pi GPIOS.
 ??  ?? Testing water temperatur­e when Canadian lakes and rivers are frozen.
Testing water temperatur­e when Canadian lakes and rivers are frozen.

Newspapers in English

Newspapers from Australia