// Include the AccelStepper library:
#include <AccelStepper.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#include "U8glib.h"
/*
#define OLED_RESET -1 
#define SCREEN_ADDRESS 0x3D
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
*/

// Define stepper motor connections and motor interface type. Motor interface type must be set to 1 when using a driver:
#define potentiometer A0  //10k Variable Resistor
#define ledPinY 5
#define ledPinG 6
#define ledPinR 7
#define dirPin 8
#define stepPin 9
#define enablePin 13
#define MS1Pin 12
#define MS2Pin 11
#define MS3Pin 10
#define motorInterfaceType 1
#define STARTSTOP_SWITCH  4
#define HOME_BUTTON       3

/* -- Constants -- */

int HOME = 0;
int END_POS = 1000;

int prev_FREQ = 0;
#define MAX_FREQ 1000.0
#define HOMING_FREQ 800.0
#define MAX_WORK_FREQ 200.0
#define PITCH 1.27
#define BASIC_SPR 200.0
#define MICROSTEPS 1.0

#define SYR_D_IN 5.0
#define SYR_LENGTH 30.0

float read_ADC;
float FREQ_MAP;

float A_SYR = SYR_D_IN * SYR_D_IN * 3.14 / 4;
int prev_FLOW_RATE = 0;

// Create a new instance of the AccelStepper class:
AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin);

// Create a new instance of the Adafruit_SSD1306 class:
// Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0 | U8G_I2C_OPT_NO_ACK | U8G_I2C_OPT_FAST); // Fast I2C / TWI
// U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);   // SPI communication: SCL = 13, SDA = 11, RES = 10, DC = 9, CS = 8

char buffer1[20];
char buffer2[20];       // helper buffer for converting values into C-style string (array of chars)

// Variables will change:
int ledState = LOW;  // ledState used to set the LED
// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;  // will store last time LED was updated
// constants won't change:
const long interval = 300;  // interval at which to blink (milliseconds)


void setup() {
  Serial.begin(9600); // Any baud rate should work
  Serial.println(prev_FREQ);
  Serial.println(prev_FLOW_RATE);
  stepper.setMaxSpeed(MAX_FREQ);

  // HOME = stepper.currentPosition();
  // stepper.setCurrentPosition(HOME);
 
  pinMode(STARTSTOP_SWITCH, INPUT_PULLUP);
  pinMode(HOME_BUTTON, INPUT_PULLUP);
  pinMode(enablePin, OUTPUT);
  pinMode(ledPinR, OUTPUT);
  pinMode(ledPinG, OUTPUT);
  pinMode(ledPinY, OUTPUT);
  pinMode(potentiometer, INPUT_PULLUP); // declare potentiometer as input 
  // pinMode(dirPin, OUTPUT);
  // pinMode(stepPin, OUTPUT);
  // digitalWrite(MS1Pin, LOW);
  // digitalWrite(MS2Pin, LOW);
  // digitalWrite(MS3Pin, LOW);
  // digitalWrite(enablePin, HIGH); // Disable motor initially

  u8g.setColorIndex(1);          // set color to white
  // u8g.setFont(u8g_font_6x10r);   // set smaller font for tickmarks  
    u8g.setFont(u8g_font_10x20r);  
 
  /*
  // initialize OLED display with I2C address 0x3C
  if (!oled.begin(SSD1306_SWITCHCAPVCC, 0x3D)) {
    Serial.println(F("failed to start SSD1306 OLED"));
    while (1);
  }

  oled.display();
  delay(2000);         // wait two seconds for initializing
  oled.clearDisplay(); // clear display
  oled.setTextSize(1);         // set text size
  oled.setTextColor(SSD1306_WHITE);    // set text color
  oled.setCursor(10, 30);       // set position to display
  oled.print(F("SYRINGE PUMP v.0.1")); // set text
  oled.display();
  delay(2000);
  //delay(2000);
  oled.clearDisplay(); // clear display
  oled.setTextSize(1);
  oled.setTextColor(SSD1306_WHITE);
  oled.setCursor(2, 2);
  oled.print(F("Freq. [Hz]:")); // set text  
  oled.setCursor(2, 28);
  oled.print(F("Q [uL/min]:")); // set text
  oled.setCursor(2, 52);
  oled.print(F("State:")); // set text 
  */
  

}



void loop() {

  read_ADC = analogRead(potentiometer); // read analogue to digital value 0 to 1023
  FREQ_MAP = read_ADC * MAX_WORK_FREQ / 1023 ; // map ADC value and calculate frequency (pulses per second)
  int FREQ = FREQ_MAP;
  int FLOW_RATE = 60 * FREQ * PITCH * A_SYR / (BASIC_SPR * MICROSTEPS); // flow rate in uL/min (microliters per minute)
  // oled.display();

  unsigned long currentMillis = millis();
    u8g.firstPage();
    do {

      u8g.drawStr(25,20, itoa(FREQ,buffer1,10));
      u8g.drawStr(25,50, itoa(FLOW_RATE,buffer2,10));


/*
  if  (FREQ != prev_FREQ) {
    Serial.println(FREQ);
    Serial.println(FLOW_RATE);
    oledprint (FREQ, FLOW_RATE);
  }
  prev_FREQ = FREQ;
  */


  if (digitalRead(STARTSTOP_SWITCH) == HIGH)  {
    if (stepper.currentPosition() <= END_POS+1) {
      
      stepper.moveTo(END_POS);
      stepper.setSpeed(FREQ);
      stepper.runSpeedToPosition();
     
      // stepper.setSpeed(FREQ);
      // stepper.runSpeed();
      digitalWrite(ledPinG, HIGH);
      digitalWrite(ledPinY, LOW);
      /*
      oledprint (FREQ, FLOW_RATE);
      oled.setTextSize(1);
      oled.setTextColor(SSD1306_WHITE);
      oled.setCursor(60, 52);
      oled.print(F("MOVING")); // set text 
      /*
      Serial.println("МОТОР ЈЕ У ПОКРЕТУ.");
        if (digitalRead(HOME_BUTTON) == 0) {
          Serial.println("МОТОР ЈЕ У ПОКРЕТУ. ЗАУСТАВИ МОТОР ДА БИ ГА ПОСЛАО У ПОЛАЗНИ ПОЛОЖАЈ.");
        }
      */
    }
    else {
      stepper.stop();
      digitalWrite(ledPinR, HIGH);
      digitalWrite(ledPinG, LOW);
      /*
      oled.clearDisplay(); // clear display
      oledprint (FREQ, FLOW_RATE);
      oled.setTextSize(1);
      oled.setTextColor(SSD1306_WHITE);
      oled.setCursor(60, 52);
      oled.print(F("END")); // set text  
      //Serial.println("ДОСТИГНУТ ЈЕ КРАЈЊИ ПОЛОЖАЈ.");
      */
    }

  }
  else {
    stepper.stop();
    /*
    oled.clearDisplay(); // clear display
    oledprint (FREQ, FLOW_RATE);
    oled.setTextSize(1);
    oled.setTextColor(SSD1306_WHITE);
    oled.setCursor(60, 52);
    oled.print(F("WAITING")); // set text 
    */

    if (stepper.currentPosition() != 0) {
      if (currentMillis - previousMillis >= interval) {
        // save the last time you blinked the LED
        previousMillis = currentMillis;
        // if the LED is off turn it on and vice-versa:
        ledState = (ledState == LOW) ? HIGH : LOW;
        // set the LED with the ledState of the variable:
        digitalWrite(ledPinG, ledState);
      }
      else {
      digitalWrite(ledPinG, LOW);
      }
    }

  }

  if (digitalRead(HOME_BUTTON) == 0) {
    /*
    oled.clearDisplay(); // clear display
    oledprint (FREQ, FLOW_RATE);
    oled.setTextSize(1);
    oled.setTextColor(SSD1306_WHITE);
    oled.setCursor(60, 52);
    oled.print(F("moving")); // set text  
    */
    stepper.moveTo(HOME);
    stepper.setSpeed(HOMING_FREQ);
    while (stepper.distanceToGo() < 0) {
      stepper.runSpeedToPosition();
      digitalWrite(ledPinR, LOW);
      digitalWrite(ledPinG, HIGH);
    }
    //Serial.println("ПОЛАЗНИ ПОЛОЖАЈ ЗАУЗЕТ.");
    digitalWrite(ledPinY, HIGH);
    digitalWrite(ledPinG, LOW);
  }

  if (stepper.currentPosition() == 0) {
    /*
    oled.clearDisplay(); // clear display
    oledprint (FREQ, FLOW_RATE);
    oled.setTextSize(1);
    oled.setTextColor(SSD1306_WHITE);
    oled.setCursor(60, 52);
    oled.print(F("HOME")); // set text  
    */
    digitalWrite(ledPinY, HIGH);
    digitalWrite(ledPinG, LOW);
    digitalWrite(ledPinR, LOW);
  }

    } while ( u8g.nextPage() );

 }
  
/*  
 void oledprint (long FREQ, long FLOW_RATE) {

    oled.clearDisplay(); // clear display
    oled.setTextSize(1);
    oled.setTextColor(SSD1306_WHITE);
    oled.setCursor(2, 2);
    oled.print(F("Freq. [Hz]:")); // set text  
    oled.setCursor(2, 28);
    oled.print(F("Q [uL/min]:")); // set text
    oled.setCursor(2, 52);
    oled.print(F("State:")); // set text 
    // oled.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // Draw 'inverse' text
    oled.setCursor(74, 2);
    oled.setTextSize(2); // Draw 2X-scale text
    oled.println(FREQ); // set text
    oled.setCursor(74, 28);
    oled.setTextSize(2); // Draw 2X-scale text
    oled.println(FLOW_RATE); // set text

 }    
  
*/




 


  
A4988