J'ai bien avancé dans cette partie qui semble fonctionnelle.
et voici le code
//*************************************************************************
// GESTION DE 8 AIGUILLAGES PAR SERVOMOTEURS
//*************************************************************************
// le 25/12/2020 à 00:09
// fonctionnement testé le 25/12/2020 à 06:22 => OK
//=========================================================================
// I) Détection du mode de fonctionnement par BP permanent connecté sur A0
// I-a le BP est enfoncé en position basse => mode "REGLAGE"
// - sélection du servomoteur concerné
// sélecteur rotatif 8 positions sur A5 => à faire
// - positionnement du servo concerné au point milieu
// - RV butée gauche sur A3
// - RV butée droite sur A4
// - 1 BP enregistrement sur eeprom
// I-b le BP reste en position haute => mode "COMMANDE"
// - sélection du BP enfoncé sur A1
// - connection du servomoteur concerné au pin+2
// - lecture des données de ce servomoteur
// - basculement de la position
// - enregistrement en eeprom
// II) Gestion des 16 leds (bicolores) concernées
//=========================================================================
#include
#include
Servo servoAiguillage[8];
const int limitAngleMin = 1250;
const int limitAngleMax = 1750;
const int PointMilieu = 1500;
int angleMin[8] = {1250, 1250, 1250, 1250, 1250, 1250, 1250, 1250}; // à initialiser dans l'eeprom
int angleMax[8] = {1750, 1750, 1750, 1750, 1750, 1750, 1750, 1750}; // à initialiser dans eeprom
int angleIntermediaire[8] = {PointMilieu, PointMilieu, PointMilieu, PointMilieu, PointMilieu, PointMilieu, PointMilieu, PointMilieu}; // valeur de l'angle intermédiaire pendant le mouvement
int DernierePositionServo[8]; // PointMilieu = milieu, angleMin[0] = gauche, angleMax[0] = droite => à lire dans eeprom
int sensMouvement[8];
const byte vitesse = 1; // multiplicateur permettant de régler la vitesse de déplacement
int Limite[8];
int valeurLectureButee; // valeur de la résistance variable trascrite en mS
const byte pinBPMode = 0; // le BP de sélection de mode est connecté sur A0 => A3 en production
const byte pinBPAiguillages = 1; // les 8 BP de choix d'aiguillage en fonctionnement sont connectés sur A1 => A4 en production
const byte pinRVButees = 2; // la résistance variable de réglage des butées est connecté sur A2 => A5 en production
const byte pinSwitchSelecteurServo = 3; // les 8 switches de sélection du servo à régler sont connectés sur A3 => A6 en production
const byte pinBPValidationReglage = 4; // le BP de validation des réglages est connecté sur A4 => A7 en production
const byte pinServo = 2; // les servos sont connectés à partir de D2
byte numPoussoir;
const byte Temporisation = 3;
byte CalculLimite(){
if (DernierePositionServo[numPoussoir] == PointMilieu){ // le servo est au PointMilieu, il doit regagner angleMin[0]
sensMouvement[numPoussoir] = -1;
Limite[numPoussoir] = angleMin[numPoussoir];
DernierePositionServo[numPoussoir] = angleMin[numPoussoir];
} else if (DernierePositionServo[numPoussoir] == angleMin[numPoussoir]){ // le servo est en butée gauche, il doit regagner angleMax[0]
sensMouvement[numPoussoir] = 1;
Limite[numPoussoir] = angleMax[numPoussoir];
DernierePositionServo[numPoussoir] = angleMax[numPoussoir];
} else { // le servo est en butée droite (ou autre), il doit regagner angleMin[0]
sensMouvement[numPoussoir] = -1;
Limite[numPoussoir] = angleMin[numPoussoir];
DernierePositionServo[numPoussoir] = angleMin[numPoussoir];
}
}
void setup() {
Serial.begin(9600); // connexion au moniteur série de l'ordinateur
/* lecture des derniers réglages dans l'eeprom */
/* Initialisation si première utilisation */
/* les informations du servo 1 sont dans les bytes 0 à 9, ceux du servo 2 de 10 à 19 ... and so on ... */
for(byte i = 0; i < 8; i++)
{
angleMin[i] = EEPROM.read(i * 10) | ((int)EEPROM.read((i * 10) + 1)) << 8; // lecture des 2 bytes pour int angleMin[]
if (angleMin[i] > 1500 || angleMin[i] < 256){ // si incohérence de valeur ou initialisation (=255)
angleMin[i] = limitAngleMin; // on enregistre la limite pour angleMin
EEPROM.update((i * 10), angleMin[i] & 0xFF); // écrit le premier byte de la valeur int
EEPROM.update((i * 10) + 1, angleMin[i] >> 8); // écrit le second byte de la valeur int
} // fin de if (angleMin[i] > 1500 || angleMin[i] < 256)
angleMax[i] = EEPROM.read((i * 10) + 2) | ((int)EEPROM.read((i * 10) + 3)) << 8;// lecture des 2 bytes pour int angleMax[]
if (angleMax[i] < 1500) { // si incohérence de valeur ou initialisation (=255)
angleMax[i] = limitAngleMax; // on enregistre la limite pour angleMax
EEPROM.update((i * 10) + 2, angleMax[i] & 0xFF); // écrit le premier byte de la valeur int
EEPROM.update((i * 10) + 3, angleMax[i] >> 8); // écrit le second byte de la valeur int
} // fin de if (angleMax[i] == 0)
DernierePositionServo[i] = EEPROM.read((i * 10) + 4) | ((int)EEPROM.read((i * 10) + 5)) << 8;
if (DernierePositionServo[i] < angleMin[i] || DernierePositionServo[i] > angleMax[i]){
DernierePositionServo[i] = PointMilieu;
EEPROM.update((i * 10) + 4, DernierePositionServo[i] & 0xFF); // écrit le premier byte de la valeur int
EEPROM.update((i * 10) + 5, DernierePositionServo[i] >> 8); // écrit le second byte de la valeur int
} // if (DernierePositionServo[i] == 0
/* fin de lecture des données et d'initialisation de l'eeprom */
angleIntermediaire[i] = DernierePositionServo[i]; // on met le servo à sa dernière position
servoAiguillage[i].attach(i + pinServo);
servoAiguillage[i].writeMicroseconds(angleIntermediaire[i]);
delay(150);
servoAiguillage[i].detach();
} // fin de for
} // fin de setup
void loop() {
if (analogRead(pinBPMode) <= 512) { // le bouton MODE est connecté à la broche A0
//Serial.print("Bouton : "); // Debug
//Serial.print(pinChoixMode); // Debug
//Serial.print(" en mode REGLAGE : "); // Debug
//Serial.println(analogRead(pinChoixMode)); // Debug
//*************************
// mode REGLAGE
//*************************
/* Détermination de l'aiguillage en cours */
byte ServoEnCours = (analogRead(pinSwitchSelecteurServo) + 64) / 128; // retourne le n° du servo à régler sélectionné par switches
delay(25); // pour éviter les rebonds
ServoEnCours = 0; //Débug
if (ServoEnCours < 8) {
servoAiguillage[ServoEnCours].attach(pinServo + ServoEnCours); // on connecte le servo à régler au pin correspondant à partir de D2
if (byte j = 0){
j += 1;
servoAiguillage[ServoEnCours].writeMicroseconds(PointMilieu); // positionne le servo au point milieu
} else {
valeurLectureButee = analogRead(pinRVButees); // Lecture de la résistance variable sur le pin A2 => valeurs de 0 à 1023)
delay(25); // pour éviter les rebonds ... utilité à vérifier
valeurLectureButee = map(valeurLectureButee, 0, 1023, 0, 2500); // conversion en microsecondes
if (valeurLectureButee > limitAngleMax) { // on reste dans les limites
valeurLectureButee = limitAngleMax;
} else if (valeurLectureButee < limitAngleMin){
valeurLectureButee = limitAngleMin;
} // fin de if (valeurLectureButee > limitAngleMax)
Serial.print("Réglage aiguillage N° ");
Serial.println(ServoEnCours); //Débug
Serial.println(valeurLectureButee); //Débug
servoAiguillage[ServoEnCours].writeMicroseconds(valeurLectureButee); // positionne le servomoteur
delay(Temporisation); // repos
/* on enregistre le réglage par l'action d'un bouton */
int validation = analogRead(pinBPValidationReglage); // on détecte si le bouton poussoir de validation a été appuyé
delay(25); // pour éviter les rebonds ... utilité à vérifier
if ( validation < 513) {
// si valeurLectureButee < PointMilieu c'est la butée gauche qui a été réglée => angleMin[ServoEnCours] = valeurLectureButee
// sinon c'est la butée droite qui a été réglée => angleMax[ServoEnCours] = valeurLectureButee
Serial.print(validation); // débug
if (valeurLectureButee < PointMilieu){
angleMin[ServoEnCours] = valeurLectureButee;
Serial.print("Angle mini N° "); //Débug
Serial.println(ServoEnCours); //Débug
Serial.print("réglé à "); //Débug
Serial.println(angleMin[ServoEnCours]); //Débug
EEPROM.update((ServoEnCours * 10), angleMin[ServoEnCours] & 0xFF); // écrit le premier byte de la valeur int angleMin
EEPROM.update((ServoEnCours * 10) + 1, angleMin[ServoEnCours] >> 8); // écrit le second byte de la valeur int angleMin
} else {
angleMax[ServoEnCours] = valeurLectureButee;
Serial.print("Angle maxi N° "); //Débug
Serial.println(ServoEnCours); //Débug
Serial.print("réglé à "); //Débug
Serial.println(angleMax[ServoEnCours]); //Débug
EEPROM.update((ServoEnCours * 10) + 2, angleMax[ServoEnCours] & 0xFF); // écrit le premier byte de la valeur int angleMax
EEPROM.update((ServoEnCours * 10) + 3, angleMax[ServoEnCours] >> 8); // écrit le second byte de la valeur int angleMax
} // fin de (valeurLectureButee < PointMilieu)
angleIntermediaire[ServoEnCours] = valeurLectureButee;
} // fin de if (validation < 513)
} // fin de if (byte j = 0)
} // fin de if (ServoEnCours < 8)
} else {
//Serial.print("Bouton : "); // Debug
//Serial.print(pinChoixMode); // Debug
//Serial.print(" en mode COMMANDE : "); // Debug
//Serial.println(analogRead(pinChoixMode)); // Debug
//*************************
// mode COMMANDE
//*************************
if (analogRead(pinBPAiguillages) <1023) { // on a appuyé sur un des BP de commande des aiguillages
// on passe en mode "COMMANDE" des servos
Serial.println("Mode commande des servos"); // Débug
numPoussoir = (analogRead(pinBPAiguillages) + 64) / 128; // retourne le n° du poussoir activé pour 8 poussoirs
// numPoussoir = (analogRead(pinBPAiguillages) + 256) / 512; // retourne le n° du poussoir activé pour 2 poussoirs
delay(25); // pour éviter les rebonds ... utilité à vérifier
// Serial.println(analogRead(pinBPAiguillages)); // Débug
Serial.print("Poussoir N° "); // Débug
Serial.println(numPoussoir); // Débug
if (numPoussoir < 8) {
servoAiguillage[numPoussoir].attach(numPoussoir + pinServo); // on connecte le servomoteur correspondant au BP
CalculLimite();
Serial.println(Limite[numPoussoir]);
Serial.println(sensMouvement[numPoussoir]);
Serial.println(DernierePositionServo[numPoussoir]);
do {
angleIntermediaire[numPoussoir] = angleIntermediaire[numPoussoir] + (sensMouvement[numPoussoir] * vitesse);
servoAiguillage[numPoussoir].writeMicroseconds(angleIntermediaire[numPoussoir]);
if(angleIntermediaire[numPoussoir] == Limite[numPoussoir]){
EEPROM.update((numPoussoir * 10) + 4, angleIntermediaire[numPoussoir] & 0xFF); // écrit le premier byte de la valeur int
EEPROM.update((numPoussoir * 10) + 5, angleIntermediaire[numPoussoir] >> 8); // écrit le premier byte de la valeur int
Serial.print("Dernière position : "); // Débug
Serial.println(angleIntermediaire[numPoussoir]); // Débug
break;
} // fin de if(angleIntermediaire[numPoussoir] == Limite[numPoussoir])
delay(Temporisation);
}
while(1); // fin de do
delay(150);
servoAiguillage[numPoussoir].detach();
} // fin de if (numPoussoir < 8)
} // fin de (analogRead(pinBPAiguillages) <1023)
} // (analogRead(pinBPMode) > 512)
}// fin de loop
Reste à déterminer si je gère les leds témoins par programmation ou par un des micro-contacts des moteurs d'aiguillages comme prévu initialement. Le choix du servomoteur en cours de réglage se fera au plus simple, soit par un sélecteur rotatif si j'en trouve des minis à 8 positions, soit tout simplement par un jeu de cavaliers.
Il va falloir créer une platine qui va regrouper tous ces éléments en ajoutant un témoin de mode de fonctionnement (Vert = COMMANDE, bleu = REGLAGE), éventuellement un petit buzer pour "marquer" les actions du bouton de validation de réglages et, ce serait l'idéal, un petit écran pour visualiser les valeurs des réglages.
J'ai commencé à étudier ce PCB
Les essais avec un montage réel d'aiguillage sur mon plateau de test met en évidence un point faible de mon système. En raison des fixations mécaniques des moteurs d'aiguillages, il est très difficile, voire quasiment impossible, de faire correspondre le point milieu théorique du servomoteur (1500 mS) avec celui des aiguillages. Il faudra donc définir et enregistrer le point milieu de chaque aiguillage. Ce qui m'oblige à modifier ma procédure de réglage pour qu'elle tienne compte de cette valeur. Il faudra donc un ordre précis des réglages.
A noter que l'espace entre les deux positions gauche et droite est tres faible de l'ordre de 75mS, il faut donc augmenter la sensibilité de la résistance variable ... à bientôt pour la suite.
Cet article provient de Le réseau du Mesnil-sur-Jorg
L'url pour cet article est :
http://wgnt-train.fr/article.php?sid=153