I am using an arduino uno, and I am using TMC26XStepper.h and not EEPROM.h, because I am using the TOS-100 motion control, in order to control the stepper motor.
Here is the rest of the code:
#include <LiquidCrystal.h>
#include "TMC26XStepper.h"
/************************
BASIC SETTINGS
************************/
// Stepper motor
#define NOFMICROSTEPS 32 // The number of microsteps per step
#define NOFSTEPSPER360 200 // The number of steps per revolution
#define MAXRPM 240 // Maximum RPM (rotations per minute)
#define INVERTDIRECTION true // If the carriage moves in the opposite direction, change to 'false'
// Leadscrew
#define MMPER360 2 // Leadscrew pitch, mm per revolution
// Arduino pins
#define STEP_PIN 2 // STEP pin (A4988)
#define DIRECTION_PIN 3 // DIR pin (A4988)
#define ENABLE_PIN 5 // EN pin (A4988)
#define ENDSTOP_PIN1 A1 // Endstop pin (forward movement)
#define ENDSTOP_PIN2 A2 // Endstop pin (backward movement)
#define BUZZER_PIN 4 // Buzzer pin
#define BUTTONS_PIN A0 // Button pin (lcd keypad shield)
/************************/
#define DEBOUNCEDELAY 50
#define LONGPRESSDELAY 450
#define AUTOCHANGINGDELAY 300
#define NITEMS 43
#define LINK2S 12
#define LINK2E 13
#define LINK2V 20
#define LINK2T 21
#define LINK2F 22
#define LINK2DIA 41
#define LINK2LPV 42
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
struct MenuItem
{
uint8_t button[4];
uint8_t type;
char *text;
uint8_t address;
uint32_t value;
};
enum listOfButtons {RIGHT, UP, DOWN, LEFT, SELECT, NA};
enum listOfButtonStates {RELEASE, SHORTPRESS, MEDIUMPRESS, LONGPRESS};
enum listOfPrograms {CHANGEVALUE = 200, SELECTFROMLIST, INFUSEVOLUME, INFUSETIME, REFILLVOLUME, REFILLFULL, CYCLEMODE, FIRMWAREINFO};
enum listOfItemTypes {TEXT, LIST, VOLUME, TIME, FLOWRATE, LENGTHPERVOLUME, DIAMETER};
const char firmwareInfo[] = "0.9a";
const uint16_t volumeDivider[2] = {1000, 1};
const uint16_t timeDivider[3] = {1, 60, 3600};
const uint16_t flowrateDivider[4] = {60000, 1000, 60, 1};
const float stepsPERmm = NOFSTEPSPER360 / MMPER360;
MenuItem items[NITEMS];
uint8_t lastButton = NA;
uint8_t buttonState = RELEASE;
uint32_t buttonPressTime = 0;
uint8_t currentItem = 1;
float coef;
uint8_t endStopPin;
volatile uint32_t ustepCounter;
uint32_t ustepCounterLimit;
uint32_t getValue(uint8_t itemNo);
void changeValue();
void setValue(uint8_t itemNo, uint8_t digits[8]);
void selectFromList();
void calculateActualValue(uint8_t itemNo);
void recalculateSyringe(uint8_t itemNo);
void printScreen();
void printUnits();
void printFirmwareInfo();
void printTimeAndVolume(uint16_t pumpingTime, uint32_t pumpingVolume);
void showScreensaver();
void readFromEEPROM(uint8_t itemNo);
void writeToEEPROM(uint8_t itemNo);
void getButtonState();
uint16_t valueDivider (uint8_t n);
uint8_t getElementNo(uint8_t linkToList);
void waitingForButton(uint8_t buttonCode, uint8_t itemNo);
void beep (uint16_t delayOn = 15, uint16_t delayOff = 100);
bool checkEndstop(int8_t pumpingDirection);
void infuseVolume();
void infuseTime();
void refillVolume();
void refillFull();
void pumpSingly(int8_t pumpingDirection, uint32_t flowrate, uint32_t volume);
void pumpContinuously();
uint8_t pump(uint32_t flowrate, uint32_t volume);
/************************
setup
************************/
void setup()
{
lcd.begin(16, 2);
pinMode(STEP_PIN, OUTPUT);
pinMode(DIRECTION_PIN, OUTPUT);
pinMode(ENABLE_PIN, OUTPUT);
pinMode(ENDSTOP_PIN1, INPUT_PULLUP);
pinMode(ENDSTOP_PIN2, INPUT_PULLUP);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(ENABLE_PIN, HIGH);
items[1] = {5, 0, 2, 0, TEXT, "Infuse"};
items[2] = {7, 1, 3, 0, TEXT, "Refill"};
items[3] = {9, 2, 4, 0, TEXT, "Cycle Mode"};
items[4] = {10, 3, 0, 0, TEXT, "Settings"};
items[5] = {15, 0, 6, 1, TEXT, "Target Volume"};
items[6] = {16, 5, 0, 1, TEXT, "Target Time"};
items[7] = {17, 0, 8, 2, TEXT, "Full Refill"};
items[8] = {18, 7, 0, 2, TEXT, "Target Volume"};
items[9] = {19, 0, CHANGEVALUE, 3, FLOWRATE, "infuse flow:", 1, 120000000};
items[10] = {20, 0, 11, 4, TEXT, "Units"};
items[11] = {23, 10, 12, 4, TEXT, "Syringe"};
items[12] = {25, 11, 13, 4, LIST, "Sound", 2};
items[13] = {27, 12, 14, 4, LIST, "EEPROM", 3};
items[14] = {FIRMWAREINFO, 13, 0, 4, TEXT, "Firmware"};
items[15] = {29, 0, CHANGEVALUE, 5, VOLUME, "volume:", 4, 1000000};
items[16] = {30, 0, CHANGEVALUE, 6, TIME, "time:", 5, 60000};
items[17] = {REFILLFULL, 0, CHANGEVALUE, 7, FLOWRATE, "flowrate:", 6, 2000000};
items[18] = {31, 0, CHANGEVALUE, 8, VOLUME, "volume:", 7, 1000000};
items[19] = {CYCLEMODE, 0, CHANGEVALUE, 9, FLOWRATE, "refill flow:", 8, 2000000};
items[20] = {32, 0, 21, 10, LIST, "Volume Units", 9};
items[21] = {34, 20, 22, 10, LIST, "Time Units", 10};
items[22] = {37, 21, 0, 10, LIST, "Flowrate Units", 11};
items[23] = {41, 0, 24, 11, TEXT, "Diameter"};
items[24] = {42, 23, 0, 11, TEXT, "Length/Volume"};
items[25] = {SELECTFROMLIST, 0, 26, 12, TEXT, "on"};
items[26] = {SELECTFROMLIST, 25, 0, 12, TEXT, "off"};
items[27] = {SELECTFROMLIST, 0, 28, 13, TEXT, "on"};
items[28] = {SELECTFROMLIST, 27, 0, 13, TEXT, "off"};
items[29] = {INFUSEVOLUME, 0, CHANGEVALUE, 15, FLOWRATE, "flowrate:", 12, 2000000};
items[30] = {INFUSETIME, 0, CHANGEVALUE, 16, FLOWRATE, "flowrate:", 13, 2000000};
items[31] = {REFILLVOLUME, 0, CHANGEVALUE, 18, FLOWRATE, "flowrate:", 14, 2000000};
items[32] = {SELECTFROMLIST, 0, 33, 20, TEXT, "mL"};
items[33] = {SELECTFROMLIST, 32, 0, 20, TEXT, "uL"};
items[34] = {SELECTFROMLIST, 0, 35, 21, TEXT, "s"};
items[35] = {SELECTFROMLIST, 34, 36, 21, TEXT, "min"};
items[36] = {SELECTFROMLIST, 35, 0, 21, TEXT, "h"};
items[37] = {SELECTFROMLIST, 0, 38, 22, TEXT, "mL/s"};
items[38] = {SELECTFROMLIST, 37, 39, 22, TEXT, "mL/min"};
items[39] = {SELECTFROMLIST, 38, 40, 22, TEXT, "uL/s"};
items[40] = {SELECTFROMLIST, 39, 0, 22, TEXT, "uL/min"};
items[41] = {0, 0, CHANGEVALUE, 23, DIAMETER, "diameter:", 15, 11284};
items[42] = {0, 0, CHANGEVALUE, 24, LENGTHPERVOLUME, "length/volume:", 16, 10000};
for (uint8_t i = 1; i < NITEMS; i++)
{
if (items[i].type != TEXT) readFromEEPROM(i);
}
recalculateSyringe(LINK2DIA);
beep();
showScreensaver();
}
/************************
loop
************************/
void loop()
{
uint8_t nextItem;
getButtonState();
if (buttonState == SHORTPRESS && lastButton != SELECT)
{
buttonState = MEDIUMPRESS;
nextItem = items[currentItem].button[lastButton];
if (nextItem != 0 && nextItem < 200)
{
currentItem = nextItem;
printScreen();
}
else if (nextItem == CHANGEVALUE) changeValue();
else if (nextItem == SELECTFROMLIST) selectFromList();
else if (nextItem == INFUSEVOLUME) infuseVolume();
else if (nextItem == INFUSETIME) infuseTime();
else if (nextItem == REFILLVOLUME) refillVolume();
else if (nextItem == REFILLFULL) refillFull();
else if (nextItem == CYCLEMODE) pumpContinuously();
else if (nextItem == FIRMWAREINFO) printFirmwareInfo();
}
}
/************************
getValue
************************/
uint32_t getValue(uint8_t itemNo)
{
uint16_t divider = valueDivider(items[itemNo].type);
uint8_t lastDigitIncrement = 0;
if ( uint16_t(items[itemNo].value % divider) > divider / 2) lastDigitIncrement = 1;
if (items[itemNo].value / divider > 99999999)
{
items[itemNo].value = divider * 99999999;
return 99999999;
}
else return (items[itemNo].value / divider) + lastDigitIncrement;
}
/************************
changeValue
************************/
void changeValue()
{
uint8_t digits[8];
uint32_t value = getValue(currentItem);
for (int8_t i = 7; i >= 0; i--)
{
digits[i] = uint8_t(value % 10);
value /= 10;
}
lcd.setCursor(0, 1);
for (int8_t i = 0; i < 4; i++) lcd.print(digits[i]);
lcd.setCursor(0, 1);
lcd.cursor();
int8_t i = 0;
while (i >= 0 && i < 8)
{
getButtonState();
if (buttonState == SHORTPRESS || buttonState == LONGPRESS)
{
if (lastButton == UP) digits[i] = (digits[i] + 1) % 10;
else if (lastButton == DOWN) digits[i] = (digits[i] + 9) % 10;
lcd.print(digits[i]);
if (lastButton == RIGHT) i++;
else if (lastButton == LEFT) i--;
if (i == -1 && buttonState != SHORTPRESS) i++;
if (i == 8 && buttonState != SHORTPRESS) i--;
if (i < 5)lcd.setCursor(i, 1);
else lcd.setCursor(i + 1, 1);
if (buttonState == SHORTPRESS) buttonState = MEDIUMPRESS;
else if (buttonState == LONGPRESS)
{
uint32_t nextMillis = millis() + AUTOCHANGINGDELAY;
while (nextMillis > millis() && buttonState == LONGPRESS) getButtonState();
}
}
}
if (i == 8)
{
bool isSame = true;
value = getValue(currentItem);
for (int8_t j = 7; j >= 0 && isSame == true; j--)
{
if (digits[j] != uint8_t(value % 10)) isSame = false;
value /= 10;
}
bool isZero = true;
for (int8_t j = 7; j >= 0 && isZero == true; j--)
{
if (digits[j] != 0) isZero = false;
}
if (isSame == false && isZero == false)
{
setValue(currentItem, digits);
beep();
}
}
lcd.noCursor();
lcd.setCursor(0, 1);
printScreen();
}
/************************
setValue
************************/
void setValue(uint8_t itemNo, uint8_t digits[8])
{
uint32_t value = 0;
for (int8_t i = 0; i < 8; i++) value = value * 10 + digits[i];
uint16_t divider = valueDivider(items[itemNo].type);
if (4294000000 / divider < value) items[itemNo].value = 4294000000;
else items[itemNo].value = value * divider;
if (itemNo == LINK2LPV || itemNo == LINK2DIA)
{
recalculateSyringe(itemNo);
writeToEEPROM(LINK2LPV);
writeToEEPROM(LINK2DIA);
}
else writeToEEPROM(itemNo);
}
/************************
selectFromList
************************/
void selectFromList()
{
uint8_t parentItem = items[currentItem].button[LEFT];
items[parentItem].button[RIGHT] = currentItem;
writeToEEPROM(parentItem);
beep();
currentItem = parentItem;
printScreen();
}
/************************
calculateActualValue
************************/
void calculateActualValue(uint8_t itemNo)
{
if (items[itemNo].type == FLOWRATE)
{
float maxFlowrate = 1e9 * MAXRPM * MMPER360 / (float)items[LINK2LPV].value;
if ((float)(items[itemNo].value) > maxFlowrate) items[itemNo].value = (uint32_t)maxFlowrate;
float ustepsPERmin = coef * NOFMICROSTEPS * (float)items[itemNo].value;
if (ustepsPERmin < 14.4) ustepsPERmin = 14.4;
float multiplier;
if (ustepsPERmin >= 229) multiplier = 15000000;
else multiplier = 937500;
float tempFloat = multiplier / ustepsPERmin;
uint16_t countsPERustepActual = (uint16_t)(tempFloat + 0.5);
tempFloat = multiplier / (float)countsPERustepActual;
tempFloat /= (float)(coef * NOFMICROSTEPS);
items[itemNo].value = (uint32_t)tempFloat;
}
else if (items[itemNo].type == VOLUME)
{
uint32_t nSteps = (uint32_t)(coef * (float)items[itemNo].value + 0.5);
float tempFloat = (float)nSteps / coef;
items[itemNo].value = (uint32_t)tempFloat;
}
else if (items[itemNo].type == TIME)
{
if (items[itemNo].value > 59994000) items[itemNo].value = 59994000;
items[itemNo].value -= (items[itemNo].value % 1000);
}
}
/************************
recalculateSyringe
************************/
void recalculateSyringe(uint8_t itemNo)
{
if (itemNo == LINK2LPV)
{
float temp = 1128379 / sqrt((float)items[LINK2LPV].value);
items[LINK2DIA].value = uint32_t(temp + 0.5);
}
else if (itemNo == LINK2DIA)
{
float temp = 1128379 / (float)items[LINK2DIA].value;
temp *= temp;
items[LINK2LPV].value = uint32_t(temp + 0.5);
}
coef = ((float)items[LINK2LPV].value * stepsPERmm) * 1e-9;
}
/************************
printScreen
************************/
void printScreen()
{
lcd.clear();
lcd.setCursor(0, 0);
if (items[currentItem].type == TEXT || items[currentItem].type == LIST)
{
lcd.print(F("> "));
lcd.print(items[currentItem].text);
if (items[currentItem].button[DOWN] != 0 && items[currentItem].button[DOWN] < 200)
{
lcd.setCursor(0, 1);
lcd.print(F(" "));
lcd.print(items[items[currentItem].button[DOWN]].text);
}
}
else
{
calculateActualValue(currentItem);
uint32_t value = getValue(currentItem);
char outputLine[10] = " 0.000";
for (int8_t i = 8; i >= 0 && value > 0; i--)
{
if (i != 5)
{
outputLine[i] = char((value % 10) + '0');
value /= 10;
}
}
lcd.print(items[currentItem].text);
lcd.setCursor(0, 1);
lcd.print(outputLine);
printUnits();
}
}
/************************
printUnits
************************/
void printUnits()
{
lcd.print(F(" "));
if (items[currentItem].type == VOLUME) lcd.print(items[items[LINK2V].button[RIGHT]].text);
else if (items[currentItem].type == TIME) lcd.print(items[items[LINK2T].button[RIGHT]].text);
else if (items[currentItem].type == FLOWRATE) lcd.print(items[items[LINK2F].button[RIGHT]].text);
else if (items[currentItem].type == LENGTHPERVOLUME)
{
lcd.print(F("mm/"));
lcd.print(items[items[LINK2V].button[RIGHT]].text);
}
else if (items[currentItem].type == DIAMETER) lcd.print(F("mm"));
}
/************************
printFirmwareInfo
************************/
void printFirmwareInfo()
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(F("version:"));
lcd.setCursor(0, 1);
lcd.print(F(" "));
lcd.print(firmwareInfo);
waitingForButton(LEFT, currentItem);
}
/************************
printTimeAndVolume
************************/
void printTimeAndVolume(uint16_t pumpingTime, uint32_t pumpingVolume)
{
char outputLine[17] = " 0:00 0000xL";
outputLine[14] = items[items[LINK2V].button[RIGHT]].text[0];
uint8_t pointLocation;
if (pumpingVolume < 100000)pointLocation = 3;
else if (pumpingVolume < 1000000)
{
pointLocation = 4;
pumpingVolume /= 10;
}
else
{
pointLocation = 6;
pumpingVolume /= 100;
}
if (pointLocation < 6)outputLine[pointLocation + 8] = '.';
uint16_t timeDivider;
for (int8_t i = 5; i >= 0; i--)
{
if (pumpingTime > 0 && i != 3)
{
if (i == 4) timeDivider = 6;
else timeDivider = 10;
outputLine[i] = uint8_t(pumpingTime % timeDivider) + '0';
pumpingTime /= timeDivider;
}
if (pumpingVolume > 0 && i != pointLocation)
{
outputLine[i + 8] = uint8_t(pumpingVolume % 10) + '0';
pumpingVolume /= 10;
}
}
lcd.setCursor(0, 1);
lcd.print(outputLine);
}
/************************
showScreensaver
************************/
void showScreensaver()
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(F(" OpenSP 0.9 "));
lcd.setCursor(0, 1);
lcd.print(F("www.mass-spec.ru"));
currentItem = 1;
waitingForButton(NA, currentItem);
}
/************************
getButtonState
************************/
void getButtonState()
{
uint8_t button;
uint8_t x = analogRead(BUTTONS_PIN) / 4;
if (x < 13) button = RIGHT;
else if (x < 46) button = UP;
else if (x < 84) button = DOWN;
else if (x < 131) button = LEFT;
else if (x < 207) button = SELECT;
else button = NA;
if (button == NA)
{
lastButton = NA;
buttonState = RELEASE;
}
else if (button != lastButton)
{
lastButton = button;
buttonState = RELEASE;
buttonPressTime = millis();
}
else if (millis() - buttonPressTime > LONGPRESSDELAY) buttonState = LONGPRESS;
else if (millis() - buttonPressTime > DEBOUNCEDELAY && buttonState == RELEASE) buttonState = SHORTPRESS;
}
/************************
valueDivider
************************/
uint16_t valueDivider (uint8_t itemType)
{
if (itemType == VOLUME) return volumeDivider[getElementNo(LINK2V)];
else if (itemType == TIME) return timeDivider[getElementNo(LINK2T)];
else if (itemType == FLOWRATE) return flowrateDivider[getElementNo(LINK2F)];
else if (itemType == LENGTHPERVOLUME) return 1000 / volumeDivider[getElementNo(LINK2V)];
else if (itemType == DIAMETER) return 1;
}
/************************
getElementNo
************************/
uint8_t getElementNo(uint8_t linkToList)
{
uint8_t uppermostItem = items[linkToList].button[RIGHT];
uint8_t elementNo = 0;
while (items[uppermostItem].button[UP] != 0)
{
uppermostItem = items[uppermostItem].button[UP];
elementNo++;
}
return elementNo;
}
/************************
waitingForButton
************************/
void waitingForButton(uint8_t button, uint8_t itemNo)
{
if (button == NA) while (buttonState != SHORTPRESS) getButtonState();
else while (buttonState != SHORTPRESS || lastButton != button) getButtonState();
buttonState = MEDIUMPRESS;
currentItem = itemNo;
printScreen();
}
/************************
beep
************************/
void beep (uint16_t delayOn, uint16_t delayOff)
{
uint8_t daughterItem = items[LINK2S].button[RIGHT];
if (items[daughterItem].text == "on")
{
digitalWrite(BUZZER_PIN, HIGH);
delay(delayOn);
digitalWrite(BUZZER_PIN, LOW);
delay(delayOff);
}
}
/************************
checkEndstop
************************/
bool checkEndstop(int8_t pumpingDirection)
{
bool canMove = true;
if (digitalRead(ENDSTOP_PIN1) == LOW && pumpingDirection > 0) canMove = false;
else if (digitalRead(ENDSTOP_PIN2) == LOW && pumpingDirection < 0) canMove = false;
if (canMove == false)
{
lcd.clear();
lcd.setCursor(0, 0);
if (pumpingDirection > 0) lcd.print(F("SYRINGE IS EMPTY"));
else if (pumpingDirection < 0) lcd.print(F("SYRINGE IS FULL"));
beep(300);
waitingForButton(LEFT, 1);
return false;
}
else return true;
}
/************************
readFromTMC26XStepper
************************/
void readFromTMC26XStepper(uint8_t itemNo)
{
if (items[itemNo].type == LIST)
{
uint8_t temp;
TMC26XStepper.get(4 * items[itemNo].address, temp);
if (temp != 0 && temp + 1 != 0)
{
if (items[temp].button[LEFT] == itemNo) items[itemNo].button[RIGHT] = temp;
}
}
else
{
uint32_t temp;
TMC26XStepper.get(4 * items[itemNo].address, temp);
if (temp != 0 && temp + 1 != 0) items[itemNo].value = temp;
}
}
/************************
writeToTMC26XStepper
************************/
void writeToTMC26XStepper(uint8_t itemNo)
{
uint8_t daughterItem = items[LINK2E].button[RIGHT];
if (items[daughterItem].text == "on" || itemNo == LINK2E)
{
if (items[itemNo].type == LIST) TMC26XStepper.put(4 * items[itemNo].address, items[itemNo].button[RIGHT]);
else TMC26XStepper.put(4 * items[itemNo].address, items[itemNo].value);
}
}
/************************
infuseVolume
************************/
void infuseVolume()
{
int8_t pumpingDirection = 1;
uint32_t flowrate = items[currentItem].value;
uint32_t volume = items[items[currentItem].button[LEFT]].value;
pumpSingly(pumpingDirection, flowrate, volume);
}
/************************
infuseTime
************************/
void infuseTime()
{
int8_t pumpingDirection = 1;
uint32_t pumpTime = items[items[currentItem].button[LEFT]].value;
uint32_t flowrate = items[currentItem].value;
float tempFloat = (float)flowrate * (float)pumpTime;
tempFloat /= 60000;
uint32_t volume;
if (tempFloat > 4294000000) volume = 4294000000;
else volume = (uint32_t)tempFloat;
pumpSingly(pumpingDirection, flowrate, volume);
}
/************************
refillVolume
************************/
void refillVolume()
{
int8_t pumpingDirection = -1;
uint32_t flowrate = items[currentItem].value;
uint32_t volume = items[items[currentItem].button[LEFT]].value;
pumpSingly(pumpingDirection, flowrate, volume);
}
/************************
refillFull
************************/
void refillFull()
{
int8_t pumpingDirection = -1;
uint32_t flowrate = items[currentItem].value;
uint32_t volume = 4294000000;
pumpSingly(pumpingDirection, flowrate, volume);
}
/************************
pumpSingly
************************/
void pumpSingly(int8_t pumpingDirection, uint32_t flowrate, uint32_t volume)
{
if (checkEndstop(pumpingDirection) == true)
{
pump(pumpingDirection, flowrate, volume);
beep(300);
waitingForButton(LEFT, 1);
}
}
/************************
pumpContinuously
************************/
void pumpContinuously()
{
int8_t pumpingDirection[2] = {1, -1};
uint32_t flowrate[2] = {items[items[currentItem].button[LEFT]].value, items[currentItem].value};
uint32_t volume = 4294000000;
uint8_t i = 0;
while (pump(pumpingDirection[i], flowrate[i], volume) != 2)
{
i = 1 - i;
beep();
delay(1000);
}
beep(300);
waitingForButton(LEFT, 1);
}
/************************
pump
************************/
uint8_t pump(int8_t pumpingDirection, uint32_t flowrate, uint32_t volume)
{
float tempFloat;
ustepCounterLimit = (uint32_t)(coef * volume + 0.5);
ustepCounterLimit *= NOFMICROSTEPS;
float ustepsPERmin = coef * NOFMICROSTEPS * (float)flowrate;
if (ustepsPERmin < 14.4) ustepsPERmin = 14.4;
float multiplier;
if (ustepsPERmin >= 229) multiplier = 15000000;
else multiplier = 937500;
tempFloat = multiplier / ustepsPERmin;
uint16_t countsPERustepActual = (uint16_t)(tempFloat + 0.5);
float ustepsPERsActual = multiplier / (float)countsPERustepActual;
ustepsPERsActual /= 60;
lcd.clear();
lcd.setCursor(0, 0);
if (pumpingDirection > 0)
{
endStopPin = ENDSTOP_PIN1;
if (INVERTDIRECTION == true) digitalWrite(DIRECTION_PIN, LOW);
else digitalWrite(DIRECTION_PIN, HIGH);
lcd.print(F(" >> INFUSING >> "));
}
else
{
endStopPin = ENDSTOP_PIN2;
if (INVERTDIRECTION == true) digitalWrite(DIRECTION_PIN, HIGH);
else digitalWrite(DIRECTION_PIN, LOW);
lcd.print(F(" << REFILLING <<"));
}
lcd.setCursor(0, 1);
printTimeAndVolume(0, 0);
TCNT1 = 0;
TCCR1A = 0;
TCCR1B |= (1 << WGM12);
if (ustepsPERmin >= 229)
{
TCCR1B &= ~( 1 << CS12);
TCCR1B |= (1 << CS11);
TCCR1B |= (1 << CS10);
}
else
{
TCCR1B |= (1 << CS12);
TCCR1B &= ~( 1 << CS11);
TCCR1B |= (1 << CS10);
}
digitalWrite(ENABLE_PIN, LOW);
digitalWrite(STEP_PIN, LOW);
ustepCounter = 1;
uint32_t ustepCounterActual;
float coef2 = ((float)items[LINK2LPV].value * stepsPERmm * 1e-9) * (float)valueDivider(VOLUME) * NOFMICROSTEPS * 10;
bool isManualStop = false;
uint32_t pumpingVolume;
uint16_t pumpingTime = 1;
uint32_t nextMillis = millis() + 1000;
OCR1A = (countsPERustepActual - 1);
TIMSK1 |= (1 << OCIE1A);
while ( (TIMSK1 & (1 << OCIE1A)) )
{
getButtonState();
if (buttonState == SHORTPRESS && lastButton == LEFT)
{
buttonState = MEDIUMPRESS;
lcd.setCursor(0, 0);
lcd.print(F(" STOP PUMPING? "));
lcd.setCursor(0, 1);
lcd.print(F("(YES) (NO)"));
while ( (TIMSK1 & (1 << OCIE1A)) )
{
getButtonState();
if (buttonState == SHORTPRESS)
{
buttonState = MEDIUMPRESS;
if (lastButton == LEFT)
{
TIMSK1 &= ~( 1 << OCIE1A);
isManualStop = true;
}
else if (lastButton == RIGHT)
{
lcd.setCursor(0, 0);
if (pumpingDirection > 0) lcd.print(F(" >> INFUSING >> "));
else lcd.print(F(" << REFILLING <<"));
break;
}
}
}
}
if (nextMillis <= millis())
{
cli();
ustepCounterActual = ustepCounter;
sei();
pumpingVolume = (uint32_t)(((float)ustepCounterActual / coef2) + 0.5);
printTimeAndVolume(pumpingTime, pumpingVolume);
pumpingTime++;
nextMillis += 1000;
}
}
digitalWrite(ENABLE_PIN, HIGH);
lcd.setCursor(0, 1);
pumpingVolume = (uint32_t)(((float)ustepCounter / coef2) + 0.5);
printTimeAndVolume(pumpingTime, pumpingVolume);
lcd.setCursor(0, 0);
if (isManualStop)
{
lcd.print(F(" MANUAL STOP "));
return 2;
}
if (ustepCounterLimit == ustepCounter - 1)
{
lcd.print(F(" FINISHED "));
return 0;
}
else
{
lcd.print(F("UNEXPECTED STOP "));
return 1;
}
}
/************************
ISR(TIMER1_COMPA_vect)
************************/
ISR(TIMER1_COMPA_vect)
{
digitalWrite(STEP_PIN, HIGH);
if (ustepCounter == ustepCounterLimit) TIMSK1 &= ~( 1 << OCIE1A);
if ( digitalRead(endStopPin) == LOW) TIMSK1 &= ~( 1 << OCIE1A);
delayMicroseconds(10);
digitalWrite(STEP_PIN, LOW);
ustepCounter++;
}