#include <Wire.h> // Librairie pour I2C
#include <Adafruit_GFX.h> // Librairie graphique de base
#include <Adafruit_SSD1306.h> // Librairie pour l'OLED
#include <Servo.h> // Librairie standard pour le servomoteur
#include <Bounce2.h> // Librairie pour gérer les rebonds du bouton
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
// Initialisation de l'écran OLED
Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Définition des pins
const int potPin = A0; // Pin du potentiomètre (A0 sur Arduino Nano)
const int buttonPin = 2; // Pin du bouton poussoir (D2 sur Arduino Nano)
const int servoPin = 9; // Pin du servomoteur (D9 sur Arduino Nano)
const int ledPin = 13; // LED utilisée pour indiquer le mode (D13 intégré sur Nano)
// Définition des constantes pour les angles
const int angleMini = 500;
const int angleMaxi = 2500;
const int angleMilieu = (angleMini + angleMaxi) / 2;
Servo monServo;
Bounce bouton; // Objet Bounce pour le bouton
// Variables pour le mode "hold" et le clignotement de la LED
bool holdMode = false; // false = mode normal (pot actif), true = servo au milieu et LED clignote
unsigned long lastBlinkMillis = 0;
const unsigned long BLINK_INTERVAL = 300; // Intervalle clignotement en ms
bool ledState = LOW;
void setup() {
Serial.begin(9600);
// Initialisation du bouton avec Bounce2
pinMode(buttonPin, INPUT_PULLUP); // Le bouton est en PULLUP
bouton.attach(buttonPin); // Attacher Bounce2 à la pin du bouton
bouton.interval(10); // Temps de debounce (en millisecondes)
// Initialisation du servomoteur
monServo.attach(servoPin); // Attacher le servomoteur à la pin
// Initialisation de la LED
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);
// Initialisation de l'écran OLED
if(!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Adresse I2C de l'écran OLED
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
oled.clearDisplay();
oled.setTextSize(1); // Taille du texte
oled.setTextColor(WHITE); // Couleur du texte
oled.setCursor(0, 0); // Positionnement du curseur
oled.println(F("Servo Ready"));
oled.display();
monServo.writeMicroseconds(angleMilieu); // Position initiale au milieu
delay(500);
}
void loop() {
// Mise à jour de l'état du bouton avec Bounce2
bouton.update();
// Détection du front descendant pour basculer le mode (toggle)
if (bouton.fell()) {
// Changer l'état du mode hold à chaque appui
holdMode = !holdMode;
if (holdMode) {
// Entrée en mode hold : positionner au milieu et démarrer clignotement
monServo.writeMicroseconds(angleMilieu);
afficherAngle(angleMilieu);
// initialiser l'état de clignotement immédiatement
lastBlinkMillis = millis();
ledState = HIGH;
digitalWrite(ledPin, ledState);
} else {
// Sortie du mode hold : éteindre la LED, laisser le pot reprendre la main
ledState = LOW;
digitalWrite(ledPin, ledState);
// on peut afficher la valeur actuelle lue par le pot au prochain cycle
}
}
// Si on est en mode hold : maintenir la LED en clignotement (tâche de fond non bloquante)
if (holdMode) {
unsigned long now = millis();
if (now - lastBlinkMillis >= BLINK_INTERVAL) {
lastBlinkMillis = now;
ledState = !ledState;
digitalWrite(ledPin, ledState);
}
// Le servo est déjà positionné au milieu lors du basculement.
// Pour sécurité on ré-applique la consigne au cas où (sans bloquer).
monServo.writeMicroseconds(angleMilieu);
// Afficher la position milieu pendant le mode hold
afficherAngle(angleMilieu);
} else {
// Sinon, on ajuste l'angle en fonction du potentiomètre (mode normal)
int potValue = analogRead(potPin); // Lire la valeur du potentiomètre
int servoValue = map(potValue, 0, 1023, angleMini, angleMaxi); // Mapper la valeur pour les microsecondes
monServo.writeMicroseconds(servoValue); // Positionner le servo
afficherAngle(servoValue); // Afficher l'angle
}
delay(100); // Petit délai pour éviter de surcharger le rafraîchissement
}
void afficherAngle(int angle) {
oled.clearDisplay();
oled.setCursor(0, 0);
oled.print(F("Angle: "));
oled.println(angle);
oled.display();
}