//Timer setup
volatile unsigned long count = 0;
volatile int InterruptCounter = 0;
volatile bool isDone = false;
volatile bool pumping = false;
static int stepneeded = 0;
hw_timer_t *timer = NULL;
portMUX_TYPE timerMUX = portMUX_INITIALIZER_UNLOCKED;
volatile bool processDone = false;
//Flag setup
static bool pump_out = false;
int i=0;
int x=0;
int volume_input_count=0;
int speed_input_count=0;
int diameter_input_count=0;
static int volume_value =0, speed_value=0, diameter =0;
int pump_out_count = 0;
int step_pump_out = 0;
//Menu setup
bool edit_Volume = false;
bool edit_Speed = false;
bool edit_Diameter = false;
typedef struct
{
char* name_;
int value;
char* suffix;
} menu_item;
menu_item menu[10];
//Motor setup
#define STEP_PER_REV 200
#define MICROSTEP_PER_STEP 2
#define MICROSTEP_PER_REV (STEP_PER_REV * MICROSTEP_PER_STEP)
#define SCREW_PITCH_MM 8
unsigned int syringe_diameter_mm;
#define DIR_PIN 26
#define STEP_PIN 25
volatile bool stepState = false;
//LCD and Keypad
#include <LCD_I2C.h>
LCD_I2C lcd(0x27, 16, 2);
#include <Keypad.h>
#define ROW_NUM 4
#define COLUMN_NUM 4
char keys[ROW_NUM][COLUMN_NUM] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9','C'},
{'*', '0', '#','D'},
};
byte pin_rows[ROW_NUM] = {15, 2, 0, 4};
byte pin_column[COLUMN_NUM] = {16, 17, 5, 18};
Keypad keypad = Keypad( makeKeymap(keys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM );
void IRAM_ATTR onTimer() {
// Code to make the motor step
portENTER_CRITICAL_ISR(&timerMUX);
// statement
digitalWrite(DIR_PIN, HIGH);
if ( InterruptCounter < 2*stepneeded){
stepState = !stepState;
digitalWrite(STEP_PIN, stepState? HIGH: LOW);
InterruptCounter++;
}
else {
processDone = true;
pumping = false;
}
portEXIT_CRITICAL_ISR(&timerMUX);
}
void update_lcd(int i){
lcd.clear();
// first line
lcd.setCursor(0, 0);
lcd.print(menu[i].name_);
// second line
if (menu[i].name_ == "Volume Setup"){
lcd.setCursor(0,1);
lcd.print(volume_value);
lcd.print(menu[1].suffix);
}
if (menu[i].name_ == "Speed Setup"){
lcd.setCursor(0,1);
lcd.print(speed_value);
lcd.print(menu[2].suffix);
}
if (menu[i].name_ == "Diameter Setup"){
lcd.setCursor(0,1);
lcd.print(diameter);
lcd.print(menu[3].suffix);
}
if (menu[i].name_ == " Start" && pumping == true){
lcd.setCursor(0,1);
lcd.print(menu[0].suffix);
}
if (menu[i].name_ == "Pump out" && pump_out == true){
lcd.setCursor(0,1);
lcd.print(menu[4].suffix);
}
}
int timeperInterrrupt(float diameter, int speed){
float radius = diameter / 20;
float step_per_ml = 200 / (0.8*3.14*radius*radius);
Serial.println(step_per_ml);
float step_per_second = speed * step_per_ml;
Serial.println(step_per_second);
float step_per_microsecond = 60000000 / step_per_second ;
Serial.println(step_per_microsecond);
int timeperInterrupt = (step_per_microsecond / 2);
return timeperInterrupt;
}
void setup() {
Serial.begin(9600);
timer = timerBegin(1000000);
timerAttachInterrupt(timer, &onTimer);
timerStop(timer);
pinMode(DIR_PIN, OUTPUT);
pinMode(STEP_PIN, OUTPUT);
lcd.begin();
lcd.backlight();
menu[0].name_ = " Start";
menu[0].suffix = " RUNNING! ";
menu[1].name_ = "Volume Setup";
menu[1].suffix = " mL";
menu[2].name_ = "Speed Setup";
menu[2].suffix = " mL/min";
menu[3].name_ = "Diameter Setup";
menu[3].suffix = " mm";
menu[4].name_ = "Pump out";
menu[4].suffix = "PUMPING!";
update_lcd(i);
}
void loop() {
/* ---------------- BUTTON HANDLING ----------------------- */
char key = keypad.getKey();
if (key){
switch (key){
case 'A':
i++;
if(i > 4){ i = 0;}
update_lcd(i);
break;
case 'B':
i--;
if(i < 0){ i = 4;}
update_lcd(i);
break;
case '*':
if (i==1){
edit_Volume = true;
}
if (i==2){
edit_Speed = true;
}
if (i==3){
edit_Diameter = true;
}
break;
case 'C':
pump_out_count++;
break;
case 'D':
if(i==0){
Serial.print("Pressed");
pumping = true;
update_lcd(i);
stepneeded = Step_Needed(volume_value);
Serial.println(stepneeded);
int timeperInterrupt = timeperInterrrupt(diameter, speed_value);
Serial.println(timeperInterrupt);
timerAlarm(timer, timeperInterrupt, true, 0);
timerStart(timer);
}
break;
default:
if (edit_Volume && key >= '0' && key <= '9' && volume_input_count < 3){
int digit_V = key - '0';
volume_value = volume_value * 10 + digit_V;
update_lcd(i);
volume_input_count++;
if ( volume_input_count == 2){ edit_Volume = false;}
}
if (edit_Speed && key >= '0' && key <= '9' && speed_input_count < 3) {
int digit_S = key - '0';
speed_value = speed_value * 10 + digit_S;
update_lcd(i);
speed_input_count++;
if ( speed_input_count == 2){ edit_Speed = false;}
}
if (edit_Diameter && key >= '0' && key <= '9' && diameter_input_count < 3){
int digit_D = key - '0';
diameter = diameter * 10 + digit_D;
update_lcd(i);
diameter_input_count++;
if ( diameter_input_count == 2){ edit_Diameter = false;}
break;
}
}
}
if (pump_out_count % 2 != 0 && pump_out_count > 0 ){
digitalWrite(DIR_PIN, HIGH);
digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(1000);
digitalWrite(STEP_PIN, LOW);
delayMicroseconds(1000);
step_pump_out++;
Serial.println(step_pump_out);
}
if (pump_out_count % 2 == 0 && pump_out_count > 0 && step_pump_out > 0 ){
digitalWrite(DIR_PIN, LOW);
digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(1000);
digitalWrite(STEP_PIN, LOW);
delayMicroseconds(1000);
step_pump_out--;
Serial.println(step_pump_out);
}
if (processDone == true){
timerStop(timer);
timerWrite(timer, 0);
processDone = false;
int step = Step_Needed(volume_value);
lcd.setCursor(0,1);
lcd.print(" Process Done");
delay(2000);
lcd.setCursor(0,1);
lcd.print(" System reseted");
delay(2000);
resetSystem();
update_lcd(i);
}
}
int Step_Needed(int volume){
float volumePerStep = (8 * (diameter/2) * (diameter/2) * 3.14)/200000;
int StepNeeded = volume_value / volumePerStep;
return StepNeeded;
}
void resetSystem(){
int step = Step_Needed(volume_value);
digitalWrite(DIR_PIN, LOW);
for (int i = 0; i < step; i++) {
digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(500);
digitalWrite(STEP_PIN, LOW);
delayMicroseconds(500);
}
count = 0;
InterruptCounter = 0;
pumping = false;
stepneeded = 0;
i=0;
x=0;
volume_input_count=0;
speed_input_count=0;
diameter_input_count=0;
volume_value =0, speed_value=0, diameter =0;
edit_Volume = false;
edit_Speed = false;
edit_Diameter = false;
}