Gestion electro mécanique d'un embrayage moto

Bonjour à tous.
Dans le cadre de mon loisir de prédilection , à savoir l'enduro moto, j'ai décidé il y a quelque temps d'utiliser un système d'embrayage automatique.
Ce dernier de marque Rekluse propose une solution mécanique utilisant la force centrifuge et donc de masselottes et ressorts de rappel pour embrayer ou débrayer la liaison moteur / boite de vitesse en fonction d'un certain régime moteur. Le tout est "réglable" en modifiant le poids des masselottes et la raideurs des ressorts de rappel. Cela fonctionne relativement bien mais, le système dans son ensemble manque un peu de fluidité et de constance.
Mais surtout, les disques d'embrayages du kit Rekluse ont tendance à s'user trop rapidement.
Je souhaite donc revenir a un montage classique mais au lieu d'avoir une commande manuelle d'embrayage à câble, je voudrais qu'elle soit gérer par un servomoteur dont la position sera fonction du régime moteur, lui même géré par l'arduino.
Voilà 1 mois que je travail sur ce projet.
Rapidement j'ai besoin d'une course de 10mm soit environ 40 degrés angulaire avec un palonnier de 15mm

Voilà ce que je sais:

Le régime moteur est déterminé par un signal carré "RPM" fourni par l'ecu.
J'ai commandé un mini oscilloscope afin d'en savoir plus sur ce dernier.
Je souhaite utiliser un Arduino Nano pour des raisons de compacité.

J'ai mesuré une traction de 18KG sur la biellette d'actionnement de l'embrayage.
J'ai donc porté mon choix sur un servomoteur RC de 45kg alimenté en 12/16 volt directement par le circuit électrique de la moto. Entièrement métal, ces servo son parfaits pour une utilisation en milieu sévère.
Ce dernier sera positionné sur un platine que j'ai réalisé proche de la biellette d'actionnement de l'embrayage et la traction se fera par l'intermédiaire d'un câble.

Je souhaite pouvoir avoir un débrayage manuel au pouce par bouton poussoir.

Je souhaite enfin que le servo soit en position embrayé si la moto est au point mort cela afin d'éviter que ce dernier soit en traction prolonger pour rien.

Principe de fonctionnement.

Position 0 du servo = Moteur embrayé
Position 1 du servo (40 degré)= Moteur débrayé

Si bouton poussoir fermé
Servo position 1
Si voyant point mort allumé
Servo position 0
Si aucune de ces conditions précédente n'est valable
Servo position variable en fonction du régime moteur.

Connectique Arduino
2 entrées digitales (Bouton poussoir et signal point mort)
Tensions 13,8 volt à réduire par pont diviseur
1 entré Analogique (signal carré RPM)
Caractéristique du signal à venir sous peu mais il y aura certainement une correction de la tension a effectuer.
Une sortie Analogique pour le pilotage du servo.

J'ai lu qu'il était possible d'alimenter l'Arduino directement en 13,8 V...à confirmer.

Pour la programmation tout reste à faire.

De ce que j'ai lu et avec des connaissance en programmation proche de zero voici ce que j'imagine:

Utilisation d'une fonction If / if else (bouton poussoir / neutre / signal RPM)

Utilisation de la fonction Pulsein pour l'analyse du signal carré.

Et utilisation de la bibliothèque servo arduino pour le pilotage du servo.

J'avous avoir des doutes sur mes capacités pour éditer le programme dans son ensemble mais j’espère trouver parmi vous une aide pour finaliser mon projet.

C'est max. 12v.

Ce sera une entrée logique (qui pourra aussi configuré sur une entrée de A0 à A5) pour pulseIn().

Pour le servo la bibliothèque VarSpeedServo elle a plus de possibilités dont le réglage de la vitesse.

Cordialement
jpbbricole

Bonjour et déjà un grand merci pour tes recommandations.
Pour l'alimentation de l'Arduino je passerai par un buck ou autre diviseur de tension.
Aucune puissance particulière requise, le servo étant alimenter séparément en 13,8V
Pour la bibliothèque servo, pourquoi pas, la gestion de la vitesse peut être un paramètre inintéressant.
Mon problème pour l'instant est d'écrire mon code...
Il y à 2 mois je ne connaissais pas l'existence de l'Arduino.
Je pense etre arrivé à quelque chose concernant la gestion par interrupteur (bouton poussoir et contacteur de point mort).
Je bute plus sur l'utilisation de mon signal carré (tour moteur) pour le pilotage du servo.
Je suis un peu perdu car je lis tout et son contraire.
Soit utiliser la fonction Pulsein (durée d'impulsion), ou le comptage des impulsions par attachInterrupt.

Je vais tenter de proposer un premier de code qui attendra volontiers vos remarques.
Encore merci.

pulseIn() permet de mesurer soit la durée du niveau haut, soit celle du niveau bas. Or, rien ne dit que le signal à mesurer est carré donc pulseIn() risque d'introduire une erreur dans la mesure de la fréquence du signal.

Bonjour,
oui c'est ce que je commence à comprendre au fur et à mesure de mes lectures.
Effectivement un moyen de mesurer la fréquence des impulsions et l'utilisation de cette valeur pour le positionnement de mon servo est a priori ce vers quoi je dois orienter mes recherches.

Bonjour louisduro

Pour ça, il y a des bibliothèques, comme OneButton

C'est la méthode la plus "sage" et pas forcément la plus compliquée. Lors de chaque interrupt, on incrémente un compteur. Parallèlement un compteur de temp agit toutes les secondes, ou plus rapidement et affiche ou traite la valeur de ce compteur, de cette valeur on peut en déduire les RPM et agir en conséquence.

A+
Cordialement
jpbbricole

Voilà ce que j'ai pu écrire pour le moment.
Cela concerne juste la gestion du servo par les 2 interrupteurs (bouton poussoir guidon et capteur de point mort).
J'espère que vous serez indulgent

#include "Servo.h"

Servo servo1;

int bouton1 = 5;
int etatbouton1 = 0;

int bouton2 = 6;
int etatbouton2 = 0;

void setup() {
   servo1.attach(12);
   pinMode(Bouton1, INPUT);
   pinMode(Bouton2, INPUT);
}

void loop() {
  etatbouton1 = digitalRead (bouton1);
  etatbouton2 = digitalRead (bouton2);

  if (etatbouton1==HIGH) {
    servo1.write (40);
  }
  if (etatbouton2==HIGH) {
    servo1.write (0);
  }

J'ai trouvé cela, qui me permettrai éventuellement d'avoir une fréquence utilisable dans mon code...mais je n'ai aucune idée comment.

#include <FreqMeasure.h>

void setup() {
  Serial.begin(57600);
  FreqMeasure.begin();
}

double sum=0;
int count=0;

void loop() {
  if (FreqMeasure.available()) {
    // average several reading together
    sum = sum + FreqMeasure.read();
    count = count + 1;
    if (count > 30) {
      double frequency = F_CPU / (sum / count);
      Serial.println(frequency);
      sum = 0;
      count = 0;
    }
  }
}
}


La doc est ici
https://www.pjrc.com/teensy/td_libs_FreqMeasure.html

Bonsoir louisduro

On a tous débuté un jour :wink:

Je n'ai pas essayé ton code, mais, au niveau de la gestion des boutons tu fais:
if (etatbouton1==HIGH)
c'est pas "bon" et pas pratique. Si tu lis ton bouton ainsi, ça veut dire que tu travaille en mode PULLDOWN, donc que tu dois amener du +5V pour alimenter tes boutons.

C'est mieux de faire l'inverse, tu alimentes tes boutons avec un GND et tu travailles en mode PULLUP, initialisé par:
pinMode(Bouton1, INPUT_PULLUP);
et lu par:
if (etatbouton1==LOW)
Avantage de la technique PULLUP est que le GND se trouve partout sur une moto, le +5V, moins.

Regardes le détail de ces termes PULLUP et PULLDOWN, ici;

Autre point à tenir compte, comme une moto est un endroit assez perturbé, électriquement parlant, il est bon de dédoubler les résistances internes de PULLUP, par des résistances externes, 2,2k serait pas mal, entre le +5V et la pin de l'Arduino (au plus près).

Cordialement
jpbbricole

Bonjour jpbbricole.

En fait j'avais effectivement le choix entre pullup et pulldown, mais le contacteur de point mort (intégré à la boite de vitesse) ferme un circuit "+12v" pour alimenter le voyant lumineux au tableau de bord.
Donc comme je dois réaliser un pulldown pour celui-ci autant faire de même pour les deux...
La tension de base oscille entre 13 et 13,8 V. Je pensais réaliser un diviseur de tension avec R1 20k et R2 10K pour obtenir 4,6 v max.
Par contre je ne comprend pas comment réaliser le dédoublement de résistance???

Mais mon plus gros probleme réside dans l'utilisation de mon signal RPM pour la gestion de mon servomoteur.
Pourtant cela parait très simple avec une variable "tension" de type potentiomètre comme par exemple

int val = analogRead(A1); 
val = map(val, 0, 1023, 0, 180);

Mais dans mon cas l'entrée analogique doit être calculé par l'arduino...
C'est compliqué pour mon niveau.

Bonjour louisduro

OK, compris :wink:

J'ai aussi un de ces petits oscillo, outil terriblement utile!
Si c'est un signal carré, tu fais un fréquencemètre, en comptant le nombre d'impulsions en 1 seconde, par exemple, ce qui te donne de quoi régler ton servo.
En utilisant la pin 2 comme interruption, je pense que le signal est aussi en 12V. tu as l'air de maîtriser :wink:
Si tu veux un exemple ...

A+
Cordialement
jpbbricole

Bonjour;

Il y a ici des sujets où il y a l'équivalent d'un fréquencemètre (mesure de débit d'eau), voir avec @jpbbricole


Bonjour.
J'ai reçu mon oscilloscope de poche.
Voici ce que j'obtiens.
Mesure faite moteur au ralenti.
Je pense donc qu'il s'agit donc bien d'un signal carré.
A régime élevé le cycle descend à 14ms.
La tension monte à 15 volts.
C'est donc ce signal que je désire utiliser pour déterminer la position de mon servo en fonction du régime moteur.
Tout vos commentaires sont les bienvenus


J'ai aussi réaliser un circuit sur Tinkercad que je découvre aussi.
Cela fonctionne à priori.
Néanmoins j'ai remplacer l'entrée analogique RPM par un potentiomètre en attendant.
Voici le code.

#include "Servo.h"

Servo servoclutch;

const int servoclutchPin = 12;
const int poussoirPin = 2;
const int neutralPin = 4;
int rpmPin = 0;

const int degresOuverture = 40;
const int degresFermeture = 0;
int val;

void setup() 
{
  
  pinMode(poussoirPin, INPUT_PULLUP);
  pinMode(neutralPin, INPUT_PULLUP); 
  pinMode(rpmPin, INPUT);
  servoclutch.attach(servoclutchPin);
}

void loop() 
{
  while (digitalRead(poussoirPin) == HIGH)   
  {
    servoclutch.write(degresOuverture);
   } 
  if (digitalRead(neutralPin) == HIGH)
  {
    servoclutch.write(degresFermeture);
    }
  else if
   (val = analogRead(rpmPin));            
       val = map(val, 0, 1023, 0, 40);    
  {
     servoclutch.write(val);
   }
   
}  

Bonsoir;

MISE A JOUR DE MON MESSAGE.

Le signal RPM est un signal qui a pour valeur maxi 12 à 15V selon le régime.

Une autre méthode basique d'ecrêter le signal à 5 V max, qu'il fasse 12 ou 15V est celle utilisée entre sur certain kit Arduino et illustrée ci dessous

Dans cet exemple, les signaux arrivant en AI1...AI6 sont ceux à ecrêter, et ceux allant en A1...A6 varient de 0 à 5V grâce à la diode zener.

Sur ton oscillo, le signal a une période de 71,6ms, et un Duty cycle de 50,2% (on va dire 50%) c'est indiqué sur l'écran.

Donc si tu mesure le temps où le signal est à l'état HAUT par "pulsein", tu as le temps de 1/2 période.
A partir de ce temps, tu peux déterminer la fréquence en pulse par secondes ou pulses par minutes et déduire la valeur RPM = 60/(2 X temps de la 1/2période).

Ici sur ton exemple RPM = 60/0,0716 = 838 RPM, ca te semble cohérent?

hello
puisque tu détectes l'appui sur le BP d'embrayage et que tu utilises un µ, as tu penser à intégrer un shifter à ton projet ?

Je comprend enfin l'avantage de la fonction pulsein.
Je connais les valeurs de longueur d'impulsion en fonction de mon régime moteur.
Donc je voudrais faire varier la position de mon servo en fonction de ma longueur d'impulsion "HIGH" ou "LOW".
J'ai beau chercher sur le net je ne trouve pas d'exemple d'intégration de cette fonction.
Je cherche en fait à créer un équivalent de "MAP" entre longueur d'impulsion / degré servo .

Bonsoir louisduro

Il n'y a pas besoin de créer une sorte de map, le map() Arduino suffit, il faut connaître les 2 temps extrêmes et les 2 degrés extrêmes et mettre ça dans la fonction.

Cordialement
jpbbricole

Bonsoir,
non le ralenti est plutôt de 1600 rpm. Mais il me semblait plus logique et simple de corréler longueur d'impulsion / position servo.

Les shifters ne sont pas très utile en tout terrain, mais plus en vitesse.