Close

CODE

A project log for NOVA-YOUR FOOD MAKER COMPANION

Introducing the revolutionary cooking robot, a marvel of technology and culinary innovation!

jobinpthomas1jobinpthomas1 06/21/2023 at 05:120 Comments

#include <FreeRTOS.h>
#include <task.h>
#include <LiquidCrystal_I2C.h>
#include <VNH3SP30.h>
#include "DFRobotDFPlayerMini.h"
#include <DueTimer.h>
#include <ButtonDebounce.h>

#define INDUCTION_LEVEL 0
#define MIX_INTERVAL 1
#define COOK_TIME 2
#define NOVA 3
#define PAUSE 4
#define PLAY 5
#define SAUTE_LEVEL 6

volatile bool change_flag, set_flag;
bool timerFlag = LOW;
bool playFlag = LOW;

//Create the Player object
DFRobotDFPlayerMini player;

//Create the motor object
VNH3SP30 strrMotor;
//Create the lcd object
LiquidCrystal_I2C lcd(0x27, 16, 2);

char temp[2];
volatile int stoveLevel = 0;
volatile float HeatLevelCounter = 0.0;
volatile int stoveLastState = 0;
unsigned char setHeatCommand[5] = { 0xFF, 0x55, 0x01, 0x00, 0xFE };
bool saute_flag = LOW;
bool induction_flag = LOW;
volatile long int main_count = 0;
bool startBit = LOW;
bool shakeState = LOW;
int timer;
volatile int displayChange = 3;
volatile int displayLastChange = 3;
volatile long int timerSet = 0;
unsigned long int timerPause = 0;
unsigned long int timermillis;
volatile int timerMin;
volatile float sauteLevel = 1.0;
volatile bool sauteBit = LOW;
volatile int sauteLevelSet = 1;
volatile int sauteLevelLastSet = int(sauteLevelSet);

//PLAY/PAUSE
#define PP_SWITCH 7

//DF PLAYER
#define DF_RX 14
#define DF_TX 15

//TIMER ENCODER
#define TIMER_ENC_A 31
#define TIMER_ENC_B 29
#define TIMER_SWITCH 33

/*------------------------------------------------------------------STIRRER FUNCTIONS STARTS ------------------------------------------------------------------*/

// Quadrature Encoder Matrix
const int QEM[4][4] = {
  { 0, -1, 1, 2 },
  { 1, 0, 2, -1 },
  { -1, 2, 0, 1 },
  { 2, 1, -1, 0 }
};

//enum strrLocations { downLevel1,
//                     downLevel2,
//                     downLevel3,
//                     downLevel4
//                   };

const int strrPosMatrix[5] = { -1500, -2500,
                               -3500,
                               -4500,
                               -5500
                             };

volatile long int strrEncoder = 0;
volatile unsigned char strrNew, strrOld;
int sauteState, sauteLastState;
volatile float sauteCounter = 0.0;
volatile int sauteSet;

//MOTOR DRIVER
#define MOT_IN1 9
#define MOT_IN2 10
#define MOT_PWM 8

//stirrer rotary encoder
#define SAUTE_ENCA 35
#define SAUTE_ENCB 39
#define SAUTE_SWITCH 37

//BLDC
#define STRR_BLDC_DIR 53
#define STRR_BLDC_PWM 51
//#define STRR_BLDC_FDBK  10

//LIMIT SWITCH
#define STRR_VER_TOP_LMT 25
#define STRR_VER_BTM_LMT 27

//Stirrer motor encoder
#define STRR_VERT_ENC_A 47
#define STRR_VERT_ENC_B 49

#define STRR_CW() \
  { \
    digitalWrite(STRR_BLDC_PWM, LOW); \
    digitalWrite(STRR_BLDC_DIR, HIGH); \
  }

#define STRR_CCW() \
  { \
    digitalWrite(STRR_BLDC_PWM, HIGH); \
    digitalWrite(STRR_BLDC_DIR, LOW); \
  }

#define STRR_STOP() \
  { \
    digitalWrite(STRR_BLDC_PWM, HIGH); \
    digitalWrite(STRR_BLDC_DIR, HIGH); \
  }

#define STRR_UP() \
  { \
    analogWrite(MOT_PWM, 70); \
    digitalWrite(MOT_IN1, LOW); \
    digitalWrite(MOT_IN2, HIGH); \
  }
#define STRR_DOWN() \
  { \
    analogWrite(MOT_PWM, 70); \
    digitalWrite(MOT_IN1, HIGH); \
    digitalWrite(MOT_IN2, LOW); \
  }

#define STRR_VER_STOP() \
  { \
    digitalWrite(MOT_PWM, LOW); \
    digitalWrite(MOT_IN1, HIGH); \
    digitalWrite(MOT_IN2, HIGH); \
  }

void enAStrInterrupt() {
  strrNew = (digitalRead(STRR_VERT_ENC_A) << 1) | (digitalRead(STRR_VERT_ENC_B));
  strrEncoder += QEM[strrOld][strrNew];
  strrOld = strrNew;
}

void enBStrInterrupt() {
  strrNew = (digitalRead(STRR_VERT_ENC_A) << 1) | (digitalRead(STRR_VERT_ENC_B));
  strrEncoder += QEM[strrOld][strrNew];
  strrOld = strrNew;
}

void shake() {
  if (shakeState == LOW) {
    shakeState = HIGH;
    STRR_CW();
  } else {
    shakeState = LOW;
    STRR_CCW();
  }
}

void strrMovDown() {
  STRR_DOWN();
  while (strrEncoder < 400) ;
  Timer2.attachInterrupt(shake).start(350000);
  while (digitalRead(STRR_VER_BTM_LMT) != HIGH);
  STRR_VER_STOP();
  Timer2.stop();
}

void strrMovUp() {
  STRR_UP();
  while (digitalRead(STRR_VER_TOP_LMT) != HIGH);
  STRR_VER_STOP();
}

void moveStirrerTo(int pos) {

  int Threshold = -20;
  int HighTreshold = -5000;
  int error = 0;
  int target = strrPosMatrix[pos];
  error = target - strrEncoder;
  strrMotor.setSpeed(-300);

  while (1) {
    error = target - strrEncoder;
    if (error < HighTreshold) {
      strrMotor.setSpeed(-300);
    } else if ((error > HighTreshold) && (error < Threshold)) {
      strrMotor.setSpeed(-80);
    } else if ((error > HighTreshold) && (error > Threshold)) {
      strrMotor.brake(500);
      error = target - strrEncoder;
      if (error > Threshold) {
        break;
      }
    }
  }
}

void strrHome() {
  if (digitalRead(STRR_VER_TOP_LMT) != HIGH) {
    Serial.println("Stirrer moving Home");
    strrMovUp();
    strrEncoder = 0;
    Serial.println("Stirrer Homing completed");
  }
}

void oneMix() {
  Serial.println("One mix started");
  STRR_CW();
  int lastState = millis();
  while (millis() - lastState <= 3200) {
    if (startBit == LOW) break;
  }
  STRR_STOP();
  lastState = millis();
  while (millis() - lastState <= 200) {
    if (startBit == LOW) break;
  }
  STRR_CCW();
  lastState = millis();
  while (millis() - lastState <= 3200) {
    if (startBit == LOW) break;
  }
  STRR_STOP();
  lastState = millis();
  while (millis() - lastState <= 200) {
    if (startBit == LOW) break;
  }
  Serial.println("One mix finished");
}

void saute() {
    if (startBit == HIGH) {
      strrMovDown();
      strrEncoder = 0;
    }
    if (startBit == HIGH) oneMix();
    for (int i = 0; i <= sauteLevelSet; i++) {
      if (startBit == HIGH && sauteLevelSet > 1) moveStirrerTo(i-2);
      if (startBit == HIGH) oneMix();
      if (startBit == HIGH) STRR_CW();
      int lastState = millis();
      while (millis() - lastState <= 4000) {
        if (startBit == LOW) break;
      }
      STRR_STOP();
    }
    if (startBit == LOW) inductionOff();
    strrEncoder = 500;
}

volatile int sauteLastSet = int(sauteCounter);
void sauteEnAIsr() {
  if (change_flag == LOW) change_flag = HIGH;
  if (sauteBit == LOW) {
    if (displayChange != 1) displayChange = 1;
    if ((int(sauteCounter) >= 0) && (int(sauteCounter) <= 600)) {
      sauteState = digitalRead(SAUTE_ENCA);
      if (sauteState != sauteLastState) {
        if (digitalRead(SAUTE_ENCB) != sauteState) {
          sauteCounter += 0.5;
        } else {
          sauteCounter -= 0.5;
        }
      }
      sauteLastState = sauteState;
    }
    if (sauteCounter <  -1.0) sauteCounter = -1.0;
    else if (sauteCounter > 600.0) sauteCounter = 600.0;
    //    change_flag = LOW;
    //  set_flag = HIGH;
    saute_flag = HIGH;
    //  Timer1.stop();
    //  sauteSet = int(sauteCounter) * 30;
  }
  else {
    if (displayChange != 6) displayChange = 6;
    if ((int(sauteLevel) >= 0) && (int(sauteLevel) <= 5)) {
      sauteState = digitalRead(SAUTE_ENCA);
      if (sauteState != sauteLastState) {
        if (digitalRead(SAUTE_ENCB) != sauteState) {
          sauteLevel += 0.5;
        } else {
          sauteLevel -= 0.5;
        }
      }
      sauteLastState = sauteState;
    }
    if (sauteLevel <  0.0) sauteLevel = 0.0;
    else if (sauteLevel > 5.0) sauteLevel = 5.0;
    //    change_flag = LOW;
    //  set_flag = HIGH;
    //    saute_flag = HIGH;
    //  Timer1.stop();
    //  sauteSet = int(sauteCounter) * 30;
  }
}

void sauteEnBIsr() {
  if (change_flag == LOW) change_flag = HIGH;
  if (sauteBit == LOW) {
    if (displayChange != 1) displayChange = 1;
    if ((int(sauteCounter) >= 0) && (int(sauteCounter) <= 600)) {
      sauteState = digitalRead(SAUTE_ENCA);
      if (sauteState != sauteLastState) {
        if (digitalRead(SAUTE_ENCB) != sauteState) {
          sauteCounter += 0.5;
        } else {
          sauteCounter -= 0.5;
        }
      }
      sauteLastState = sauteState;
    }
    if (sauteCounter <  0.0) sauteCounter = 0.0;
    else if (sauteCounter > 600.0) sauteCounter = 600.0;
    //    change_flag = LOW;
    //  set_flag = HIGH;
    saute_flag = HIGH;
    //  Timer1.stop();
    //  sauteSet = int(sauteCounter) * 30;
  }
  else {
    if (displayChange != 6) displayChange = 6;
    if ((int(sauteLevel) >= 0) && (int(sauteLevel) <= 5)) {
      sauteState = digitalRead(SAUTE_ENCA);
      if (sauteState != sauteLastState) {
        if (digitalRead(SAUTE_ENCB) != sauteState) {
          sauteLevel += 0.5;
        } else {
          sauteLevel -= 0.5;
        }
      }
      sauteLastState = sauteState;
    }
    if (sauteLevel <  0.0) sauteLevel = 0.0;
    else if (sauteLevel > 5.0) sauteLevel = 5.0;
    //    change_flag = LOW;
    //  set_flag = HIGH;
    //    saute_flag = HIGH;
    //  Timer1.stop();
    //  sauteSet = int(sauteCounter) * 30;
  }
}

void sauteSwitchIsr() {
  set_flag = HIGH;
  saute_flag = HIGH;
  Timer1.stop();
  sauteSet = int(sauteCounter) * 30;
  change_flag = LOW;
}

/*------------------------------------------------------------------STIRRER FUNCTIONS ENDS ------------------------------------------------------------------*/

/*-----------------------------------------------------------------INDUCTION FUNCTION STARTS------------------------------------------------------------------*/

//INDUCTION ENCODER
#define INDUCTION_ENC_A 43
#define INDUCTION_ENC_B 45
#define INDUCTION_SWITCH 41

//INDUCTION UART
#define INDUCTION_TX 16
#define INDUCTION_RX 17

int aState;
int aLastState;
char indtemp[2];

const unsigned char onCommand[5] = { 0xFF, 0x55, 0x00, 0x00, 0xFE };
const unsigned char cookCommand[5] = { 0xFF, 0x55, 0x01, 0x08, 0xFE };
const unsigned char offCommand[5] = { 0xFF, 0x00, 0x00, 0x00, 0xFE };
const unsigned char queryCommand[5] = { 0xFF, 0x77, 0x0F, 0x0F, 0xFE };
unsigned char inputBuf[9];
int i;

int inductionOn() {
  Serial2.write(onCommand, 5);  //Turning on(Standby)
  delay(500);
  Serial2.write(cookCommand, 5);  //Cook Command(Hot pot fn)
  delay(500);
  Serial2.write(queryCommand, 5);  //Sending query command
  delay(500);
  for (i = 0; i < 9; i++) {
    while (!Serial2.available())
      ;
    inputBuf[i] = Serial2.read();
  }

  if ((inputBuf[1] == 0x55) && (inputBuf[2] == 0x01) && (inputBuf[7] == 0x00)) {  // (on/off),fn & fault signal
    Serial.println("Started cooking");
    return 0;
  } else if (inputBuf[7]) {
    Serial.println("\nInduction fault ");
    return (inputBuf[7] * -1);
  } else {
    Serial.println("Not able to turn on the stove ");
    return (-9);
  }
}

int inductionOff() {
  Serial2.write(offCommand, 5);  //Induction turning off
  delay(500);
  Serial2.write(queryCommand, 5);  //Sending query command
  for (i = 0; i < 9; i++) {
    while (!Serial2.available())
      ;
    inputBuf[i] = Serial2.read();
  }
  if ((inputBuf[1] == 0x00) && (inputBuf[2] == 0x00)) {  //cheching (on/off) & function,power
    return 1;
  } else if (inputBuf[7]) {
    Serial.println("\nInduction fault ");
    return (inputBuf[7] * -1);
  } else {
    Serial.println("Not able to turn on the stove ");
    return (-9);
  }
}

int setinductionHeatLevel(int level) {
  setHeatCommand[3] = level;
  Serial2.write(setHeatCommand, 5);
  delay(500);
  Serial2.write(queryCommand, 5);  //Sending query command
  delay(500);
  for (i = 0; i < 9; i++) {
    while (!Serial1.available())
      ;
    inputBuf[i] = Serial1.read();
  }
  induction_flag = LOW;
  if ((inputBuf[1] == 0x55) && (inputBuf[3] == level)) return 0;
  else if (inputBuf[7]) {
    Serial.println("\nInduction fault ");
    return (inputBuf[7] * -1);
  } else {
    Serial.println("not able to change heat level ");
    return (-9);
  }
}

void inductionEncIsrA() {
  if (change_flag == LOW) change_flag = HIGH;
  if (displayChange != 0) displayChange = 0;
  aState = digitalRead(INDUCTION_ENC_A);
  if ((HeatLevelCounter >= 0.0) && (HeatLevelCounter <= 12.0)) {
    if (aState != aLastState) {
      if (digitalRead(INDUCTION_ENC_B) != aState) {
        HeatLevelCounter += 0.5;
      } else {
        HeatLevelCounter -= 0.5;
      }
    }
    aLastState = aState;
  }
  if (HeatLevelCounter < 0.0) HeatLevelCounter = 0.0;
  else if (HeatLevelCounter > 12.0) HeatLevelCounter = 12.0;
  //    change_flag = LOW;
  //  set_flag = HIGH;
  //  stoveLevel = int(HeatLevelCounter);
  //  setHeatCommand[3] = stoveLevel;
}

void inductionEncIsrB() {
  if (change_flag == LOW) change_flag = HIGH;
  if (displayChange != 0) displayChange = 0;
  aState = digitalRead(INDUCTION_ENC_A);
  if ((HeatLevelCounter >= 0.0) && (HeatLevelCounter <= 12.0)) {
    if (aState != aLastState) {
      if (digitalRead(INDUCTION_ENC_B) != aState) {
        HeatLevelCounter += 0.5;
      } else {
        HeatLevelCounter -= 0.5;
      }
    }
    aLastState = aState;
  }
  if (HeatLevelCounter < 0.0) HeatLevelCounter = 0.0;
  else if (HeatLevelCounter > 12.0) HeatLevelCounter = 12.0;
  //    change_flag = LOW;
  //  set_flag = HIGH;
  //  stoveLevel = int(HeatLevelCounter);
  //  setHeatCommand[3] = stoveLevel;
}

void inductionSwitchIsr() {
  set_flag = HIGH;
  change_flag = LOW;
  stoveLevel = int(HeatLevelCounter);
  setHeatCommand[3] = stoveLevel;
}

/*-----------------------------------------------------------------INDUCTION FUNCTION ENDS------------------------------------------------------------------*/

/*-----------------------------------------------------------------TIMER FUNCTIONS START---------------------------------------------------------------------*/
int timerState;
int timerLastState;
volatile float timerCount = 0.0;
volatile int timerLastCount = int(timerCount);
char heatLevel[2];
void timerEnAIsr() {
  if (change_flag == LOW) change_flag = HIGH;
  if (displayChange != 2) displayChange = 2;
  {
    timerState = digitalRead(TIMER_ENC_A);
    if (timerCount >= 0.0) {
      if (timerState != timerLastState) {
        if (digitalRead(TIMER_ENC_B) != timerState) {
          timerCount += 0.5;
        } else {
          timerCount -= 0.5;
        }
      }
    }
    if (timerCount < 0.0) {
      timerCount += 0.5;
    }
  }
  timerLastState = timerState;
}

void timerEnBIsr() {
  if (change_flag == LOW) change_flag = HIGH;
  if (displayChange != 2) displayChange = 2;
  {
    timerState = digitalRead(TIMER_ENC_A);
    if (timerCount >= 0.0) {
      if (timerState != timerLastState) {
        if (digitalRead(TIMER_ENC_B) != timerState) {
          timerCount += 0.5;
        } else {
          timerCount -= 0.5;
        }
      }
    }
    if (timerCount < 0.0) {
      timerCount += 0.5;
    }
  }
  timerLastState = timerState;
}

void TimerStart() {
  if (startBit == HIGH && timerSet > 0) {
    timerFlag = HIGH;
    timerSet -= 1;
  }
}

void timerSwitchIsr() {
  change_flag = LOW;
  set_flag = HIGH;
  timerSet = int(timerCount) * 60;
}

//void ppIsr() {
//
//  if (startBit == LOW) {
//    startBit = HIGH;
//  }
//  else {
//    displayChange = 4;
//    startBit = LOW;
//    player.play(3);
//  }
//}
volatile bool resumeBit = LOW;
void taskOne(void *pvParameters)
{
  while (1) {
    //    Serial.println("waiting");
    if (startBit == HIGH) {
      if (sauteLevelSet > 0) saute();
      else if(sauteLevelSet == 0) strrHome();
      int lastMillis = millis();
      while (millis() - lastMillis <= (sauteSet * 1000)) {
        if (startBit == LOW) break;
      }
    }
    if (startBit == LOW) {
      digitalWrite(STRR_BLDC_PWM, HIGH);
      inductionOff();
      strrHome();
    }
  }
}
volatile int timerLastSet = 0;
volatile int count = 0;
int buttonState;             // the current reading from the input pin
void taskTwo(void *pvParameters) {
  while (1) {
    if ((startBit == HIGH) && (change_flag == LOW) /*&& (timerFlag == HIGH)*/ && timerLastSet != timerSet) {
      if (displayChange != 5) displayChange = 5;
      timerLastSet = timerSet;
      //      int(timerCount) = timerSet / 60;
      if (displayChange != displayLastChange) {
        displayLastChange = displayChange;
        lcd.clear();
        lcd.setCursor(11, 0);
        lcd.print("TIMER");
        lcd.setCursor(0, 0);
        lcd.print("HEAT");
        sauteBit = LOW;
        vTaskDelay(30);
      }
      //    if(startBit == LOW) inductionOff();
      sprintf(heatLevel, "%2d", stoveLastState);
      lcd.setCursor(0, 1);
      lcd.print(heatLevel);
      if (stoveLevel != stoveLastState) {
        stoveLastState = stoveLevel;
        if (stoveLevel == 0) {
          Serial2.write(offCommand, 5);
        }
        else {
          setHeatCommand[3] = stoveLastState;
          Serial2.write(setHeatCommand, 5);
        }
      }
      //      Serial.println(timerSet);
      if (timerSet % 2 == 0)
      {
        if (((int(timerSet/2) + 60) / 3600) > 0) {
          lcd.setCursor(5, 1);
          sprintf(temp, "%2d", ((int(timerSet/2) + 60) / 3600));
          lcd.print(temp);
          lcd.setCursor(7, 1);
          lcd.print("H");
          lcd.setCursor(8, 1);
          lcd.print(" ");
        }
        if (((int(timerSet/2) / 60) % 60) > 0) {
          lcd.setCursor(6, 1);
          lcd.print("   ");
          lcd.setCursor(9, 1);
          sprintf(temp, "%02d", ((int(timerSet/2) / 60) % 60));
          lcd.print(temp);
          lcd.setCursor(11, 1);
          lcd.print("M");
          lcd.setCursor(12, 1);
          lcd.print(" ");
        }
        if (((int(timerSet/2) / 60) % 60) == 0) {
          lcd.setCursor(9, 1);
          lcd.print("   ");
        }
        lcd.setCursor(13, 1);
        sprintf(temp, "%02d", int(timerSet/2) % 60);
        lcd.print(temp);
        lcd.setCursor(15, 1);
        lcd.print("S");
      }
      else
      {
        if (((int(timerSet/2) + 60) / 3600) > 0) {
          lcd.setCursor(5, 1);
          sprintf(temp, "%2d", ((int(timerSet/2) + 60) / 3600));
          lcd.print(temp);
          lcd.setCursor(7, 1);
          lcd.print("H");
          lcd.setCursor(8, 1);
          lcd.print(":");
        }
        if (((int(timerSet/2) / 60) % 60) > 0) {
          lcd.setCursor(6, 1);
          lcd.print("   ");
          lcd.setCursor(9, 1);
          sprintf(temp, "%02d", ((int(timerSet/2) / 60) % 60));
          lcd.print(temp);
          lcd.setCursor(11, 1);
          lcd.print("M");
          lcd.setCursor(12, 1);
          lcd.print(":");
        }
        if (((int(timerSet/2) / 60) % 60) == 0) {
          lcd.setCursor(9, 1);
          lcd.print("   ");
        }
        lcd.setCursor(13, 1);
        sprintf(temp, "%02d", int(timerSet/2) % 60);
        lcd.print(temp);
        lcd.setCursor(15, 1);
        lcd.print("S");
      }
      if (timerSet == 0) {
        startBit = LOW;
        resumeBit = LOW;
        player.play(6);
        lcd.clear();
        lcd.setCursor(5, 0);
        lcd.print("COOKING");
        lcd.setCursor(4, 1);
        lcd.print("COMPLETED");
        inductionOff();
        stoveLevel = 0;
        HeatLevelCounter = 0.0;
        stoveLastState = 0;
        sauteLevel = 1.0;
        sauteLevelSet = 1;
        timerCount = 0.0;
        sauteCounter = 0.0;
        strrHome();
        int displayLastState = millis();
        while (millis() - displayLastState <= 3000) {
          if (change_flag == HIGH) break;
        }
        //        displayChange = 3;
        if (change_flag == LOW) displayChange = 3;
        timerFlag = LOW;
      }
      //      timerFlag = LOW;
    }
    else if ((change_flag == HIGH) || (startBit == LOW)) {
      switch (displayChange) {
        case INDUCTION_LEVEL:
//          if ((stoveLevel) != int(HeatLevelCounter)) {
            if (displayChange != displayLastChange) {
              displayLastChange = displayChange;
              lcd.clear();
              vTaskDelay(30);
            }
            sauteBit = LOW;
            lcd.setCursor(0, 0);
            lcd.print("INDUCTION LEVEL");
            setHeatCommand[3] = int(HeatLevelCounter);
            lcd.setCursor(3, 1);
            lcd.print("LEVEL:");
            lcd.setCursor(9, 1);
            sprintf(indtemp, "%2d", setHeatCommand[3]);
            lcd.print(indtemp);
//          }
          break;

        case MIX_INTERVAL:
//          if ((sauteLastSet) != int(sauteCounter)) {
            if (displayChange != displayLastChange) {
              displayLastChange = displayChange;
              lcd.clear();
              vTaskDelay(30);
            }
            sauteLastSet = int(sauteCounter);
            lcd.setCursor(2, 0);
            lcd.print("MIX INTERVAL");
            lcd.setCursor(2, 1);
            sprintf(temp, "%2d", (int(sauteCounter) * 15) / 60);
            lcd.print(temp);
            lcd.setCursor(4, 1);
            lcd.print("Min");
            lcd.setCursor(7, 1);
            lcd.print(":");
            lcd.setCursor(8, 1);
            sprintf(temp, "%02d", (int(sauteCounter) * 15) % 60);
            lcd.print(temp);
            lcd.setCursor(10, 1);
            lcd.print("Sec");
//          }
          break;

        case SAUTE_LEVEL:
//          if ((sauteLevelLastSet) != int(sauteLevel)) {
            if (displayChange != displayLastChange) {
              displayLastChange = displayChange;
              lcd.clear();
              vTaskDelay(30);
            }
            sauteLevelLastSet = int(sauteLevel);
            lcd.setCursor(3, 0);
            lcd.print("MIX LEVEL");
            lcd.setCursor(3, 1);
            lcd.print("LEVEL:");
            lcd.setCursor(9, 1);
            sprintf(indtemp, "%2d", int(sauteLevel));
            if(int(sauteLevel) == 0) lcd.print("NO");
            else lcd.print(indtemp);
//          }
          break;

        case COOK_TIME:
//          if ((timerLastCount) != int(timerCount)) {
            if (displayChange != displayLastChange) {
              displayLastChange = displayChange;
              lcd.clear();
              vTaskDelay(30);
            }
            timerLastCount = int(timerCount);
            sauteBit = LOW;
            lcd.setCursor(4, 0);
            lcd.print("COOK TIME");
            lcd.setCursor(2, 1);
            sprintf(temp, "%2d", (int(timerCount) * 60) / 3600);
            lcd.print(temp);
            lcd.setCursor(4, 1);
            lcd.print("Hr");
            lcd.setCursor(7, 1);
            lcd.print(":");
            lcd.setCursor(8, 1);
            sprintf(temp, "%02d", ((int(timerCount) * 60) / 60) % 60);
            lcd.print(temp);
            lcd.setCursor(10, 1);
            lcd.print("Min");
//          }
          break;

        case PAUSE:
          if (displayChange != displayLastChange) {
            displayLastChange = displayChange;
            lcd.clear();
            vTaskDelay(30);
          }
          lcd.setCursor(10, 0);
          lcd.print("PAUSED");
          lcd.setCursor(6, 1);
          if (((timerSet + 60) / 3600) > 0) {
            lcd.setCursor(5, 1);
            sprintf(temp, "%2d", ((int(timerSet/2) + 60) / 3600));
            lcd.print(temp);
            lcd.setCursor(7, 1);
            lcd.print("H");
            lcd.setCursor(8, 1);
            lcd.print(":");
          }
          if (((timerSet / 60) % 60) > 0) {
            lcd.setCursor(9, 1);
            sprintf(temp, "%02d", ((int(timerSet/2) / 60) % 60));
            lcd.print(temp);
            lcd.setCursor(11, 1);
            lcd.print("M");
            lcd.setCursor(12, 1);
            lcd.print(":");
          }
          lcd.setCursor(13, 1);
          sprintf(temp, "%02d", int(timerSet/2) % 60);
          lcd.print(temp);
          lcd.setCursor(15, 1);
          lcd.print("S");
          break;

        case NOVA:
          if (displayChange != displayLastChange) {
            displayLastChange = displayChange;
            lcd.clear();
            vTaskDelay(30);
          }
          lcd.setCursor(6, 0);
          lcd.print("NOVA");
          lcd.setCursor(1, 1);
          lcd.print("LET'S COOK ");
          lcd.setCursor(12, 1);
          switch (count % 3) {
            case 0:
              lcd.print(">>  ");
              break;
            case 1:
              lcd.print(" >> ");
              break;
            case 2:
              lcd.print("  >>");
              count = -1;
              break;
            default:
              break;
          }
          //              count++;
          break;

        default:
          break;
      }
      long int mainLastState = millis();
      while (millis() - mainLastState <= 1500 && displayChange != NOVA) {
        if ((change_flag == HIGH) || ((displayLastChange != displayChange) && displayChange != PLAY) || buttonState == HIGH) break;
      }
      if ((change_flag == LOW) || (displayLastChange != displayChange)) {
        switch (displayLastChange) {
          case INDUCTION_LEVEL:
            stoveLevel = int(HeatLevelCounter);
            //            setHeatCommand[3] = stoveLevel;
            break;

          case MIX_INTERVAL:
            sauteSet = int(sauteCounter) * 15;
            break;

          case COOK_TIME:
            timerSet = int(timerCount) * 120;
            break;

          case SAUTE_LEVEL:
            sauteLevelSet = int(sauteLevel);
            break;

          default:
            break;
        }
      }
      set_flag = LOW;
      int lastMillis = millis();
      while ((millis() - lastMillis) <= 1500 && displayChange != NOVA) {
        if (change_flag == HIGH || ((displayLastChange != displayChange) && displayChange != PLAY) || buttonState == HIGH) break;
      }
    }
  }
}

void taskThree(void *pvParameters) {
  unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
  unsigned long debounceDelay = 50;
  int lastButtonState = LOW;
  while (1) {
    int reading = digitalRead(PP_SWITCH);
    if (reading != lastButtonState) {
      lastDebounceTime = millis();
    }

    if ((millis() - lastDebounceTime) > debounceDelay) {
      if (reading != buttonState) {
        buttonState = reading;
        if (buttonState == HIGH) {
          Serial.println("PRESSED");
          if (startBit == LOW) {
            startBit = HIGH;
//            setHeatCommand[3] = stoveLevel;
//            Serial2.write(setHeatCommand, 5);
            stoveLastState = 0;
            if (resumeBit == LOW) player.play(11);
            else player.play(4);
            if(resumeBit == LOW) resumeBit = HIGH;
          }
          else if (startBit == HIGH) {
            displayChange = 4;
            startBit = LOW;
            player.play(3);
          }
        }
      }
    }
    lastButtonState = reading;
  }
}

void sound() {
  player.play(12);

}

void taskFour(void *pvParameters) {
  playFlag = LOW;
  while (1) {
    if (playFlag == HIGH) {
      sound();
      //      vTaskDelay(1000);
    }
  }
}

void taskFive(void *pvParameters) {
  while (1) {
    if (change_flag == HIGH) {
      vTaskDelay(50);
      change_flag = LOW;
    }
  }
}

void taskSix(void *pvParameters) {
  unsigned long LastDebounceTime = 0;  // the last time the output pin was toggled
  unsigned long DebounceDelay = 100;
  int ButtonState;             // the current reading from the input pin
  int LastButtonState = HIGH;
  char sauteTemp[2];
  while (1) {
    int Reading = digitalRead(SAUTE_SWITCH);
    if (Reading != LastButtonState) {
      LastDebounceTime = millis();
    }

    if ((millis() - LastDebounceTime) > DebounceDelay) {
      if (Reading != ButtonState) {
        ButtonState = Reading;
        if (ButtonState == LOW) {
          //          Serial.println("PRESSED");
          if (sauteBit == HIGH) {
            sauteBit = LOW;
            displayChange = 1;
            change_flag = HIGH;
          }
          else if (sauteBit == LOW) {
            sauteBit = HIGH;
            displayChange = 6;
            change_flag = HIGH;
          }
        }
      }
    }
    LastButtonState = Reading;
  }
}

void countStart() {
  if (displayChange == NOVA) count += 1;
  //  if(count == 3) count = 0;
}

/*******************************TIMER FUNCTIONS END***********************************/

void setup() {
  Serial.begin(9600);
  Serial1.begin(9600);
  Serial2.begin(9600);
  Serial3.begin(9600);
  pinMode(MOT_IN1, OUTPUT);
  pinMode(MOT_IN2, OUTPUT);
  pinMode(MOT_PWM, OUTPUT);
  pinMode(STRR_VER_BTM_LMT, INPUT);
  pinMode(STRR_VER_TOP_LMT, INPUT);
  pinMode(STRR_BLDC_DIR, OUTPUT);
  pinMode(STRR_BLDC_PWM, OUTPUT);
  pinMode(SAUTE_SWITCH, INPUT);
  //  pinMode(INDUCTION_SWITCH, INPUT_PULLUP);
  digitalWrite(STRR_BLDC_PWM, HIGH);
  strrMotor.begin(MOT_PWM, MOT_IN1, MOT_IN2);
  pinMode(TIMER_ENC_A, INPUT_PULLUP);
  pinMode(TIMER_ENC_B, INPUT_PULLUP);
  pinMode(SAUTE_ENCA, INPUT_PULLUP);
  pinMode(SAUTE_ENCB, INPUT_PULLUP);
  pinMode(INDUCTION_ENC_A, INPUT_PULLUP);
  pinMode(INDUCTION_ENC_B, INPUT_PULLUP);
  //  pinMode(TIMER_SWITCH, INPUT_PULLUP);
  pinMode(PP_SWITCH, INPUT);
  attachInterrupt(digitalPinToInterrupt(STRR_VERT_ENC_A), enAStrInterrupt, CHANGE);
  attachInterrupt(digitalPinToInterrupt(STRR_VERT_ENC_B), enBStrInterrupt, CHANGE);
  attachInterrupt(digitalPinToInterrupt(INDUCTION_ENC_A), inductionEncIsrA, CHANGE);
  attachInterrupt(digitalPinToInterrupt(INDUCTION_ENC_B), inductionEncIsrB, CHANGE);
  attachInterrupt(digitalPinToInterrupt(SAUTE_ENCA), sauteEnAIsr, CHANGE);
  attachInterrupt(digitalPinToInterrupt(SAUTE_ENCB), sauteEnBIsr, CHANGE);
  attachInterrupt(digitalPinToInterrupt(TIMER_ENC_A), timerEnAIsr, CHANGE);
  attachInterrupt(digitalPinToInterrupt(TIMER_ENC_B), timerEnBIsr, CHANGE);
  //  attachInterrupt(digitalPinToInterrupt(TIMER_SWITCH), timerSwitchIsr, FALLING);
  //  attachInterrupt(digitalPinToInterrupt(SAUTE_SWITCH), sauteSwitchIsr, FALLING);
  //  attachInterrupt(digitalPinToInterrupt(INDUCTION_SWITCH), inductionSwitchIsr, FALLING);
  //  attachInterrupt(digitalPinToInterrupt(PP_SWITCH), ppIsr, RISING);
  Timer3.attachInterrupt(TimerStart).start(500000);
  Timer4.attachInterrupt(countStart).start(500000);
  inductionOff();
  // Init serial port for DFPlayer Mini
  if (player.begin(Serial3)) Serial.println("Player-OK");
  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(6, 0);
  //  lcd.print("NOVA");
  //  player.play(10);
  //  delay(3000);
  displayChange = 3;
    xTaskCreate(taskOne, (const portCHAR *)"taskOne", 128, NULL, 1, NULL);
    xTaskCreate(taskTwo , (const portCHAR *)"taskTwo", 256, NULL, 1, NULL);
    xTaskCreate(taskThree , (const portCHAR *)"taskThree", 128, NULL, 1, NULL);
  //  xTaskCreate(taskFour , (const portCHAR *)"taskFour", 256, NULL, 1, NULL);
    xTaskCreate(taskFive , (const portCHAR *)"taskFive", 128, NULL, 1, NULL);
    xTaskCreate(taskSix , (const portCHAR *)"taskSix", 128, NULL, 1, NULL);
  vTaskStartScheduler();
  saute_flag = HIGH;

//  strrHome();
//  delay(2000);
// strrMovDown();
////  inductionOff();
////  delay(1000);
//  inductionOn();
//  delay(2000);
//  inductionOff();
//  setinductionHeatLevel(3);
 
}

void loop() {
//  STRR_CW();
//  delay(8000);
//  STRR_CCW();
//  delay(4000);

}

Discussions