Ötz-T: 3D-printed open-source turbidity sensor with Arduino shield for suspended sediment monitoring

Graphical abstract


Hardware in context
The transfer of sediment from land to oceans plays an important role in the global denudational cycle [19,46], the global geochemical cycle [31,28], the function of coastal ecosystems [36,3], and the evolution of deltas and other coastal landforms [34,30,37]. Proper monitoring of this sediment flux should capture the temporal and spatial variability in concentrations at suitable timescales. This variability in suspended sediment concentrations (SSC) can then be used to quantify human effects on sediment production [45,21], the natural erosion gradients over entire mountain ranges [20], and the uncertainty in erosion rates related to short-term sampling [10]. It can also give us a better understanding of possible short-term hydrological processes in a catchment leading to sediment production, e.g. hillslope erosion by rainfall events, glacier ice melt erosion, even hydropower storage in dams, as well as longer-term variability caused by ongoing climate change [33,21,8,9]. Measurements of SSC are also important for understanding how the impacts of hydroclimatic forcing on activating sediment sources may propagate through the river system in observations and also in physically-based hydrology-sediment models [5,6,9,25,41]. However, understanding such processes requires a temporal and spatial perspective on sediment pathways of production and storage within the catchment which cannot easily be achieved by current methods and sensing technology to measure SSCs.
The primary method to quantify SSC is by gravimetric analysis of bottle samples taken at river cross-sections in regular or irregular intervals. This method is reliable but has many disadvantages such as being discontinuous, inefficient and costly. Alternatively, the spatial distribution of SSC can be obtained using satellite imagery which is based on the reflectance of water surface as it is affected by suspended sediment. Dissolved and suspended sediment concentrations together with gross biological activity affect the intrinsic colour of natural waters [35,42], which makes optical satellite remote sensing of oceans, coastal areas, large lakes/rivers possible. When calibrated with ground measurements, such satellite data can be very useful for SSC estimates [11,29,14] and can give a range of additional water quality parameters [43] at large scales but not with high temporal resolutions (they are limited by the repeatability given by satellite overpasses) and with poor point accuracy. Terrestrial photography is another possibility to obtain SSCs from the optical sensing of river turbidity [18,16], for example by mobile phone cameras [27]. However, all satellite, ground-based and UAV optical sensing methods are limited by cost, poor temporal resolution, insufficient spatial footprint, and are strongly affected by many other constraints, which make them currently not very suitable for regular long-term monitoring of SSC in rivers.
The current state-of-the-art method to obtain continuous SSC data at high temporal resolutions is by dedicated in situ turbidity sensors, where via calibration a strong relation between turbidity and SSC can commonly be ensured. The main deficiency, however, of these commercial sensors is that they are expensive (e.g. state-of-the-art turbidity sensor by Campbell is about 6000€, In-Situ is 7000€), making widespread deployment at many sites along a river system to quantify spatial variability next to impossible.
The appealing alternative are low-cost turbidity sensors, and several such sensors have been documented in peerreviewed literature, such as the appliance-based sensors of Gillett [17] and Trevathan [40], the backscatter systems of Jiang [22] and Eidam [13], the dual-beam detectors of Lambrou [26] and Wang [44], the handheld system of Kelley [23], and the flow-through systems of Kitchener [24] and again Gillett [17]. However, none of these systems are sufficiently accurate in the entire 0-4000 Nephelometric Turbidity Unit (NTU) range and also sufficiently robust for deployment in rivers in the field.
The open-source, low-cost, in situ turbidity sensor for river network monitoring [12] which we developed in our group meets the criteria of sufficient range and accuracy, and suitability for river deployment. This sensor was calibrated for the full 0-4000 NTU range, in addition to 0-16 g/L range, and errors were quantified in laboratory tests. Its performance was also compared to other commercially available turbidity sensors. Although the first version was built for in situ river network monitoring, there were several improvements that the sensor needed to undergo before long-term, underwater deployment could be possible. In this work, we present these improvements which lead to the Ötz-T (or Ötz-Turbidity, inspired by the natural mummy, Ötzi, found in the Ötztal alps in 1991), and we test this latest version during a flood event on the Ötztal Ache in September 2022.

Hardware description
The Ötz-T sensor is a 19 cm long (9 cm diameter) 3D printed standalone device used to measure the turbidity in rivers over extended periods of time and costs $25 times less than comparable commercial turbidity sensors. This sensor measures turbidity using an IR LED (850 nm) and two IR detectors, and it also features a temperature and pressure sensor to obtain river temperature and stage.
The sensor features a custom printed circuit board (PCB) shown in Fig. 1. The PCB is robust and was built to sit as a shield on top of the ultra low-power Arduino MKR WAN 1310. The Arduino MKR WAN 1310 was chosen as the microcontroller because it has several powerful features for our application. It houses a SAMD21 chip which is optimized for low-power functionality and the MKR WAN 1310 also has LoRa built in, which we would like to utilize in future builds. Using an Arduino also enables us to program our device using the Arduino IDE, which we believe makes the project more accessible to those with less programming experience. This shield has all the I2C connectors highlighted in green in Fig. 1. Since our IR detector has a fixed I2C address, we had to use the second I2C bus on the SAMD21. The second bus consists of the pins PA22 and PA23. It is important to note that these pins don't have 10 k pull-up resistors built into the Arduino so we had to add them to our shield. To control the IR LED, we used a MOSFET together with an AL5809 (Fig. 1 purple highlight) which is a simple LED Driver. There is a small RTC circuit on the shield as well ( Fig. 1 orange highlight). Even though the Arduino has an RTC built in, we decided to add an external one with a backup battery to keep track of time even if the Arduino is not powered. The commonly used DS3231 is very expensive and was not available to order at the time we designed the circuit. For this reason, we chose the PCF8523T which is much less expensive than the DS3231 but a bit less accurate; we observed a drift of 3 min over a month of running the sensor. A simple micro SD Card ( Fig. 1 blue highlight) was used to store the data. We have also included a stepper motor circuit and controller chip on the shield ( Fig. 1 pink highlight), so we can control a stepper motor which we would use as a wiper to clean the optics on the sensor from biofouling and sediment deposits. However, due to the unavailability of the selected TMC2300 chip, we couldn't validate this circuit. The TMC2300 was chosen since it supports voltages as low as 2 V, which is ideal for our battery-powered application.
There are two ways to power the shield: either with rechargeable LiPo batteries or with non-rechargeable alkaline batteries. We chose to use a rechargeable LiPo cell, where the jumper (J1) on the MKR WAN 1310 should always be shorted in this case.
The PCB is designed in a way that it directly mounts to the Arduino. Both our PCB and the Arduino are open-source and our PCB will remain open-source and can always be found in the Zenodo repository. We also have separate PCBs for the LED, the IR sensors, and the pressure/temperature sensor. The main purpose of these PCBs is to have a simple way to mount the sensors to the casing and connect the wires.
This shield is perfect for our application, but it can also be used for a wide variety of other applications. Our highlights include: Low-power Arduino MKR WAN 1310 Programmed in Arduino IDE Entirely 3D printed Turbidity, pressure, and temperature sensor 2 separate i2C ports on three headers 2 IR detectors for direct light to SSC calibration SD card reader RTC with a backup battery Cost effective  ( Fig. 3b). It is also possible to solder the PCBs by hand. Finish the PCB assembly by adding a coat of acrylic laqueur (listed in the Bill of materials).
Connectors. The PCBs have many connectors to connect the different parts. All the 4 Pin Connectors, used for the I2C sensors, have the same pinout, see Table 1.
The 2 Pin Connectors are used for the IR LED and the battery connections (see the 4 Pin (green) and 2 Pin (purple and black) connections in Fig. 1). Use a clamp to crimp the Molex connectors to the wires. The orientation of the connectors are marked in the Altium design files.
Sensor housing 3D printing components. Begin by 3D printing all of the.stl components listed in the Design files summary. Each component should be printed only once except the Detector_Zapfen.stl should be printed twice. For optimal printing performance, we suggest the following options when slicing the.stl files: ''Avoid crossing perimeters" should be enabled so that there is less material to clean after printing.   4 shows how to place the components on the printing bed for optimal printing. All of the components are placed on the bed to avoid overhangs and the ensure a smooth surface. The Zapfen are needed because without them it is very difficult to get a clean print in the Teeth around the lenses. Printing the Zapfen as separate components, as in Fig. 4 d and e, we get a high accuracy print that aligns the optical components to our satisfaction. We can then insert the Zapfen into the Teeth. If using Prusa I3 Mk3/Mk3S Filament Printer, we have provided the.gcode files, which can be used directly on the printer, and include all of the perimeter settings, predefined supports, and layer heights. We chose XPETG as the filament material since it does not dissolve when exposed to UV and water. Once the components have been printed, spray the Cap and Thread with acrylic laqueur (see Bill of materials). Although the components are waterproof, we have found that this helps keep water out of the walls of the 3D printed components.
Component assembly. Once all of the pieces are printed, assemble them as in Fig. 5. Glue the lenses into the zapfen. Once the glue is dry we suggest testing if the lenses leak since this can destroy the IR detectors. Solder wires (according to Table 1) to the back of the LED, pressure, and IR detector PCBs. Then glue the IR detector and LED PCBs into the Zapfen. Glue the three Zapfen into the Teeth (the two IR detectors should be at 45 o and 135 o relative to the LED). Afterwards, glue the pressure sensor into the Teeth. We used the epoxy listed in the Bill of materials. Feed the wires from the LED, IR detector, and pressure/    temperature sensor PCBs through the holes in the Teeth. Glue the Thread and Teeth together, then fill the Teeth with epoxy. Add/crimp the Molex 2-pin and 4-pin connectors to the wires (according to Table 1). Once the epoxy is dry, add the o-rings to the Thread and coat the o-rings in vacuum grease. Finally, connect the wires to the main PCB as in the layout in Fig. 1 and the provided schematic.

Operation instructions
Begin by uploading the first program set_time.ino to the Arduino MKR WAN 1310. Please note that you will need a USB micro B cable to connect the Arduino to your computer and you will need Arduino IDE installed [1]. Please follow the instructions in set_time.ino about changing the date in the program. After the program has flashed, every time the Arduino restarts (disconnect and reconnect to power) it will restart the RTC time to the original compile time of the set_time.ino program. To mitigate this issue, the next program, main.ino, can be immediately flashed without disconnecting power or set_time.ino can be re-flashed after commenting-out line 79 (''setPCF85263();"). Follow by flashing main.ino onto the Arduino. Please note that additional libraries may need to be downloaded and added to your library (e.g. the MS5803-05 external library [32]). The main.ino program was written to take a measurement every hour (one measurement is an average of 15 measurements) to conserve battery, but this can be changed in the code if you require higher temporal resolution to capture larger variability e.g. from flushing of sediment from a dam.
After flashing the Arduino, disconnect the USB, insert a microSD card and connect the 3.7 V LiPo battery. Once the battery is connected, the device should begin taking measurements. In order to avoid large sleep currents and accidentally using a corrupted card, we recommend using this SD card formatter [4] and testing the read-write capabilities of the cards with H2testw [38].
Once everything is running, we added some silica packets into the housing before closing the sensors for calibration, then installation.
Calibration Before installation, we calibrated the sensor using three different dilutions of formazin: 0, 100, and 500 NTU. These three points were chosen because we wanted to limit our exposure to formazin, which is a known carcinogen, and we expected the Ötztal Ache's turbidity to be within this range since 90% of the time this river has an SSC of <5 mg/L [7]. In addition, our last open-source sensor [12] had 12 formazin calibration points and we wanted to see if we could obtain similarly accurate data with less calibration points. The form of the model that converts the digital IR light output to NTU is: where D IR is the digital reading output by the IR detector's ADC, and the calibration coefficients are listed in Table 2. The fit for the three NTU dilutions in shown in Fig. 6. The residual standard error of this model is 2.26 NTU (Adj:R 2 ¼ 0:99) and the Pvalue < 2:2e À 16. This model was built using only the backscattering detector, other alternatives which combine detectors at different angles were compared in [12].

Safety concerns
LiPo batteries can be extremely dangerous if mishandled; for example, if the positive and negative terminals touch, if they are left out in the sun, and/or if a NiCd/NiMH charger is accidentally used. Please follow manufacturers safety instructions.

Validation and characterization Validation
We validated the sensor by installing it in the Ötztal Ache in Tirol over three days to measure the SSCs during the passage of a flood. The Ötz-T was installed $4.13 km downstream of the Tumpen dam (Fig. 7). The Ötz-T sensor took one measurement every hour from 14.09.2022 15:35 to 17.09.2022 08:24. Each measurement consists of a temperature, a pressure, and a turbidity reading (which is an average of 15 turbidity measurements, see main.ino code). The Tumpen dam data was obtained from the Hydrographische Dienst Tirol [39]; their measurements are made using a probe on the riverbank. In the following figures we are showing the measurements of the Ötz-T together with observations at the Tumpen dam upstream.  The temperature measurements are shown in Fig. 8a. The Ötz-T data (black) seem to follow the same trend as the data from the Tumpen dam (purple). However, the Ötz-T data seems to overestimate the temperature and an offset (delay) also seems be present. Although it is difficult to conclude about the origin of the offset due to the low recording resolution, it is likely that this is a real feature related to the attenuation of the flood waves in the 4.13 km reach between the measurements. At flow velocities of 0.5-1 m 3 =s we may expect attenuation of 6-120 min.
The pressure measurements can be seen in Fig. 8b. The Ötz-T pressure sensor is calibrated in a vacuum and the measurements plotted in Fig. 8b (black) are the Ötz-T absolute pressure minus the atmospheric pressure recorded in Imst, Austria for the same time period. The Tumpen data (blue) is the height of the water from their measurement probe. Both measurements follow the same trends but with a shift, which again can be attributed to flow attenuation over the 4.13 km of the river reach. The turbidity measurements are shown in Fig. 8c. The teal line is the SSC data from the Tumpen dam and the black dotted line is our Ötz-T turbidity data in units of NTU. The Tumpen SSC data is obtained via a turbidity probe on the river bank, which is then routinely calibrated to suspended sediment samples [39]. As can be seen in Fig. 8c, our turbidity data follows the trend of the SSC data (peaks and troughs) very well, again with the offset related to the delay of the sediment wave arriving to our downstream site. There are a few notable differences between the two datasets. First, around midnight on 15.09 (left grey highlight) there are two small sediment peaks in our turbidity data where there is only one large peak in the SSC data upstream. The pressure data (Fig. 8b, left grey highlight) observes a dip at the same time. Later (right grey highlight), there is again a peak in the pressure data and another NTU peak which is not as large as the SSC peak. This suggests that there can be fluctuations in the stage-SSC relationship related to short term sediment flux variations (e.g. some disturbance to the flow regime around the gauge causing a drop in stage and rise in SSC). Another explanation is that SSC and NTU usually have a relationship of the form: where a and b are regression-estimated coefficients and are different for every watershed and sediment type (e.g. Costa [8] found a = 0.56 and b = 1.25 and Felix [15] found a = 0.59 and b = 1). Therefore, we cannot expect a linear relationship between the SSC and the NTU data. This same explanation can be applied to the trough and peak occurring just before 17.09. An alternative explanation could be that there were not enough formazin calibration points between 0-100NTU to properly capture the trough. Whether these peaks and troughs could not be fully captured due to the minimal calibration points of the conversion between SSC and NTU should be validated in future studies.

Characterization
The sensor we have presented here is an improvement from the previous open-source turbidity sensor [12]. This new version now incorporates a temperature and pressure sensor to monitor river stage and water temperature. It has an entirely 3D printed design so anyone with access to a hobby 3D printer can build the device. This sensor version now uses an Arduino MKR WAN 1310, enabling the microcontroller to reach extremely low power (104lA [2]) and with all of the i2C devices and the SD card, the sensor sleeps $200lA. This low current draw extends the battery life of our device from one day (the previous sensor [12]) to one month. The sensor is also now programmed in the widely adapted Arduino IDE. Finally, the customized PCB shield is more robust than the previous prototyping board used.
There are many improvements that this sensor may still undergo. First, we would like to add a motor to the device to wipe the optics from any deposited debris or biofauling. This feature is necessary if the sensor is to be used in long-term deployments. We have found that the best micro SD cards add 110lA to the device sleep current, even when the cards were idle. For this reason, in the next version we plan on using an SPI flash to store the data while also including a micro SD card slot to retrieve the data quickly in the field. Additionally, the LED driver we chose pulled 200 mA while taking measurements and significantly drained our battery. We aim to optimize this high LED current draw and improve the overall battery consumption of the device. Finally, the Ötz-T costs almost four times as much as our previous sensor version (61.37 CHF [12]). The parts of this sensor that increase the cost are the epoxy (28.62 CHF), the LiPo battery (41.45 CHF), the Arduino MKR WAN 1310 (38.68 CHF), and the MS5803-05 pressure/temperature sensor (27.91 CHF). All together these components account for 63% of the costs (or 136.66 CHF). We hope to eliminate some of these high costs by building our own microcontroller (eliminating the Arduino MKR), redesigning the teeth (to avoid the excessive use of epoxy), and switching to alkaline Dcell batteries.
Although we only used one of the two available IR detectors for our calibration and Ötztal measurements, the Ötz-T features two IR detectors. With enough gravimetric samples, the two IR detectors' ADC readings can be directly calibrated to SSC (e.g. calibrating D IR from eqn.1 to SSC directly). Traditional calibration needs to anyways undergo a gravimetric calibration (NTU to SSC as in eqn.2) and in this way, one would avoid the lengthy and dangerous formazin calibration step. In addition, using the D IR -SSC calibration is a better representation of the entire catchment since the IR detector response curve changes with different grain type and particle size. Therefore, calibrating to catchment gavimetric samples leads to a calibration more representative of the catchment sediment types and particle size. And using two IR detectors instead of one leads to a better model fit [12].
Our hope is that the Ötz-T sensor brings accessibility to global river research for many applications. We think that with the transparent design presented here, researchers can build and repair the instruments themselves, ultimately making the data from our world's rivers, lakes, and oceans available to all.