/*
******************************************
* Module de réglage *
* des courses *
* de sero-moteur *
* *
* Application => réglage des angles *
* des aiguillages *
* Lecture des valeurs sur écran Oled I2C *
******************************************
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! Licence d’utilisation – Philippe Guenet !
! !
! Ce code est librement téléchargeable pour un usage personnel et non commercial. !
! !
! Toute utilisation commerciale, professionnelle ou rémunérée est interdite. !
! !
! La redistribution, la copie publique ou l’intégration dans un autre projet !
! sont interdites. !
! !
! Aucune modification ou adaptation n’est autorisée sans l’accord écrit préalable !
! de l’auteur. !
! !
! L’auteur conserve tous les droits de propriété intellectuelle sur ce code. !
! !
! L’auteur ne saurait être tenu responsable d’aucun dommage résultant de !
! l’utilisation de ce code. !
! !
! L’utilisation du code vaut acceptation de ces conditions. !
! !
! © Philippe Guenet – Tous droits réservés - [email protected] - https://wgnt-train.fr !
! !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Pour des raisons de sécurité mécanique on démarre en position "Point Milieu". Il faut donc
appuyer sur le bouton poussoir pour aller en mode "Réglage"
*/
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Servo.h>
#include <Bounce2.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
Servo servoAiguillage;
Bounce boutonMode;
// =====================================================================
// Broches
// =====================================================================
const byte POT_PIN = A1;
const byte BP_PIN = 4;
const byte SWITCH_PIN = 5;
const byte LED_PIN = 7;
const byte SERVO_PIN = 10;
// =====================================================================
// Paramètres servo
// =====================================================================
const int SERVO_MIN_US = 1000;
const int SERVO_MAX_US = 2000;
const int SERVO_MILIEU_US = (SERVO_MIN_US + SERVO_MAX_US) / 2;
const int ANGLE_MIN_DEG = 30;
const int ANGLE_MAX_DEG = 150;
const int DIFFERENTIEL = 5;
int positionServoUs = SERVO_MILIEU_US;
bool dernierModeAffichage = HIGH;
// =====================================================================
// Gestion LED
// =====================================================================
const unsigned long PERIODE_CLIGNOTEMENT = 300;
unsigned long precedentClignotement = 0;
bool etatLed = LOW;
enum ModeSysteme
{
MODE_POINT_MILIEU,
MODE_REGLAGE
};
ModeSysteme modeCourant = MODE_POINT_MILIEU;
// =====================================================================
// Prototypes
// =====================================================================
void changerMode();
void gererModeMilieu();
void gererModeReglage();
int lirePotentiometreFiltre();
void afficherPosition(int valeurUs);
bool affichageEnDegres();
int convertirUsVersDegres(int valeurUs);
// =====================================================================
// Setup
// =====================================================================
void setup() {
pinMode(BP_PIN, INPUT_PULLUP);
pinMode(SWITCH_PIN, INPUT_PULLUP);
pinMode(LED_PIN, OUTPUT);
boutonMode.attach(BP_PIN);
boutonMode.interval(10);
servoAiguillage.attach(SERVO_PIN);
oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
oled.clearDisplay();
oled.setTextColor(WHITE);
oled.setTextSize(2);
oled.setCursor(48, 0);
oled.print(F("PRET"));
oled.display();
delay(500);
positionServoUs = SERVO_MILIEU_US;
servoAiguillage.writeMicroseconds(positionServoUs);
dernierModeAffichage = digitalRead(SWITCH_PIN);
afficherPosition(positionServoUs);
} // Fin de setup()
void loop() {
boutonMode.update();
bool modeAffichage = digitalRead(SWITCH_PIN);
if (modeAffichage != dernierModeAffichage) {
dernierModeAffichage = modeAffichage;
afficherPosition(positionServoUs);
} // Fin de if (modeAffichage != dernierModeAffichage)
if (boutonMode.fell()) {
changerMode();
} // Fin de if (boutonMode.fell())
switch (modeCourant) {
case MODE_POINT_MILIEU:
gererModeMilieu();
break;
case MODE_REGLAGE:
gererModeReglage();
break;
} // Fin de switch (modeCourant)
} // Fin de loop()
void changerMode(){
if (modeCourant == MODE_REGLAGE) {
modeCourant = MODE_POINT_MILIEU;
positionServoUs = SERVO_MILIEU_US;
servoAiguillage.writeMicroseconds(positionServoUs);
afficherPosition(positionServoUs);
precedentClignotement = millis();
} else {
modeCourant = MODE_REGLAGE;
digitalWrite(LED_PIN, LOW);
etatLed = LOW;
int valeurPot = lirePotentiometreFiltre();
positionServoUs = map(valeurPot, 0, 1023, SERVO_MIN_US, SERVO_MAX_US);
servoAiguillage.writeMicroseconds(positionServoUs);
afficherPosition(positionServoUs);
} // Fin de if (modeCourant == MODE_REGLAGE)
} // Fin de procédure changerMode()
void gererModeMilieu() {
if (millis() - precedentClignotement >= PERIODE_CLIGNOTEMENT) {
precedentClignotement = millis();
etatLed = !etatLed;
digitalWrite(LED_PIN, etatLed);
} // Fin de if (millis() - precedentClignotement >= PERIODE_CLIGNOTEMENT)
} // Fin de procédure gererModeMilieu()
void gererModeReglage() {
int valeurPot = lirePotentiometreFiltre();
int nouvellePosition = map(valeurPot, 0, 1023, SERVO_MIN_US, SERVO_MAX_US);
if (abs(nouvellePosition - positionServoUs) > DIFFERENTIEL) {
positionServoUs = nouvellePosition;
servoAiguillage.writeMicroseconds(positionServoUs);
afficherPosition(positionServoUs);
} // Fin de if (abs(nouvellePosition - positionServoUs) > DIFFERENTIEL)
} // Fin de procédure gererModeReglage()
int lirePotentiometreFiltre() {
long somme = 0;
for (byte i = 0; i < 5; i++) {
somme += analogRead(POT_PIN);
} // Fin de for (byte i = 0; i < 5; i++)
return somme / 5;
} // Fin de procédure lirePotentiometreFiltre()
void afficherPosition(int valeurUs) {
oled.clearDisplay();
oled.setTextColor(WHITE);
oled.setTextSize(1);
String titre = F("Reglage Aiguillage");
int16_t x1, y1;
uint16_t w1, h1;
oled.getTextBounds(titre, 0, 0, &x1, &y1, &w1, &h1);
oled.setCursor((SCREEN_WIDTH - w1) / 2, 0);
oled.print(titre);
String texteMode;
if (modeCourant == MODE_REGLAGE) {
texteMode = F("MODE REGLAGE");
} else {
texteMode = F("MODE POINT MILIEU");
} // Fin de if (modeCourant == MODE_REGLAGE)
oled.getTextBounds(texteMode, 0, 0, &x1, &y1, &w1, &h1);
oled.setCursor((SCREEN_WIDTH - w1) / 2, 10);
oled.print(texteMode);
String valeurAffichee;
if (affichageEnDegres()) {
int angleDegres = convertirUsVersDegres(valeurUs);
valeurAffichee = String(angleDegres) + (char)247;
} else {
valeurAffichee = String(valeurUs) + " us";
} // Fin de if (affichageEnDegres())
oled.setTextSize(2);
int16_t x2, y2;
uint16_t w2, h2;
oled.getTextBounds(valeurAffichee, 0, 0, &x2, &y2, &w2, &h2);
oled.setCursor((SCREEN_WIDTH - w2) / 2, 22);
oled.print(valeurAffichee);
const int barreX = 10;
const int barreY = 50;
const int barreLargeur = SCREEN_WIDTH - 20;
const int barreHauteur = 8;
oled.drawRect(barreX, barreY, barreLargeur, barreHauteur, WHITE);
int largeurRemplie = map(valeurUs, SERVO_MIN_US, SERVO_MAX_US, 0, barreLargeur - 2);
oled.fillRect(barreX + 1, barreY + 1, largeurRemplie, barreHauteur - 2, WHITE);
int positionMilieu =
map(SERVO_MILIEU_US, SERVO_MIN_US, SERVO_MAX_US, 0, barreLargeur - 2);
oled.drawLine(barreX + 1 + positionMilieu, barreY - 3, barreX + 1 + positionMilieu, barreY + barreHauteur + 2, WHITE);
int positionActuelle = map(valeurUs, SERVO_MIN_US, SERVO_MAX_US, 0, barreLargeur - 2);
oled.fillTriangle(barreX + 1 + positionActuelle - 3, barreY - 4, barreX + 1 + positionActuelle + 3, barreY - 4, barreX + 1 + positionActuelle, barreY - 1, WHITE);
oled.setTextSize(1);
oled.setCursor(barreX, barreY + 10);
oled.print(F("MIN"));
oled.setCursor(barreX + barreLargeur - 18, barreY + 10);
oled.print(F("MAX"));
oled.display();
} // Fin de procédure afficherPosition(int valeurUs)
bool affichageEnDegres() { return digitalRead(SWITCH_PIN);}
int convertirUsVersDegres(int valeurUs) {
return map(valeurUs,
SERVO_MIN_US,
SERVO_MAX_US,
ANGLE_MIN_DEG,
ANGLE_MAX_DEG);
}