1

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);
}
  • Why you are using 'LiquidCrystal_12C.h library for display ? – Prayuktibid Apr 6 '17 at 17:11
  • What LCD are you using? – Gerben Apr 6 '17 at 18:08
  • Because my lcd have I2C shield. I'm using 20x4 LCD display with I2C shield. – rjadkins Apr 7 '17 at 5:51
  • Might need to consider the int range in this statement; "rpm = (60000000/duration);" – Mikael Patel Apr 7 '17 at 12:16
  • what is suitable for the rpm formula?? – rjadkins Apr 7 '17 at 12:51
1

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);

  • I truly believe my lcd is not the problem. I am using a 20x4 LCD display with I2C shield. I have tried running the code from the website instructables.com/id/Simple-Motor-Speed-Tester-Tachometer . The changes I have made on the code from the website was changing the LCD command and use the command for LCD 20x4 I2C. When I tested it, the rpm sensor works and the rpm displayed on the lcd. However, combing it with my own coding of speed and time control, the sensor does not work and no rpm display on lcd – rjadkins Apr 7 '17 at 5:50
  • Did your check whether the if statement was executed? Coz if it does not, there would never be a delay in your main loop, and you would not be able to see anything in your LCD Display – Photon Apr 7 '17 at 6:09
  • Other than that, did you check whether the getTheNumber() function is working properly, outputting the correct values? – Photon Apr 7 '17 at 6:11
  • Before I add the rpm measurements code, the speed and time control coding work perfectly fine, just how I wanted it to be. Now with the addition of rpm measurement code. The rpm of the spinning motor is not show on the LCD. Is this have something with delay()?? Does the delay() causing the reading of rpm not shown of the LCD?? Is there any other way for me to change my coding so that the speed, timing and rpm measurement work as a single functional unit? – rjadkins Apr 7 '17 at 11:55
  • Maybe you can try out something like multi-threading of the display (or Protothread for Arduino's case)? There are quite a few examples on it online. – Photon May 17 '17 at 13:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.