Created
October 9, 2015 19:13
-
-
Save Craigson/5ecb810bf592d86a5bda to your computer and use it in GitHub Desktop.
Firmware for the syringe pump control interface
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Stepper: | |
* coil A+ yellow | |
* coil A- red | |
* coil B+ grey | |
* coil B- green | |
*/ | |
#define stp 2 //step pin | |
#define dir 3 //direction pin | |
#define MS1 4 //step resolution pin 1 | |
#define MS2 5 //step resolution pin 2 | |
#define EN 6 //enable pin | |
#define MP 8 | |
#define FWD 9 //fwd button input pin | |
#define RVRS 10 //reverse button input pin | |
#define MTR 13 //vibration motor pin | |
char user_input; | |
int state; | |
double drop_diameter; //variable to store the value the user enters | |
double drop_volume; | |
double cylinder_volume; | |
double syringe_id; //variable for storing the inner diameter of the syringe | |
double plunger_travel_distance; | |
double travel_per_revolution; //variable to store the distance travelled by the plunger per 360' rotation | |
double rev_count; | |
double number_of_steps; | |
int rounded_steps, num_microsteps; | |
double remainder; | |
int buttonPushCounter = 0; // counter for the number of button presses | |
int buttonState = 0; // current state of the button | |
int lastButtonState = 0; | |
String inString = ""; | |
bool buttonOn; | |
char TempString[10]; | |
//volume of cylinder: V = PI * r^2 * h | |
//volume of drop: V = 4/3 * PI * r^3 | |
//rod travel is 1.5875mm per turn | |
//syringe inner diameter is 4.62mm | |
void setup() { | |
pinMode(stp, OUTPUT); | |
pinMode(dir, OUTPUT); | |
pinMode(MS1, OUTPUT); | |
pinMode(MS2, OUTPUT); | |
pinMode(EN, OUTPUT); | |
pinMode(MTR, OUTPUT); | |
pinMode(FWD, INPUT); | |
pinMode(RVRS, INPUT); | |
pinMode(12, OUTPUT); | |
digitalWrite(MTR, LOW); | |
digitalWrite(FWD, LOW); | |
digitalWrite(RVRS, LOW); | |
digitalWrite(12, LOW); | |
resetEDPins(); //Set step, direction, microstep and enable pins to default states | |
delay(500); | |
Serial.begin(9600); //Open Serial connection for debugging | |
delay(500); | |
Serial.println("Begin motor control"); | |
Serial.println(); | |
Serial.println("Enter the desired drop diameter in mm (accurate to 2 decimal places)."); | |
Serial.println("\n"); | |
Serial.println("** For example, if a drop with a 4mm diameter is required, enter 4.00 **"); | |
//DEFINE COMPONENT VALUES | |
syringe_id = 4.62; //in mm | |
travel_per_revolution = 1.5875; // in mm; | |
} | |
void loop() { | |
//READ THE BUTTON STATE | |
buttonState = digitalRead(FWD); | |
if (buttonState != lastButtonState) { | |
if (digitalRead(FWD) == HIGH) | |
{ | |
executeFullSteps(300); | |
resetEDPins(); | |
} | |
} | |
lastButtonState = buttonState; | |
//WAIT FOR USER INPUT | |
while (Serial.available()) { | |
Serial.println("--------------------------------------------"); | |
Serial.println("\n"); | |
String str = Serial.readStringUntil('\n'); | |
drop_diameter = (double)str.toFloat(); | |
TempString[10]; // CHARACTER ARRAY TO STORE DOUBLE VALUES FOR PRINTING | |
// dtostrf( [doubleVar] , [sizeBeforePoint] , [sizeAfterPoint] , [WhereToStoreIt] ) | |
dtostrf(drop_diameter, 2, 8, TempString); //CONVERT DOUBLE TO STRING | |
String diam = String(TempString); // CAST TO STRING FROM CHAR ARRAY | |
Serial.print("Required drop diameter: "); | |
Serial.print(diam); | |
Serial.print("mm"); | |
Serial.println("\n"); | |
double drop_radius = drop_diameter / 2; // CONVERT TO RADIUS FOR VOLUME CALCULATIONS | |
digitalWrite(EN, LOW); //Pull enable pin low to allow motor control | |
//volume of a sphere: V = (4/3)*PI*r^3 | |
drop_volume = (4 * PI * (pow( ( drop_diameter / 2), 3 )) ) / 3; //in mm^3 | |
dtostrf(drop_volume, 2, 8, TempString); | |
// dtostrf( [doubleVar] , [sizeBeforePoint] , [sizeAfterPoint] , [WhereToStoreIt] ) | |
String drop_vol = String(TempString); // cast it to string from char | |
Serial.print("drop volume: "); | |
Serial.print(drop_vol); | |
Serial.println("uLitres"); | |
/* | |
the volume of water displaced by the syringe plunger will be equal | |
to the volume of the desired droplet, thus sphere_volume = cylinder_volume. | |
volume of a cylinder: V = PI * r^2 * h, where h = plunger_travel_distance | |
therefore, drop_volume = PI * pow( (syringe_id/2), 2) * plunger_travel_distance | |
therefore, plunger_travel_distance = drop_volume / (PI * pow( (syringe_id/2),2 ) ); | |
*/ | |
plunger_travel_distance = drop_volume / (PI * pow( (syringe_id / 2), 2 ) ); | |
dtostrf(plunger_travel_distance, 2, 8, TempString); | |
// dtostrf( [doubleVar] , [sizeBeforePoint] , [sizeAfterPoint] , [WhereToStoreIt] ) | |
String trav_dist = String(TempString); // cast it to string from char | |
Serial.println(" "); | |
Serial.print("plunger travelled: "); | |
Serial.print(trav_dist); | |
Serial.print("mm"); | |
Serial.println("\n"); | |
/* | |
the stepper motor has a resolution of 200 steps / revolution, while the threaded rod has | |
a travel of 1/16", or 1.5875mm, per revolution, ie. the plunger travels 1.5875mm per full | |
revolution (200 steps). | |
*/ | |
//DETERMINE THE NUMBER OF ROTATIONS | |
rev_count = plunger_travel_distance / travel_per_revolution; | |
Serial.print("Number of revolutions: "); | |
Serial.print(rev_count); | |
Serial.println("\n"); | |
//CONVERT TO NUMBER OF STEPS REQUIRED | |
number_of_steps = rev_count * 200; | |
Serial.print("Total number of steps: "); | |
Serial.print(number_of_steps); | |
Serial.println("\n"); | |
//CONVERT TO INTEGER FOR NUMBER OF FULL STEPS REQUIRED | |
int rounded_steps = floor(number_of_steps); | |
Serial.print("Full steps: "); | |
Serial.print(rounded_steps); | |
Serial.println("\n"); | |
//USE THE DIFFERENCE TO DETERMINE THE NUMBER OF MICROSTEPS | |
remainder = number_of_steps - rounded_steps; | |
//DETERMINE THE NUMBER OF 1/8 MICROSTEPS TO FOLLOW THE FULL STEP | |
num_microsteps = remainder / 0.125; | |
Serial.print("1/8 microsteps: "); | |
Serial.print(num_microsteps); | |
Serial.println("\n"); | |
//DRIVE THE MOTOR | |
executeFullSteps(rounded_steps); | |
if (num_microsteps != 0) { | |
executeMicroSteps(num_microsteps); | |
} | |
//VIBRATE THE VIBRATION MOTOR TO RELEASE THE DROPLET | |
shakeLoose(); | |
Serial.println(""); | |
Serial.print("plunger moved a total of "); | |
Serial.print(plunger_travel_distance); | |
Serial.print("mm to displace "); | |
Serial.print(drop_volume); | |
Serial.println("uLitres of water"); | |
Serial.println("\n"); | |
Serial.println("-----------------------------------"); | |
} | |
//RESET MOTOR PINS | |
resetEDPins(); | |
inString = ""; | |
} | |
//Reset Easy Driver pins to default states | |
void resetEDPins() | |
{ | |
digitalWrite(stp, LOW); | |
digitalWrite(dir, LOW); | |
digitalWrite(MS1, LOW); | |
digitalWrite(MS2, LOW); | |
digitalWrite(EN, HIGH); | |
} | |
void executeFullSteps(int full_steps) | |
{ | |
Serial.print("executing "); | |
Serial.print(full_steps); | |
Serial.println(" full steps."); | |
digitalWrite(dir, HIGH); //Pull direction pin low to move "forward" | |
digitalWrite(MS1, LOW); //Pull MS1, and MS2 low to set logic to full step resolution | |
digitalWrite(MS2, LOW); | |
for (int x = 0; x < full_steps; x++) // | |
{ | |
digitalWrite(stp, HIGH); //Trigger one step forward | |
delay(5); | |
digitalWrite(stp, LOW); //Pull step pin low so it can be triggered again | |
delay(5); | |
} | |
} | |
void executeMicroSteps(int micro_steps) | |
{ | |
Serial.print("executing "); | |
Serial.print(micro_steps); | |
Serial.println(" microsteps."); | |
digitalWrite(dir, LOW); //Pull direction pin low to move "forward" | |
digitalWrite(MS1, HIGH); //Pull MS1, and MS2 high to set logic to 1/8th microstep resolution | |
digitalWrite(MS2, HIGH); | |
for (int x = 0; x < micro_steps; x++) // | |
{ | |
digitalWrite(stp, HIGH); //Trigger one step forward | |
delay(11); | |
digitalWrite(stp, LOW); //Pull step pin low so it can be triggered again | |
delay(11); | |
} | |
delay(500); | |
} | |
void shakeLoose() { | |
digitalWrite(MTR, HIGH); | |
delay(2000); | |
digitalWrite(MTR, LOW); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment