user31541: I manage to control a brushless motor using a 4x3 keypad. I am able to key in the speed (using a servo value of 0-180) and the time for the motor to run. Besides that, while the motor spins according to the speed and time entered, I am using an Infrared Obstacle Avoidance Sensor module to calculate the RPM. However, I cannot seem to be getting the RPM to display on the LCD screen. I copy-pasted the Infrared Obstacle Avoidance Sensor module code from https://www.instructables.com/id/Simple-Motor-Speed-Tester-Tachometer/. 
I have tried the code from the link on my sensor and it works very well. However, when I incorporate the IR coding from the link with my speed and time control coding, the code from the link does not seem to work.
So, why does the code from the link cannot function when I combine it with my code? How do I resolve this problem?
Below is the code, I am hoping for any guidance and advice from the experts. Thanks in advance. Any suggestion or changes are welcome.
#include <Keypad.h>
#include <Wire.h>  // Comes with Arduino IDE
#include <LiquidCrystal_I2C.h>
#include <Servo.h>
Servo myservo;
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
// Set the LCD I2C address

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns
char keys[ROWS][COLS] =
{
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};

byte rowPins[ROWS] = {9,8,7,6}; //row pinouts of the keypad (L1, L2, L3, L4)
byte colPins[COLS] = {5,4,3}; //column pinouts of the keypad (R1, R2, R3)
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
const int dataIN = 2; //IR sensor INPUT
unsigned long prevmillis; // To store time
unsigned long duration; // To store time difference
int rpm; // RPM value
boolean currentstate; // Current state of IR input scan
boolean prevstate; // State of IR sensor in previous scan

void setup() {
  pinMode(dataIN,INPUT);
  Serial.begin(9600);
  lcd.begin(20,4);
  myservo.attach(11);
  prevmillis = 0;
  prevstate = LOW;
  lcd.setCursor(4,1);
  lcd.print("SPIN COATER");
  lcd.setCursor(6,2);
  lcd.print("MACHINE");
  delay(5000);
  lcd.clear();
  lcd.setCursor(3,1);
  lcd.print("S = speed(sv)");
  lcd.setCursor(3,2);
  lcd.print("T = time(sec)");
  delay(5000);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Servo value (sv):");
  lcd.setCursor (3,2);
  lcd.print("Between 103-180");
  delay (10000); 
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("S=");
  lcd.setCursor(0,1);
  lcd.print("T=");
  lcd.setCursor(0,2);
  lcd.print("S=");
  lcd.setCursor(0,3);
  lcd.print("T=");
  lcd.setCursor(10,0);
  lcd.print("S=");
  lcd.setCursor(10,1);
  lcd.print("T=");
  lcd.setCursor(10,2);
  lcd.print("RPM");
}

void loop() {
  // RPM Measurement
  currentstate = digitalRead(dataIN); // Read IR sensor state
  if(prevstate != currentstate) {
    // If there is change in input
    if(currentstate == HIGH) {
      // If input only changes from LOW to HIGH
      duration = ( micros() - prevmillis );
      // Time difference between revolution in microsecond
      rpm = (60000000/duration);
      // rpm = (1/ time millis)*1000*1000*60;
      prevmillis = micros();
      // store time for nect revolution calculation
    }
  }
  prevstate = currentstate;
  // store this scan (prev scan) data for next scan
  lcd.setCursor(10,3);
  lcd.print(rpm);
  int stage1speed = getTheNumber();
  lcd.setCursor(2,0);
  lcd.print(stage1speed);
  lcd.print("sv");
  int stage1time = getTheNumber();
  lcd.setCursor(2,1);
  lcd.print(stage1time);
  lcd.print("sec");
  int stage2speed = getTheNumber();
  lcd.setCursor(2,2);
  lcd.print(stage2speed);
  lcd.print("sv");
  int stage2time = getTheNumber();
  lcd.setCursor(2,3);
  lcd.print(stage2time);
  lcd.print("sec");
  int stage3speed = getTheNumber();
  lcd.setCursor(12,0);
  lcd.print(stage3speed);
  lcd.print("sv");
  int stage3time = getTheNumber();
  lcd.setCursor(12,1);
  lcd.print(stage3time);
  lcd.print("sec");
  if (stage1speed > 0 && stage1time > 0 && stage2speed > 0 && stage2time > 0 && stage2speed > 0 && stage2time > 0) {
    myservo.write(stage1speed);
    delay(stage1time*1000);
    myservo.write(stage2speed);
    delay(stage2time*1000);
    myservo.write(stage3speed);
    delay(stage3time*1000);
    myservo.write(0);
    stage1speed = 0;
    stage1time = 0;
    stage2speed = 0;
    stage2time =0;
    stage3speed = 0;
    stage3time =0;
  }
}

int getTheNumber() {
  char buffer[4];
  // Input up to 3 numbers until we find a * or #
  int i=0;
  while (1) {
    char key = keypad.getKey();
    // If it's a number AND we have space left, add to our string
    if ('0' <= key && key <= '9' && i < 3) {
      buffer[i] = key;
      i++;
    } else if ('#' == key && i > 0) {
      // If it's a * or #, end
      // Null terminate
      buffer[i] = 0;
      int value = atoi(buffer); // Convert to an integer
      break;
    }
  }
  return atoi(buffer);
}


user20158: What LCD library are you using? Based on what is online, the LiquidCrystal_I2C.h instantiates with 3 arguments (+ 1 optional):

LiquidCrystal_I2C(uint8_t lcd_addr, uint8_t lcd_cols, uint8_t
  lcd_rows, uint8_t charsize = LCD_5x8DOTS);

So an example of creating an object of it would look like this:

LiquidCrystal_I2C(0x3F,16,2);

Whereas for LiquidCrystal.h, it instantiates with either 6, 7, 11 or 10 arguments:

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);


31541: <p>I manage to control a brushless motor using a 4x3 keypad. I am able to key in the speed (using a servo value of 0-180) and the time for the motor to run. Besides that, while the motor spins according to the speed and time entered, I am using an Infrared Obstacle Avoidance Sensor module to calculate the RPM. However, I cannot seem to be getting the RPM to display on the LCD screen. I copy-pasted the Infrared Obstacle Avoidance Sensor module code from <a href="https://www.instructables.com/id/Simple-Motor-Speed-Tester-Tachometer/" rel="nofollow noreferrer">https://www.instructables.com/id/Simple-Motor-Speed-Tester-Tachometer/</a>. </p>

<p>I have tried the code from the link on my sensor and it works very well. However, when I incorporate the IR coding from the link with my speed and time control coding, the code from the link does not seem to work.</p>

<p>So, why does the code from the link cannot function when I combine it with my code? How do I resolve this problem?</p>

<p>Below is the code, I am hoping for any guidance and advice from the experts. Thanks in advance. Any suggestion or changes are welcome.</p>

<pre><code>#include &lt;Keypad.h&gt;
#include &lt;Wire.h&gt;  // Comes with Arduino IDE
#include &lt;LiquidCrystal_I2C.h&gt;
#include &lt;Servo.h&gt;
Servo myservo;
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
// Set the LCD I2C address

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns
char keys[ROWS][COLS] =
{
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};

byte rowPins[ROWS] = {9,8,7,6}; //row pinouts of the keypad (L1, L2, L3, L4)
byte colPins[COLS] = {5,4,3}; //column pinouts of the keypad (R1, R2, R3)
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
const int dataIN = 2; //IR sensor INPUT
unsigned long prevmillis; // To store time
unsigned long duration; // To store time difference
int rpm; // RPM value
boolean currentstate; // Current state of IR input scan
boolean prevstate; // State of IR sensor in previous scan

void setup() {
  pinMode(dataIN,INPUT);
  Serial.begin(9600);
  lcd.begin(20,4);
  myservo.attach(11);
  prevmillis = 0;
  prevstate = LOW;
  lcd.setCursor(4,1);
  lcd.print("SPIN COATER");
  lcd.setCursor(6,2);
  lcd.print("MACHINE");
  delay(5000);
  lcd.clear();
  lcd.setCursor(3,1);
  lcd.print("S = speed(sv)");
  lcd.setCursor(3,2);
  lcd.print("T = time(sec)");
  delay(5000);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Servo value (sv):");
  lcd.setCursor (3,2);
  lcd.print("Between 103-180");
  delay (10000); 
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("S=");
  lcd.setCursor(0,1);
  lcd.print("T=");
  lcd.setCursor(0,2);
  lcd.print("S=");
  lcd.setCursor(0,3);
  lcd.print("T=");
  lcd.setCursor(10,0);
  lcd.print("S=");
  lcd.setCursor(10,1);
  lcd.print("T=");
  lcd.setCursor(10,2);
  lcd.print("RPM");
}

void loop() {
  // RPM Measurement
  currentstate = digitalRead(dataIN); // Read IR sensor state
  if(prevstate != currentstate) {
    // If there is change in input
    if(currentstate == HIGH) {
      // If input only changes from LOW to HIGH
      duration = ( micros() - prevmillis );
      // Time difference between revolution in microsecond
      rpm = (60000000/duration);
      // rpm = (1/ time millis)*1000*1000*60;
      prevmillis = micros();
      // store time for nect revolution calculation
    }
  }
  prevstate = currentstate;
  // store this scan (prev scan) data for next scan
  lcd.setCursor(10,3);
  lcd.print(rpm);
  int stage1speed = getTheNumber();
  lcd.setCursor(2,0);
  lcd.print(stage1speed);
  lcd.print("sv");
  int stage1time = getTheNumber();
  lcd.setCursor(2,1);
  lcd.print(stage1time);
  lcd.print("sec");
  int stage2speed = getTheNumber();
  lcd.setCursor(2,2);
  lcd.print(stage2speed);
  lcd.print("sv");
  int stage2time = getTheNumber();
  lcd.setCursor(2,3);
  lcd.print(stage2time);
  lcd.print("sec");
  int stage3speed = getTheNumber();
  lcd.setCursor(12,0);
  lcd.print(stage3speed);
  lcd.print("sv");
  int stage3time = getTheNumber();
  lcd.setCursor(12,1);
  lcd.print(stage3time);
  lcd.print("sec");
  if (stage1speed &gt; 0 &amp;&amp; stage1time &gt; 0 &amp;&amp; stage2speed &gt; 0 &amp;&amp; stage2time &gt; 0 &amp;&amp; stage2speed &gt; 0 &amp;&amp; stage2time &gt; 0) {
    myservo.write(stage1speed);
    delay(stage1time*1000);
    myservo.write(stage2speed);
    delay(stage2time*1000);
    myservo.write(stage3speed);
    delay(stage3time*1000);
    myservo.write(0);
    stage1speed = 0;
    stage1time = 0;
    stage2speed = 0;
    stage2time =0;
    stage3speed = 0;
    stage3time =0;
  }
}

int getTheNumber() {
  char buffer[4];
  // Input up to 3 numbers until we find a * or #
  int i=0;
  while (1) {
    char key = keypad.getKey();
    // If it's a number AND we have space left, add to our string
    if ('0' &lt;= key &amp;&amp; key &lt;= '9' &amp;&amp; i &lt; 3) {
      buffer[i] = key;
      i++;
    } else if ('#' == key &amp;&amp; i &gt; 0) {
      // If it's a * or #, end
      // Null terminate
      buffer[i] = 0;
      int value = atoi(buffer); // Convert to an integer
      break;
    }
  }
  return atoi(buffer);
}
</code></pre>
 20158: <p>What LCD library are you using? Based on what is online, the <em>LiquidCrystal_I2C.h</em> instantiates with 3 arguments (+ 1 optional):</p>

<blockquote>
  <p>LiquidCrystal_I2C(uint8_t lcd_addr, uint8_t lcd_cols, uint8_t
  lcd_rows, uint8_t charsize = LCD_5x8DOTS);</p>
</blockquote>

<p>So an example of creating an object of it would look like this:</p>

<blockquote>
  <p>LiquidCrystal_I2C(0x3F,16,2);</p>
</blockquote>

<p>Whereas for <em>LiquidCrystal.h</em>, it instantiates with either 6, 7, 11 or 10 arguments:</p>

<blockquote>
  <p>LiquidCrystal lcd(12, 11, 5, 4, 3, 2);</p>
</blockquote>
