// Fire animation demo with 8 custom characters on 2x16 LCD
// Author: Yaroslaw Turbin, 26-10-2024
// Code improvement and organization: Anderson, 06-11-2024
#include <Wire.h>
#include <FastLED.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>
// LCD setup
const int LCD_COLS = 16;
const int LCD_ROWS = 2;
hd44780_I2Cexp lcd; // I2C LCD object
// Fire animation parameters
#define NUM_ROWS 8
#define NUM_COLS 40
byte firebuff[NUM_ROWS * NUM_COLS]; // Buffer for fire effect
byte customChars[8][8]; // Storage for custom characters
// Initialize the LCD display
void setup() {
Serial.begin(115200); // Serial for debugging FPS if needed
// Initialize the LCD with defined columns and rows
lcd.begin(LCD_COLS, LCD_ROWS);
lcd.backlight();
lcd.noCursor();
lcd.clear();
// Display initial message
lcd.setCursor(1, 0);
lcd.print("WORLD IN FIRE");
lcd.setCursor(0, 1);
lcd.print(" \1\2\3\4\5\6\7 \1\2\3\4\5\6\7");
}
// Generate fire effect and update fire buffer
void generateFireEffect() {
int timeOffset = millis() / 3;
int index = 0;
for (byte row = 0; row < NUM_ROWS; row++) {
for (byte col = 0; col < NUM_COLS; col++) {
byte color = qsub8(inoise8(col * 50, row * 50 + millis(), timeOffset),
abs8(row - (NUM_ROWS - 1)) * 255 / (NUM_ROWS + 10));
firebuff[index] = (color > 96) ? 255 : 0;
index++;
}
}
}
// Convert fire buffer section to a custom character format
void convertBufferToCustomChar(int offset, byte *symbol) {
for (byte row = 0; row < 8; row++) {
byte bits = 0;
for (byte col = 0; col < 5; col++) {
byte color = firebuff[offset + row * NUM_COLS + col];
bits <<= 1;
if (color) bits |= 0x01;
}
symbol[row] = bits;
}
}
// Calculate and display Frames Per Second (FPS) in serial
void displayFPS() {
static int frameCount = 0;
static unsigned long lastTime = millis();
frameCount++;
if (millis() - lastTime > 8000) {
Serial.print(F("FPS: "));
Serial.println(frameCount / 8);
frameCount = 0;
lastTime = millis();
}
}
void loop() {
// Generate the fire effect pattern
generateFireEffect();
// Update the LCD with custom characters
for (byte i = 0; i < 8; i++) {
convertBufferToCustomChar(i * 5, customChars[i]);
lcd.createChar(i, customChars[i]);
}
// Display the fire animation on the LCD
lcd.setCursor(0, 1);
for (byte i = 0; i < 8; i++) {
lcd.write(i);
}
// Optional: Uncomment to display FPS in the Serial Monitor
// displayFPS();
delay(100); // Control animation speed
}