#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
/*
* Connections
* SSD1306 OLED | Arduino Uno
* ---------------------------
* VCC | +5V (Vcc/power/+ve)
* GND | GND (Ground/-ve/0v)
* SCL | A5 (Serial Clock Line)
* SDA | A4 (Serial Data Line)
*
* KY-040 Rotary Encoder
* ---------------------------
* CLK | D2
* DT | D3
* SW | D4
* VCC | +5V
* GND | GND
*/
const int SCREEN_WIDTH = 128; // OLED display width, in pixels
const int SCREEN_HEIGHT = 64; // OLED display height, in pixels
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Liste des noms à afficher avec des caractères complexes
const char* names[] = {"Alice-Marie Ngom Dieme Badiane", "Bob-Zelda Zion Lion Iron", "Charlie-Balthazar", "Diana-Leclerc", "Edward-Jones", "Fiona-Delacroix",
"Giorgio-Rossi", "Hannah-Debussy", "Ivy-Durand", "Jacques-Michel", "Katherine-Moreno", "Louis-Mendes"};
const int numNames = sizeof(names) / sizeof(names[0]);
// Broches du KY-040
#define ENCODER_PIN_A 2
#define ENCODER_PIN_B 3
#define ENCODER_BUTTON_PIN 4
// Variables pour l'encodeur
volatile int encoderPosition = 0; // Position actuelle
int lastReportedPosition = -1; // Dernière position connue
int currentSelection = 0; // Index de la ligne sélectionnée
bool encoderUpdated = false; // Mise à jour détectée
// Variables pour le défilement
int startIndex = 0; // Indice du premier élément affiché
const int maxVisibleLines = 6; // Nombre de lignes visibles sur l'écran
// Variables pour le défilement horizontal
int scrollOffset = 0; // Décalage de défilement horizontal
const int maxScrollSpeed = 2; // Vitesse de défilement horizontal
int scrollSpeed = 0; // Vitesse actuelle de défilement
// Derniers états des broches de l'encodeur
int lastA = LOW;
void readEncoder() {
int A = digitalRead(ENCODER_PIN_A);
int B = digitalRead(ENCODER_PIN_B);
// Détecte les changements dans CLK (pin A)
if (A != lastA) {
if (A == HIGH) {
if (B == LOW) {
encoderPosition++;
} else {
encoderPosition--;
}
encoderUpdated = true;
}
lastA = A; // Mise à jour de l'état précédent
}
}
void setup() {
Serial.begin(9600);
// Initialisation de l'écran OLED
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Adresse 0x3C pour l'écran OLED
Serial.println(F("SSD1306 allocation failed"));
while (true); // Boucle infinie si erreur
}
// Effacer l'écran et afficher un message initial
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 10);
display.println("Initialisation...");
display.display();
delay(1000);
// Initialisation des broches pour l'encodeur
pinMode(ENCODER_PIN_A, INPUT_PULLUP);
pinMode(ENCODER_PIN_B, INPUT_PULLUP);
pinMode(ENCODER_BUTTON_PIN, INPUT_PULLUP);
// Configuration des interruptions pour détecter les changements sur CLK (pin A)
attachInterrupt(digitalPinToInterrupt(ENCODER_PIN_A), readEncoder, CHANGE);
// Affichage initial de la liste
updateDisplay();
}
void loop() {
// Vérifiez si l'encodeur a changé
if (encoderUpdated) {
encoderUpdated = false;
// Limitez la position dans les bornes valides
currentSelection = constrain(encoderPosition, 0, numNames - 1);
// Mettez à jour l'affichage uniquement si la position a changé
if (currentSelection != lastReportedPosition) {
lastReportedPosition = currentSelection;
// Calculer la ligne visible à afficher
if (currentSelection >= startIndex + maxVisibleLines) {
startIndex = currentSelection - maxVisibleLines + 1;
} else if (currentSelection < startIndex) {
startIndex = currentSelection;
}
// Si le nom est trop long, ajuster le défilement horizontal
if (strlen(names[currentSelection]) > SCREEN_WIDTH / 6) {
scrollSpeed = maxScrollSpeed; // Activer le défilement horizontal
} else {
scrollSpeed = 0; // Désactiver le défilement horizontal
}
updateDisplay();
}
}
// Vérifiez l'état du bouton-poussoir
if (digitalRead(ENCODER_BUTTON_PIN) == LOW) {
Serial.println("Bouton appuyé!");
delay(300); // Anti-rebond basique
}
}
void updateDisplay() {
display.clearDisplay();
// Afficher les noms dans la liste avec un défilement vertical
for (int i = 0; i < maxVisibleLines; i++) {
int index = startIndex + i;
if (index >= numNames) break; // Ne pas afficher d'éléments en dehors de la liste
if (index == currentSelection) {
// Effet "négatif" pour la ligne sélectionnée
display.setTextColor(BLACK, WHITE);
} else {
display.setTextColor(WHITE, BLACK);
}
// Décalage vertical des noms
display.setCursor(0, i * 10); // Chaque ligne occupe 10 pixels de hauteur
// Affichage avec défilement horizontal si nécessaire
if (scrollSpeed > 0 && index == currentSelection) {
display.print(names[index] + scrollOffset);
scrollOffset -= scrollSpeed;
if (scrollOffset < -strlen(names[index]) * 6) { // Si le nom est totalement défilé
scrollOffset = SCREEN_WIDTH; // Réinitialiser le défilement
}
} else {
display.print(names[index]);
}
}
display.display();
}