A Review of SLA Printed Bag Caps To Improve Sealing Over FDM Bag Caps

A Review of SLA Printed Bag Caps To Improve Sealing Over FDM Bag Caps

An important feature of the OPEnSampler is the ability to seal the collected water post-sample such that evaporation and contact with the air have a negligible impact on concentrations of minerals and isotopes in the samples. We’ve tried many different options but solid resin-based 3D printed caps proved to be the best option.

Redesigning the Bottle Trays

Redesigning the Bottle Trays

A tray to hold 12 ISCO bottles was previously designed without considering the weight of water when they are filled. The plastic tray was redesigned using Fusion360's sheet material modeling and static stress simulation tools.

Capstone: Project Features

This post provides a very general description of the functionality that will be delivered by the OPEnSampler capstone project, and includes a link to our requirements specification on GitHub. It discusses the two primary pieces of the project: the OPEnSampler Companion App and status update functionality.

Shipping the OPEnSampler

Shipping the OPEnSampler

The late-summer OPEnSampler has entered the shipping process! I'm excited to work closely with the researchers in Zürich and get feedback on our design. Additionally, there will be a round of documentation updates very soon for the new batch of samplers.

Capstone Team Intro: Travis Whitehead

I'm Travis Whitehead, one of three CS students contributing to the OPEnSampler for my capstone project. This post elaborates on the capstone process and serves as a personal introduction sharing a little bit about me and my future involvement with the OPEnSampler project.

Capstone Team Intro: Chase Coltman

Hello OPEns Lab Community, my name is Chase Coltman and I am one of the three members of Capstone team assigned to the development of the OpenSampler Companion Application.

OPEnSampler October 17 Update

OPEnSampler October 17 Update

Much has happened with the samplers in the past two weeks! There are two categories of updates: those relevant to the Zurich Sampler and those relevant to the new versions of samplers. In short, the frames have been assembled for the new samplers and the PCBs are being soldered up; the new pumps arrived; the final pieces of the Zurich Sampler are coming together and it will be ready to ship very soon.

Choosing a Different Peristaltic Pump

Due to concerns about the vendor, we are not able to use the Honlite pump featured in the post "Choosing a Peristaltic Pump" a few weeks ago. Luckily, I found a $99 pump that should do the trick on Amazon. This post discusses the considerations necessary to use it.

Assembly Day 1

Azad and I spent part of the morning assembling the frame of the bottle-based OPEnSampler. I found quite a few changes I will make when assembling the next sampler. In the end we found the device didn't quite fit in the duffle bag and so some machining will need to be done to reduce a couple dimensions.

Investigating a Solenoid Valve's Strong and Weak Orientations

Investigating a Solenoid Valve's Strong and Weak Orientations

We observed our $1 solenoid valves were failing under low pressure conditions. After some investigation and testing, we found we could safely orient the valves in  to ensure the flush valve will fail first while the sample valves will form quite strong seals when closed. This solution allows us to continue to use the cheaper valves and keep our cost of materials down.

Choosing a Peristaltic Pump

Choosing a Peristaltic Pump

There are currently two pumps to choose from for the OPEnSampler: a low flow rate, unknown-precision peristaltic pump and a high flow rate, "low precision" pump. They have their pros and cons and this writeup will discuss the angles of attack for deciding which one is more appropriate for our system.

Reviewing the Diameter and Material of OPEnSampler Tubing

Reviewing the Diameter and Material of OPEnSampler Tubing

The EPA recommends a flow rate of 2 ft./s or greater to minimize the relative difference in velocities of suspended sediments. They also recommend a tubing diameter of 1/4 in. as well, but not for a particularly well documented reason. One unanswered question brought up in the design review meeting was the impact of tubing diameter on the quality of water samples. This short writeup discusses some of the considerations involved in the decision to use 1/4'' OD Teflon tubing for future sampler designs.

OPEnSampler Update August 9, 2017

Much progress has been made with the OPEnSampler! The frame is lightweight, the entire system fits into the Pelican rolling cooler, and the sample control works as expected. 24 bags fit with room inside the frame, and the system can be set on any face without issues, easing maintenance, testing, transport, and drawing out samples. Some issues persist in this iteration, namely light leaking from the bags and a low flow rate due to the cheap pumps.

OPEnSampler Update, Bertha


Our efforts over the past moths have culminated in a robust lab-tested prototype of the OPEnSampler we endearingly call "Bertha." We've determined this will be our in-house lab prototype that we will use as a testing bed for integrating new features and hardware. Lessons learned experimenting with Bertha will directly translate into field-deployable OPEnSampler versions to be distributed for use. This post details the technical specifications of Bertha, features, Serial Commands, and use cases.

Technical Specs

  • Frame dimensions are 24in x 12in x 12in and made out of 40mmx40mm extrusion.
  • 2 12VDC Peristaltic pumps (250ml water pumped in 2min)
  • 24 250ml aluminum-lined Mylar bags (spout packs)
  • 25 12VDC valves (24 valves attached to bags, 25th valve is used as a system flush outlet valve)
  • Arduino Uno, Microprocessor
  • Custom PCB with TPIC power-shits registers for handling valve actuation
  • Motor driver board
  • High Precision, Temp-compensated Real-Time Clock, for microprocessor sleep/wake(sample) scheduling.
  • Mode switch toggles between Sampler operation modes: standard operation mode, serial command mode.
  • EEPROM saves configuration of sampler parameters (sample duration, flush duration, next valve to sample, etc).
  • Serial command set for configuring the sampler's behavior out in the field and for sending discrete commands (puppet-string) to turn on/off discrete components of the sampler. e.g. turn pups on/off/reverse and open/close specified valves.
  • Power-save Sleep mode, for ling battery life in the field. At the moment, drawing 24 250ml samples should require just 1 Amp Hour of a 12VDC battery. In standard operation mode, sampler stands by in low-power sleep in between taking samples. In serial command mode, electronics remain awake and stand by for configuration commands from computer.


In consultations with many different researchers hoping to use this OPENSampler, we identified that the technical specifications of the sampler will vary depending on the context of use. This includes: What kind of water source is being sampled, what is being tested or analyzed, and environmental conditions and considerations in the field. To this end, we decided to make a "core" system that would be extensible using attachments for particular deployment contexts. This architecture is not dissimilar with many vacuum cleaner systems, where the core remains immutable but changes utility based on the attachments used.

Packaging: The frame is designed to be dropped into a variety of different "packages" depending on the field requirements. In many instances, a waterproof duffle bag may suffice for carrying the device into back-country environments. Rigid stack-able boxes made from corrugated plastic may be desirable for other deployments. For field deployments requiring samples be temperature protected (from wither extreme heat or cold), dropping this into a rolling lockable travel cooler such as the Pelican 80qt Elite.


Switch the sampler into "serial command mode." Not required, but should be done for best practice. After programming the Uno over USB, you may either switch the sampler directly into standard operation mode or send serial commands to configure your sampler's parameters. Switching modes back and fourth may be done at anytime. In operation mode, a sample cycle is initiated whenever the specified time has elapsed.

Each sample cycle consists of the following states:

  1. System Flush
  2. Sample Draw (in next bag in sequence)
  3. System Sleep/standby

Samples may be removed from the device without manually removing bags. This is achieved by switching the sampler into serial command mode and typing commands into the Arduino Serial Monitor window to draw samples out one by one in any desired order. See commands below. This process may be automated (and should be) using a program to send a sequence of timed commands. A sample python script can be found on the project GitHub site.

Sampler Configurable Parameters and Factory Defaults Are:

  • IsDaily = True (Take a sample either daily or at a set periodic rate throughout the day)
  • 8:00 (default daily time to take sample)
  • Sampler Duration = 100 seconds (takes 120 seconds to fill 250ml)
  • Flush Duration = 30 seconds (this will need to be set based on the length of tubing away from main sampler - longer tubing requires longer flush duration for full system purge)
  • Sample volume = 250 (in ml, this isn't being used right now, but there in case features need in the future)
  • Sample Valve Number = 1 (next bag to draw sample into)
  • Sample Period = 3 (if the IsDaily flag is FALSE,

The above parameters may be changed at anytime by switching into Serial Command Mode. Parameters are saved in EEPROM and are preserved even if the sampler looses power. Sampler operation will proceed with the new configuration behavior when switched back into operation mode.

Serial Command Set

  • CLK, Checks the current RTC time, Hr:Min:Sec - useful for checking before using SA to set sample alarm
  • SAD (int)X (int)X, sets "Daily Sample Alarm" Hr:Mn to take samples daily at time. Uses 24hr format.
        ex: SAD 9 30 sets sample alarm to 9:30AM daily.
        ex: SAD 16 22 sets sample alarm to 4:22PM daily.
        Also sets Is_Daily flag for initialization if power-down restart, clears Is_Hourly flag
  • SAP (int)X, sets "Periodic Sample Alarm" to take samples at specified period duration in Min.
        ex: SAH 30 sets sample alarm to go off every 30min.
        ex: SAH 47 sets sample alarm to go off 47min.
  • FD (int)X, sets "Flush duration" period in ms, should be about 20sec, but will change with the length of tubing you use to get from sampler to water source
  • SD (int)X, sets "Sample Duration" time that pumps run water into each bag in milliseconds
      ** removed for this version : SV (int)X, sets "Sample Volume" in ml, a transform of Sample Duration, may not be 100% accurate, 2min per 250ml,
  • VN (int)X, Sets the next valve/bag to place sample. Sampler saves curent valve number during operation in EEPROM in case of power failure, it picks up where it left off. This ensures you can reset the valve count before each new deployment, or manually skip to next available bag should the sampler malfunction
  • RST, Full system "factory" reset - set default sample period, sample duration, reset vlve counter, writes defaults to EEPROM (over-wirghting previous settings)

Pupet-String Commands:

  • Vx (int)#, Turn valve on/off where x is valve number (starting at 1, V0 is flush valve). # is 1 for on (open) and 0 for off (close) example: V1 1 opens valve 1. V1 0 closes it.
  • M #, turn motor on/off and direction. #=0 for off, #=1 for draw water into sampler, #=-1 for draw water out of sampler    example: M 1 will begin drawing water into sampler.

From here, you may use Arduino IDE, Python, or other software to send timed sequences to sampler. For example: V0 1 followed by M 1will begin flush.  The sequence (press return where you see / ) V0 0 / V1 1 / M 1will disable flush and draw water into bag1
    You could also make a "macro" or timed program in something like Python for drawing water out of the sampler sequentially into your analysis machine without removing bags! Example of this is on the project GitHub site.

Features to be integrated for Zurich Version

The Zurich version is underway, with frame being constructed out of much lighter 15mmx15mm extrusion. This will make the total sampler weight (without filled with water) about 10lbs!

Packaging: The frame is designed to be dropped into a variety of different "packages" depending on the field requirements. The package for Zurich is intended to be a waterproof duffle bag. However, for field deployments requiring samples be temperature protected (from wither extreme heat or cold),

Currently, all sampler status messages are reflected on the Arduino IDE Serial Monitor window when sampler is attached to host computer. We're evaluating an OLED display that will show all status information during sampler operation.  There will also be a wake button for the display that will show the status of the sampler at anytime during its sleep cycle.

Features for future versions

One major issue is not knowing the operational status of your sampler when left out in the field. Instead of being forced to check in on the sampler in person, we plan to integrate a GSM extension for the core, which will send updates over texts or emails using any 2G SIM card.

A Simpler Pump Test: No SD


This is a follow-up to the previous post, "A Simple Pump Test". There were several complications with storing the pump data on an SD so this post will describe a new method that stores data on the Arduino's own memory.


In the field, the pumps will be run for 2.5 minutes per sample for 24 samples, resulting in one hour of total runtime. As described in the previous post, the pumps used in the sampler are poorly documented and information on their lifespan and behavior under long periods of use is needed. 

The SD breakout board used in the previous test was a 3.3v board and was not compatible with 5v arduino logic without some voltage conversion in between. While it worked some of the time, it resulted in corrupt data after a few points. Rather than using a 5v board or something to step down the signal voltage, the Arduino's own memory can be used to store a small amount of data.

Arduinos have a small amount of available memory that doesn't get reset between power cycles, known as EEPROM. A single byte can be stored per register, and an Arduino Uno has 512 available registers.

Setup and Method

A 12v peristaltic dosing pump is wired such that the positive end is connected to a 12v source and the negative end is split between a .85 Ohm resistor and the Arduino's A0 analog input pin. The Arduino's GND is connected to GND on the power source and VIN is connected to 12v. The other end of the .85 Ohm resistor is connected to GND.

A jumper wire connects GND to the Arduino's digital pin 3, which is initialized to INPUT_PULLUP.

When powered on, the Arduino continuously checks that pin 3 is LOW. If it is, the voltage across the .85 ohm resistor is effectively measured via an analog read of pin A0 and the value is stored in a register of EEPROM. The register address is incremented and the loop resets.

If pin 3 is HIGH, data collection is turned off and the Arduino checks for a serial input of "p". If the user inputs in the serial monitor "p" then it prints all the data from the registers separated by spaces. This data should be copied and pasted into a text file, but can be reprinted as long as pin 3 is HIGH.


// A simple voltage logger that is 

#include <EEPROM.h>

const int sensorPin = A0;
const int startPin = 3;

long sTime = 0; // last sample time
int maxPoints = 240; // maximum number of points to store
int sDelay = 30000; // delay between samples
int addr = 0;

void storeData();

void setup() {
  pinMode(startPin,INPUT_PULLUP); // if grounded, enable recording


void loop() {
  //If datalogging is enabled, store data in a new address
    if(millis() - sTime > sDelay){
      Serial.println("reading data point " + String(addr));
    Serial.println("Enter 'p' to print out data");
      int input = 0;
      if(Serial.available() > 0){
        input = Serial.read();
      if (input == 112){
        for(int i = 0; i < maxPoints && i < EEPROM.length(); i++){
          Serial.print(" ");

 * store the sensorPin voltage and increment the address. If the address has
 * reached the limit of number of the points or hit the last address of
 * the EEPROM, don't store data and return from the function.
void storeData(){
  if(addr == EEPROM.length() || addr == maxPoints){
    Serial.println("Max addr reached");
    sTime = millis();
  EEPROM.write(addr, analogRead(sensorPin)/4);
  sTime = millis();

Python Code

# This code will take in data via a text file that was collected using
# the pumptest arduino code. Data points should be separated by spaces.

import matplotlib.pyplot as plt

data = []
splitter = []
voltage = []
current = []
average = []
avg = 0

with open('pumplog_2_p1t2.txt') as f: #file name for test data to be graphed
    reader = f.readlines() #read in the data

for line in reader: #split up the data. Could be conbined with converting to int but is more readable this way.

for point in splitter[0]:
    data.append(int(point) * 4) # turn each point of data into an int. Data values were divided by 4
                                # to fit into EEPROM.

for point in data: # calculate the voltage at each point.
    voltage.append(point * 5 / 1024)

for point in voltage: # calculate the current at each point.
    current.append(point / .85)

for point in current: # calculate the average current.
    avg += point
avg = avg / len(data)

for point in data: # turn average into a plottable list

plt.title("Pump 1 Test 2") #rename based on test
plt.xlabel("time (minutes)")
plt.ylabel("current (A)")


Initial Results


Three tests have been run so far. They were graphed using Python 3 and matplotlib.pyplot. Another test is currently being run on the second pump. The data between the two pumps will be compared using a two-sample T test to check if the two pumps perform the same. The same method will be used for the pumps under condition of pumping water.

The initial three tests might suggest that there is a long term decrease in the pumps' current draw. Future tests should be conducted for a full day and a linear regression analysis should be performed. More importantly, such inconsistency in the current draw suggests the flow rate though these pumps is not constant. A test should be conducted to observe the trend and variance in the mass flow rate of water through the pump via a logging scale. A better conclusion can be made once the first round of testing is finished and statistically analyzed.


A Simple Pump Test


Peristaltic 12V dosing pumps are cheap and provide a large enough volumetric flow rate for our needs. Unfortunately there is not much information available on the type we are using. This post will discuss the method we are using to test the reliability and consistency of these pumps over a period of two hours. It is the first of several tests we will be conducting on different components of our water sampler.


Setup and Method

A pump is held in a clamp and powered from a 12v source. A .85 ohm, 1.4 watt rated resistor connects the pump to ground. The voltage across the .85 ohm resistor is measured over time using an arduino and this data is stored in an SD card. 

The arduino reads the voltage on an analog pin and stores that, along with the time since starting in milliseconds, in the SD card. Initially there is a delay of one second in between data points and after sixty points the delay increases to one minute. This data will be transferred to a computer where it will be used to show the current through the pump over time.



// A simple voltage logger that is heavily
// based on the SD Datalogger example sketch.

#include <SPI.h>
#include <SD.h>

const int chipSelect = 4;
const int sensorPin = 0;

int n = 0;

void setup() {

  Serial.print("Initializing SD card...");

    Serial.println("Card failed, or not present.");
  Serial.println("card initialized.");


void loop() {
    String dataString = makeDataString();
    File dataFile = SD.open("pumpLog.txt", FILE_WRITE);
      Serial.println("error opening pumpLog.txt");

    else delay(60000);

String makeDataString(){
  return String(analogRead(sensorPin)) + ", " + String(millis()) + "; ";


Once the pump has run for two hours, the power will be turned off and the data from the SD card will be transferred to a computer. Using Ohm's Law the voltage across the resistor will show the current through the system. The data will show what kind of trend, if any, the current draw has through the pump. It will also show if the current draw varies with a resolution of one minute.

This test will be repeated for two other pumps. Then it will be repeated with water flowing through the pump tube.

New Design: Water Sampler 4040


I finished the new design of the 24-bottle water sampler which will be fabricated within the next week before the electronics PCB gets here. The new design is made entirely out of 4040 (a 40 mm x 40 mm profile) extruded aluminum, common store-bought joints, and 3D printed components.

water sampler 40404 render


This redesign solves several issues with the original foam enclosure:

1. The 4040 frame does not require a laser cutter to manufacture

2. The frame is rigid

3. Mounting objects rigidly to the frame is very easy

Materials and Methods

This design uses 2 primary materials at the moment: 4040 extruded aluminum, and 3D printed ABS plastic. All of the printed parts could be replaced with machined mounts and brackets in the absence of a 3D printer. 4040 was chosen for the frame material because of its ease of use and because we have tons of it here at the lab, but future designs will most likely use slimmer extrusions like 2020 to save cost and weight.

Explanation of the Design

Four long extrusions make up the outer corners of the frame. They are 600mm long, roughly corresponding to the 24 inch length of the original design. The short outer-frame pieces are all 210 mm long to provide enough space for the bags to hang. A 600mm length piece of 4040 runs across the top and provides channels to mount the valves, pumps, and electronics. Two 520mm lengths of 4040 across the sides, offset from the top by a few centimeters, provide the channels for the bag caps which the sample bags hang from.

The orange brackets are 3D printed and connect the central channel perpendicularly to to the frame. Other brackets are store-bought and aren't included in the design. All mounting is done using t-nuts and/or t-bolts that slide in to the 4040 channel to limit the amount of machining required to assemble the sampler. A thin sheet of PETG plastic will cover the top of the assembly and protect the device from rain but could easily be replaced with a large trash bag or tarp.