Projet TIPE Spe PC: Propulsion d'un aimant à l'aide de bobines

Bonjour,

Avec mon ami, on a pour projet de faire une catapulte magnétique à l'aide de bobines contrôlés via des relais Arduino. On a une alimentation externe pour les bobines (2.5 A) et on utilise une Arduino REV3 je crois.
Pour le principe, on a un mobile attaché a un fil de pèche tendu dans un tube en plexiglass que l'on fait passer dans nos bobines, nos deux capteurs sont entre les bobines. Et je pense c'est "normal" mais lors de l'activation des relais, indépendamment de si les bobines sont alimentés ou non, on voit quelque chose sur notre moniteur série, si quelqu'un sait, c'est surement du brouillage.

Jusqu'ici, tout allait bien, sauf que nous souhaitons, à l'aide de deux capteurs a effets Hall, déterminer la vitesse de notre mobile afin de pouvoir allumer la seconde bobine au bon moment, connaissant la distance entre les bobines et entre les capteurs. On a l'impression que notre carte est potentiellement trop lente par rapport aux calculs à fournir.
Voilà, donc sur le code si joint, on arrive pas à faire apparaitre et à utiliser notre vitesse justement pour contrôler la bobine. Si une âme charitable aurait une bonne idée pour fusionner les deux codes, et ainsi pouvoir contrôler notre seconde bobine.

Si besoin de plus de précisions, je resterai actif assez longtemps sur ce post. (Je n'ai pas vraiment accès à mon matériel de TIPE avant le 12 mai 2025)
Merci à vous !

Codes :
-Capteur de vitesse

int analogPin1 = A0; //pin pour le capteur
int analogPin2 = A1;
int analogVal1;
int analogVal2;

unsigned long debut = 0;
unsigned long fin = 0;


float vitesse;


void setup() {
 Serial.begin(9600); // vitesse de transmission
 pinMode(analogPin1, INPUT); //la pin est en entrée
 pinMode(analogPin2, INPUT);
}

void loop() {
  analogVal1 =analogRead(analogPin1);
  analogVal2 =analogRead(analogPin2);
  //Serial.println(analogVal1 - analogVal2-15); //afficher la valeur analogique avec un offset de 545 points ( valeur moyenne)
  Serial.println(analogVal1-530);
  Serial.print(",");
  //Serial.println();
  Serial.println(analogVal2-520);
  if (analogVal1 -545 < -15)
  {
    debut = millis();
    //Serial.println(debut); 
  }
  if (analogVal2 < -15)
  {
    fin = millis(); 
  }
  //Serial.println(fin-debut);
  vitesse = (8E-2)/(fin - debut);
  //Serial.print(vitesse);     
  fin=0;
  debut=0;
  delay(20); //délai 100ms

}

Ce que fait ce code, fin normalement, c'est que le premier capteur détecte le maximum de champ magnétique, et enregistre le temps à cet instant, puis la même chose pour le second. On fait la soustraction des deux et connaissant la distance entre les deux capteurs, on a notre vitesse. Sauf que justement c'est ce code qui coince :,(
(Les -530, -520 ect sont juste la pour remettre les valeurs au zéro)

-Relais Arduino

int relais1 = 12;
int relais2 = 11;
int relais3 = 13;
int ledrouge = 1;
int ledverte = 2;

const int ledPin = 13;

plotting.graphcolor.00 = #2c7bb6
plotting.graphcolor.01 = #fdae61


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(relais1, OUTPUT);
  pinMode(relais2, OUTPUT);
  pinMode(relais3, OUTPUT);
  Serial.println(F("Initialize System"));
  pinMode(ledPin, OUTPUT);
}


void loop() {
    digitalWrite(relais2, LOW);
    digitalWrite(relais1, HIGH);
    delay(300);
    digitalWrite(relais1, LOW);
    digitalWrite(relais2, HIGH);
    delay(250);
    digitalWrite(relais2, LOW);
    //digitalWrite(relais3, HIGH);
    delay(5000);
    //digitalWrite(relais3, LOW)
}

Bonsoir,

il faudrait justement expliquer en quoi ça coince, ce que tu obtiens et pourquoi ce n'est pas ce que tu attends.

Pour le reste, le design général de ton code n'est pas bon : si tu veux faire un chronométrage, il faut passer par les interruptions, pas des mesures au fil de la boucle loop() avec en plus un delay() qui va être bloquant.
Tu veux d'ailleurs fusionner tes deux codes mais l'un à un delay(20) et l'autre plusieurs delay()allant jusqu'à 5s. Ça ne va pas le faire...

Donc première chose à faire : regarder du côté des interruptions et réaliser la partie chrono pour valider ce point

analogRead() n'est pas très rapide.
Pour votre application, un simple détecteur à effet Hall tout-ou-rien aurait été largement suffisant et plus rapide qu'un détecteur analogique.
D'ailleurs, quel capteur utilisez-vous?


Concernant la suggestion d'utiliser des interruptions pour gérer la commande des relais, dans cette application ce n'est pas réellement indispensable dans la mesure ou le programme ne fait rien d'autre, une boucle d'attente sera sans doute plus rapide qu'une gestion d'interruption. De toute les façons, on ne peut pas faire générer d'interruption sur un résultat de conversion analogique.
Le choix d'utiliser des relais pour commander les bobines est discutable. Les relais apportent un retard lié à la mécanique qui complique un peu la gestion et apporte un aléa sur le temps de commutation.

Il serait préférable de faire passer le -545 de l'autre coté du signe < pour faire la comparaison avec une constante et ainsi faire sauter la soustraction car je ne sais pas si le compilateur fait cette optimisation de lui-même.

Il est assez facile de passer d'un capteur analogique à un capteur tout ou rien. Pour le besoin exprimé c'est effectivement mieux.

Merci de la précision, j'ignorais cela. Cela dit, il semble que @unpseudoneutre voulait intégrer une deuxième partie dans son script. À lui de préciser maintenant :wink:

Bonsoir,
En fait, le code coince car on arrive pas à récupérer notre vitesse entre nos deux capteurs. On cherche le maximum de tension renvoyée par le capteur et on enregistre le temps a ce moment la, puis la même avec le second. Sauf que cette détection de maximum coince et c'est ce que l'on cherche à récupérer.

Je vois pas exactement ce que tu entends par interruptions, en effet j'ai commencé à apprendre à programmer une carte Arduino juste pour mon projet de TIPE donc je sais que mon code est pas fondamentalement bon. Je fais avec les moyens que j'ai, c'est pour cela que je cherche de l'aide ici. Si tu pouvais m'expliquer comment le modifier plus "clairement" cela m'aiderai beaucoup !

Je vois pas en quoi un capteur tout-ou-rien changerai la donne, sauf que là le temps va nous manquer et on aura pas le temps de changer pour ce type de capteur. On devra rester avec nos capteurs analogiques. On utilise ceux là AZDelivery 3x KY-024

Pour les relais, c'est uniquement car notre alimentation pour nos bobines est extérieure, il nous fallait un moyen de pouvoir alimenter les bobines en 2.5 Ampères et contrôler avec Arduino. On a utiliser ce que nous avions sous la main rapidement, et pour les forts courants les relais Arduino semblait parfait, surtout que sur le chronomètre, le système marche :slight_smile: .
Et l'idée derrière tout cela était que par la suite, le relais de la seconde bobine s'active pour justement repropulser l'aimant. L'idée après c'est que l'on déclenche uniquement la première bobine et que la seconde s'active grâce à la vitesse calculée par nos capteurs. La boucle ici est uniquement pour être sûr d'avoir au moins un système qui fonctionne sur la base du chronomètre

Parce que l'acquisition de l'information est bien plus rapide.
Il n'est pas indispensable de connaitre le max pour mesurer le temps entre les 2 capteurs. L'information "le mobile est passé" est suffisante. Tu connais la distance et tu as l'information du passage tu peux en tirer une information de vitesse.

Ce capteur a 2 sorties.

  • A0 une sortie analogique
  • D0 une sortie tout-ou-rien. On règle le seuil de déclenchement avec le potentiomètre qui est sur la carte. Il faudrait régler le seuil pour être certain de capter tous les passages mais il ne faut pas le mettre trop bas pour ne pas déclencher sur du bruit.

En utilisant la sortie tout-ou-rien tu peux facilement faire une boucle d'attente très réactive.
Si j'en crois la doc du capteur, c'est un niveau 0 qui indique une détection (à vérifier).
'''
while(digitalRead(entreeTOR){}; // on attend le passage à zéro de la sortie digitale
long passage = millis(); // on mémorise "l'heure du passage"
'''

Si tu veux optimiser encore plus, tu peux utiliser la librairie digitalReadFast digitalWriteFast , qui optimise les accès aux broches digitales. Et contrairement à ce que son nom pourrait donner à penser elle a aussi une fonction digitalReadFast() qui permet de lire une entrée digitale beaucoup plus rapidement que le digitalRead() de la librairie standard Arduino.

EDIT: correction du nom de la librairie