#include <Keypad.h>
#include <LiquidCrystal_I2C.h>
#include <Stepper.h>
/*
Initialize stepper and set pins
*/
#define STEPS 800.0
Stepper stepper(STEPS, 11, 10);
/*
Initialize LCD and set pins
*/
LiquidCrystal_I2C lcd(0x27, 16, 2);
/*
Initialize keypad, set pins and keys
*/
const int ROW_NUM = 4;
const int COLUMN_NUM = 4;
char keys[ROW_NUM][COLUMN_NUM] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte pin_rows[ROW_NUM] = {22, 24, 26, 28};
byte pin_column[COLUMN_NUM] = {36, 38, 40, 42};
Keypad keypad = Keypad(makeKeymap(keys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM );
/*
Config relays
*/
#define RELAYS 4
struct Relay {
int pin;
bool status;
};
Relay relays[RELAYS] = {{44, false}, {44, false}, {44, false}, {44, false}}
void init_relays() {
for (int i = 0; i < RELAYS; i++) {
toggle_relay(i);
pinMode(relays[i].pin, OUTPUT);
digitalWrite(relays[i].pin, LOW);
}
}
void toggle_relay(int relay_number) {
int index = relay_number - 1 ;
if (relays[index] != nullptr) {
relays[index].status = !relays[index].status;
digitalWrite(relays[index].pin, relays[index].status ? HIGH : LOW);
}
}
void set_relay(int relay_number, bool status) {
int index = relay_number - 1 ;
if (relays[index] != nullptr) {
relays[index].status = status;
}
}
void toggle_relays() {
for (int i = 0; i < RELAYS; i++) {
toggle_relay(i);
}
}
void set_relays(bool status) {
for (int i = 0; i < RELAYS; i++) {
set_relay(i, status);
}
}
/*
Functions prototype
*/
int int_prompt(String text, int default_value, char break_key);
int key_to_int(char key);
bool key_is_number(char key);
/*
Initial program
*/
void setup() {
lcd.init();
lcd.backlight();
Serial.begin(9600);
Serial.println();
init_relays();
}
/*
Run program
*/
int speed = 0;
int degree = 0;
int dir = 0;
void loop() {
if (speed && degree) {
Serial.println("config stepper");
stepper.setSpeed(speed);
lcd.clear();
char key;
int step_count = STEPS * 1000 * degree / 360000;
Serial.print("step count: ");
Serial.println(step_count);
Serial.println("start stepper");
set_relays(true);
while ((key = keypad.getKey()) != '*' && step_count > 0) {
stepper.step(dir ? 1 : -1);
step_count--;
int int_key = key_to_int(key);
if (key_is_number(key) && int_key >= 1 && int_key <= RELAYS) {
toggle_relay(int_key);
}
}
set_relays(false);
}
Serial.println("get inputs");
speed = int_prompt("enter speed", speed, 'C');
Serial.print("speed: ");
Serial.println(speed);
dir = int_prompt("enter direction", dir, 'C');
Serial.print("direction: ");
Serial.println(dir);
degree = int_prompt("enter degree", degree, '#');
Serial.print("degree: ");
Serial.println(degree);
}
/*
Print a question on LCD and get input from keypad
and return result as number.
*/
int int_prompt(String text, int default_value, char break_key = 'c') {
Serial.print("get input (");
Serial.print(text);
Serial.print("): ");
text.concat(": ");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(text.c_str());
String input;
// if (default_value) {
// input.concat(default_value);
// }
char key;
while ((key = keypad.getKey()) != break_key) {
if (key) {
Serial.print(key);
}
if (key_is_number(key)) {
input.concat(key);
lcd.setCursor(0, 1);
lcd.print(input.c_str());
} else if (key == 'B') {
input.remove(input.length() - 1);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(text.c_str());
lcd.setCursor(0, 1);
lcd.print(input.c_str());
}
}
Serial.println();
return input.toInt();
}
int key_to_int(char key) {
return key - 48;
}
/*
Check pressed key of keypad is number or not.
*/
bool key_is_number(char key) {
int number = key_to_int(key);
bool is_number = number >= 0 && number <= 9;
return is_number;
}