//#include <LiquidCrystal_I2C.h>
#include <LiquidCrystal.h>
#include <Bounce2.h> //for buttons
// LDR Characteristics
const float GAMMA = 0.7;
const float RL10 = 50;
// motor
const int pinPWMA = 10;
const int pinAIN2 = 11;
const int pinAIN1 = 12;
const int pinSTBY = 1;
const int waitTime = 2000; //espera entre fases
const int speed = 200; //velocidad de giro
const int pinMotorA[3] = { pinPWMA, pinAIN2, pinAIN1 };
//PANTALLA LCD Crear el objeto LCD con los pines correspondientes (rs, en, d4, d5, d6, d7)
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
//buttons config
byte button_pins[] = {2, 3, 12}; // button pins, 2,3 = up/down, 12 = select
#define NUMBUTTONS sizeof(button_pins)
Bounce * buttons = new Bounce[NUMBUTTONS];
//menu config
#define MENU_SIZE 4
char *menu[MENU_SIZE] = { "Abrir", "Cerrar", "Conf", "Salir"};
int cursor = 0;
bool config = false;
int umbralAbrir = 15;
int umbralCerrar = 20;
int temp = 0;
int estado = 0;
int contador = 0;
void setup() {
//para usar la terminal
Serial.begin(9600);
iniciarPantalla();
iniciarMotor();
iniciarBotones();
showConfigMenu("abrir");
showConfigMenu("cerrar");
mostrarModoTrabajo();
}
//********************** main loop **********************
void loop() {
if ((contador == 0) or (contador == 1000)) { //1 minuto aprox
Serial.print("entro");
if (getLux() > umbralAbrir) {
abrirPuerta(pinMotorA,speed);
} else if (getLux() < umbralCerrar) {
cerrarPuerta(pinMotorA,speed);
}
contador = 0;
delay (500);
}
if (mirarSiBotonPulsado()) {
mostrarMenu();
mostrarModoTrabajo();
}
delay (50);
contador++;
}
//functions ******
//LDR
float getLux() {
int analogValue = analogRead(A0);
float voltage = analogValue / 1024. * 5;
float resistance = 2000 * voltage / (1 - voltage / 5);
float lux = pow(RL10 * 1e3 * pow(10, GAMMA) / resistance, (1 / GAMMA));
return lux;
}
//pantalla LCD 1602
void iniciarPantalla() {
// Inicializar el LCD con el número de columnas y filas del LCD
lcd.begin(16, 2);
}
// motor related
void iniciarMotor(){
pinMode(pinAIN2, OUTPUT);
pinMode(pinAIN1, OUTPUT);
pinMode(pinPWMA, OUTPUT);
}
void enableMotors()
{
digitalWrite(pinSTBY, HIGH);
}
void disableMotors()
{
digitalWrite(pinSTBY, LOW);
}
void abrirPuerta(const int pinMotor[3], int speed)
{
digitalWrite(pinMotor[1], HIGH);
digitalWrite(pinMotor[2], LOW);
analogWrite(pinMotor[0], speed);
}
void cerrarPuerta(const int pinMotor[3], int speed)
{
digitalWrite(pinMotor[1], LOW);
digitalWrite(pinMotor[2], HIGH);
analogWrite(pinMotor[0], speed);
}
void stopMotor(const int pinMotor[3])
{
digitalWrite(pinMotor[1], LOW);
digitalWrite(pinMotor[2], LOW);
analogWrite(pinMotor[0], 0);
}
//botones
void iniciarBotones() {
//buttons init
// Make input & enable pull-up resistors on switch pins
for (int i = 0; i < NUMBUTTONS; i++) {
buttons[i].attach( button_pins[i], INPUT_PULLUP); // setup the bounce instance for the current button
buttons[i].interval(25); // interval in ms
}
}
void procesarDesplazamientoMenu() {
// process button press:
while(true){
for (int i = 0; i < NUMBUTTONS; i++) {
Serial.print(cursor);
buttons[i].update(); // Update the Bounce instance
if ( buttons[i].fell() ) { // If it fell
if (i == 2) { // select
lcd.clear();
lcd.setCursor(0, 0);
//lcd.print(">>");
//lcd.print(menu[cursor]);
if (cursor == 3){return;}
executeChoice(cursor);
}
else {
// erase previous cursor:
if (cursor > 1 ) { //estabamos en el menu derecho
lcd.setCursor(8, cursor - 2);
lcd.print(' ');
} else {
lcd.setCursor(0, cursor);
lcd.print('>');
}
lcd.setCursor(0, cursor);
lcd.print(' ');
if (i == 0) { // up
cursor++;
if (cursor > (MENU_SIZE - 1)) cursor = 0;
}
else { // down
cursor--;
if (cursor < 0) cursor = (MENU_SIZE - 1);
}
// show cursor at new line:
if (cursor > 1) { //show cursor for right column
lcd.setCursor(8, cursor - 2);
lcd.print('>');
} else {
lcd.setCursor(0, cursor);
lcd.print('>');
}
}
} // end if button fell...
}
} // end for-loop of button check
}
void mostrarMenu() {
cursor = 0;
lcd.clear();
// show menu items:
for (int i = 0; i < MENU_SIZE; i++) {
if (i < 2) { //limite a dos lineas de pantalla
lcd.setCursor(2, i);
lcd.print(menu[i]);
} else {
lcd.setCursor(9, i - 2);
lcd.print(menu[i]);
}
}
lcd.setCursor(0, 0);
lcd.print('>');
procesarDesplazamientoMenu();
}
void mostrarModoTrabajo() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Modo automatico");
lcd.setCursor(0, 1);
lcd.print("Pulsa para manual");
}
/**
muestra el menu para configurar el umbral
arg: tipo:String. Values: "abrir"/"cerrar"
*/
void showConfigMenu(String tipo) {
lcd.clear();
lcd.print("Conf. umbral ");
lcd.print(tipo);
lcd.setCursor(0, 2);
if (tipo == "abrir") {
lcd.print(umbralAbrir);
umbralAbrir = procesarBotonesConfig(umbralAbrir);
} else if (tipo == "cerrar") {
lcd.print(umbralCerrar);
umbralCerrar = procesarBotonesConfig(umbralCerrar);
}
}
/**
Execute the task which matches the chosen menu item.
*/
void executeChoice(int choice) {
switch (choice) {
case 0 : //
abrirPuerta(pinMotorA, speed); mostrarMenu();
break;
case 1 :
cerrarPuerta(pinMotorA, speed); mostrarMenu();
break;
case 2 :
showConfigMenu("abrir");/*config*/;showConfigMenu("cerrar");mostrarMenu();
break;
case 3 :
break;break;
default :
Serial.print("Execute choice "); Serial.print(choice); Serial.print(" - "); Serial.println(menu[choice]);
break;
}
}
int mirarSiBotonPulsado() {
for (int i = 0; i < NUMBUTTONS; i++) {
buttons[i].update(); // Update the Bounce instance
if ( buttons[i].fell() ) {
return 1;
}
} return 0;
}
int procesarBotonesConfig(int valor) {
int valortemp = valor;
while (true) { //mientras no confirme
for (int i = 0; i < NUMBUTTONS; i++) {
buttons[i].update(); // Update the Bounce instance
if ( buttons[i].fell() ) { // If it fell
if (i == 2) {
valor = valortemp;
config = false;
return valortemp;
}
if ( i == 0) {
valortemp--;
if (valortemp < 0) {
valortemp = 0;
lcd.setCursor(0, 2);
lcd.print(" ");
}
}
if (i == 1) {
valortemp++;
lcd.setCursor(0, 2);
lcd.print(" ");
}
}
lcd.setCursor(0, 2);
lcd.print(valortemp);
}
}
}