Home

Contact Me





LinkedIn

1.0 Background


The Manual System is a commercial product I built for my employer, Cell Microsystems (CMS). The purpose of the Manual System is to extend a linear stepper motor by a distance set by the user. I achieved this by converting an analog input (0-1023) from a 10K potentiometer to mm with an Arduino. I coded the Arduiuno to output a pulse-width-modulated (PWM) signal to turn the motor a certain number of steps which correlate to the distance set by the potentiometer. A motor drive shield was used in conjunctoin with the Arduino Uno.

*NOTE: This product's manufacture is confidential and thus I will not provide circuit diagrams or too much detail.

2.0 Final Product


Manual System

CMS Manual System

Manual System

CMS Manual System in Case

3.0 Videos

Biological Models

System Operation

Biological Models

Table Explaining Functionality

4.0 Code

  
#include  //needed to drive motor
#include  //needed for circuits
#include  //needed w LCD i2C Library 

AF_Stepper motor(20,1);  //20 steps/rev w motor; Motor connected to port 1 (M1/M2)

LiquidCrystal_I2C lcd(0x27, 16, 2);

//LCDvariablename(address [use find_lcd_screen_address program to locate], 16x2 characters)


int sensorPin = A1;         //select the input pin for the potentiometer
int button = A2;            //select the pin for the button
int sensorValue = 0;        //Initialize variable to store the value coming from the sensor
int homePos = 700;          //number of steps down to home position; overshot to ensure fully 0
int state;              //Initialize variable to store value from button
int motorMove = 0; //state of travel mode
int travelSteps = 0; //number of steps set by pot
int travelDist = 0; //number of steps to travel 
int travelPercent = 0; //percent to display on LCD screen (1-100%)
int align = 0;              //Initialize variable to check if in alignment mode
int delta = 0;              //Initialize variable for movement in alignment mode
int welcome = 1;            //Initialize variable for welcome screen state 
int reading;           // the current reading from the input pin
int check = 0;

void welcomeScreen() {
  motor.step(homePos, BACKWARD, SINGLE); //travel motor to 0 position
  while (welcome == 1){ //repeat while welcome = 1 is true
  lcd.setCursor(0,0); //use first row
  lcd.print("       CMS      ");  //welcome screen 
  lcd.setCursor(0,1); //use second row        
  lcd.print("  Manual System  ");  //welcome screen
  reading = digitalRead(button);  //read state of button (high or low)
   if ((reading) == HIGH)  {  //While the button is pressed
       while ((analogRead(sensorPin) < 5) == 1)  {   //loop while the potentiometer is set below 5 (for safety)
        delay(100); //debounce button
        reading = digitalRead(button); //check button state to ensure it has been released. 
		//This allows for the user to press it for any period of time
        if (reading == LOW){ //if the button is not pressed any longer
        welcome = 0; //set welcome screen to 0 so it never shows up again
        align = 1; //allow alignment mode
        delay(100); //debounce the button (ms)
        Alignment(); //enter alignment mode (always entered upon first boot up for safety)
       }
       }
   delay(100);                             //debounce the button
}
  }
}

void CheckHold()  { //check if button has been pressed
  motor.release();                           //release motor when not in alignment or travel
  delay(100); //debounce the button
  reading = digitalRead(button); //check state of button (HIGH or LOW)
   if (reading == HIGH)  {  //if the button is pressed
    check = 1; //if button has been pressed, loop until it is not pressed anymore
    while (check == 1) {
       if ((analogRead(sensorPin) < 5) == 1)  {   //If the potentiometer is set below 5..
        delay(100);
        reading = digitalRead(button); //recheck button
        if (reading == LOW){ //if it has been released
        motorMove = 0; //disable travel mode
        align = 1; //allow alignment mode
        check = 0; //exit check loop
        delay(100); //debounce button
        Alignment(); //enter alignment mode.
       }
       }
      else { //if pot is greater than 5
        delay(100); //debounce
        reading = digitalRead(button); //read button
        if (reading == LOW){ //if button is released
        motorMove = 1; //enable travel mode
        align = 0; //disable alignment mode
        check = 0; //exit check loop
        delay(100); //debounce
        NeedleRelease(); //enter travel mode
       }
     }
   delay(100);                             //debounce the button
}
}
}

void NeedleRelease()  {
    align = 0; //disable alignment mode
    lcd.clear(); //clear screen
    lcd.setCursor(0,0); //use first row
    lcd.print("   Traveling   ");  //centered "traveling" state
    lcd.setCursor(0,1); //use second row
    lcd.print("      ");  //centering text
    lcd.print(travelPercent);  //print travel distance (1-100%)
    lcd.print("%    ");  //print travel distance (1-100%)                                    
    motor.step(travelSteps, FORWARD, SINGLE); //run motor to the number of steps set by pot
    delay(100); //pause 100ms
    motor.step(homePos, BACKWARD, SINGLE); //run motor to home (overshot)
    delay(500) ;                           //Must wait 500 ms before next release
    lcd.clear();        //clear screen
    motor.release();                       //Make the motor "float" so that it does not consume power
    motorMove = 0; //disable release mode
    loop(); //return to home loop
}

void Alignment()  {
  welcome = 0; //disable welcome screen from now on
  delay(100); //delay
  lcd.clear(); //clear LCD screen
  lcd.setCursor(0,0); //use first row
  lcd.print(" Alignment Mode");  //print which mode
  sensorValue = analogRead(sensorPin);                
  //Read the value from the potentiometer - Range can be from 0 - 1023
  MOVE = round(sensorValue*0.5);                     
  //Multiply value by 0.5 to make max number of steps 512 (10.24 mm) 
  motor.step(MOVE, FORWARD, SINGLE);                  
  //Move motor to position set by potentiometer
  delay(100); //delay
  while (align == 1)  {                              
  //While in alignment mode execute the following code:
  sensorValue = analogRead(sensorPin); //0-1023
  travelPercent = round(sensorValue*.098); //convert potentiometer value to percent
  lcd.setCursor(0,1); //use second row
  lcd.print(" Distance: ");  //print travel distance (1-100%)
  lcd.print(travelPercent);  //print travel distance (1-100%)
  lcd.print("%    ");  //print travel distance (1-100%) 
  travelSteps = round(sensorValue*.5); //capping max steps at = 1023/2 = ~512 steps
  travelDist = travelSteps - delta; //num steps to travel (checks for change from prvious pot value)
  if (travelDist > 4) { //if change is positive & > 4
    motor.step(travelDist, FORWARD, SINGLE); //travel difference in steps
    delta = travelSteps;  //keep track of previous value
  }
  else if (travelDist < -4) { //if change is negative & > 4
    motor.step(abs(travelDist), BACKWARD, SINGLE); //travel difference in steps
    delta = travelSteps;  //keep track of previous value
  }
  motor.release();  //Float the motor to save power
  delay(10); //small delay
  reading = digitalRead(button); //check button state
   if (reading == HIGH)  {  //if the button is pressed
    check = 1; //loop until button is low
    while (check == 1) {  //loop until button is low
        delay(100);
        reading = digitalRead(button);
        if (reading == LOW){ //if button is released
          lcd.clear();
          lcd.setCursor(0,0); //use second row
          lcd.print("    Exiting     ");  //print mode
           lcd.setCursor(0,1); //use second row
          lcd.print(" Alignment Mode");  //print mode
          motor.step(travelSteps, BACKWARD, SINGLE);                  //Return the motor to its initial position
          lcd.clear(); //clear screen
          delay(100); //delay for noise reduction
          align = 0; //disable alignment
          check = 0; //disable check loop
          delay(100); //delay
          loop(); //return to home loop
       }
   delay(100);                             //debounce the button
    }
}
}
}

void setup() {
  Serial.begin(9600); //begin serial communication (9600 for LCD)
  lcd.begin();//Initializing display
  lcd.backlight();//To Power ON the back light NOTE: if backlight doesn't turn on, ensure power jumper is attached
  lcd.clear(); //clear screen
  motor.setSpeed(1500);               //Sets speed in steps per second     
  pinMode(button, INPUT);             //Set the button pin to be an digial input
  delay(100); //delay
  welcomeScreen(); //upon start up, open welcome screen
}

//The following loop runs forever
void loop() {
  welcome = 0; //disable welcome screen
  lcd.setCursor(0,0); //use first row
  lcd.print("Press button to");  //print travel distance (1-100%)
  lcd.setCursor(0,1); //use second row
  lcd.print("Align or Release");  //print travel distance (1-100%)    
  reading = digitalRead(button);      //Check the state of the button
  if (reading == HIGH){ //if the button is pressed..
     CheckHold();                    //Run CheckHold() function
  }
}