Low-Energy River Quality Monitor

Introduction: Low-Energy River Quality Monitor

Monitoring the water quality of a river is a difficult task. A scientist who wishes to make measurements of water quality at different stages along a river must either have a dedicated team willing to repeatedly hike out to various sections of the river on a regular basis or plant long-term monitoring stations at many fixed positions along the river. In this project, you'll learn how to build your own floating sensor capsule that takes advantage of the flow of the river, making measurements as it drifts down a river, while periodically transmitting its data and location to a remote server. In building this project you will be introduced to the mbed browser-based development environment that allows you to write and compile code in the browser.

The video demonstrates the end result. When the GPS is on, it flashes with a red light, whereas the pH has a green LED.

Teacher Notes

Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.

Step 1: Tools and Materials.



  • Drill press
  • Clamps
  • Caliper

This is quite the list. Before you go out and grab these parts, let me just explain the thoughts behind some of the parts so you can spend your money wisely :).

If you don’t care about the thoughts behind the parts and simply want to spend your money feel free to skip this bit.

Why a 4.7 Quart Bowl? * warning math

Well in order to float, the weight of the water you displace must be less than your weight.

Equating the weight of the bowl to the weight of water the bowl displaces we get the following relationship: m = pv, where p is the density of water and v is the volume of water displaced. v = 0.00444786m^3 and p = 1000kg/m^3 so we can get about 4.4kg of mass in our bowl before it goes under, much more than the mass of the parts that will go into the bowl.

Why Aquarium Sealant?

Aquarium Safe = Animal Safe = Good for rivers as we’re not polluting them :) Nice, tight waterproof seal that is reliable unlike epoxy which is brittle and might crack.

Why cylindrical metal bit?

Metal is a good conductor of a lot of things, including heat. If we put the metal bit out of the container, then it will have the temperature of the water, and we could easily touch the analog temperature sensor to the part of the bit inside the bowl to get the temperature of the water. This is much easier than waterproofing the sensor.

Why ph sensor?

It was a common metric measured in water, but it’s a little pricy. The point is that you might want to attach whatever sensor you’d like to the device, but you’d have to modify the code, wiring, etc. to get it to work. We just demonstrated our device with a ph sensor.

Why the nucleo-l152re?

Our project is a low-energy device, so we want a low-energy microcontroller. Compared to a more general-purpose microcontroller the nucleo’s processor much lower power consumption while active and, especially important, while asleep since that’s what the device will be spending most of its time doing.

Step 2: Sealing the Bowl

Drilling the Holes

Take the bowl, a caliper, the metal cylindrical bit, and the ph sensor. Using the caliper to get the width of both the bit and the sensor find the appropriate drill bits that will cut through the bowl and leave a tight seal. Be sure when you drill the bowl to have a piece of wood under the plastic of the bowl so that the plastic doesn’t catch on the drill. Be sure to clamp down the bowl when drilling. I recommend that you “peck” the bowl multiple times instead of going straight through so that you can get a cleaner hole.

Sealing the Holes

Clean the bowl with rubbing alcohol. In order to make the hole more tight and give the silicon caulking something to hold on to, apply electrical take over the two drilled holes on both sides of the container. Wedge something sharp and small to make a hole in the take and then place the temperature sensor into the hole as seen.

Wearing gloves, apply the Silicon Sealant on both sides of the container generously. You want to make sure the seal will be good, so make sure you see no holes. Apply pressure on the object for 5 minutes to help the silicon bind with the material. It will take 24 hours to fully strengthen.

After 24 hours you should get some nice seals. BEFORE PLACING YOUR ELECTRONICS, you'll want to test these seals. Here's a nice experiment we did to test our seals.

Testing the Seals

For our water absorbent device we used the tampons and pop rocks out, finally. Using clear tape, tape the pop rocks around each seal that you've created tightly. Place some pop rocks around the top of the bowl to see if there is leakage from the top. Use the tampons to avoid cross-contamination between the leakage area. After going for a swim with the bowl (we tested in depth about 8 feet) if you see the pop rocks disappear in any area, you have a leakage there. Seal it again and test it BEFORE moving on.

Step 3: Wiring Up All the Electrical Components

At this point your container should be waterproof. I am now going to wire up the different components.

Battery to the Transformer and Nucleo:

To connect the battery to the transformer and Nucleo, follow these steps:

  1. Secure the battery tightly in a Ziploc bag to ensure water protection.
  2. Solder the GND wire of the battery to the GND wire of the transformer.
  3. Solder the Live wire of the battery to the Live wire of the transformer and to another wire connecting to the Vin of the Nucleo.
  4. Keep the Nucleo disconnected from this wire except when you are conducting tests.
  5. Make sure to tape over any exposed connections to prevent short circuiting.

The battery has now been completely wired.

Temperature Sensor to Nucleo:

To connect the temperature sensor, follow these steps:

  1. Solder a 1k ohm resistor onto the V Output (the middle pin) of the temperature sensor.
  2. Connect a wire from the other end of the 1 kΩ resistor to the A0 pin on the Nucleo.
  3. Connect the temperature sensor's ground to the GND pin in bus CN5 on the Nucleo.
  4. Connect the temperature sensor's voltage pin to the 5V pin in bus CN6 on the Nucleo.
  5. Press the temperature sensor against the cylindrical metallic bit sticking out of your container and tape it so that the two keep on making contact. This allows the temperature sensor to measure the temperature of the water rather than the container.
  6. Make sure to tape over any exposed connections and to keep the resistor attached to the temperature sensor and the Nucleo.

The temperature sensor has now been completely wired.

pH Sensor to Nucleo:

To connect the pH sensor, follow these steps:

  1. Connect the RX pin of the pH sensor to pin PC_11 on the Nucleo.
  2. Connect the TX pin of the pH sensor to pin PC_10 on the Nucleo.
  3. Connect the GND pin of the pH sensor to the GND pin in bus CN6 on the Nucleo.
  4. If you wish to test out your pH sensor without connecting the GPS, then connect the 3.3V pin of the pH sensor to the 3.3V pin in bus CN6 on the Nucleo.
  5. If you wish to connect both the pH sensor and the GPS simultaneously, connect the 3.3V pin of the pH sensor to the 3.3V pin of the GPS.
  6. Remember, to remove the solution that protects the pH sensor when conducting tests in water.

The pH sensor has now been completely wired.

GPS to Nucleo:

To connect the GPS, follow these steps:

  1. Connect the EN pin of the GPS to pin D7 on the Nucleo.
  2. Connect the RX pin of the GPS to pin PB_11 on the Nucleo.
  3. Connect the TX pin of the GPS to pin D6 on the Nucleo.
  4. Connect the GND pin of the GPS to the GND pin in bus CN7 on the Nucleo.
  5. Connect the Vin pin of the GPS to the 3.3V pin in bus CN6 on the Nucleo.
  6. Connect the antenna of the GPS.
  7. If you wish to connect both the pH sensor and the GPS simultaneously, connect the 3.3V pin of the pH sensor to the 3.3V pin of the GPS.

The GPS has now been completely wired.

GSM to Nucleo:

To connect the GSM to the Nucleo, follow these steps:

  1. Connect the TX pin of the GSM to pin D2 on the Nucleo.
  2. Connect the RX pin of the GSM to pin D8 on the Nucleo.
  3. Connect the Rst pin of the GSM to pin D3 on the Nucleo.
  4. Connect the RI pin of the GSM to pin D4 on the Nucleo.
  5. Connect the Key pin of the GSM to pin D5 on the Nucleo.
  6. Connect the GND pin of the GSM to the unconnected GND pin in bus CN6 on the Nucleo.
  7. Connect the Vio pin of the GSM to pin 18 in bus CN7 on the Nucleo.
  8. Connect the antenna of the GSM.

The GSM is now connected to the Nucleo. However, it still requires external voltage to work.

GSM to Transformer:

To connect the GSM to the Transformer, follow these steps:

  1. Solder the GND wire of your JST cable to the GND wire of the Transformer.
  2. Solder the Live wire of your JST cable to the Live wire of the transformer.
  3. Connect the JST cable to your GSM.
  4. Make sure to tape over any exposed connections to prevent short circuiting or water damage.
  5. To use the GSM, remember to insert your MiniSIM card into the GSM.

The GSM is now completely wired up.

Now all your components have been wired up and you are ready to proceed with the software component. Please ensure that your jumpers are properly configured to transfer code to the Nucleo.

Have JP1 connected (if you want to limit the allowed current that the nucleo can draw) and JP5 to have the jumpers on the two pins closest to U5V for USB transport. For powering the nucleo not using the USB, make sure to change JP5 to have the jumper of the two pins closets to E5V.

Step 4: Loading and Running the Software

Initial Setup

To communicate with the Nucleo board, we first need to install the USB drivers found here. This allows us to download the software to the board, as well as receive data over serial. While optional, it is also recommended that you download and install any firmware updates for the board, found here. Once the board is connected, you should see an new storage device. To transfer and install any new software for the Nucleo, simply save or copy the program to this new storage media, and you should see the board's lights blink. Note that the file, once copied, will disappear from the device. However, so long as the lights blinked and ended on green, the board continuously runs the last downloaded software.

To properly debug the software, it is recommended that you set up a serial port connection with the Nucleo. While a variety of programs can be used, on Windows, we used the Arduino software package. If you connect the Nucleo and click on the "Serial Port Monitor" button (a small magnifying glass in the corner of the screen), it will display all information sent from the board. This includes some informational print statements included in our version of the code.

Setting Up the Code

The full code can be found here. The easiest way to start running the project is by using the provided online compiler found at https://www.developer.mbed.org. Since the server to send the data to is different for each person, you have to do a small amount of modifications to get the software to run. First, navigate to the "main.h" file, and change the line #3 so that it says:

#define URL "Your_URL"

Where Your_URL is the URL you want the data to be sent to. Note that you need to put the quotation marks around the URL. The best site we found for sending data to is RequestBin. Simply create a RequestBin, copy the "Bin URL" (of the form "http://requestb.in/19lz95m1") to the Your_URL field, and refresh the page. The page will the display the data sent to it by the Nucleo board. Note that to view the data, add the line "?inspect" to the end of the URL.

Once you have changed the "main.h" file, in the mbed compiler, click the compile button at the top. It will then download a ".bin" file. Copy that file to the Nucleo board, and it will start running the program.

Modifying the Code

There are a number of easy changes you can make to the code to either change the hardware layout, change the SIM card company (it is T-Mobile by default), change the number of readings per send, and the frequency of taking a reading. All of these modifications take place in the "main.h" file.

First, to change the hardware layout, you can simply change the port given by the specific sensor. So, for example, if you wanted to change the GPS TX pin from the default D6 to say PC_10, you would change line 13 to say:

#define GPS_TX PC_10

Note that this is not a valid pin change, as we have the pH sensor's TX pin on PC_10. Further, only specific pins are TX, while others are RX, and many are neither. You should look at the Nucleo pinout here to determine which pins are valid.

To change the APN URL, you can simply change line 4 to

#define NETWORK_APN "Your_network_apn"

Note that as with the URL in the prior paragraph, you need to include quotes around the network APN.

To change either the number of readings to send or the frequency of taking a reading, we can modify lines 6 and 7. Line 6 defines the number of readings to be collected before sending. The recommended range is between 1 and 100. Line 7 defines the number of seconds to sleep for between each reading. The default is 360, and so it takes a reading every 6 minutes (so 10 per hour). This can be changed to almost any positive number, but very large numbers will have undefined behavior.

Those are probably the primary edits that you would want to change, but more advanced edits are included in the next section.

Modifying the Code (Advanced)

The main "advanced" edit we focus on is adding a sensor. This requires a fair amount of modifications, but is not terribly complicated. First, you have to include the sensor library in the Full-Project folder in the mbed compiler and add the appropriate include line in "main.cpp" (e.g. #include "Custom_Sensor.h"). Then, we have to change the reading struct in "main.h" by adding the line(s) for whatever sensor you want to include. For example, if you want to include an integer reading, you have to add the line "int customSensorReading" to the struct. Moving back to "main.cpp" we need to add a global instance of the sensor, however it is initialized. Then, we can simply add the sensor to each of the associated functions (setup(), enterSleep(), read(), etc.) to get it to work properly. The final major edit needed is in the send() function. We note that the call to "sprintf" includes all the fields from the reading struct. We have to add both a formatted string line (e.g. %d for an integer) and the associated data field (data[i].customSensorReading) to the sprintf call. Finally, we need to modify the SIZE_OF_ENTRY define at line 28 by adding the size of whatever data structure you added to the reading struct plus one. This is a little more complicated, as it needs to be the size of the structure added to sprintf. So, if we added a float and called %10f in sprintf, we would need to add 10+1 = 11 to the SIZE_OF_ENTRY define (as the 10 in %10f indicates you want to copy 10 bytes of information to the sprintf string).

Step 5: Securing the Circuit in the Capsule

Now that most of the circuit components are wired up, it is time to secure the circuit in the capsule. Depending on the specifics of how long your wires are you may need to make modifications to the way you secure the circuit. The general idea is this: To make sure the capsule doesn't flip over, the capsule needs to be rotationally balanced and bottom heavy. Any flexibility for components to slide around will exacerbate any imbalance, so all components should be fixed in place.


Since the battery is particularly sensitive to leaks, wrap the battery in the plastic bag (pictured), leaving the two power wires coming out as they will need to be connected to the rest of the circuitry. Try to let the top of the bag containing the battery be as flat as possible, since we will later attach the bread board to the top of the bag. The plastic bag will provide the battery with a second layer of protection in case of a leakage. Fix the plastic bag and battery to the base of the bowl between the metal conductor and pH probe using a command strips.

To keep wires neat, fold the battery wires over the battery and tape them down. Recall that the voltage supply and ground wires are forked because we will need to transform some of the power to power the GSM at a lower voltage, so there should be a total of four wires coming out of the battery. To make sure you do not short-circuit the battery, check that you have wrapped tape around the exposed metal from the two power supply wires, and keep them there until you are ready to attach them to the rest of the circuit.

Water protection:

Tape six of the water-absorbent parts of the tampons to the base of the bowl. These will absorb water in case of a small leakage, reducing the likelihood that the water will run into the electronics.

Bread board:

With command strips or peeling the paper off the bottom of your breadboard, attach the bread board to the top of the battery.

pH probe:

You should already have attached the pH board to the breadboard in earlier step. Plug the pH probe into the pH board. To keep the probe wire out of the way, wrap the wire around the rim of the bowl (not too high, so as not to interfere with the seal when we put the lid back on the bowl) and tape the wire down with electrical tape as pictured.


Notice that there are multiple holes in the Nucleo. With a couple of zipties, make small "handles" on the underside of the Nucleo, looping them through the holes. With tape, fix the handles to the base of the bowl. With the temperature probe on the left and the pH probe, the Nucleo will lie on the side of the battery closest to you.

Temperature probe:

The temperature probe should be tightly taped to the side of the metal conductor. The more contact there is between the temperature probe and the metal conductor, the better the measurements will be.


Tape the transformer to the base of the bowl at the side of the battery farthest from you.


With a command strip, or tape, fix the GSM to the base of the bowl between the pH probe and the Nucleo.


Fasten GPS to the left wall of the container with a command strip. Tape the antenna to the wall as well.

All components of the circuit should now be fixed in place. Remember that the circuit will not switch on yet, as the battery is not connected. Simply connect the battery's voltage to VIN on the nucleo, after switching the JP5 jumper to external power and your low-energy river quality monitor will be on!


Be the First to Share


    • Backyard Contest

      Backyard Contest
    • Silly Hats Speed Challenge

      Silly Hats Speed Challenge
    • Arduino Contest 2020

      Arduino Contest 2020

    5 Discussions


    3 years ago

    Are you only monitoring for pH and temperature?


    3 years ago

    Are you only monitoring the pH and temperature of the water?


    4 years ago

    Silicone sealant does not adhere well to polyethylene or polypropylene bowls. Hot glue (which is mostly melted polyethylene) bonds well to both of those, to glass or metal probes and to PVC-insulated cables. It also hardens almost instantly. I needed to seal a barb fitting to apply vacuum or pressure to a similar container and hot glue was the only product that sealed consistently. There are versions with flexibility optimized for sealing or tensile strength optimized for fastening but the least expensive hot glue has been adequate for both.


    Reply 4 years ago

    Hey RobertC29,

    Thanks for the input!

    We ran into the problem of Silicon not bonding the best with polypropylene bowls. We used tape over the holes before we put the silicon so the silicon would mostly bond with the tape, since it doesn't bond well with the bowl. This was sufficient to seal the bowl. We didn't use hot glue as we weren't sure it would be flexible enough, but flexibility optimized hot glue is something we didn't know about! Thanks!