je suis en train de concevoir un petit système monté sur une grue; un capteur inductif détecte les
dents de la couronne de la grue. le temps écoulé entre la détection de 2 dents me donne une valeur qui va déclencher ou non un relais. si le temps est trop court c'est que la vitesse de rotation de la grue est trop rapide, dans ce cas j'active le relais qui activera a son tour un ralentisseur couplé aux moteurs de la grue.
J'ai réalisé un montage avec une carte UNO. le relais 5v est branché sur la borne 7 et le gnd.
le capteur (ILS pour le test) est câblé sur la borne 8 et le gnd.
j'ai écris un code mais ca ne fonctionne pas correctement.
peux importe la vitesse de détection le relais s'enclenche.
par contre il s'éteint bien au bout d'un moment si il ne détecte qu'une impulsion
voici le code
type or paste code here
`const int capteurPin = 8; // Broche à laquelle est connecté le capteur d'impulsions
const int relaisPin = 7; // Broche à laquelle est connecté le relais
unsigned long dernierTemps = 0; // Variable pour stocker le dernier temps d'impulsion
void setup() {
pinMode(capteurPin, INPUT);
pinMode(relaisPin, OUTPUT);
digitalWrite(relaisPin, LOW); // Initialiser le relais éteint
Serial.begin(9600); // Initialisation de la communication série pour le débogage
}
void loop() {
int etatCapteur = digitalRead(capteurPin);
if (etatCapteur == HIGH) { // Lorsqu'une impulsion est détectée
unsigned long tempsActuel = millis();
unsigned long tempsEcoule = tempsActuel - dernierTemps;
if (tempsEcoule <= 3000) { // Si le temps entre deux impulsions est inferieur ou égal à 3 secondes
digitalWrite(relaisPin, HIGH); // Activer le relais
Serial.println("Relais activé");
}
else {
digitalWrite(relaisPin, LOW);
}
dernierTemps = tempsActuel; // Mettre à jour le dernier temps d'impulsion
}
else { // Si aucune impulsion n'est détectée
unsigned long tempsActuel = millis();
unsigned long tempsEcoule = tempsActuel - dernierTemps;
if (tempsEcoule > 3000) { // Si le temps depuis la dernière impulsion est supérieur à 3 secondes
digitalWrite(relaisPin, LOW); // Désactiver le relais
Serial.println("Relais désactivé");
}
}
}
Je précise pour jpbbricole, les grues sont installées sur une ile française ,c'est lorsque la grue est en girouette et qu'il y a de forts coups de vent, on veut activer les ralentisseurs des moteurs pour ralentir la rotation de la grue.
pour tester mon code j'ai utilisé un simple ILS qui créé des impulsion grâce au passage d'un aimant.
pour le montage final je vais utiliser un capteur inductif 5v (LJ12A3-4NA-A710).
peut etre devrais-je utiliser le capteur inductif directement ?
le pulseIn() je ne connaissais pas , je vais voir ca de suite.
De plus, selon moi, déterminer la fréquence d'une signal périodique en mesurant la période avec
N'est pas forcémrnt la meilleure solution!
"For example, if value is HIGH, pulseIn() waits for the pin to go from LOW to HIGH, starts timing, then waits for the pin to go LOW and stops timing. Returns the length of the pulse in microseconds"
Un signal peut être périodique et ne pas avoir un rapport cyclique de 50%, par exemple avoir un période de 100ms, être HIGH pendant 10ms et LOW pendant 90ms, comme un signal périodique de PWM.
Il est périodique, mais si vous ne mesurez que le temps où il est à niveau HIGH, vous aurez tout faux sur sa rélle période.
Il vaut mieux je trouve, agir par interruption sur un front montant ou descendant qui eux n'arrivent que tous les T = période du signal.
en fait j'ai remarqué aussi que , si le capteur reste sur HIGH un moment, il n'y a pas de coupure du relais.
en gros si le capteur reste en face d'une dent de la couronne trop longtemps je veux désactiver les ralentisseurs, or pour le moment ca ne fonctionne pas.
On ne cherche la période mais la vitesse.
Le temps de niveau HIGH est quand même proportionnel au temps que passe la dent devant le détecteur, donc la vitesse.
Pour ma culture personnelle, j'ai un peu de mal à visualiser votre systéme à couronne dentée.
Il me semble que vous ne remettez pas correctement "à l'heure" la variable dernierTemps
Je l'aurais mise à l'heure par
Juste aprés le
Par contre, votre commande de relais me fait peur si c'est réllement un relais 5V (et non un module).
Quel est donc ce relais SVP?
PS:
Si le ILS se ferme face à une dent et qu'il est relié un PULLUP, c'est effectivement un niveau bas (LOW) qu'il renvoit dans ce cas là.
QUESTION:
Voici mon scénario:
La grue est freinée en rotation, le capteur ILS est positionné en face de la fin d'une dent.
Cela fait plus de 3s que la grue est freinée, vous relâchez le relais, la grue repart en rotation, comme l'IKS est en face d'une fin de dent, il faut moins de 3s pour finir le passage de la fin de la dent devant l'ILS.
Une autre piste pourrait être l'usage d'une interruption.
Je te donne un exemple, l'ILS doit être sur la pin 2.
Je n'ai pas essayé avec un ILS, il faudra, peut être un anti-rebonds?
Le programme:
/*
Name: ARDFR_fredo37_GrueRoiueVitesse.ino
Created: 07.03.2024 20:06:56
Author: jpbbricole/fredo37
Remarque: Mesurer le vitesse d'une roue dentée (couronne d'une grue)
https://forum.arduino.cc/t/probleme-pour-commander-un-relais-avec-capteur-ils/1232291
*/
const int capteurPin = 2; // Pin2 pour interruption
const int capteurEtatOn = FALLING; // Passage de HIGH à LOW
const int relaisPin = 7; // Commande du relais
const int relaisEtatOn = HIGH; // Etat pout faire tirer le relais
volatile unsigned long captPulseDbut; // Début de l'impulsion
volatile unsigned long captPulseDuree; // Temps entre 2 dents
volatile boolean captPulseNouvelle = false; // Si nouvelle mesure
unsigned long captPulseMinimum = 1000; // Minimum 1000 microsecondes
unsigned long captPulseAlerte = 30000; //Seuild'alerte microsecondes
void setup()
{
Serial.begin(115200);
pinMode(capteurPin, INPUT_PULLUP); // Autre côté du capteur à GND
pinMode(relaisPin, OUTPUT);
digitalWrite(relaisPin, !relaisEtatOn); // Faire tirer le relais
attachInterrupt(digitalPinToInterrupt(capteurPin), capteurPulse, capteurEtatOn); // Démarrer l'interruption
}
void loop()
{
if (captPulseNouvelle)
{
if (captPulseDuree > captPulseMinimum)
{
Serial.println(captPulseDuree);
if (captPulseDuree < captPulseAlerte)
{
Serial.println("\tRelais tire");
}
}
captPulseNouvelle = false;
}
}
void capteurPulse()
{
captPulseDuree = micros() - captPulseDbut;
captPulseDbut = micros();
captPulseNouvelle = true; // Nouvelle mesure disponible
}
PS:Quel est le temps entre 2 dents à vitesse maximum ?
Mais puisque le défilement des dents est très lent ... Si j'ai bien compris, et qu'on mesure "une vitesse" ou plutôt un temps d'arrêt sur une dent, ça devrait pouvoir marcher sans utiliser les interruptions.
Surtout si on remet les pendules à l'heure aux bons moments.
Et je présent que ce n'est pas le cas, comme expliqué au post11.
C'est bien aussi, je crois, avant d'essayer de nouvelles formules, de savoir pourquoi l'actuelle ne marche pas.
Parce qu'il ne faut pas tester l'état mais le changement d'état.
Il faut tenir compte de l'état actuel et de l'état précédent pour détecter un front.
On est sur des temps de l'ordre de plusieurs secondes, et l'Arduino n'a rien d'autre à faire. Je ne vois pas bien l'intérêt de s'embêter avec des interruptions.
Le défilement des dents d'une couronne de grue n'est pas de l'ordre de plusieurs secondes, c'est beaucoup plus rapide!
Certes, il n'est pas utile de travailler en microsecondes comme dans mon exemple, des millisecondes doivent suffire.
En quoi, c'est embêtant d'utiliser les interruptions?
Personnellement je les prends pour une simplification.
Il y a quelque part une incohérence dans la définition du problème.
D'un côté on peut lire:
Et de l'autre on lit:
On est effectivement en millis, mais 3000 millis, ça reste = à 3s.
Donc au vu du code, je considére que l'utilisateur estime que si une dent reste visible moins de 3 secondes par l'ILS, c'est que ça va trop vite et qu'il faut freiner.
ET QUE
SI une dent reste visible plus de 3 secondes par l'ILS, c'est que ça ne va pas assez vite et qu'il ne faut plus freiner
Donc on peut chercher des bugs de code, si on veut, mais là il me semble, il y a un bug d'algorithme.
En gros, si le moteur va trop vite, on le freine.
Mais comme quand on le freine, il ne va plus assez vite, on relâche le frein.
De plus, on nous dit que quand l'axe tourne normalement, il y a sous l'ILS une nouvelle dent toutes les quelques millis-secondes:
Donc le seuil "Rester moins de 3 secondes sur une dent = trop vite" est incohérent avec à vitesse normale, on reste quelques millis secondes sur une dent.
Je pense personnellement que cela complexifie le code du point de vue d'un débutant.
Surtout que là l'interruption n'apporte rien par rapport à une lecture avec prise du temps au changement d'état.
Surement, mais @fredo37 indique le temps entre deux impulsions doit être limité à 3s !
D'ailleurs le capteur peut détecter toutes les dents, elles sont toutes magnétisées, j'avais crue comprendre qu'un aimant était utilisé?
A priori le moniteur peut être utilisé, pourquoi pas simplement loggé les variables pour montrer à @fredo37 ce que fait sont programme ?