Mesure de vitesse en rad/s

Salut tout le monde !

J'ai besoin de calculer une vitesse en rad/s pour un projet universitaire , avec un aimant attaché sur une roue et un capteur hall, dans mon progamme "Vitesse" me donne une valeur en rad/milis et j'ai éssayé de la convertir avec "TrueVitesse". Je pense que les valeur obtenue après modification son fausses , quelqu'un veux bien me dire si y'a erreur ou non ?

const byte ledPin = 13;
const byte interruptPin = 3;
volatile byte state = LOW;
unsigned long Vitesse=0;
unsigned long Temps=0;
 float TrueVitesse;
float pi=3.14;
void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), EffetHall, RISING);
  Serial.println(F("Système intialisé"));
  //Vitesse=millis();
}

void loop() {
  
  //digitalWrite(ledPin, state);
}

void EffetHall() {
  
  Vitesse= 2*pi/millis()-Temps;
  TrueVitesse = Vitesse*10^-3;
  Temps=millis();
  Serial.println(String(TrueVitesse)+"rad/s");
}

Merci beaucoup !

si vous faites 3 radians en une unité de temps, combien de radians ferez vous en 1000 unités de temps ?

Quand vous faites 2*pi/millis()-Temps, ne manque-t-il pas des parenthèses ?

Sinon en C++ l'expression 10^-3 ne fait pas ce que vous croyez.... écrivez 0.001 ou 1e-3 (l'opérateur ^ est le "bitwise XOR")

j'ai rajouté des parenthèses entre à millis()-Temps et changer pour
0.001, maintenant j'ai constamment la valeur 0.

Les valeurs en radians sont fausses, et on ne peut se baser dessus. Mais il y a un affichage dans le fonction d'interruption. C'est une fonction qui prend du temps et si elle est trop longue, des interruptions vont manquer. A voir si un tour dure plus ou moins que la fonction.
Dans le doute, la fonction d'interruption devrait calculer les temps et loop l'afficher.

Le temps mesuré est le temps entre deux impulsions moins le temps des 3 premières instructions, car Temps n'est mis à jour qu'à la fin. Pour avoir une meilleure mesure, il vaut mieux aussi ne mesurer d'abord le temps et ensuite faire les calculs, genre

mesure = millis();
<calculs>
Temps = mesure;

 


 

On évite de faire la concaténation de chaines en Arduino à cause du fractionnement. Je ne suis pas sûr en plus que cela soit plus rapide au contraire.. Il vaut mieux écrire en deux fois. Du coup Serial.print(TrueVitesse); fonctionne

 


 

PI aurait suffit, c'est une constante connue (les constantes sont en majuscules)

Si vous mangez 3 bonbons en 1s, combien de bonbons aurez vous mangé en 1000s ?

1 Like

Salut. Vous oubliez qu'au sein d'un "ISR" les millis ni les delays ni les micros ne passent bien. Cela peut être vu dans la capture d'écran que vous avez faite, les résultats s'accumulent avec à chaque fois une valeur plus grande.

L'algorithme fonctionne bien si vous le placez à l'intérieur de la loop et que les résultats sont constants. Je pense que vous devriez retirer tous les calculs avec des millis du "ISR".

Je n'ai maintenant rien pour le prouver, pourriez-vous essayer cet autre code ?

const byte interruptPin = 3;
volatile float Temps;
float TrueVitesse;

void setup() {
  Serial.begin(9600); 
  pinMode(interruptPin, INPUT_PULLUP);  
  Serial.println(F("Système intialisé"));
}

void loop() {
  attachInterrupt(digitalPinToInterrupt(interruptPin), EffetHall, RISING);
  delay (1000);
  detachInterrupt(digitalPinToInterrupt(interruptPin));
  TrueVitesse = 2 * PI * Temps;
  Serial.println(String(TrueVitesse) + "rad/s");
  Temps = 0;
}

void EffetHall() {
  Temps++;
}

Voyons quels résultats cela donne. Les salutations.

Il faudrait encore dire pourquoi. A répéter des affirmations sorties du contexte, on finit par affirmer n'importe quoi.

J'ai joué avec une fonction d'interruption qui bien qu'appelée toute les ms contenait un delay(1000) et cela faisait bon ménage. Mais sorti du contexte, cette phrase peut soulever des oppositions.

pourquoi un float pour un compteur entier ?

Pourquoi tant de complexité pour l'affichage...

alors que cela fait le Job beaucoup plus efficacement (mémoire et temps CPU)

Serial.print(TrueVitesse);
Serial.println(F(" rad/s"));

Sinon l'usage de millis() dans une ISR pour lire le moment n'est pas rédhibitoire, on lira la valeur du compteur sans souci. L'usage de print est plus discutable (mais la bibliothèque gère maintenant la voie série même si les interruptions sont désactivées). Il est vrai cependant que la bonne pratique est de limiter au maximum ce que l'on fait dans l'ISR et de déporter ensuite le reste dans le coeur du programme.

La solution avec un delay(1000) présente peu d'intérêt si l'on souhaite faire autre chose que mesurer cette vitesse.

Merci pour le coup de main ,0.00rad/s est constamment envoyé si jamais .

J'ai un peu de mal à comprendre, le problème viens de mon équation, de l'ordre des calculs ou bien de monde code ?

Je suis tout à fait d'accord avec tout ce que tu dis @J-M-L. Ce code n'était qu'un test, il n'était pas censé être rigoureux.
Mais les résultats sont plus cohérents, même s'ils sont ratés, nous n'avons plus cette accumulation dans les résultats. Pour moi, les calculs avec les millis à l'intérieur de l' "ISR" échouent, vous devriez les retirer et les placer dans la loop.

Je ne pense pas que C’était dû à la lecture de millis…
Mais oui il vaut mieux éviter de passer trop de temps dans l’interruption