#include <Wire.h>
// ── Broches ───────────────────────────────────────────────
#define PIN_BTN 4
#define PIN_BTN_LED 7
#define PIN_LED_R 0
#define PIN_LED_G 1
#define PIN_LED_B 10
#define PIN_SDA 5
#define PIN_SCL 6
#define PIN_BUZZER 3
#define PIN_SWITCH 2
// ── MPU6050 ───────────────────────────────────────────────
#define MPU_ADDR 0x68
#define MPU_ACCEL_XOUT_H 0x3B
#define MPU_PWR_MGMT_1 0x6B
// ── Timings ───────────────────────────────────────────────
#define T_SHORT 400
#define T_500MS 500
#define T_1S 1000
#define T_1500MS 1500
#define T_2S 2000
#define T_3S 3000
#define T_15S 15000
#define DEBOUNCE 50
// ── Couleurs ──────────────────────────────────────────────
struct RGB { uint8_t r, g, b; const char* name; };
const RGB COLORS[] = {
{255,0,0,"Rouge"},{0,255,0,"Vert"},{0,0,255,"Bleu"},
{255,255,0,"Jaune"},{255,128,0,"Orange"},
{128,0,255,"Violet"},{0,255,255,"Cyan"},
{255,255,255,"Blanc"},
};
#define N_COLORS 8
// ── États ─────────────────────────────────────────────────
enum Mode { DEEP_SLEEP, IDLE, BLADE_ON };
Mode mode = IDLE;
bool switchOn = false;
bool bladeOn = false;
uint8_t colorIdx = 0;
uint8_t volume = 80;
// ✅ NOUVEAU
bool inSettings = false;
// ── Bouton ────────────────────────────────────────────────
bool btnState = HIGH;
unsigned long pressStart = 0;
unsigned long lastChange = 0;
bool isHeld = false;
int blinkReached = 0;
bool shortFlag = false;
// ── Gestes ────────────────────────────────────────────────
enum Gesture { G_NONE, G_CLASH, G_TWIST_R, G_TWIST_L };
Gesture pendingGesture = G_NONE;
// ── LED anim ──────────────────────────────────────────────
enum LedAnim { ANIM_NONE, ANIM_COLOR_CYCLE };
LedAnim ledAnim = ANIM_NONE;
unsigned long animStart = 0;
// ── Blink bouton ──────────────────────────────────────────
uint8_t blinkCount=0, blinkTarget=0;
uint16_t blinkInterv=200;
unsigned long lastBlink=0;
bool blinkState=false;
// ─────────────────────────────────────────────────────────
void setup() {
Serial.begin(115200);
pinMode(PIN_LED_R, OUTPUT);
pinMode(PIN_LED_G, OUTPUT);
pinMode(PIN_LED_B, OUTPUT);
pinMode(PIN_BTN_LED, OUTPUT);
pinMode(PIN_BTN, INPUT_PULLUP);
pinMode(PIN_SWITCH, INPUT_PULLUP);
pinMode(PIN_BUZZER, OUTPUT);
Wire.begin(PIN_SDA, PIN_SCL);
Wire.beginTransmission(MPU_ADDR);
Wire.write(MPU_PWR_MGMT_1);
Wire.write(0);
Wire.endTransmission();
Serial.println("Sabre prêt");
}
// ─────────────────────────────────────────────────────────
void loop() {
switchOn = (digitalRead(PIN_SWITCH) == LOW);
readSerial();
updateButton();
updateBlink();
updateLedAnim();
updateBtnLED(); // ✅ centralisé
if (!switchOn) handleSimpleMode();
else handleFullMode();
}
// ── LED bouton centralisée ✅ ─────────────────────────────
void updateBtnLED() {
if (mode == DEEP_SLEEP) {
digitalWrite(PIN_BTN_LED, LOW);
return;
}
if (inSettings) {
digitalWrite(PIN_BTN_LED, LOW);
return;
}
digitalWrite(PIN_BTN_LED, HIGH);
}
// ── Bouton ────────────────────────────────────────────────
void updateButton() {
uint8_t raw = digitalRead(PIN_BTN);
unsigned long now = millis();
if (raw != btnState && now - lastChange > DEBOUNCE) {
btnState = raw;
lastChange = now;
if (btnState == LOW) {
pressStart = now;
isHeld = true;
blinkReached = 0;
inSettings = true; // ✅ entrée réglage
} else {
isHeld = false;
inSettings = false; // ✅ sortie réglage
if (now - pressStart < T_SHORT) shortFlag = true;
}
}
if (isHeld) {
long held = now - pressStart;
if (held >= T_2S && blinkReached < 2000) {
blinkReached = 2000;
startColorCycle();
}
}
}
// ── Mode simple ───────────────────────────────────────────
void handleSimpleMode() {
if (shortFlag) {
shortFlag = false;
bladeOn = !bladeOn;
if (bladeOn) {
setColorDirect(colorIdx);
} else {
setRGB(0,0,0);
}
}
}
// ── Mode complet ──────────────────────────────────────────
void handleFullMode() {
if (mode == IDLE && shortFlag) {
shortFlag = false;
igniteBlade();
}
if (mode == BLADE_ON && shortFlag) {
shortFlag = false;
extinguishBlade();
}
}
// ── Actions ───────────────────────────────────────────────
void igniteBlade() {
mode = BLADE_ON;
bladeOn = true;
setColorDirect(colorIdx);
playTone(600,200);
}
void extinguishBlade() {
mode = IDLE;
bladeOn = false;
setRGB(0,0,0);
playTone(300,200);
}
// ── Couleurs ──────────────────────────────────────────────
void setRGB(int r,int g,int b){
digitalWrite(PIN_LED_R,r>0);
digitalWrite(PIN_LED_G,g>0);
digitalWrite(PIN_LED_B,b>0);
}
void setColorDirect(uint8_t idx) {
RGB c = COLORS[idx];
setRGB(c.r,c.g,c.b);
}
// ── Couleur cycle ─────────────────────────────────────────
void startColorCycle() {
ledAnim = ANIM_COLOR_CYCLE;
animStart = millis();
}
void updateLedAnim() {
if (ledAnim == ANIM_NONE) return;
unsigned long e = millis() - animStart;
uint8_t idx = (e / 800) % N_COLORS;
colorIdx = idx;
setColorDirect(idx);
if (shortFlag) {
shortFlag = false;
ledAnim = ANIM_NONE;
}
}
// ── Blink (LED bouton utilisé aussi pour feedback) ────────
void startBlink(uint8_t n,uint16_t ms){
blinkTarget=n*2;
blinkCount=0;
blinkInterv=ms;
}
void updateBlink(){
if (!blinkTarget) return;
if (millis()-lastBlink>=blinkInterv){
lastBlink=millis();
blinkState=!blinkState;
digitalWrite(PIN_BTN_LED,blinkState);
if(++blinkCount>=blinkTarget){
blinkTarget=0;
}
}
}
// ── Serial ────────────────────────────────────────────────
void readSerial(){
if(!Serial.available()) return;
char c=Serial.read();
if(c=='c') pendingGesture=G_CLASH;
if(c=='r') pendingGesture=G_TWIST_R;
if(c=='l') pendingGesture=G_TWIST_L;
}
// ── Audio ─────────────────────────────────────────────────
void playTone(int f,int d){
digitalWrite(PIN_BUZZER,HIGH);
delay(10);
digitalWrite(PIN_BUZZER,LOW);
}