Untitled
unknown
csharp
a year ago
21 kB
18
Indexable
/*
* ESP32-S3 Akıllı LED ve Motor Kontrol Sistemi - Simple Fire Simulation
* Geliştirici: Muharrem Arslan
*
* Özellikler:
* - Tek dokunuş: Motor aç/kapat + LED kontrol
* - Çift dokunuş: Parlaklık ayarı (her durumda çalışır)
* - Basılı tutma: Renk değiştirme (sadece normal modda)
* - 3x dokunuş: ALEV SİMÜLASYONU (sadece alev renkleri)
* - Motor hareket ederken touch algılama tamamen kapalı
* - Motor kapalıyken LED'ler sönük
* - 18650 batarya koruması
* - Róbert Ulbricht Fire Algorithm (Basit + Etkili)
*/
#include <FastLED.h>
#include <AccelStepper.h>
#include <EEPROM.h>
// Pin Tanımlamaları
#define LED_PIN 18
#define LED_COUNT 7
#define TOUCH_PIN T4
#define STEP_PIN 14
#define DIR_PIN 12
#define MT3608_EN_PIN 23
#define BATTERY_PIN 33
// Sistem Sabitleri
#define MOTOR_STEPS 250
#define MOTOR_SPEED 2000
#define MOTOR_ACCEL 1000
#define TOUCH_THRESHOLD 45
#define LONG_PRESS_TIME 1200
#define TRIPLE_TAP_TIME 800
#define MOTOR_TRANSITION_TIME 2000
// Fire Simulation Sabitleri - Basit Algoritma
#define FIRE_BASE_COLOR_R 80 // Temel kırmızı değer
#define FIRE_BASE_COLOR_G 35 // Temel yeşil değer
#define FIRE_BASE_COLOR_B 0 // Temel mavi değer
#define FIRE_RANDOM_MAX 80 // Maksimum karartma değeri
// Batarya Sabitleri
#define BATTERY_MIN_VOLTAGE 3.0
#define BATTERY_MAX_VOLTAGE 4.2
#define BATTERY_CRITICAL 3.2
#define VOLTAGE_DIVIDER_RATIO 1.27
#define ADC_RESOLUTION 4095
#define ADC_VREF 3.3
// EEPROM Adresleri
#define EEPROM_SIZE 512
#define ADDR_BRIGHTNESS 0
#define ADDR_EFFECT 1
#define ADDR_MOTOR_POS 2
#define ADDR_COLOR_HUE 3
// Nesneler
CRGB leds[LED_COUNT];
AccelStepper stepper(AccelStepper::DRIVER, STEP_PIN, DIR_PIN);
// Fire Simulation Değişkenleri
unsigned long lastFireUpdate = 0;
uint32_t nextUpdateDelay = 100;
bool fireEffectActive = false;
// Sistem Değişkenleri
bool systemOn = false;
bool motorOpen = false;
bool motorMoving = false;
bool batteryLow = false;
bool systemShutdown = false;
// Touch Değişkenleri
unsigned long lastTouchTime = 0;
unsigned long touchStartTime = 0;
unsigned long touchReleaseTime = 0;
int touchCount = 0;
bool longPressActive = false;
bool touchPressed = false;
bool touchProcessed = false;
// Batarya Değişkenleri
float batteryVoltage = 0.0;
uint8_t batteryPercentage = 0;
unsigned long lastBatteryCheck = 0;
unsigned long lowBatteryWarningTime = 0;
bool lowBatteryLedState = false;
// LED ve Renk Değişkenleri
uint8_t brightness = 150;
uint8_t brightnessLevels[] = {64, 127, 191, 255};
uint8_t brightnessIndex = 1;
uint8_t currentHue = 0;
uint8_t savedHue = 0;
bool colorChanging = false;
unsigned long lastColorUpdate = 0;
unsigned long motorStartTime = 0;
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("=== ESP32 LED Motor Kontrol - Simple Fire Simulation ===");
Serial.println("Geliştirici: Muharrem Arslan");
// Sistem başlatma
analogReadResolution(12);
analogSetAttenuation(ADC_11db);
EEPROM.begin(EEPROM_SIZE);
loadSettings();
pinMode(MT3608_EN_PIN, OUTPUT);
pinMode(BATTERY_PIN, INPUT);
digitalWrite(MT3608_EN_PIN, LOW);
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, LED_COUNT);
FastLED.setBrightness(brightness);
FastLED.clear();
FastLED.show();
stepper.setMaxSpeed(MOTOR_SPEED);
stepper.setAcceleration(MOTOR_ACCEL);
stepper.setCurrentPosition(0);
touchSetCycles(0x1000, 0x1000);
// Fire simulation başlatma
initializeFireSimulation();
// Touch test
Serial.println("\n=== TOUCH SENSOR TEST ===");
for (int i = 0; i < 5; i++) {
uint16_t touchVal = touchRead(TOUCH_PIN);
Serial.println("Touch " + String(i+1) + ": " + String(touchVal));
delay(200);
}
Serial.println("Threshold: " + String(TOUCH_THRESHOLD));
// Batarya kontrolü
checkBatteryLevel();
Serial.println("Batarya: " + String(batteryVoltage, 2) + "V (" + String(batteryPercentage) + "%)");
// Kalibrasyon
if (!batteryLow) {
performStartupCalibration();
Serial.println("\n=== SİSTEM HAZIR ===");
Serial.println("Touch Komutları:");
Serial.println("- 1x: Motor aç/kapat");
Serial.println("- 2x: Parlaklık ayarı");
Serial.println("- Basılı tut: Renk seç (sadece normal modda)");
Serial.println("- 3x dokunuş: ALEV SİMÜLASYONU (sadece alev renkleri)");
Serial.println("- Motor hareket ederken TOUCH KAPALI");
} else {
Serial.println("UYARI: Düşük batarya - kalibrasyon atlandı");
}
// Sistem otomatik aç - LED güç kaynağını aktif et
systemOn = true;
digitalWrite(MT3608_EN_PIN, HIGH);
delay(100);
Serial.println("LED güç kaynağı aktif - Fire efekt hazır");
}
void loop() {
// Batarya kontrolü (10 saniyede bir)
if (millis() - lastBatteryCheck > 10000) {
checkBatteryLevel();
lastBatteryCheck = millis();
}
// Düşük batarya kontrolü
if (batteryLow && !systemShutdown) {
handleLowBattery();
return;
}
if (!systemShutdown) {
// Motor durumu kontrol et
checkMotorStatus();
// Touch algılama - SADECE motor durgunken
if (!motorMoving) {
handleTouch();
}
// LED güncelleme - System her zaman aktif
updateLEDs();
stepper.run();
}
delay(10);
}
void initializeFireSimulation() {
Serial.println("Basit Fire Simulation hazırlandı (Róbert Ulbricht algoritması)");
}
void updateFireSimulation() {
if (millis() - lastFireUpdate < nextUpdateDelay) return;
lastFireUpdate = millis();
// Her LED için temel ateş rengi + rastgele karartma
for (int i = 0; i < LED_COUNT; i++) {
// Rastgele karartma değeri (0-80 arası)
int randomDark = random(0, FIRE_RANDOM_MAX);
// RGB değerlerinden karartma değerini çıkar
int newR = FIRE_BASE_COLOR_R - randomDark;
int newG = FIRE_BASE_COLOR_G - (randomDark / 2); // Yeşil daha az kararsın
int newB = FIRE_BASE_COLOR_B - (randomDark / 2); // Mavi daha az kararsın
// Negatif değerleri 0'la sınırla
if (newR < 0) newR = 0;
if (newG < 0) newG = 0;
if (newB < 0) newB = 0;
leds[i] = CRGB(newR, newG, newB);
}
FastLED.setBrightness(brightness);
FastLED.show();
// Bir sonraki güncelleme için rastgele gecikme (50-150ms)
nextUpdateDelay = random(50, 150);
}
void checkMotorStatus() {
if (motorMoving && stepper.distanceToGo() == 0) {
motorMoving = false;
Serial.println(">>> MOTOR DURDU - TOUCH AKTİF <<<");
// Touch değişkenlerini temizle
resetTouchVariables();
// LED durumunu ayarla
if (!motorOpen) {
// Motor kapandı - LED'leri kapat
FastLED.clear();
FastLED.show();
}
}
// Debug mesajları (motor hareket ederken)
static unsigned long lastDebug = 0;
if (motorMoving && millis() - lastDebug > 2000) {
lastDebug = millis();
Serial.println("Motor hareket - Kalan: " + String(stepper.distanceToGo()) + " - Touch KAPALI");
}
}
void resetTouchVariables() {
touchPressed = false;
touchProcessed = false;
longPressActive = false;
colorChanging = false;
touchCount = 0;
lastTouchTime = 0;
}
void handleTouch() {
uint16_t touchValue = touchRead(TOUCH_PIN);
bool currentTouch = touchValue < TOUCH_THRESHOLD;
// Touch başlangıcı
if (currentTouch && !touchPressed) {
touchPressed = true;
touchStartTime = millis();
longPressActive = false;
touchProcessed = false;
colorChanging = false;
if (millis() - lastTouchTime < TRIPLE_TAP_TIME) {
touchCount++;
Serial.println("Art arda touch: " + String(touchCount));
} else {
touchCount = 1;
Serial.println("Yeni touch başladı");
}
}
// Touch bırakma
if (!currentTouch && touchPressed) {
touchPressed = false;
touchReleaseTime = millis();
lastTouchTime = millis();
unsigned long touchDuration = touchReleaseTime - touchStartTime;
if (colorChanging) {
savedHue = currentHue;
saveSettings();
colorChanging = false;
Serial.println("Renk kaydedildi: " + String(savedHue));
// Seçilen rengi 2 saniye daha göster
Serial.println("Seçilen renk 2 saniye gösteriliyor...");
CRGB selectedColor = CHSV(savedHue, 255, 255);
fill_solid(leds, LED_COUNT, selectedColor);
FastLED.setBrightness(brightness);
FastLED.show();
delay(2000);
touchProcessed = true;
touchCount = 0;
} else if (touchDuration >= LONG_PRESS_TIME && !longPressActive) {
Serial.println("UZUN BASMA - Renk değiştir");
startColorChanging();
touchProcessed = true;
touchCount = 0;
}
}
// Uzun basma aktif iken
if (touchPressed && (millis() - touchStartTime >= LONG_PRESS_TIME) && !colorChanging) {
colorChanging = true;
longPressActive = true;
Serial.println("Renk değiştirme başladı!");
}
// Touch timeout - komut işleme
if (touchCount > 0 && !touchPressed && !touchProcessed &&
(millis() - lastTouchTime > TRIPLE_TAP_TIME)) {
processTouch();
touchCount = 0;
touchProcessed = true;
}
}
void processTouch() {
Serial.println("Touch işlemi - Count: " + String(touchCount));
if (touchCount == 1) {
Serial.println(">>> TEK DOKUNUŞ");
handleSingleTap();
} else if (touchCount == 2) {
Serial.println(">>> ÇİFT DOKUNUŞ");
changeBrightness();
} else if (touchCount >= 3) {
Serial.println(">>> ÜÇLÜ DOKUNUŞ");
handleTripleTap();
}
}
void handleSingleTap() {
if (motorMoving) {
Serial.println("Motor hareket halinde - komut engellendi!");
return;
}
if (fireEffectActive) {
fireEffectActive = false;
Serial.println("Alev simülasyonu durduruldu");
saveSettings();
}
toggleMotor();
}
void toggleMotor() {
if (batteryLow) {
Serial.println("Düşük batarya - motor açılamıyor!");
showLowBatteryWarning();
delay(1000);
return;
}
if (motorMoving) {
Serial.println("Motor zaten hareket halinde!");
return;
}
motorOpen = !motorOpen;
motorMoving = true;
motorStartTime = millis();
if (motorOpen) {
Serial.println(">>> MOTOR AÇILIYOR - TOUCH KAPALI <<<");
stepper.moveTo(MOTOR_STEPS);
} else {
Serial.println(">>> MOTOR KAPANIYOR - TOUCH KAPALI <<<");
stepper.moveTo(0);
}
saveSettings();
}
void changeBrightness() {
brightnessIndex = (brightnessIndex + 1) % 4;
brightness = brightnessLevels[brightnessIndex];
saveSettings();
uint8_t percent = (brightness * 100) / 255;
Serial.println("Parlaklık: %" + String(percent));
if (fireEffectActive || motorMoving) {
// Fire efektinde veya motor hareketinde parlaklık demosu
for (int i = 0; i < 3; i++) {
FastLED.setBrightness(brightness / 4);
FastLED.show();
delay(150);
FastLED.setBrightness(brightness);
FastLED.show();
delay(150);
}
} else {
// Önizleme modu (2 saniye)
Serial.println("Parlaklık önizlemesi...");
CRGB color = CHSV(savedHue, 255, 255);
fill_solid(leds, LED_COUNT, color);
FastLED.setBrightness(brightness);
FastLED.show();
delay(2000);
if (!motorOpen) {
FastLED.clear();
FastLED.show();
}
}
}
void handleTripleTap() {
fireEffectActive = !fireEffectActive;
saveSettings();
if (fireEffectActive) {
Serial.println("BASIT ALEV SİMÜLASYONU BAŞLATILDI");
Serial.println("Algoritma: Róbert Ulbricht - Temel renk + rastgele karartma");
// Basit başlangıç efekti
for (int i = 0; i < 3; i++) {
fill_solid(leds, LED_COUNT, CRGB(FIRE_BASE_COLOR_R, FIRE_BASE_COLOR_G, FIRE_BASE_COLOR_B));
FastLED.setBrightness(brightness);
FastLED.show();
delay(200);
FastLED.clear();
FastLED.show();
delay(200);
}
// İlk güncelleme gecikmesini ayarla
nextUpdateDelay = random(50, 150);
} else {
Serial.println("Alev simülasyonu durduruldu");
// Söndürme efekti
for (int fade = brightness; fade > 0; fade -= 20) {
FastLED.setBrightness(fade);
FastLED.show();
delay(50);
}
FastLED.clear();
FastLED.show();
}
}
void startColorChanging() {
if (!fireEffectActive) {
colorChanging = true;
currentHue = savedHue;
Serial.println("Renk değiştirme aktif - Mevcut: " + String(currentHue));
} else {
Serial.println("Ateş efekti aktifken renk değiştirilemez - Sadece alev renkleri!");
// Uyarı efekti
for (int i = 0; i < 3; i++) {
FastLED.setBrightness(brightness / 2);
FastLED.show();
delay(150);
FastLED.setBrightness(brightness);
FastLED.show();
delay(150);
}
}
}
void updateLEDs() {
if (motorMoving) {
updateMotorTransition();
} else if (!motorOpen && !fireEffectActive && !colorChanging) {
// Motor kapalı + efekt yok = LED kapalı
FastLED.clear();
FastLED.show();
} else if (colorChanging) {
updateColorChanging();
} else if (fireEffectActive) {
updateFireSimulation();
} else if (motorOpen) {
showSolidColor();
}
}
void updateMotorTransition() {
if (stepper.distanceToGo() == 0) {
return; // Motor durmuş
}
unsigned long elapsed = millis() - motorStartTime;
float progress = constrain((float)elapsed / MOTOR_TRANSITION_TIME, 0.0, 1.0);
uint8_t targetBrightness;
if (motorOpen) {
// Açılırken: 0% → 100%
targetBrightness = brightness * progress;
} else {
// Kapanırken: 100% → 0%
targetBrightness = brightness * (1.0 - progress);
}
if (targetBrightness > 0) {
CRGB color = CHSV(savedHue, 255, 255);
fill_solid(leds, LED_COUNT, color);
FastLED.setBrightness(targetBrightness);
FastLED.show();
} else {
FastLED.clear();
FastLED.show();
}
}
void updateColorChanging() {
if (millis() - lastColorUpdate < 30) return;
lastColorUpdate = millis();
currentHue += 3;
if (currentHue > 255) currentHue = 0;
CRGB color = CHSV(currentHue, 255, 255);
fill_solid(leds, LED_COUNT, color);
FastLED.setBrightness(brightness);
FastLED.show();
}
void showSolidColor() {
CRGB color = CHSV(savedHue, 255, 255);
fill_solid(leds, LED_COUNT, color);
FastLED.setBrightness(brightness);
FastLED.show();
}
void checkBatteryLevel() {
int adcValue = analogRead(BATTERY_PIN);
float adcVoltage = (adcValue * ADC_VREF) / ADC_RESOLUTION;
batteryVoltage = adcVoltage * VOLTAGE_DIVIDER_RATIO;
batteryVoltage = constrain(batteryVoltage, 2.5, 4.3);
if (batteryVoltage >= BATTERY_MAX_VOLTAGE) {
batteryPercentage = 100;
} else if (batteryVoltage <= BATTERY_MIN_VOLTAGE) {
batteryPercentage = 0;
} else {
batteryPercentage = ((batteryVoltage - BATTERY_MIN_VOLTAGE) /
(BATTERY_MAX_VOLTAGE - BATTERY_MIN_VOLTAGE)) * 100;
}
if (batteryVoltage <= BATTERY_CRITICAL && !batteryLow) {
Serial.println("KRİTİK: Batarya düşük - acil kapatma!");
batteryLow = true;
if (systemOn) {
emergencyShutdown();
}
} else if (batteryVoltage > BATTERY_CRITICAL) {
batteryLow = false;
}
}
void handleLowBattery() {
if (millis() - lowBatteryWarningTime > 1000) {
lowBatteryWarningTime = millis();
lowBatteryLedState = !lowBatteryLedState;
if (lowBatteryLedState) {
fill_solid(leds, LED_COUNT, CRGB::Red);
FastLED.setBrightness(150);
} else {
FastLED.clear();
}
FastLED.show();
}
}
void showLowBatteryWarning() {
for (int i = 0; i < 3; i++) {
fill_solid(leds, LED_COUNT, CRGB::Red);
FastLED.setBrightness(150);
FastLED.show();
delay(200);
FastLED.clear();
FastLED.show();
delay(200);
}
}
void emergencyShutdown() {
Serial.println("ACİL KAPATMA!");
FastLED.clear();
FastLED.show();
if (motorOpen) {
Serial.println("Motor güvenli konuma getiriliyor...");
stepper.moveTo(0);
while (stepper.distanceToGo() != 0) {
stepper.run();
delay(10);
}
motorOpen = false;
}
motorMoving = false;
digitalWrite(MT3608_EN_PIN, LOW);
systemOn = false;
systemShutdown = true;
Serial.println("Sistem güvenle kapatıldı!");
}
void performStartupCalibration() {
Serial.println("\n=== KALİBRASYON ===");
digitalWrite(MT3608_EN_PIN, HIGH);
delay(500);
// Başlangıç göstergesi
for (int i = 0; i < 3; i++) {
fill_solid(leds, LED_COUNT, CRGB::Blue);
FastLED.setBrightness(100);
FastLED.show();
delay(300);
FastLED.clear();
FastLED.show();
delay(300);
}
Serial.println("Motor açılıyor...");
motorMoving = true;
stepper.moveTo(MOTOR_STEPS);
unsigned long startTime = millis();
int ledPos = 0;
while (stepper.distanceToGo() != 0) {
stepper.run();
if (millis() - startTime > 15000) {
Serial.println("Timeout - kalibrasyon durdu");
break;
}
static unsigned long lastLed = 0;
if (millis() - lastLed > 200) {
lastLed = millis();
FastLED.clear();
leds[ledPos] = CRGB::Green;
FastLED.setBrightness(150);
FastLED.show();
ledPos = (ledPos + 1) % LED_COUNT;
}
delay(5);
}
delay(1000);
Serial.println("Motor kapanıyor...");
stepper.moveTo(0);
startTime = millis();
ledPos = LED_COUNT - 1;
while (stepper.distanceToGo() != 0) {
stepper.run();
if (millis() - startTime > 15000) {
Serial.println("Geri hareket timeout");
break;
}
static unsigned long lastLed2 = 0;
if (millis() - lastLed2 > 200) {
lastLed2 = millis();
FastLED.clear();
leds[ledPos] = CRGB::Orange;
FastLED.setBrightness(150);
FastLED.show();
ledPos = (ledPos == 0) ? LED_COUNT - 1 : ledPos - 1;
}
delay(5);
}
// Tamamlandı
for (int i = 0; i < 3; i++) {
fill_solid(leds, LED_COUNT, CRGB::White);
FastLED.setBrightness(200);
FastLED.show();
delay(200);
FastLED.clear();
FastLED.show();
delay(200);
}
stepper.setCurrentPosition(0);
motorOpen = false;
motorMoving = false;
Serial.println("KALİBRASYON TAMAMLANDI!");
}
void saveSettings() {
EEPROM.write(ADDR_BRIGHTNESS, brightnessIndex);
EEPROM.write(ADDR_EFFECT, fireEffectActive ? 1 : 0);
EEPROM.write(ADDR_MOTOR_POS, motorOpen ? 1 : 0);
EEPROM.write(ADDR_COLOR_HUE, savedHue);
EEPROM.commit();
}
void loadSettings() {
brightnessIndex = EEPROM.read(ADDR_BRIGHTNESS);
if (brightnessIndex > 3) brightnessIndex = 1;
brightness = brightnessLevels[brightnessIndex];
uint8_t effect = EEPROM.read(ADDR_EFFECT);
fireEffectActive = false; // Her zaman kapalı başlasın
uint8_t motorPos = EEPROM.read(ADDR_MOTOR_POS);
motorOpen = (motorPos == 1);
if (motorOpen) {
stepper.setCurrentPosition(MOTOR_STEPS);
}
savedHue = EEPROM.read(ADDR_COLOR_HUE);
currentHue = savedHue;
Serial.println("\nAyarlar yüklendi:");
Serial.println("- Parlaklık: %" + String((brightness * 100) / 255));
Serial.println("- Alev efekti: " + String(fireEffectActive ? "Aktif" : "Pasif"));
Serial.println("- Motor: " + String(motorOpen ? "Açık" : "Kapalı"));
Serial.println("- Renk: " + String(savedHue));
}Editor is loading...
Leave a Comment