#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
// define variables
String txtMsg = "Arduino";
int i, j;
unsigned long previousMillis = 0;
const long interval = 50;
const long holdInterval = 5000;
enum State {
MOVE_CHAR_IN,
MOVE_CHAR_OUT,
WAIT_BETWEEN_CHARS,
HOLD_DISPLAY
};
State currentState = MOVE_CHAR_IN;
void setup() {
lcd.init();
lcd.clear();
lcd.backlight();
i = txtMsg.length() - 1; // start from last character
j = 0; // start from first LCD position
}
void loop() {
unsigned long currentMillis = millis();
switch (currentState) {
case MOVE_CHAR_IN:
if (currentMillis - previousMillis >= interval) {
lcd.setCursor(j, 1);
lcd.print(txtMsg[i]);
if (j > 0) {
lcd.setCursor(j - 1, 1);
lcd.print(' ');
}
j++;
previousMillis = currentMillis;
if (j == i + 2) {
currentState = WAIT_BETWEEN_CHARS;
}
}
break;
case WAIT_BETWEEN_CHARS:
if (currentMillis - previousMillis >= interval) {
i--;
j = 0;
previousMillis = currentMillis;
if (i < 0) {
currentState = HOLD_DISPLAY;
} else {
currentState = MOVE_CHAR_IN;
}
}
break;
case HOLD_DISPLAY:
if (currentMillis - previousMillis >= holdInterval) {
i = txtMsg.length() - 1;
j = 0;
previousMillis = currentMillis;
lcd.clear();
currentState = MOVE_CHAR_OUT;
}
break;
case MOVE_CHAR_OUT:
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
lcd.setCursor(i, 1);
lcd.print(txtMsg[i - 1]);
if (j > 0) {
j--;
lcd.setCursor(j, 1);
lcd.print(' ');
}
else {
lcd.setCursor(0, 1);
lcd.print(" "); // Clear line
currentState = MOVE_CHAR_IN;
}
}
break;
}
}