Conveyor with keypad 4x4 and Water Flow Sensor for Automatic Bottle Filling

why my code doesn't running correctly. first, the code for water flow sensor not working/doesn't running when ir sensor 1 detecting object. second, when i push S button in keypad to save the data, the LCD show saving views, but not come back to main views (lcd show blank). the code is below. plis help me to done my project. sorry for my english :). note : Let's just say that the circuit schematic is correct.

/*--------------------------- Inisialisasi Keypad 4x4 ---------------------------*/
#include <Keypad.h>

const byte ROWS = 4;  //4 baris
const byte COLS = 4;  //4 kolom
char keys[ROWS][COLS] = {
  { '1', '2', '3', 'A' },
  { '4', '5', '6', 'B' },
  { '7', '8', '9', 'C' },
  { '*', '0', 'S', 'D' }  //S = Simpan
};

byte colPins[COLS] = { 6, 5, 4, 3 };   // pin 2,3,4,5 untuk pin kolom keypad (lihat gambar)
byte rowPins[ROWS] = { 10, 9, 8, 7 };  // pin 6,7,8,9 untuk pin baris keypad (lihat gambar)

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

char key;

#define maksBit 4
char userInput[maksBit];
byte hitungData = 0;
int userInputInt = 0;
/*--------------------------- Akhir Keypad 4x4 ---------------------------*/

/*--------------------------- Inisialisasi LCD I2C ---------------------------*/
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x26, 16, 2);  // SDA: A4, SCL:A5.
/*--------------------------- Akhir LCD I2C ---------------------------*/

/*--------------------------- Inisialisasi Sensor Water Flow ---------------------------*/
volatile int flow_frequency;  

float l_minute;
float totalIsi = 0.0;
unsigned char flowsensor = 2;  // Sensor Input
unsigned long currentTime;
unsigned long cloopTime;
/*--------------------------- Akhir Sensor Water Flow ---------------------------*/

/*---------------------- Inisialisasi Relay Pompa Air ------------------------*/
byte relayPompa = A0;   //pin POMPA
#define pompaAktif LOW  
/*---------------------- Akhir Relay Pompa Air ------------------------*/

/*-------------------- Inisialisasi Relay Motor Konveyor ---------------------*/
byte relayKonveyor = A1;  //pin Relay Konveyor
#define konvAktif LOW     
/*-------------------- Akhir Relay Motor Konveyor ---------------------*/

/*--------------------------- Inisialisasi Sensor Infrared 1 ---------------------------*/
int SensorIR1 = 11;
#define adaBarang LOW
/*-------------------- Akhir Relay Motor Konveyor ---------------------*/

/*--------------------------- Inisialisasi Sensor Infrared 2 ---------------------------*/
int SensorIR2 = 12;  
// #define adaBarang        HIGH    
/*-------------------- Akhir Relay Motor Konveyor ---------------------*/

/*--------------------------- Inisialisasi EEPROM ---------------------------*/
#include <EEPROM.h>
#define address 10
/*--------------------------- Akhir EEPROM ---------------------------*/


void flow()  // Interrupt function
{
  flow_frequency++;
}

void setup() {
  Serial.begin(9600);
  pinMode(relayKonveyor, OUTPUT);  //Konveyor Pin
  pinMode(relayPompa, OUTPUT);     //Motor Pin
  pinMode(SensorIR1, INPUT);       //Sensor IR 1
  pinMode(SensorIR2, INPUT);       //Sensor IR 2

  /*--------------------------- Setup LCD I2C ---------------------------*/
  lcd.init();      
  lcd.backlight();  
  /*--------------------------- Akhir LCD I2C ---------------------------*/

  /*--------------------------- Setup Sensor Water Flow ---------------------------*/
  pinMode(flowsensor, INPUT);
  digitalWrite(flowsensor, HIGH);  // Optional Internal Pull-Up

  attachInterrupt(digitalPinToInterrupt(flowsensor), flow, RISING);  // Setup Interrupt

  currentTime = millis();
  cloopTime = currentTime;
  /*--------------------------- Akhir Sensor Water Flow ---------------------------*/

  /*--------------------------- Utama ---------------------------*/
  lcd.setCursor(0, 0);            
  lcd.print("AUTOMATIC BOTTLE");  
  lcd.setCursor(0, 1);
  lcd.print("FILLER MACHINE");
  delay(2000);
  lcd.clear();  // Menghapus seluruh Output pada LCD
  /*--------------------------- Utama ---------------------------*/
}

void loop() {
  viewLCD();
  stopIsi();
  startKonv();
  Baca();
  key = keypad.getKey();
  if (key) {
    pencetan(key);
  }

  if (digitalRead(SensorIR1) == adaBarang) {
    stopKonv();
    while (totalIsi <= userInputInt && digitalRead(SensorIR1) == adaBarang) {
      stopKonv();
      startIsi();
    }
    stopIsi();
    startKonv();
    delay(1000);
  } else if (digitalRead(SensorIR2) == adaBarang) {
    stopKonv();
  } else if (digitalRead(SensorIR2) == adaBarang && digitalRead(SensorIR2) == adaBarang) {
    stopKonv();
  } else {
    startKonv();
    totalIsi = 0;
  }
}

/*--------------------------- Awal Fungsi LCD I2C ---------------------------*/
void viewLCD() {
  //ATAS
  lcd.setCursor(0, 0);    
  lcd.print("MAX ISI:");  
  lcd.setCursor(14, 0);
  lcd.print("mL");

  //BAWAH
  lcd.setCursor(0, 1);
  lcd.print("ISI:");
  lcd.setCursor(14, 1);
  lcd.print("mL");
}

void viewSimpan() {
  lcd.clear();
  lcd.setCursor(4, 0);      
  lcd.print("TERSIMPAN!");  
  lcd.setCursor(7, 1);
  Baca();
  delay(50);
  lcd.print(userInputInt);
  delay(1000);
  lcd.clear();
  delay(10);
}
/*--------------------------- Akhir Fungsi LCD I2C ---------------------------*/

/*--------------------------- Awal Fungsi Keypad 4x4 ---------------------------*/
void pencetan(char Key) {
  Serial.println(Key);
  String s;

  if (Key == 'A') {
    s = "100";
    s.toCharArray(userInput, maksBit);
    lcd.setCursor(9, 0);
    lcd.print("100");
    hitungData = +3;
  } else if (Key == 'B') {
    s = "250";
    s.toCharArray(userInput, maksBit);
    lcd.setCursor(9, 0);
    lcd.print("250");
    hitungData = +3;
  } else if (Key == 'C') {
    s = "500";
    s.toCharArray(userInput, maksBit);
    lcd.setCursor(9, 0);
    lcd.print("500");
    hitungData = +3;
  } else if (Key == 'D') {
    hitungData--;
    userInput[hitungData] = NULL;
    lcd.setCursor(hitungData + 9, 0);
    lcd.print(userInput[hitungData]);
  }
  else if (Key == 'S') {
    Simpan();
    clearData();
  } else if (Key == '*') {
    lcd.clear();
    Baca();
    lcd.setCursor(0, 0);         
    lcd.print("Nilai Sekarang:");  
    lcd.setCursor(7, 1);
    lcd.print(userInputInt);
    delay(1000);
    lcd.clear();
  } else {
    userInput[hitungData] = Key;
    lcd.setCursor(hitungData + 9, 0);
    lcd.print(userInput[hitungData]);
    hitungData++;
    if (hitungData == maksBit + 1) {
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("maks. bit = 4");
      delay(1500);
      clearData();
      lcd.clear();
    }
  }
  Serial.println(userInput);
}

void clearData() {
  while (hitungData >= 0) {
    userInput[hitungData--] = 0;
  }
}
/*--------------------------- Akhir Fungsi Keypad 4x4 ---------------------------*/

/*--------------------------- Awal Fungsi EEPROM ---------------------------*/
void Simpan() {
  String b;

  b = String(userInput[0]) + String(userInput[1]) + String(userInput[2]) + String(userInput[3]);
  int number = b.toInt();

  EEPROM.update(address, number >> 8);
  EEPROM.update(address + 1, number & 0xFF);
  delay(5);  
  viewSimpan();
  b = "";
  number = NULL;
}

int ambilData() {
  return (EEPROM.read(address) << 8) + EEPROM.read(address + 1);
}

void Baca() {
  userInputInt = ambilData();
  Serial.println(userInputInt);
}
/*--------------------------- Akhir Fungsi EEPROM ---------------------------*/

/*--------------------------- Awal Fungsi Sensor Water Flow ---------------------------*/
void totalAir() {
  currentTime = millis();
  // Every second, calculate and print litres/hour
  if (currentTime >= (cloopTime)) {
    cloopTime = currentTime;  // Updates cloopTime
    if (flow_frequency != 0) {
      l_minute = ((flow_frequency * 16.67) / 7.5);  // (Pulse frequency x 60 min) / 7.5Q = flowrate in L/hour. 16.67 is value from converting L/hour to mL/second
      l_minute = l_minute / 60;
      totalIsi += l_minute;
      flow_frequency = 0;  // Reset Counter
      Serial.println(totalIsi, 2);
    }
  }
}
//interrupt function added above void setup
/*--------------------------- Akhir Fungsi Sensor Water Flow ---------------------------*/

/*--------------------------- Awal Fungsi Pompa Air & Solenoid Valve ---------------------------*/
void startIsi() {
  digitalWrite(relayPompa, pompaAktif);
  totalAir();
  lcd.clear();
  lcd.setCursor(9, 1);
  lcd.print(totalIsi);
}

void stopIsi() {
  digitalWrite(relayPompa, !pompaAktif);
  totalIsi = 0;  //reset pembacaan isi botol
}
/*--------------------------- Akhir Fungsi Pompa Air & Solenoid Valve ---------------------------*/

/*--------------------------- Awal Fungsi Konveyor ---------------------------*/
void startKonv() {
  digitalWrite(relayKonveyor, konvAktif);
}

void stopKonv() {
  digitalWrite(relayKonveyor, !konvAktif);
}
/*--------------------------- Akhir Fungsi Konveyor ---------------------------*/

Just curious. How did you get along this far only to now discover problems?

I have seen many projects with wiring issues...

  1. It is more conventional to use INPUT_PULLUP
  pinMode(flowsensor, INPUT);
  digitalWrite(flowsensor, HIGH);  // Optional Internal Pull-Up
  1. This doesn't make sense (the 2 conditions are redundant):
  } else if (digitalRead(SensorIR2) == adaBarang) {
    stopKonv();
  } else if (digitalRead(SensorIR2) == adaBarang && digitalRead(SensorIR2) == adaBarang) {
    stopKonv();
  1. currentTime will always be >= cloopTime but your comment says you want to update every second??? Also, if you are using an UNO or any other 8-bit Arduino you need to disable interrupts when reading or modifying flow_frequency outside of the ISR.
void totalAir() {
  currentTime = millis();
  // Every second, calculate and print litres/hour
  if (currentTime >= (cloopTime)) {
    cloopTime = currentTime;  // Updates cloopTime
    if (flow_frequency != 0) {
      l_minute = ((flow_frequency * 16.67) / 7.5);  // (Pulse frequency x 60 min) / 7.5Q = flowrate in L/hour. 16.67 is value from converting L/hour to mL/second
      l_minute = l_minute / 60;
      totalIsi += l_minute;
      flow_frequency = 0;  // Reset Counter
      Serial.println(totalIsi, 2);
    }
  }
}
  1. The code is hard to follow with respect to the hitungData variable which is used to index into userInput array. You need to ensure that you are not writing past the end of the userInput array otherwise you will get very strange results.

i already tried the coding, one by one. and then i tried to combine them. but, when i combined them, it goes nothing (different with my expectation)

variable hitungData is Indonesian of countData. i think it's already correct because the value can saved by EEPROM and readed correctly too (I used serial.print the saved data in eeprom). but the problem is why after i pressed S button, it not come back to default view in viewLCD (only showed blank view). Besides that, the function 'totalAir' or code to read value from waterflow sensor didn't work.

but thanks for your opinion and advice. it gave me a lot of pointers

userInput is defined as follows.

#define maksBit 4
char userInput[maksBit];

This means that the valid indices for userInput would be 0..3. Additionally, if you are using it as a string then you need to terminate it with a 0 and therefore it can hold 3 ASCII characters plus the 0.

I am concerned about the following else block. You are comparing (hitungData == maksBit + 1). If this is true you have already written past the end of the userInput and have not written a terminating 0. Writing past the end of an array can cause really strange behavior because you have corrupted memory.

  } else {
    userInput[hitungData] = Key;
    lcd.setCursor(hitungData + 9, 0);
    lcd.print(userInput[hitungData]);
    hitungData++;
    if (hitungData == maksBit + 1) {
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("maks. bit = 4");
      delay(1500);
      clearData();
      lcd.clear();
    }
  }
  Serial.println(userInput);

the function of totalAir to read measurment from water flow ssensor won't read the flow

Use the serial.Print() to look at the variables you are using in the "if" statements so you can determine why totalAir is not reading the measurement.

  1. What Arduino are you using?
  2. Did you address the issues I pointed out in posts #3 and #7? Especially #7 because if you have a memory corruption then you will see very strange things.
  3. Are you sure the flow() ISR is executing? Hook a button to the flowsensor pin or use a wire to ground it to generate interrupts and make sure it is working by printing the value of flow_frequency in the loop() function. Disable all other functions and test that pin interrupt.
  4. If you are using an 8-bit Arduino then you will need to disable interrupts while you are reading or modifying the flow_frequency variable.