#include <Arduino.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <EEPROM.h>
#include "BootGif.h"
#include "InteractionGifs.h"
#include "FeedGif.h"
#include "IdleGif.h"
#include "LowLvlGifs.h"
#include "ChargeGif.h"
#include "WidgetGif.h"
#include "AffirmGifs.h"
#define BUTTON1_PIN 12
#define BUTTON2_PIN 13
#define POT_PIN 34
#define MOTOR_PIN 14
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
int hunger = 50;
int happiness = 50;
int boredom = 50;
unsigned long last_lvl_millis = 0;
unsigned long time_to_dec_stat = 10000;
enum State
{
IDLE,
FEED,
PLAY,
PET_STATUS,
SETTINGS
};
State currentState = IDLE;
unsigned long lastGifDisplayTime = 0;
const long gifIntervals[] = {30000, 3600000, 10800000, 18000000, 28800000}; // 30min, 1hr, 3hr, 5hr, 8hr
unsigned long lastActivityTime = millis();
const long sleepTimeout = 60000; // 60 seconds of inactivity
const int potThreshold = 50; // Adjust this value based on potentiometer sensitivity
const int NUM_GIFS = 5; // Number of GIF animations available
const int NUM_Affirm_GIFS = 30;
const int GIF_DISPLAY_TIME = 3000; // GIF display time in milliseconds
const int Vib_Play_Time = 5;
int frame = 0;
int I_frame = 0;
int F_frame = 0;
int Idle_frame = 0;
int LL_frame = 0;
int CA_frame = 0;
int W_frame = 0;
int Af_frame = 0;
#define FRAME_DELAY (42)
#define FRAME_WIDTH (64)
#define FRAME_HEIGHT (64)
#define FRAME_COUNT (sizeof(frames) / sizeof(frames[0]))
#define I_FRAME_COUNT (sizeof(Gif1) / sizeof(Gif1[0]))
#define F_FRAME_COUNT (sizeof(FeedGif) / sizeof(FeedGif[0]))
#define Idle_FRAME_COUNT (sizeof(IdleGif) / sizeof(IdleGif[0]))
#define LL_FRAME_COUNT (sizeof(SadGif) / sizeof(SadGif[0]))
#define CA_FRAME_COUNT (sizeof(ChargeGif) / sizeof(ChargeGif[0]))
#define W_FRAME_COUNT (sizeof(WidgetGif) / sizeof(WidgetGif[0]))
#define Affirm_FRAME_COUNT (sizeof(AffirmGif1) / sizeof(AffirmGif1[0]))
char userName[50]; // Array to store the user's name
int currentPattern = 0; // Current motor vibration pattern index
static int lastPotValue = -1;
int LLG_Flag = 0;
bool isFirstBoot = true; // Variable to remember boot status
bool FTF = true;
int lastButtonState = HIGH; // the previous state of the button
unsigned long lastDebounceTime = 0; // the last time the button state was toggled
unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers
unsigned long lastPressTime = 0; // time of the last button press
// Function prototypes
void setup();
void loop();
bool userIsActive();
void performActiveTasks();
State mapPotToState(int potValue);
void feedPet();
void playWithPet();
void displayRandomGifForDuration(int duration);
void displayHunger();
void FeedPetGif();
void displayPlay();
void showStatus();
void adjustSettings();
void checkGifDisplay();
void goToSleep();
void showBootAnimation();
void displayIdle();
void displayGif(int index);
void displayAffirmGif(int index);
void vibrate_motor();
void saveBootStatus();
void readBootStatus();
void displayGreeting();
void adjustAffirmationInterval();
void adjustVibrationStyle();
void vibrateConstantly();
void vibrateShortBursts();
void vibrateLongBursts();
void vibrateIncreaseIntensity();
void vibrateRandom();
void dispalyLowLvlGifs();
void state_change_check();
void displayChargeAnim();
bool detectButtonPress();
void displayWidgetGif();
void setup()
{
Serial.begin(115200);
pinMode(BUTTON1_PIN, INPUT_PULLUP);
pinMode(BUTTON2_PIN, INPUT_PULLUP);
pinMode(MOTOR_PIN, OUTPUT);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
readBootStatus(); // Read boot status from EEPROM
if (isFirstBoot)
{
showBootAnimation();
adjustSettings();
isFirstBoot = false;
saveBootStatus(); // Save boot status to EEPROM
}
else
{
displayGreeting();
}
}
void displayGreeting()
{
display.clearDisplay();
display.setCursor(0, 0);
display.print("Welcome to");
display.setCursor(0, 20);
display.print("Your Pet Pal!");
display.display();
delay(2000); // Wait for 2 seconds before proceeding
}
void loop()
{
if (userIsActive())
{
lastActivityTime = millis();
performActiveTasks();
}
if (millis() - lastActivityTime > sleepTimeout)
{
goToSleep();
Serial.println("Test3");
}
else
{
performActiveTasks();
}
}
bool userIsActive()
{
if (FTF)
{
lastPotValue = analogRead(POT_PIN);
FTF = false;
}
int currentPotValue = analogRead(POT_PIN);
// Check if the potentiometer value has changed
bool potValueChanged = (currentPotValue != lastPotValue);
// If the potentiometer value has changed, update lastActivityTime
if (potValueChanged)
{
lastActivityTime = millis();
lastPotValue = currentPotValue; // Update the last potentiometer value
}
// Check for button presses
return digitalRead(BUTTON1_PIN) == LOW ||
digitalRead(BUTTON2_PIN) == LOW ||
potValueChanged; // Check if pot value has changed
}
void performActiveTasks()
{
checkGifDisplay();
state_change_check();
if (hunger <= 50 && happiness >= 50 && boredom <= 50)
{
displayIdle();
}
if (hunger > 50 || happiness < 50 || boredom > 50)
{
dispalyLowLvlGifs();
}
int selectedOption = 0; // Default selected option
bool exitControl = false; // Flag to control exiting settings menu
unsigned long start_millis = millis();
while (!exitControl)
{
display.clearDisplay();
display.setCursor(0, 0);
display.print("Control Menu:");
display.setCursor(0, 20);
display.print("1. Charge Animation");
display.setCursor(0, 30);
display.print("2. Play Animation");
display.setCursor(0, 40);
display.print("3. Show Status");
display.setCursor(0, 50);
display.print("4. Settings");
// Map potentiometer value to select option
int potValue = analogRead(POT_PIN);
selectedOption = map(potValue, 0, 4095, 1, 4);
// Highlight selected option
display.setCursor(0, selectedOption * 10 + 10);
display.print("->");
display.display();
// Handle button presses
if (digitalRead(BUTTON1_PIN) == LOW)
{
delay(500); // Debounce delay
switch (selectedOption)
{
case 1:
// Charge Animation selected
// Implement charge animation
displayChargeAnim();
break;
case 2:
// Play Animation selected
// Implement play animation
playWithPet();
break;
case 3:
// Show Status selected
// Implement show status
showStatus();
break;
case 4:
// Settings selected
// Stay in settings menu
adjustSettings();
break;
}
}
// Check if button 2 is pressed to exit settings
if (digitalRead(BUTTON2_PIN) == LOW)
{
delay(500); // Debounce delay
exitControl = true;
}
if ((millis() - start_millis) > 10000)
{
break;
}
}
}
void state_change_check()
{
if (millis() - last_lvl_millis > time_to_dec_stat)
{
boredom = min(100, boredom + 1);
happiness = max(0, happiness - 2);
hunger = min(100, hunger + 3);
last_lvl_millis = millis();
}
}
State mapPotToState(int potValue)
{
int option = map(potValue, 0, 4095, 0, 4);
return static_cast<State>(option);
}
void feedPet()
{
hunger = max(0, hunger - 10);
happiness = min(100, happiness + 5);
displayHunger();
FeedPetGif();
}
void displayRandomGifForDuration(int duration)
{
// Display GIF based on index for specified duration
int gifIndex = random(1, NUM_GIFS);
displayGif(gifIndex);
delay(duration);
}
void displayRandomAffirmationGif(int duration)
{
// Display GIF based on index for specified duration
int gifIndex = random(1, NUM_Affirm_GIFS);
displayAffirmGif(gifIndex);
delay(duration);
}
void displayHunger()
{
display.clearDisplay();
display.setCursor(0, 0);
display.print("Hunger level: ");
display.println(hunger);
display.display();
delay(2000); // Display for 2 seconds
}
void playWithPet()
{
boredom = max(0, boredom - 10);
happiness = min(100, happiness + 5);
displayPlay();
displayRandomGifForDuration(GIF_DISPLAY_TIME);
}
void displayPlay()
{
display.clearDisplay();
display.setCursor(0, 0);
display.print("Playing with your pet!");
display.display();
delay(2000); // Display for 2 seconds
}
void dispalyLowLvlGifs()
{
LLG_Flag = (LLG_Flag + 1) % 3;
while (true)
{
state_change_check();
checkGifDisplay();
if (happiness < 50 && LLG_Flag == 1)
{
display.clearDisplay();
display.drawBitmap(32, 0, SadGif[LL_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
LL_frame = (LL_frame + 1) % LL_FRAME_COUNT;
delay(FRAME_DELAY);
if (digitalRead(BUTTON1_PIN) == LOW)
{
// currentState = PET_STATUS;
if (detectButtonPress())
{
displayWidgetGif();
break;
}
else
{
break;
}
}
if (digitalRead(BUTTON2_PIN) == LOW)
{
// currentState = PET_STATUS;
delay(500);
break;
}
}
else if (hunger > 50 && LLG_Flag == 2)
{
display.clearDisplay();
display.drawBitmap(32, 0, TiredGif[LL_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
LL_frame = (LL_frame + 1) % LL_FRAME_COUNT;
delay(FRAME_DELAY);
if (digitalRead(BUTTON1_PIN) == LOW)
{
// currentState = PET_STATUS;
if (detectButtonPress())
{
displayWidgetGif();
break;
}
else
{
break;
}
}
if (digitalRead(BUTTON2_PIN) == LOW)
{
// currentState = PET_STATUS;
delay(500);
break;
}
}
else if (boredom > 50 && LLG_Flag == 0)
{
display.clearDisplay();
display.drawBitmap(32, 0, BoredGif[LL_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
LL_frame = (LL_frame + 1) % LL_FRAME_COUNT;
delay(FRAME_DELAY);
if (digitalRead(BUTTON1_PIN) == LOW)
{
// currentState = PET_STATUS;
if (detectButtonPress())
{
displayWidgetGif();
break;
}
else
{
break;
}
}
if (digitalRead(BUTTON2_PIN) == LOW)
{
// currentState = PET_STATUS;
delay(500);
break;
}
}
}
}
bool detectButtonPress()
{
int consecutivePresses = 0;
unsigned long startTime = millis();
while (millis() - startTime < 1000)
{
int reading = digitalRead(BUTTON1_PIN);
if (reading != lastButtonState)
{
// reset the debounce timer
lastDebounceTime = millis();
delay(100);
}
if ((millis() - lastDebounceTime) > debounceDelay)
{
// if the button state has changed for more than the debounce delay
if (reading != lastButtonState)
{
lastButtonState = reading;
// if button state changed from high to low (button pressed)
if (lastButtonState == LOW)
{
// if it's the first press or within a short time after the last press, count it
if (consecutivePresses == 0 || (millis() - lastPressTime) < 500)
{
consecutivePresses++;
Serial.println(consecutivePresses);
lastPressTime = millis();
}
else
{ // otherwise, reset the count
consecutivePresses = 0;
}
}
}
}
// if three consecutive button presses are detected, return true
if (consecutivePresses == 3)
{
return true;
}
}
// if three consecutive button presses are not detected within one second, return false
return false;
}
void showStatus()
{
int selectedOption = 0; // Initialize selected option
bool marked = false; // Flag to track if an option is marked
while (true)
{
if (!marked)
{
display.clearDisplay();
display.setCursor(0, 0);
display.print("Hunger: ");
display.println(hunger);
display.setCursor(0, 20);
display.print("Happiness: ");
display.println(happiness);
display.setCursor(0, 40);
display.print("Boredom: ");
display.println(boredom);
display.display();
delay(3000); // Display for 3 seconds
marked = true; // Mark the first option
}
int potValue = analogRead(POT_PIN);
selectedOption = map(potValue, 0, 4095, 0, 2);
switch (selectedOption)
{
case 0:
// Highlight Hunger
display.clearDisplay();
display.setCursor(0, 0);
display.print("> Hunger: ");
display.println(hunger);
display.setCursor(0, 20);
display.print("Happiness: ");
display.println(happiness);
display.setCursor(0, 40);
display.print("Boredom: ");
display.println(boredom);
display.display();
break;
case 1:
// Highlight Happiness
display.clearDisplay();
display.setCursor(0, 0);
display.print("Hunger: ");
display.println(hunger);
display.setCursor(0, 20);
display.print("> Happiness: ");
display.println(happiness);
display.setCursor(0, 40);
display.print("Boredom: ");
display.println(boredom);
display.display();
break;
case 2:
// Highlight Boredom
display.clearDisplay();
display.setCursor(0, 0);
display.print("Hunger: ");
display.println(hunger);
display.setCursor(0, 20);
display.print("Happiness: ");
display.println(happiness);
display.setCursor(0, 40);
display.print("> Boredom: ");
display.println(boredom);
display.display();
break;
}
if (digitalRead(BUTTON1_PIN) == LOW)
{
delay(500); // Debounce delay
// Perform action based on the selected option
switch (selectedOption)
{
case 0:
currentState = FEED; // Action for Hunger
break;
case 1:
currentState = PLAY; // Action for Happiness
break;
case 2:
currentState = PLAY; // Action for Boredom
break;
}
// Exit the loop after an option is selected
break;
}
if (digitalRead(BUTTON2_PIN) == LOW)
{
delay(500); // Debounce delay
// Exit the loop if button 2 is pressed
break;
}
}
}
void adjustSettings()
{
int selectedOption = 1; // Default selected option
bool exitSettings = false; // Flag to control exiting settings menu
while (!exitSettings)
{
display.clearDisplay();
display.setCursor(0, 0);
display.print("Settings Menu:");
display.setCursor(0, 20);
display.print("1. Affir Interval ");
if (selectedOption == 1)
{
display.print("->"); // Indicate the selected option
}
display.setCursor(0, 30);
display.print("2. Vibration Style ");
if (selectedOption == 2)
{
display.print("->"); // Indicate the selected option
}
display.display();
int potValue = analogRead(POT_PIN);
selectedOption = map(potValue, 0, 4095, 1, 2);
if (digitalRead(BUTTON1_PIN) == LOW)
{
delay(500); // Debounce delay
switch (selectedOption)
{
case 1:
adjustAffirmationInterval();
break;
case 2:
adjustVibrationStyle();
break;
}
}
// Check if button 2 is pressed to exit settings
if (digitalRead(BUTTON2_PIN) == LOW)
{
delay(500); // Debounce delay
exitSettings = true;
}
}
}
void adjustAffirmationInterval()
{
int previousPotValue = -1;
int intervalIndex = 0; // Default interval index
while (true)
{
int potValue = analogRead(POT_PIN);
int mappedValue = map(potValue, 0, 4095, 0, 4);
if (mappedValue != previousPotValue)
{
display.clearDisplay();
display.setCursor(0, 0);
display.print("Affirmation Interval:");
switch (mappedValue)
{
case 0:
display.println("30 min");
break;
case 1:
display.println("1 hr");
break;
case 2:
display.println("3 hrs");
break;
case 3:
display.println("5 hrs");
break;
case 4:
display.println("8 hrs");
break;
}
display.setCursor(0, 20);
display.print("Press Button 1 to save");
display.display();
previousPotValue = mappedValue;
}
if (digitalRead(BUTTON1_PIN) == LOW)
{
delay(500); // Debounce delay
delay(2000); // Display saved message for 2 seconds
// Save interval setting to EEPROM or any other storage
break;
}
}
}
void adjustVibrationStyle()
{
bool SC_Flag = false;
int pre_si = -1;
// Wait for potentiometer rotation to select style
while (true)
{
int potValue = analogRead(POT_PIN);
int styleIndex = map(potValue, 0, 4095, 0, 4);
// Display the selected vibration style
// For demonstration, let's assume it's a simple text display
display.clearDisplay();
display.setCursor(0, 0);
display.print("Vibration Style:");
// Display available vibration styles here
// display.display();
if ((!SC_Flag) && (styleIndex != pre_si))
{
SC_Flag = true;
pre_si = styleIndex;
}
display.setCursor(0, 20);
switch (styleIndex)
{
case 0:
display.print("Style 1");
display.display();
if (SC_Flag)
{
vibrateConstantly();
SC_Flag = false;
}
break;
case 1:
display.print("Style 2");
display.display();
if (SC_Flag)
{
vibrateShortBursts();
SC_Flag = false;
}
break;
case 2:
display.print("Style 3");
display.display();
if (SC_Flag)
{
vibrateLongBursts();
SC_Flag = false;
}
break;
case 3:
display.print("Style 4");
display.display();
if (SC_Flag)
{
vibrateIncreaseIntensity();
SC_Flag = false;
}
break;
case 4:
display.print("Style 5");
display.display();
if (SC_Flag)
{
vibrateRandom();
SC_Flag = false;
}
break;
}
// display.display();
// Wait for button press to save style setting
if (digitalRead(BUTTON1_PIN) == LOW)
{
delay(500); // Debounce delay
delay(2000); // Display saved message for 2 seconds
// Save style setting to EEPROM or any other storage
break;
}
}
}
void checkGifDisplay()
{
if (millis() - lastGifDisplayTime >= gifIntervals[currentState])
{
vibrate_motor();
displayRandomAffirmationGif(GIF_DISPLAY_TIME);
lastGifDisplayTime = millis();
}
}
void goToSleep()
{
// Configure wake up sources
esp_sleep_enable_ext0_wakeup(GPIO_NUM_12, LOW); // Button 1
esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, LOW); // Button 2
// Enter deep sleep
esp_deep_sleep_start();
}
void showBootAnimation()
{
// Implement boot animation
int i = 0;
while (i < 10)
{
display.clearDisplay();
display.drawBitmap(32, 0, frames[frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
frame = (frame + 1) % FRAME_COUNT;
delay(FRAME_DELAY);
i++;
}
}
void displayChargeAnim()
{
while (true)
{
state_change_check();
display.clearDisplay();
display.drawBitmap(32, 0, ChargeGif[CA_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
CA_frame = (CA_frame + 1) % CA_FRAME_COUNT;
delay(FRAME_DELAY);
if (digitalRead(BUTTON1_PIN) == LOW || digitalRead(BUTTON2_PIN) == LOW)
{
// currentState = PET_STATUS;
delay(500);
break;
}
// if (hunger > 50 || happiness < 50 || boredom > 50)
// {
// break;
// }
}
}
void displayIdle()
{
// Implement idle state display
// int i = 0;
while (true)
{
state_change_check();
checkGifDisplay();
display.clearDisplay();
display.drawBitmap(32, 0, IdleGif[Idle_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Idle_frame = (Idle_frame + 1) % Idle_FRAME_COUNT;
delay(FRAME_DELAY);
if (digitalRead(BUTTON1_PIN) == LOW)
{
// currentState = PET_STATUS;
if (detectButtonPress())
{
displayWidgetGif();
break;
}
else
{
break;
}
}
if (digitalRead(BUTTON2_PIN) == LOW)
{
// currentState = PET_STATUS;
delay(500);
break;
}
if (hunger > 50 || happiness < 50 || boredom > 50)
{
break;
}
}
}
void displayWidgetGif()
{
while (true)
{
int potValue = analogRead(POT_PIN);
int WIF_delay = map(potValue, 0, 4095, 5, 405);
state_change_check();
checkGifDisplay();
display.clearDisplay();
display.drawBitmap(32, 0, WidgetGif[W_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
W_frame = (W_frame + 1) % W_FRAME_COUNT;
delay(WIF_delay);
if (digitalRead(BUTTON1_PIN) == LOW)
{
// currentState = PET_STATUS;
if (detectButtonPress())
{
break;
}
}
}
}
void FeedPetGif()
{
// Display Feed GIF
int i = 0;
while (i < 20)
{
display.clearDisplay();
display.drawBitmap(32, 0, FeedGif[F_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
F_frame = (F_frame + 1) % F_FRAME_COUNT;
delay(FRAME_DELAY);
i++;
}
}
void displayGif(int index)
{
// Display GIF based on index
// Example: display.drawBitmap(...);
int i = 0;
while (i < 60)
{
switch (index)
{
case 1:
display.clearDisplay();
display.drawBitmap(32, 0, Gif1[I_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
I_frame = (I_frame + 1) % I_FRAME_COUNT;
break;
case 2:
display.clearDisplay();
display.drawBitmap(32, 0, Gif2[I_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
I_frame = (I_frame + 1) % I_FRAME_COUNT;
break;
case 3:
display.clearDisplay();
display.drawBitmap(32, 0, Gif3[I_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
I_frame = (I_frame + 1) % I_FRAME_COUNT;
break;
case 4:
display.clearDisplay();
display.drawBitmap(32, 0, Gif4[I_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
I_frame = (I_frame + 1) % I_FRAME_COUNT;
break;
case 5:
display.clearDisplay();
display.drawBitmap(32, 0, Gif5[I_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
I_frame = (I_frame + 1) % I_FRAME_COUNT;
break;
}
delay(FRAME_DELAY);
i++;
}
}
void displayAffirmGif(int index)
{
// Display GIF based on index
int i = 0;
while (i < 60)
{
switch (index)
{
case 1:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif1[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 2:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif2[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 3:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif3[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 4:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif4[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 5:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif5[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 6:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif6[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 7:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif7[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 8:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif8[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 9:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif9[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 10:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif10[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 11:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif11[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 12:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif12[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 13:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif13[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 14:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif14[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 15:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif15[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 16:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif16[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 17:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif17[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 18:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif18[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 19:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif19[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 20:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif20[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 21:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif21[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 22:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif22[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 23:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif23[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 24:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif24[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 25:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif25[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 26:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif26[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 27:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif27[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 28:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif28[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 29:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif29[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
case 30:
display.clearDisplay();
display.drawBitmap(32, 0, AffirmGif30[Af_frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
display.display();
Af_frame = (Af_frame + 1) % Affirm_FRAME_COUNT;
break;
}
delay(FRAME_DELAY);
i++;
}
}
void vibrate_motor()
{
display.clearDisplay();
display.setCursor(0, 0);
display.print("Pattern: ");
display.println(currentPattern + 1); // Display the current pattern
display.display();
switch (currentPattern)
{
case 0:
vibrateConstantly();
break;
case 1:
vibrateShortBursts();
break;
case 2:
vibrateLongBursts();
break;
case 3:
vibrateIncreaseIntensity();
break;
case 4:
vibrateRandom();
break;
}
}
void vibrateConstantly()
{
digitalWrite(MOTOR_PIN, HIGH);
delay(1000);
digitalWrite(MOTOR_PIN, LOW);
delay(100);
}
void vibrateShortBursts()
{
for (int i = 0; i < 4; i++)
{
digitalWrite(MOTOR_PIN, HIGH);
delay(100);
digitalWrite(MOTOR_PIN, LOW);
delay(300);
}
}
void vibrateLongBursts()
{
for (int i = 0; i < 4; i++)
{
digitalWrite(MOTOR_PIN, HIGH);
delay(300);
digitalWrite(MOTOR_PIN, LOW);
delay(100);
}
}
void vibrateIncreaseIntensity()
{
for (int i = 100; i <= 255; i += 20)
{
analogWrite(MOTOR_PIN, i);
delay(200);
}
}
void vibrateRandom()
{
for (int i = 0; i < 10; i++)
{
int duration = random(100, 500);
digitalWrite(MOTOR_PIN, HIGH);
delay(duration);
digitalWrite(MOTOR_PIN, LOW);
delay(random(100, 500));
}
}
void saveBootStatus()
{
EEPROM.put(0, isFirstBoot);
EEPROM.commit();
}
void readBootStatus()
{
EEPROM.get(0, isFirstBoot);
}