Actividad avanzada. Display: Íconos y animaciones

TEMÁTICAS DE NUESTROS CURSOS


Programación

 

Explicación actividad a programar

Esta ultima actividad nos servirá para ilustrar la programación que se puede realizar con la pantalla LCD. No añadiremos ninguna funcionalidad nueva, y tampoco requeriremos de un montaje electrónico adicional. Tan solo nos centraremos en mejorar la interfaz de la pantalla, añadiendo iconos personalizados. 

La pantalla LCD 1602 permite la creación de hasta 8 caracteres personalizados. Puedes definir estos caracteres utilizando matrices de 5x8 píxeles. En este código, se definen cuatro caracteres personalizados: un icono de candado cerrado, un icono de candado abierto, un icono de "enter" y un icono de borrar.

#include <Servo.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);

// Pines
const int potPin = A0;
const int enterButtonPin = 2;
const int clearButtonPin = 3;
const int ledRedPin = 9;
const int ledGreenPin = 10;
const int ledBluePin = 11;
const int servoPin = 6;
const int buzzerPin = 7;

Servo myServo;

// Variables de estado
bool isBoxOpen = false;
int enteredDigit = 0;
int enteredCode[4];
int currentDigitIndex = 0;
const int defaultCode[4] = {6, 6, 6, 6};
int correctCode[4];
int attemptsLeft = 10;
int incorrectAttempts = 0;
bool waitingForCodeChange = false;
bool enterButtonReleased = false;

// Definición de caracteres personalizados
byte lockIcon[8] = {
    0b01110,
    0b10001,
    0b10001,
    0b11111,
    0b11011,
    0b11011,
    0b11111,
    0b00000
};

byte unlockIcon[8] = {
    0b01110,
    0b10001,
    0b10001,
    0b00111,
    0b00111,
    0b10111,
    0b11111,
    0b00000
};

byte enterIcon[8] = {
    0b00100,
    0b01110,
    0b11111,
    0b11111,
    0b01110,
    0b00100,
    0b00000,
    0b00000
};

byte clearIcon[8] = {
    0b11111,
    0b10001,
    0b10101,
    0b10001,
    0b10101,
    0b10001,
    0b11111,
    0b00000
};

void setup() {
  Serial.begin(9600);
  lcd.init();
  lcd.backlight();
  lcd.clear();

  // Crear caracteres personalizados
  lcd.createChar(0, lockIcon);
  lcd.createChar(1, unlockIcon);
  lcd.createChar(2, enterIcon);
  lcd.createChar(3, clearIcon);

  pinMode(potPin, INPUT);
  pinMode(enterButtonPin, INPUT_PULLUP);
  pinMode(clearButtonPin, INPUT_PULLUP);
  pinMode(ledRedPin, OUTPUT);
  pinMode(ledGreenPin, OUTPUT);
  pinMode(ledBluePin, OUTPUT);
  myServo.attach(servoPin);

  digitalWrite(ledRedPin, HIGH);
  digitalWrite(ledGreenPin, LOW);
  digitalWrite(ledBluePin, LOW);
  myServo.write(0);

  lcd.setCursor(0, 0);
  lcd.print("Dial:");
  lcd.setCursor(0, 1);
  lcd.print("Code:");

  readCodeFromEEPROM();

  // Si EEPROM estaba vacía, usar código por defecto
  for (int i = 0; i < 4; i++) {
    if (correctCode[i] < 0 || correctCode[i] > 9) {
      correctCode[i] = defaultCode[i];
    }
  }
}

void loop() {

   /* SI QUEREMOS VERIFICAR EL CÓDIGO CARGADO EN LA EEPROM
    Serial.print("Código cargado: ");
for (int i = 0; i < 4; i++) {
    Serial.print(correctCode[i]);
    Serial.print(" ");
}
Serial.println();
*/
  if (!isBoxOpen){
    lcd.setCursor(12, 0);
    lcd.write(0); // lock icon
    delay(300);
  }
  else{
    lcd.setCursor(13, 0);
    lcd.write(1); // unlock icon
    delay(300);
  }

  int potValue = analogRead(potPin);
  enteredDigit = map(potValue, 0, 1023, 0, 9);

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Dial:");
  lcd.setCursor(5, 0);
  lcd.print(enteredDigit);
  lcd.setCursor(0, 1);
  lcd.print("Code:");
  updateLCD();

  bool enterButtonState = digitalRead(enterButtonPin) == LOW;
  bool clearButtonState = digitalRead(clearButtonPin) == LOW;

  if (clearButtonState && !waitingForCodeChange) {
    lcd.setCursor(14, 0);
    lcd.write(3); // Clear icon
    resetCode();
    updateLCD();
    delay(1000);
  }

  if (enterButtonState && currentDigitIndex < 4 && !waitingForCodeChange) {
    enteredCode[currentDigitIndex] = enteredDigit;
    currentDigitIndex++;
    lcd.setCursor(15, 0);
    lcd.write(2); // Enter icon
    updateLCD();
    delay(300);
  }

  if (currentDigitIndex == 4 && !waitingForCodeChange) {
    if (checkCode()) {
      openBox();
      resetAttempts();
      waitingForCodeChange = true;
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Change Code?");
      lcd.setCursor(0, 1);
      lcd.print("Enter=Yes Clr=No");
    } else {
      incorrectAttempts++;
      attemptsLeft--;
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Cod. incorrecto");
      delay(1000);
      lcd.setCursor(0, 1);
      lcd.print("Intentos: ");
      lcd.print(attemptsLeft);
      delay(1000);
      resetCode();
      updateLCD();
      if (incorrectAttempts >= 10) {
        activateAlarm();
      }
    }
  }

  if (enterButtonState && clearButtonState && !waitingForCodeChange) {
    closeBox();
    delay(300);
  }

  if (waitingForCodeChange) {
    if (!enterButtonState) {
      enterButtonReleased = true; //compruebo si el usuario quiere cambiar la contraseña
    }

    if (enterButtonState && enterButtonReleased) {
      enterButtonReleased = false;
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("New Code:");
      resetCode();
      updateLCD();
      delay(300);

      while (currentDigitIndex < 4) {
        potValue = analogRead(potPin);
        enteredDigit = map(potValue, 0, 1023, 0, 9);
        lcd.setCursor(10, 0);
        lcd.print(enteredDigit);

        if (digitalRead(enterButtonPin) == LOW) {
          enteredCode[currentDigitIndex] = enteredDigit;
          currentDigitIndex++;
          updateLCD();
          delay(300);
        }
      }

      for (int i = 0; i < 4; i++) {
        EEPROM.write(i, enteredCode[i]);
        correctCode[i] = enteredCode[i];
      }

      lcd.clear();
      lcd.setCursor(0, 1);
      lcd.print("Code Updated");
      delay(1000);
      waitingForCodeChange = false;
      resetCode();
    }

    if (clearButtonState) {
      waitingForCodeChange = false;
      resetCode();
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Dial:");
      lcd.setCursor(0, 1);
      lcd.print("Code:");
    }
  }

  delay(200);
}

void resetCode() {
  currentDigitIndex = 0;
  for (int i = 0; i < 4; i++) {
    enteredCode[i] = 0;
  }
}

void updateLCD() {
  lcd.setCursor(5, 1);
  for (int i = 0; i < 4; i++) {
    if (i < currentDigitIndex) {
      lcd.print(enteredCode[i]);
    } else {
      lcd.print("_");
    }
  }
}

bool checkCode() {
  for (int i = 0; i < 4; i++) {
    if (enteredCode[i] != correctCode[i]) {
      return false;
    }
  }
  return true;
}

void openBox() {
  isBoxOpen = true;
  digitalWrite(ledRedPin, LOW);
  digitalWrite(ledGreenPin, HIGH);
  digitalWrite(ledBluePin, LOW);
  myServo.write(90);
}

void closeBox() {
  isBoxOpen = false;
  digitalWrite(ledRedPin, HIGH);
  digitalWrite(ledGreenPin, LOW);
  digitalWrite(ledBluePin, LOW);
  myServo.write(0);
}

void activateAlarm() {
  for (int i = 0; i < 10; i++) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("ALARMA ACTIVA");
    tone(buzzerPin, 1000);
    delay(500);
    noTone(buzzerPin);
    delay(500);
  }
  incorrectAttempts = 0;
  attemptsLeft = 10;
}

void resetAttempts() {
  incorrectAttempts = 0;
  attemptsLeft = 10;
}

void readCodeFromEEPROM() {
  for (int i = 0; i < 4; i++) {
    correctCode[i] = EEPROM.read(i);
  }
}

90% Completado
Vistas
3 Número de vistas
3 Vistas de miembros
0 Vistas públicas
Acciones
0 Gustos
0 No me gusta
0 Comentarios
Compartir en redes sociales
Compartir enlace
Compartir por correo

Por favor iniciar sesión para compartir esto webpage por correo.