#include <LiquidCrystal_I2C.h>
#define ledRed 4
#define ledYellow 3
#define ledGreen 2
const int col = 20;
const int row = 4;
LiquidCrystal_I2C lcd(0x27, col, row);
// Arrays for creating segments and customizing chars
byte segment[8][8] = {
{ B00011, B00111, B01111, B11111, B11111, B11111, B11111, B11111 }, // For Obsute Angel Top Left Char
{ B11000, B11100, B11110, B11111, B11111, B11111, B11111, B11111 }, // For Obsute Angel Top Right Char
{ B11111, B11111, B11111, B11111, B11111, B01111, B00111, B00011 }, // For Obsute Angel Bottom Left Char
{ B11111, B11111, B11111, B11111, B11111, B11110, B11100, B11000 }, // For Obsute Angel Bottom Right Char
{ B11111, B11110, B11100, B11000, B10000, B00000, B00000, B00000 }, // For Angel Top Left Char
{ B11111, B01111, B00111, B00011, B00001, B00000, B00000, B00000 }, // For Angel Top Right Char
{ B00000, B00000, B00000, B10000, B11000, B11100, B11110, B11111 }, // For Angel Bottom Left Char
{ B00000, B00000, B00000, B00001, B00011, B00111, B01111, B11111 } // For Angel Bottom Right Char
};
void setup() {
// LED Pin
pinMode(ledRed, OUTPUT);
pinMode(ledYellow, OUTPUT);
pinMode(ledGreen, OUTPUT);
// LCD 16x2 I2C Init
lcd.init();
lcd.backlight();
lcd.clear();
// Associates each created segment with a char
for (byte i = 0; i < 8; i++) {
lcd.createChar(i, segment[i]);
}
}
// Write Obsute Angel Top Left
void obtuseAngleTopLeftChar(int col, int row) {
lcd.setCursor(col, row);
lcd.write(0);
delay(30);
}
// Write Obsute Angel Top Right
void obtuseAngleTopRightChar(int col, int row) {
lcd.setCursor(col, row);
lcd.write(1);
delay(30);
}
// Write Obsute Angel Bottom Left
void obtuseAngleBotLeftChar(int col, int row) {
lcd.setCursor(col, row);
lcd.write(2);
delay(30);
}
// Write Obsute Angel Bottom Right
void obtuseAngleBotRightChar(int col, int row) {
lcd.setCursor(col, row);
lcd.write(3);
delay(30);
}
// Write Angel Top Left
void angleTopLeftChar(int col, int row) {
lcd.setCursor(col, row);
lcd.write(4);
delay(30);
}
// Write Angel Top Right
void angleTopRightChar(int col, int row) {
lcd.setCursor(col, row);
lcd.write(5);
delay(30);
}
// Write Angel Bottom Left
void angleBotLeftChar(int col, int row) {
lcd.setCursor(col, row);
lcd.write(6);
delay(30);
}
// Write Angel Bottom Right
void angleBotRightChar(int col, int row) {
lcd.setCursor(col, row);
lcd.write(7);
delay(30);
}
// Write Full Char
void oneFullChar(int col, int row) {
lcd.setCursor(col, row);
lcd.write(255);
delay(30);
}
void twoFullChar(int col, int row) {
lcd.setCursor(col, row);
lcd.write(255);
lcd.setCursor(col + 1, row);
lcd.write(255);
delay(30);
}
void threeFullChar(int col, int row) {
lcd.setCursor(col, row);
lcd.write(255);
lcd.setCursor(col + 1, row);
lcd.write(255);
lcd.setCursor(col + 2, row);
lcd.write(255);
delay(30);
}
// Write Blank Char
void blankChar(int col, int row) {
lcd.setCursor(col, row);
lcd.write(32);
}
void numberZero(int col, int row) {
// Row 1
obtuseAngleTopLeftChar(col, row);
oneFullChar(col + 1, row);
oneFullChar(col + 2, row);
obtuseAngleTopRightChar(col + 3, row);
// Row 2 Col Fourth
oneFullChar(col + 3, row + 1);
// Row 3 Col Fourth
oneFullChar(col + 3, row + 2);
// Row 4
obtuseAngleBotRightChar(col + 3, row + 3);
oneFullChar(col + 2, row + 3);
oneFullChar(col + 1, row + 3);
obtuseAngleBotLeftChar(col, row + 3);
// Row 3 Col First
oneFullChar(col, row + 2);
// Row 2 Col First
oneFullChar(col, row + 1);
}
void numberOne(int col, int row) {
// Row 1
obtuseAngleTopLeftChar(col + 1, row);
twoFullChar(col + 2, row);
// Row 2
twoFullChar(col + 2, row + 1);
// Row 3
twoFullChar(col + 2, row + 2);
// Row 4
twoFullChar(col + 2, row + 3);
}
void numberTwo(int col, int row) {
// Row 1
obtuseAngleTopLeftChar(col, row);
oneFullChar(col + 1, row);
oneFullChar(col + 2, row);
obtuseAngleTopRightChar(col + 3, row);
// Row 2
obtuseAngleBotRightChar(col + 3, row + 1);
obtuseAngleTopLeftChar(col + 2, row + 1);
angleBotRightChar(col + 1, row + 1);
// Row 3
angleTopLeftChar(col + 2, row + 2);
obtuseAngleBotRightChar(col + 1, row + 2);
obtuseAngleTopLeftChar(col, row + 2);
// Row 4
oneFullChar(col, row + 3);
oneFullChar(col + 1, row + 3);
oneFullChar(col + 2, row + 3);
oneFullChar(col + 3, row + 3);
}
void numberThree(int col, int row) {
// Row 1
obtuseAngleTopLeftChar(col, row);
oneFullChar(col + 1, row);
oneFullChar(col + 2, row);
obtuseAngleTopRightChar(col + 3, row);
// Row 2
obtuseAngleBotRightChar(col + 3, row + 1);
obtuseAngleTopLeftChar(col + 2, row + 1);
angleBotRightChar(col + 1, row + 1);
// Row 3
angleTopRightChar(col + 1, row + 2);
obtuseAngleBotLeftChar(col + 2, row + 2);
obtuseAngleTopRightChar(col + 3, row + 2);
// Row 4
obtuseAngleBotRightChar(col + 3, row + 3);
oneFullChar(col + 2, row + 3);
oneFullChar(col + 1, row + 3);
obtuseAngleBotLeftChar(col, row + 3);
}
void clearCountdown(int col, int row) {
// For loop to clear col and row char on select
for (int c = col; c < (col + 4); c++) {
for (int r = row; r < (row + 4); r++) {
blankChar(c, r);
};
};
}
void showCountdown(int col, int row, int from = 3, int to = 0) {
from = from > 3 ? 3 : from;
to = to < 0 ? 0 : to;
// Show error on lcd if value from > to
if (from < to) {
lcd.clear();
lcd.setCursor(3, 0);
lcd.print("ERROR FUNCTION:");
lcd.setCursor(3, 1);
lcd.print("showCountdown(),");
lcd.setCursor(0, 2);
lcd.print("MESSAGE: FROM should");
lcd.setCursor(1, 3);
lcd.print("be greater than TO");
return;
}
// For loop value from for show countdown
for (int i = from; i >= to; i = i - 1) {
clearCountdown(col, row);
if (i == 3) {
numberThree(col, row);
delay(1000);
} else if (i == 2) {
numberTwo(col, row);
delay(1000);
} else if (i == 1) {
numberOne(col, row);
delay(1000);
} else if (i == 0) {
numberZero(col, row);
}
};
}
void loop() {
lcd.clear();
digitalWrite(ledRed, HIGH);
delay(3000);
showCountdown(16, 0, 3, 2);
digitalWrite(ledRed, LOW);
digitalWrite(ledYellow, HIGH);
showCountdown(16, 0, 1, 1);
digitalWrite(ledYellow, LOW);
digitalWrite(ledGreen, HIGH);
showCountdown(16, 0, 0, 0);
delay(5000);
digitalWrite(ledGreen, LOW);
}