Introduction: Automated Titration Machine

Titration is normally a labor intensive, time consuming process that involves a trained chemist or technician. We live in the best period ever for makers; electronics are modular, prototyping is rapid, and information is readily available. Using CAD modeling, 3d printing, an arduino development board, and some ingenuity, we are going to automated this time consuming process.

Step 1: Materials and Resources.

We will using the following items and devices in this project:

Step 2: CAD Modeling

The design of the titrator is pretty open to your creativity. As long as there is an area to mount a nozzle and a pH probe above a beaker, then the unit will work.

However, my project was limited to a specific box type. I also chose to have my sensor and nozzle array actuate up and down as to prevent accidental damage to the delicate probe, and make the lives of the users easier. Also, it looks kinda cool.

Since I was utilizing 3d printing, I tried to optimize my design the best I could for the printers. For example, try to avoid trailing ledges and extrusions that extend far from the base of structure. This will require the printer to create supports, which require quite a bit of post processing to get a nice finish. Also, since 3D printing is all about convenience, I had all my ports and opening printed, to avoid fabrication time.

Step 3: Circuit Design

As show in the diagram:

The pump is powered by a stepper driver with the "step" pin being connected to pin 9 on the Arduino. We don't use the direction pin since we aren't interested in reversing our pump flow.

The stepper motor responsible for actuating our array up and down in powered by the second stepper driver. For this setup, we use both the step and direction pins, since we need to reverse the rotation of the threaded rod upon completion of the test. Step is connected to pin 7, and direction is connected to pin 7.

It is important to note that the stepper motors require a 12v DC source.

The pH circuit has both a tx and rx pin requirement. Rx is connected to pin 4, and tx is connected to pin 5. VCC and the top ground are connected to the 5v source from the arduino, as well as the arduino ground. The other two pins, ground and PRB connect to the BNC connector on your pH probe.

Step 4: Code

I used the demonstration code from Atlas Scientific for the pH circuit, since it works great. It is important to note that you need to experimentally validate your pump. To do this, hook one end of your pump to a container of water, and the other end to a graduated cylinder. Tell the pump to run for 4000 steps, and record the volume in excel. Do this AT LEAST 3 times, but the more trails, the more accurate your pump. Once you are happy with your runs, average all your tabulated volumes, and divide that by 4000. This is the volume of a single step of your motor.

//By:Kahveh Saramout - Chemical Engineer, Cand
// 12/10/2015 //pH code contributed by atlas scientific // MakeCourse - University of South Florida
#include                //we have to include the SoftwareSerial library, or else we can't use it.
#define rx 4                                          //define what pin rx is going to be.
#define tx 5                                          //define what pin tx is going to be.
SoftwareSerial myserial(rx, tx);    
//define how the soft serial port is going to work.
int dirPin2 = 6;
int steppin2 = 7;
int dirpin = 1;
int steppin = 9;
int prep = 8;
int x = 1;
int y=0;
float vol_step = 0.205;
String inputstring = "";                             //a string to hold incoming data from the PC
String sensorstring = "";           //a string to hold the data from the Atlas Scientific product
boolean input_stringcomplete = false;                 //have we received all the data from the PC
boolean sensor_stringcomplete = false  //have we received all the data from the Atlas Scientific product
float ph;                                 //used to hold a floating point number that is the pH. 
void setup() 
{
Serial.begin(9600);                      //set baud rate for the hardware serial port_0 to 9600
myserial.begin(9600);                    //set baud rate for software serial port_3 to 9600
inputstring.reserve(10);                 //set aside some bytes for receiving data from the PC
sensorstring.reserve(30);                //set aside some bytes for receiving data from Atlas Scientific product
pinMode(dirpin, OUTPUT);
pinMode(steppin, OUTPUT);
pinMode(prep, INPUT);
pinMode(dirPin2, OUTPUT);
pinMode(steppin2, OUTPUT);
}
 
void serialEvent() {                            //if the hardware serial port_0 receives a char
  char inchar = (char)Serial.read();            //get the char we just received
  inputstring += inchar;                        //add it to the inputString
  if (inchar == '\r') {                               
    input_stringcomplete = true;               //if the incoming character is a , set the flag
  
  }
}
void loop()
{
  if (x <= 1){
    Serial.println(y); 
  long j;
  for (j = 0; j<8360; j++)       // Iterate for 8360 microsteps.
  {
     digitalWrite(dirPin2, HIGH);
    digitalWrite(steppin2, LOW);  // This LOW to HIGH change is what creates the
    digitalWrite(steppin2, HIGH); // "Rising Edge" so the easydriver knows to when to step.
    delayMicroseconds(150);      // This delay time is close to top speed for this
  }y++;}     
   
  
  if (input_stringcomplete) {                         //if a string from the PC has been received in its entirety                     
    myserial.print(inputstring);                      //send that string to the Atlas Scientific product
    inputstring = "";                                 //clear the string
    input_stringcomplete = false;                     //reset the flag used to tell if we have received a completed string from the PC      
  
  }
  if (myserial.available() > 0) {                     //if we see that the Atlas Scientific product has sent a character.
    char inchar = (char)myserial.read();              //get the char we just received
    sensorstring += inchar;
    if (inchar == '\r') {
      sensor_stringcomplete = true;                   //if the incoming character is a , set the flag
     
    }
  }
  if (sensor_stringcomplete) {                        //if a string from the Atlas Scientific product has been received in its entirety
     Serial.println("pH: ");  
    //Serial.println(sensorstring);                     //send that string to the PC's serial monitor
    ph = sensorstring.toFloat();   
    Serial.println(ph);//convert the string to a floating point number so it can be evaluated by the Arduino
    long i;
  for (i = 0; i<1928; i++)       // Iterate for 1928 microsteps.
  {
    digitalWrite(steppin, LOW);  // This LOW to HIGH change is what creates the
    digitalWrite(steppin, HIGH); // "Rising Edge" so the easydriver knows to when to step.
    delayMicroseconds(200);      // This delay time is close to top speed for this
  }     
  delay(1000);// particular motor. Any faster the motor stalls.
  x++;
   Serial.println("Number of cycles: "); 
   Serial.println(x); //prints 3 of cycles
   Serial.println("Volume: ");
   Serial.println(vol_step*x); //calculates our total volume
   
    
    if (ph <= 6.999) {                                //if the pH is less than or equal to 6.999
      //Serial.println("low");                          //print "low" this is demonstrating that the Arduino is evaluating the pH as a number and not as a string
    }
Serial.println(" --------------------- "); 
    sensorstring = "";                                //clear the string:
    sensor_stringcomplete = false;                    //reset the flag used to tell if we have received a completed string from the Atlas Scientific product
  }
  if (x >= 60) { // 60 cycles and we are finished! this is how we wrap up. 
      long k;
    
     for (k = 0; k<50370; k++)       // Iterate for 50370 microsteps.
  {
     digitalWrite(dirPin2, LOW);
    digitalWrite(steppin2, LOW);  // This LOW to HIGH change is what creates the
    digitalWrite(steppin2, HIGH); // "Rising Edge" so the easydriver knows to when to step.
    delayMicroseconds(150);      // This delay time is close to top speed for this                        
    }
    while (x >= 60) {
  // Do nothing
};}

Step 5: Make It Better!

You have all this useful information, but your doing nothing with it!

Use a data capture shield on your arduino to record the serial port and use the data in excel.

Or in my case, use Matlab to capture the serial output and preform all your calculations for you!

Sorry guys, can't share this code =p