Moteur CC adapter le PWM pour une distance sur un temps fixe

bonsoir,
j'avoue que je tourne en rond...
j'ai un projet de cablecam qui à pour fonction de parcourir une distance mesurée par un encodeur avec comme objectif de la réaliser sur une durée fixe.
exemple : le moteur doit parcourir 12m sur 10sec et le PWM doit adapter le vitesse.

j'ai déjà réalisé le comptage des révolutions via attachInterrupt(digitalPinToInterrupt(ENCA),readEncoder,RISING);

volatile int  counter ;                // compteur 
int Enc_NbRevolution = 600;  // nb de révolution par tour
float time_execution = 10;      // temps en sec
float distance_mm = 12000;   // distance à parcourir en mm
float RoueCirc = 300.02;          // circonférence de la roue motrice

le signal PWM sera de 0 à 255
Avez vous des idées, pistes à me donner
merci d'avance.

Bonsoir robindesbois31

Pour ton encodeur, uitilises une bibliothèque comme Encoder.h, ça te simplifiera la vie.

Cordialement
jpbbricole

Merci je connais cette librairie.
actuellement je compte bien les révolution de l'encodeur dans la variable 'counter'
mon pb est de calculer la vitesse du moteur pour effectuer la distance sur un temps fixé

Bonsoir,

Je n'ai pas bien compris â quel niveau tu attend de l'aide de la part du forum!

As tu définit quel serait ton moteur?
Comment tu compte le piloter, c'est à dire avec quel module (pour ne pas dire "drivers"!)?
Comment est monté ton codeur sur ta roue ou moteur, avec ou sans réduction?
Escompte tu faire un asservissement de vitesse ou non?

As tu les réponse à tout cela?
Ou attend tu de nous que nous t'aidions à le faire?

Autre chose que je n'ai pas littéralement compris, c'est ce commentaire dans ton code:
"nombre de révolutions par tour"
Un tour, c'est déja une révolution non?
Tu veux sans doute dire qu'une voie de l'encodeur fait 600 tops par tour?

merci pour tes questions :slight_smile:

As tu définit quel serait ton moteur?

  • OUI c'est un moteur ICAN 24V BLDC 103W 24V avec un réducteur 1:7,5
  • aces le driver DLD-120A
    précision je le pilote bien via le PWM de 11 à 255 (10 <= Arrêt)

Comment est monté ton codeur sur ta roue ou moteur, avec ou sans réduction?

  • il est monté directement sur la roue
  • j'ai déjà fais des tests:
    PWM 11 = roue à 14,6 tr/min pour 8753 révolutions (encodeur)
    PWM 255 = roue à 520 tr/min pour 312407 révolutions
    Tu veux sans doute dire qu'une voie de l'encodeur fait 600 tops par tour?
    -Oui pour un tour d'encodeur = 600 révolutions

Escompte tu faire un asservissement de vitesse ou non?

  • OUI c'est justement mon problème...
    je voudrais adapter cette vitesse (PWM) pour effectuer la distance shouaité sur un temps donnée.

Bonjour robindesbois31

Mets ton code complèt en ligne afin que je puisse voir comment tu commandes ton moteur.

A+
Cordialement
jpbbricole

Bonjour,

C'est du super matériel que tu as choisis là !

Ne serais ce pas plutôt BLD-120 au lieu de DLD-120?

BLD-120 est bien un driver, pilotable par un PWM.

Je comprends mieux ton montage, le codeur que tu rajoute te sers juste pour mesurer la distance parcourue, à condition que la roue ne patine pas sur le câble, c'est cela?

Le moteur posséde lui même un codeur effet Hall, et le driver utilise ces signaux du moteur pour gérer entre autre la vitesse du moteur.
Donc en théorie il est capable de gérer lui même l'asservissement de vitesse du moteur (sans tenir compte du patinage, grande inconnue).

Les mesure que tu nous donne seraient encore plus parlantes avec plus de 2 points de mesures, au moins 5 stp.

J'ai lu que la fréquence du PWM devait se situer entre 1kHz et 10kHz, qu'elle est la fréquence du PWM Arduino que tu utilise?

voici le code
pour l'instant le PwmValue n'est pas calculée.

#include "Arduino_LED_Matrix.h"
#include "WiFiS3.h"
#include "RTC.h"
#include <NTPClient.h>

#include <OSCBundle.h>
#include <OSCBoards.h>


ArduinoLEDMatrix matrix;
const uint32_t go[] = {
    0x39c42,
		0x24225a24,
		0xa231c000,
		66
};
const uint32_t stop[] = {
    0x0,
		0x0,
		0x0,
		66
};

// -------------- OSC / UDP -------------
WiFiUDP Udp;        // pour OSC
WiFiUDP upd2;       // pour RTC via NTP
const unsigned int localPort                  = 2390;

// -------------- WIFI ------------------
/*Adress MAC de la carte UNO : 48:27:e2:e0:1a:c4 */
char ssid[] = "Freebox_Percewood"; //Enter your WIFI SSID
char pass[] = "pERceBOis@31460";    //Enter your WIFI password
int keyIndex = 0;                 // your network key index number (needed only for WEP)
int status = WL_IDLE_STATUS;
WiFiServer server(80);
String HTTP_req, webPage;          // stores the HTTP request

// -------------- NTP ---------------
NTPClient timeClient(upd2);
RTCTime   RTCcurrentTime;

// --------------  TIME  ----------------
unsigned long     currentMillis         = 0 ;
unsigned long     previousMillis        = 0 ;
float             temps_execution       = 12000;   // durée de l'execution du moteur en ms

// ------------ ENCODEUR ------------
/*
  modèle : LPD3806 - 600  ; Codeurs rotatifs magnétiques incrémentaux
  Black - GND
  White - Channel A       borne 2
  GREEN - Channel B       borne 3
  BLACK - GND
*/
#define ENCA 2 // White
#define ENCB 3 // GREEN
#define cpr  600                     // revolution par tour de l'encodeur                                      
volatile int  counter       = 0;     // augmentera ou diminuera en fonction de la rotation de l'encodeur.
int           newValue         ;     // via l'interface WEB
int           counter_depart= 0;   
 
// ----------  VITESSE ET DISTANCE ---------
#define RoueDiam                 95.5                // en mm
float   RoueCirc               = 3.1415 * RoueDiam;  // Distance parcourue en une rotation = D x π 
float   factor                 = RoueCirc / cpr;     // distance parcourue à chaque résolution
float   DistanceRestante_m     = 0.0;                // distance parcourue en m
float   DistanceRestante_mm    = 0.0;                // distance parcourue en m
float   kmh                    = 0.0;                // vitesse en km/h

/* ------------- MOTEUR CC ---------------
  Driver : BLD-120A
  moteur : 57BLY-1030N-J7.5  
  --- CABLAGE ----
  Jaune = U
  Vert  = V
  Bleu  = W
  PWM   =  borne 8. => Arrêt <=10 ; min=11 ; max=255
  DIR   =  borne 9. => false / true
*/
const int     pwmPin        = 8;                 // Définition de la broche PWM
int           pwmValue      = 0;                 // valeur à envoyer au moteur de 11 à 255
const int     dirPin        = 9;                 // Définition de la broche de direction
bool          dirValue      = false;             // false = horaire ; true = anti-horaire
bool          start         = false;             // start moteur
bool          dir           = false;             // false = horaire ; true = anti-horaire
float         rpm           = 0.0;               // rotation par minute


/* -------------------------------------------------------------------------
----------------------------------------------------------------------------                            
                                    SETUP
----------------------------------------------------------------------------
----------------------------------------------------------------------------*/

void setup() {
  Serial.begin(19200);
  matrix.begin();
  
  pinMode(pwmPin, OUTPUT);    
  pinMode(dirPin, OUTPUT);

  /* ENCODEUR */
  pinMode(ENCA, INPUT_PULLUP);
  pinMode(ENCB, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(ENCA),readEncoder,RISING);
  
  // ------ WIFI -----
  wifiConnxion();
  // --- RTC / NTP ---
  rtcStart();
  // --- UDP/OSC -----
  Udp.begin(localPort);
}

/* -------------------------------------------------------------------------
----------------------------------------------------------------------------                            
                                    LOOP
----------------------------------------------------------------------------
----------------------------------------------------------------------------*/
void loop() {

  currentMillis = millis();  // on ecrit les millis actuel
  if ((currentMillis - previousMillis >= temps_execution) && pwmValue>0) {
    previousMillis = currentMillis;
     pwmValue = 0;
     analogWrite(pwmPin, pwmValue); 
     Serial.print("count: ");  Serial.println(counter);
     Serial.print("rpm ");     Serial.println(rpm);
    start = false ;
    counter=0;
  }
  
  DistanceRestante_m  = (counter/cpr)*RoueCirc/1000;
  DistanceRestante_mm = (counter/cpr)*RoueCirc;
  kmh = DistanceRestante_m * 3.6/ temps_execution;
  rpm = float(counter)/cpr ; // tour/min
  webServer();

  // ------- MOTEUR START -------
  if (start && abs(counter) >= 0 && (pwmValue >= 11 && pwmValue <= 255) ){               
      analogWrite(pwmPin, pwmValue);              // Applique la valeur PWM
      //Serial.println("Vitesse du moteur réglée sur " + String(pwmValue));
  }

  // ------- OSC -------
   OSCBundle bundleIN;
   int size;
   if( (size = Udp.parsePacket())>0)
   {
     while(size--)
       bundleIN.fill(Udp.read());

      if(!bundleIN.hasError())
        bundleIN.route("/go", avionGo);
        bundleIN.route("/stop", avionStop);
   }

}



void avionGo(OSCMessage &msg, int addrOffset) {
  Serial.println("Go...");
  start = true;
  matrix.loadFrame(go);  
}
void avionStop(OSCMessage &msg, int addrOffset) {
  start = false;
  Serial.println("stop...");
  matrix.loadFrame(stop);  
}



/* -------------------------------------------                         
                 ENCODEUR
----------------------------------------------*/
void readEncoder(){
  int b = digitalRead(ENCB);
  if(b > 0){
    counter++;
  }
  else{
    counter--;
  }
}

Voici à quoi çà va ressembler...
je n'ai pas mis la seconde 'flasque' pour voir l'intérieur
la poulie bleu de l'encodeur et entrainer directement par le moteur que entraine aussi le roue motrice jaune.


Bonjour robindesbois31

Pour calculer PwmValue, j'utiliserai le système "empirique" d'essayer des valeurs. Je n'aurai pas la capacité de calculer cette valeur :woozy_face:

A voir, tu as un UNO R4 et c'est long à compiler, ce que je te propose, c'est d'inclure à ton programme, la possibilité de faire varier PwmValue avec des commandes dans le moniteur, ainsi plus besoin de recharger chaque fois le programme.
Intéressé?

A+
Cordialement
jpbbricole

Si tu connais le nombre d'impulsions sur une période de temps donné tu as une image de la vitesse.

  • Tu as ta variable qui compte les impulsions. Tu peux transformer cette donnée en distance puisque tu connais le diamètre de la roue.
  • Tu utilises millis() pour avoir une information sur le temps

==> Tu peux calculer une vitesse

Merci pour ton aide mais je voudrais trouver une méthode de calcul.

ma première approche est de mettre mon 'cableCam' sur la position d'arrivée puis mettre 'counter = 0'
puis déplacer le 'cableCam' sur sa position de départ afin que le 'counter' revoie la valeur exemple : 23998 (encodeur)
dans ce cas on aurait : =(counter/Enc_NbRevolution)*RoueCirc = (23998/600)*300,02/1000 = 12000mm soit 12m à faire.
je voudrais maintenant faire les 12000 mm en 10sec.
et enfin calculer le PwmValue, et là je sèche MDR..

Bonjour robindesbois31

Je ne pense pas que tu puisses calculer ainsi, il n'y a pas de rapport direct entre une valeur PWM et les tours/minutes de ton moteur, il y a trop de paramètres "entre deux" pour ce faire. Suivant la charge sur le moteur, sa vitesse va varier même si le PWM est stable.

Cordialement
jpbbricole

Je ne serais pas vexé si tu ne répond pas, mais pour avoir une idée de la réponse à ton systéme, à savoir Vitesse (tr/mn) = f (PWM), il serait intéressant de connaître plus de 2 points de mesures.

Tu nous indique seulement:

Ça fait 2 points seulement, entre deux, c'est une droite, une courbe ...?

Ça serait trés utile de le savoir je pense.

Notamment pour déterminer au moins empiriquement la valeur du PWM que tu souhaite.

EDIT, et je rajoute:

La fréquence par défaut de l'Arduino UNO est de 490 Hz pour les pins 3, 9, 10, 11 et de 980 Hz pour les pins 5, 6.

Ors le drivers demande un PWM de fréquence 1kHz à 10kHz, 980Hz, c'est presque, mais pas 1kHz...

Heu, la borne 8, ce n'est pas une borne PWM!

ous j'ai fais une erreur en recopiant
borne 9 = PWM
borne 9 = dir

Je ne serais pas vexé si tu ne répond pas, mais pour avoir une idée de la réponse à ton systéme, à savoir Vitesse (tr/mn) = f (PWM), il serait intéressant de connaître plus de 2 points de mesures.

  • je vais refaire quelques tests avant 12h :wink:

Ça fait 2 points seulement, entre deux, c'est une droite, une courbe ...?

  • en fait pour les premiers tests, j'ai juste mis une courroie entre le moteur et l'encodeur (rapport 1:1) pour mesurer ses tr/min...

je n'ai pas réglé la fréquence du PWM pour l'instant
je suis tombé sur ce post pour la fréquence sur un Uno R4
https://www.pschatzmann.ch/home/2023/07/01/under-the-hood-arduino-uno-r4-pwm/

Ça dépand de l'asservissement inclu dans le driver, ça sert à cela un asservissement, il y a tout ce qu'il faut pour cela (le moteur a son propre codeur, il envoie ses tops au driver), alors pourquoi ça ne marcherait pas?

Et ton PC, tu compte lui mettre un câble série de 12m de long pour lire le moniteur série, la carte Arduino étant embarquée avec le moteur.

C'est un abus de langage, le moniteur série n'est pas le seul moyen d'envoyer un message sur le port série d'un Arduino :slight_smile:
je pense que @jpbbricole pensais par exemple envoyer des commandes via son téléphone intélligent en bluetooth.

OK pour ce lien, mais il faut inclure la bibliothéque qui va avec ( #include "pwm.h") et adapter ton programme.

OU

essayer à 980hz (broche 5 ou 6 pour le PWM),et ça devrait peut-être marcher sans modif de programme (ormis le numéro de broche).

Ça en fait des essais!

Courage.