/*
******************************************
* 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 monServo;
Bounce bouton = Bounce();
// Pins
const int potPin = A1;
const int buttonPin = 4;
const int servoPin = 10;
const int ledPin = 7;
// Angles servo (µs)
const int angleMini = 1000;
const int angleMaxi = 2000;
const int angleMilieu = (angleMini + angleMaxi) / 2;
const int differentiel = 5;
// Gestion LED
unsigned long lastBlinkMillis = 0;
const unsigned long BLINK_INTERVAL = 300;
bool ledState = LOW;
// Automate
enum EtatSysteme {
MODE_REGLAGE,
MODE_MILIEU
};
EtatSysteme etat = MODE_MILIEU;
// Position réelle mémorisée du servo
int positionServo = angleMilieu;
// =====================
// SETUP
// =====================
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
pinMode(ledPin, OUTPUT);
bouton.attach(buttonPin);
bouton.interval(10);
monServo.attach(servoPin);
if (!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
while (1);
} // Fin de if (!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C))
oled.clearDisplay();
oled.setTextSize(2);
oled.setTextColor(WHITE);
oled.setCursor(50, 0);
oled.println(F("PRET"));
oled.display();
delay(500);
// Position initiale = milieu
positionServo = angleMilieu;
monServo.writeMicroseconds(positionServo);
afficherAngle(positionServo);
} // Fin de setup()
// =====================
// LOOP
// =====================
void loop() {
bouton.update();
if (bouton.fell()) {
changerEtat();
} // Fin de if (bouton.fell())
switch (etat) {
case MODE_MILIEU:
gererMilieu();
break;
case MODE_REGLAGE:
gererReglage();
break;
} // Fin de switch (etat)
} // Fin de loop()
// =====================
// CHANGEMENT D'ETAT
// =====================
void changerEtat() {
switch (etat) {
case MODE_REGLAGE:
// Passage en point milieu
etat = MODE_MILIEU;
positionServo = angleMilieu;
monServo.writeMicroseconds(positionServo);
afficherAngle(positionServo);
lastBlinkMillis = millis();
break;
case MODE_MILIEU:
// Passage en mode réglage
etat = MODE_REGLAGE;
digitalWrite(ledPin, LOW);
ledState = LOW;
int potValue = lirePotFiltre();
positionServo = map(potValue, 0, 1023, angleMini, angleMaxi);
monServo.writeMicroseconds(positionServo);
afficherAngle(positionServo);
break;
} // Fin de switch(etat)
} // Fin de procédure changerEtat()
// =====================
// MODE MILIEU
// =====================
void gererMilieu() {
if (millis() - lastBlinkMillis >= BLINK_INTERVAL) {
lastBlinkMillis = millis();
ledState = !ledState;
digitalWrite(ledPin, ledState);
} // Fin de if (millis() - lastBlinkMillis >= BLINK_INTERVAL)
} // Fin de procédure gererMilieu()
// =====================
// MODE REGLAGE
// =====================
void gererReglage() {
int potValue = lirePotFiltre();
int servoValue = map(potValue, 0, 1023, angleMini, angleMaxi);
if (abs(servoValue - positionServo) > differentiel) {
positionServo = servoValue;
monServo.writeMicroseconds(positionServo);
afficherAngle(positionServo);
} // Fin de if (abs(servoValue - positionServo) > differentiel)
} // Fin de procédure gererReglage(
// =====================
// LECTURE POT FILTRÉE
// =====================
int lirePotFiltre() {
long somme = 0;
for (int i = 0; i < 5; i++) {
somme += analogRead(potPin);
} // Fin de gererReglage(
return somme / 5;
} // Fin de procédure lirePotFiltre()
// =====================
// AFFICHAGE OLED
// =====================
void afficherAngle(int angle) {
oled.clearDisplay();
oled.setTextColor(WHITE);
oled.setTextSize(1);
String titre = "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 modeTexte = (etat == MODE_REGLAGE) ? "MODE REGLAGE" : "MODE POINT MILIEU";
oled.getTextBounds(modeTexte, 0, 0, &x1, &y1, &w1, &h1);
oled.setCursor((SCREEN_WIDTH - w1) / 2, 10);
oled.print(modeTexte);
oled.setTextSize(2);
String valeur = String(angle) + " us";
int16_t x2, y2;
uint16_t w2, h2;
oled.getTextBounds(valeur, 0, 0, &x2, &y2, &w2, &h2);
oled.setCursor((SCREEN_WIDTH - w2) / 2, 22);
oled.print(valeur);
int barreX = 10;
int barreY = 50;
int barreLargeur = SCREEN_WIDTH - 20;
int barreHauteur = 8;
oled.drawRect(barreX, barreY, barreLargeur, barreHauteur, WHITE);
int largeurRemplie = map(angle, angleMini, angleMaxi, 0, barreLargeur - 2);
oled.fillRect(barreX + 1, barreY + 1, largeurRemplie, barreHauteur - 2, WHITE);
int posMilieu = map(angleMilieu, angleMini, angleMaxi, 0, barreLargeur - 2);
oled.drawLine(barreX + 1 + posMilieu, barreY - 3,
barreX + 1 + posMilieu, barreY + barreHauteur + 2, WHITE);
int posActuelle = map(angle, angleMini, angleMaxi, 0, barreLargeur - 2);
oled.fillTriangle(
barreX + 1 + posActuelle - 3, barreY - 4,
barreX + 1 + posActuelle + 3, barreY - 4,
barreX + 1 + posActuelle, barreY - 1,
WHITE
);
oled.setTextSize(1);
oled.setCursor(barreX, barreY + 10);
oled.print("MIN");
oled.setCursor(barreX + barreLargeur - 18, barreY + 10);
oled.print("MAX");
oled.display();
} // Fin de procédure afficherAngle(int angle)