Hello everyone,
I am new to this forum and have a few question hoping that you guys can help. My project consists of Arduino, keypad, LCD screen, PWM output, and a rotary encoder. I got everything working, and I have merged all the code together except the rotary encoder that does not work properly which I suspect that "waitforkey" function hold up the whole process, and it results in the encoder only run once after I input the value. I want it to run in parallel to the main code. Therefore, I am trying to find a way to override "waitforkey" function. Any help would be appreciated. Thank you in advance.
Main code:
#include <Keypad.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
char key;
char PWM_value_array[4] = {' ',' ',' ',' '};
int val;
const byte ROWS = 4; // Four rows
const byte COLS = 3; // Three columns
// Define the Keymap
char keys[ROWS][COLS] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}
};
// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte rowPins[ROWS] = { 13, 12, 11, 10 };
// Connect keypad COL0, COL1 and COL2 to these Arduino pins.
byte colPins[COLS] = { 9, 8, 7 };
// Create the Keypad
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
void setup() {
// set up
pinMode(5,OUTPUT);
Serial.begin(9600);
lcd.begin(16,2); // iInit the LCD for 16 chars 2 lines
lcd.print("KEYPAD LCD PWM");
}
void loop()
{
BEGINNING: //Label for beginning
key = kpd.waitForKey();
if (key == '#' || key == '*'){
//If key entered is # or *, go back to beginning
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("KEYPAD LCD PWM");
lcd.setCursor(0, 1);
lcd.print("KEY= ");
goto BEGINNING;
}
lcd.setCursor(0, 1);
lcd.print("KEY= "+String(key)+"_");
PWM_value_array[0] = key;
delay(250);
//Waiting for SECOND number
key = kpd.waitForKey();
if ( key != '*' && key != '#'){
PWM_value_array[1] = key;
lcd.setCursor(0, 1);
lcd.print("KEY= "+String(PWM_value_array[0])+String(PWM_value_array[1])+"_");
}
Serial.println(key);
if (key == '*'){
//If key entered *, go back to beginning
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("KEYPAD LCD PWM");
lcd.setCursor(0, 1);
lcd.print("KEY= ");
goto BEGINNING;
}
if(key == '#'){
//We're done
val = String(PWM_value_array[0]).toInt();
goto ENDING;
}
delay(250);
//Waiting on 3rd number
key = kpd.waitForKey();
if ( key != '*' && key != '#'){
PWM_value_array[2] = key;
lcd.setCursor(0, 1);
lcd.print("KEY= "+String(PWM_value_array[0])+String(PWM_value_array[1])+String(PWM_value_array[2])+"_");
}
if (key == '*'){
//If key entered *, go back to beginning
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("KEYPAD LCD PWM");
lcd.setCursor(0, 1);
lcd.print("KEY= ");
goto BEGINNING;
}
if(key == '#'){
//We're done
val = String(String(PWM_value_array[0])+String(PWM_value_array[1])).toInt();
goto ENDING;
}
delay(250);
//Waiting on 4th character
key = kpd.waitForKey();
if ( key != '*' && key != '#'){
lcd.setCursor(0, 1);
lcd.print("NUMBER TOO LARGE");
delay(1000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("KEYPAD LCD PWM");
lcd.setCursor(0, 1);
lcd.print("KEY= ");
goto BEGINNING;
}
if (key == '*'){
//If key entered *, go back to beginning
lcd.setCursor(0, 1);
lcd.print("KEY= ");
goto BEGINNING;
}
if(key == '#'){
//We're done
val = String(String(PWM_value_array[0])+String(PWM_value_array[1])+String(PWM_value_array[2])).toInt();
}
ENDING:
if(val > 255){
val = 255;
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("KEYPAD LCD PWM");
lcd.setCursor(0, 1);
lcd.print("KEY= ");
Serial.println(val);
analogWrite(5,val);
}
Encoder Code:
#define encoder0PinA 2
#define encoder0PinB 4
volatile long encoder0Pos=0;
long newposition;
long oldposition = 0;
unsigned long newtime;
unsigned long oldtime = 0;
long vel;
void setup()
{
pinMode(encoder0PinA, INPUT);
digitalWrite(encoder0PinA, HIGH); // turn on pullup resistor
pinMode(encoder0PinB, INPUT);
digitalWrite(encoder0PinB, HIGH); // turn on pullup resistor
attachInterrupt(0, doEncoder, RISING); // encoDER ON PIN 2
Serial.begin (9600);
Serial.println("start"); // a personal quirk
}
void loop()
{
newposition = encoder0Pos;
newtime = millis();
vel = (newposition-oldposition)/600;
Serial.print ("speed = ");
Serial.println (vel);
oldposition = newposition;
oldtime = newtime;
delay(1000);
}
void doEncoder()
{
if (digitalRead(encoder0PinA) == digitalRead(encoder0PinB)) {
encoder0Pos++;
} else {
encoder0Pos--;
}
}
PS. In my encoder code, I am not using time in calculation for the angular velocity but instead I used delay(1000). I believe there is a better way to do it. If you have any suggestion, please let me know. Thank you again.