#define BLYNK_TEMPLATE_ID "TMPL6OQr6SKUf"
#define BLYNK_TEMPLATE_NAME "Increment Decrementer Segregation"
#define BLYNK_AUTH_TOKEN "CpMG1yvYkMK1DoPKxg9JUVC7K0YuQmje"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <BlynkSimpleEsp32.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
// --- Variables ---
int s = 0;
int startVal = 0; // V0
int endVal = 0; // V1
int STEPS = 0; // V2
int modTRIG = 0; // V3
int opState = 0; // V6 Switch State
// Dynamic targets based on the switch
int actualStart = 0;
int actualTarget = 0;
const int buzz = 14;
char auth[] = BLYNK_AUTH_TOKEN;
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
unsigned long lastUpdateTime = 0;
const long interval = 1000;
// --- Playful Sound Functions ---
void playChirp() {
for (int i = 800; i < 1500; i += 100) {
tone(buzz, i, 20);
delay(20);
}
noTone(buzz);
}
void playVictory() {
tone(buzz, 1000, 150); delay(150);
tone(buzz, 1200, 150); delay(150);
tone(buzz, 1500, 400); delay(400);
noTone(buzz);
}
// Helper to update the dynamic range and reset the counter
void applyLogic() {
if (opState == 0) {
actualStart = startVal;
actualTarget = endVal;
} else {
actualStart = endVal;
actualTarget = startVal;
}
s = actualStart; // Reset count to the new starting point
// Clear LCD Row 2 on reset
lcd.setCursor(0, 1);
lcd.print(" ");
}
// --- Blynk Input Handlers ---
BLYNK_WRITE(V0) { startVal = param.asInt(); applyLogic(); }
BLYNK_WRITE(V1) { endVal = param.asInt(); applyLogic(); }
BLYNK_WRITE(V2) { STEPS = param.asInt(); }
BLYNK_WRITE(V3) { modTRIG = param.asInt(); }
// V6 Switch: Determines if we count Start->End or End->Start
BLYNK_WRITE(V6) {
opState = param.asInt();
applyLogic(); // Swaps targets and resets 's'
Serial.print("Mode Switched. Target is now: ");
Serial.println(actualTarget);
}
BLYNK_CONNECTED() {
Blynk.syncVirtual(V0, V1, V2, V3, V6);
}
void setup() {
Serial.begin(9600);
Blynk.begin(auth, ssid, pass);
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Count: ");
pinMode(buzz, OUTPUT);
}
void loop() {
Blynk.run();
unsigned long currentTime = millis();
if (currentTime - lastUpdateTime >= interval) {
lastUpdateTime = currentTime;
updateCounter();
}
}
void updateCounter() {
// 1. Directional Math (Auto-detects if it needs to go up or down)
if (actualStart < actualTarget) {
s += STEPS;
} else {
s -= STEPS;
}
// 2. Completion Check
bool finished = false;
if (actualStart < actualTarget && s >= actualTarget) finished = true;
if (actualStart > actualTarget && s <= actualTarget) finished = true;
if (finished) {
lcd.setCursor(7, 0);
lcd.print(s); // Show final number before reset
lcd.setCursor(0, 1);
lcd.print("COMPLETED!! ");
Blynk.virtualWrite(V4, s);
playVictory();
s = actualStart; // Reset to the current logic's start point
return;
}
// 3. Display
lcd.setCursor(7, 0);
lcd.print(s);
lcd.print(" ");
Blynk.virtualWrite(V4, s);
// 4. Trigger & LED (V5)
if (modTRIG > 0 && s % modTRIG == 0 && s != actualStart) {
lcd.setCursor(0, 1);
lcd.print("Multi ");
lcd.print(modTRIG);
lcd.print(" found! ");
Blynk.virtualWrite(V5, 255);
playChirp();
} else {
lcd.setCursor(0, 1);
lcd.print(" ");
Blynk.virtualWrite(V5, 0);
}
}