Probleme pour commander un relais avec capteur ILS

Bonjour

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é");
    }
  }
}

Bonsoir fredo37

Je suis un ancien grutier, grue de chantier et camion grue, super boulot, que de bons souvenirs!

Peut-être qu'il faut initialiser l'entrée du capteur:
pinMode(capteurPin, INPUT_PULLUP);

Mets le type exacte de ton capteur.

Vu les temps à mesurer, tu pourrai mesurer avec pulseIn().

Sais tu la fréquence maximum?

A+
Cordialement
jpbbricole

Je plussoie, c'est primordiale, trop souvent les gens suspectent leurs codes alors que c'est leurs branchements qui sont à améliorer.

Donc il serait intéressant pour nous que tu précise quel est la ref de ton capteur stp.

Bonjour a vous et merci pour vos réponses

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.

As-tu une résistance de PULL_DOWN sur l'entrée de L'ILS ?

Bonjour,

Il faut donc déclarer l'entrée 8 en INPUT-PULLUP.

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.

mon cablage test

voila le cablage utilisé pour le test

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.

Bonjour fredo37
Si ton ILS est au GND tu dois initialiser ton entrée INPUT_PULLUP et lire
if (etatCapteur == LOW)

Je veux bien mais:

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.

En principe, vous faite:

Est-ce correct?

Bonjour fredo37

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 ?

Cordialement
jpbbricole

Comme sugeré au post6

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.

Bonsoir fdufnews

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.

Cordialement
jpbbricole

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 ?

Bonjour,

Ce n'est pas tout à fait cela je crois, j'ai lu:

Rester en face d'une dent trop longtemps, c'est un peu comme être à l'arrêt depuis trop longtemps non?

Je ne chipote pas🙄, je cherche â faire comprendre qu'il y a je crois des incohérences dans le sketch.

(Et notamment avec les fameux 3000 millis Secondes...c'est long non?)
Vrai ou Faux?

Oui, je me suis mal exprimé, je faisait référence à son programme, qui active/désactive le relais en fonction de ces 3s entre deux impulsions.

Non, non tu ne chipote pas, je suis bien d'accord avec toi.
je pense aussi qu'il faudrait déjà ré-écrire son programme comme l'indique @fdufnews

m'en vais essayer ca