Home

Contact Me





LinkedIn

1.0 Background


The Dip Station is an internal device I built for my employer, Cell Microsystems. The idea behind the dip station is to use a stepper motor to lift material into the air at a velocity set by the user.

The circuit consists of an Arduino Uno with a motor drive shield stacked on top. A motor shield is highly recommended when driving motors with an Arduino, as they can supply higher current (1.2A vs. an Arduino's 500mA output), higher voltage, and provide better pulse width modulated. The motor shield is connected to a stepper motor. There are two 10K potentiometers: 1 to control distance and 1 to control time. The microcontroller code then converts these values to a velocity and turns the stepper motor at that velocity.

2.0 Final Product


Biological Models

Full Dip Station Set Up

3.0 Videos

Biological Models

Dip Station Demonstration


5.0 Circuit Diagram

Biological Models

LCD Screen to Board

Biological Models

Circuit Diagram II
10K Pot 1 output [Time] --> A1
10K Pot 2 output [Distance] --> A2

Biological Models

"Start" Button to Board



+5V powers the red LED on the button [purely aesthetic]
GND grounds the LED on the button
GND--> "NC": "NC" stands for normally closed, so when the button is not
pressed, ground will be connected
+5V--> "NO": "NO" stands for normally open, so when the button is
pressed, +5V will be connected
to A0, signaling the Arduino
to initiate motor travel.
Biological Models

"Reset" Button to Board


+5V powers the red LED on the button [purely aesthetic]
GND grounds the LED on the button
GND--> "NO": "NO" stands for normally open, so when the button is not
pressed, ground will be disconnected.
When the button is pressed, ground will connect to
"reset" on the board through the "NO" pin.
When ground is connected to reset on an Arduino, the Arduino will reset.

6.0 Assembly



7.0 Code

  

#include  //needed to drive motor
#include  //acceleration library is smoothest
#include  //needed for circuits
#include  //needed w LCD 12C Library 


LiquidCrystal_I2C LCD(0x27, 16, 2); //usual address of LCD Screen with pixels (width, height)IW

AF_Stepper motor1(200,2);  //200 steps/rev w motor; Motor connected to port 2 (M3/M4)
void forwardstep() {  //wrapping the AFmotor lib for use with accel stepper for forward motion
  motor1.onestep(FORWARD, SINGLE);
}

void backwardstep() {   //wrapping the AFmotor lib for use with accel stepper for backward motion
  motor1.onestep(BACKWARD, SINGLE);
}

AccelStepper motor(forwardstep,backwardstep); //initializing motor as object in accel stepper

int Pot1; //potentiometer 1  (Time: A2 (min))
int Pot2; //potentiometer 2 (Distance: A3 (mm))
int button = A0; //button on analog pin A0
int Time; //Time variable
int RemTime; // Remaining Time
float Dist; // Distance variable (mm)
float mmperRev = 20; //mm in 1 rev of dowel (2*pi*r) r =3.175 (dowel diameter/2)
int numRevs;
 
void setup()  
{
  LCD.backlight(); //turn on LCD backlight
  Serial.begin(9600); // IW begin serial communication (9600 for LCD)
  pinMode(button,INPUT); // IW initialize button as input
  LCD.begin();//Initializing display iw
  delay(500); // IW delay 500ms
  LCD.clear();// IW clear screen
  motor.disableOutputs();//disable motor function
  delay(500); // delay
}
 
void loop() // run over and over
{
  
  while (!digitalRead(button))  { //while button NOT pressed (because it is "normally open" button)
  motor.disableOutputs();
  Pot1 = 1023-analogRead(A1); //// IW finding time from pot 1
  int val = 180*(float(Pot1)/1023);// IW finding time
  Time = (val-(val%5)+5); // IW finding time
  Pot2 = 1023-analogRead(A2);// IW finding dist (A1 on right dip controller/A3 on left dip controller)
  Dist = Pot2*0.01*16.49; 
  // the distance values (mm) displayed on the LCD screen. If you want the dip station to go farther, increase the multipliers here. Current range: up to 160cm.
  LCD.clear(); //clear screen 
  LCD.setCursor(0,0); //1st row 1st column
  LCD.print("Time: ");
  LCD.print(Time); //print time
  LCD.print(" minutes"); 
  LCD.setCursor(0,1); //1st column second row
  LCD.print("Dist: "); //print distance
  //if (Dist<10.5)  {
    //LCD.print(0);
  //}
  LCD.print(Dist,1);
  LCD.print(" mm");
   
  delay(100);
  }
  LCD.clear();  
  delay(500);
  while (digitalRead(button)); //after button has been pressed (5V goes to A0). 
  LCD.setCursor(0,0); 
  LCD.print("Remaining Time:"); //print time
  long T = millis();
  float numRevs = Dist/mmperRev; //total number of revs (total distance/mm per rev)
  int numSteps = ceil(numRevs*200); //total number of steps (total revs *200 bc 200 steps/rev)
  float seconds = Time*60; //minutes to seconds (total time)
  float velocity = numSteps/seconds; //find velocity (steps per second).
  motor.setSpeed(velocity);  //set speed of motor to this constant velocity value.
  motor.enableOutputs();
  do { //do while loop. loop exits when remaining time reaches 0.
  RemTime = Time-((millis()-T)/60000); //calculate remaining time.
  LCD.setCursor(0,1);
  LCD.print(RemTime);
  LCD.print(" min "); //print remaining time
  //motor.setSpeed(steps/second);
  
  motor.runSpeed(); //run the motor at the set velocity at the end of each iteration of loop.
  
} while (RemTime > 0); //do loop while remaining time is greater than 0.
  LCD.clear();
  while (RemTime = 0) {
  motor.disableOutputs();// after loop disable motor to save power
  delay(500);
  LCD.setCursor(0,0);
  LCD.print("Complete!");
  LCD.clear();
  LCD.setCursor(0,1);
  LCD.print("Please Reset");
  delay(5000);
  //wait for user to hit reset button
  }
  
}