controle moteur pas à pas nema 23 et module NRF24 L01

Bonjour à tous ,

j'ai pour projet de piloter un moteur pas à pas nema23 , avec une commande sans fil avec des modules
NRF 24
j'utilise la bibliothèque NRFLITE pour l'envoie des données qui permettent de piloter mon moteur ( avec AccelStepper )
mais visiblement , depuis que je suis passé en commande sans fil , la vitesse de mon moteur à très nettement diminué ....
est-ce du à une latence de l'envoie des données par le module NRF ?
connaissez vous d'autres bibliothèque pour l'envoie de données à ma commande Stepper qui permettrai de pallier à mon souci ?

merci d'avance pour vos réponses
cordialement

Si vous passez moins souvent dans la boucle qui appelle run parce que vous faites des trucs plus longs ailleurs alors vous allez rater des pas (suivant la vitesse choisie pour le moteur)

Sans voir votre code c’est difficile de vous aider

merci JML , effectivement avec les codes , l'analyse sera plus objective :slight_smile:

Voici donc l'émetteur actuel :

/*

Radio    Arduino
CE    -> 9
CSN   -> 10 (Hardware SPI SS)
MOSI  -> 11 (Hardware SPI MOSI)
MISO  -> 12 (Hardware SPI MISO)
SCK   -> 13 (Hardware SPI SCK)
IRQ   -> Rien
VCC   -> En dessous de 3.6 volts
GND   -> GND

*/
#include <DMXSerial.h>
#include <SPI.h>
#include <NRFLite.h>

const static uint8_t RADIO_ID = 1;             // Numéro d'indentification de notre module émetteur
const static uint8_t DESTINATION_RADIO_ID = 0;// Numéro d'identification du module récepteur (A qui notre émetteur transmet)
const static uint8_t PIN_RADIO_CE = 9;//déclaration du pin CE
const static uint8_t PIN_RADIO_CSN = 10;//déclaration du pin CSN

int Val1;//variable qui contient la valeur transmise
int Val2;
int Val3;
int Val4;


int rge = 6;
int vert = 7;

struct RadioPacket // Packet de données envoyé,
//uint8_t=variable sur 8 bit, uint32_t=variable sur 32 bit
{
    uint32_t Val1;//variable Valeur codée sur 32 bit
    uint32_t Val2;
    uint32_t Val3;
    uint32_t Val4;   
};

NRFLite _radio; //Déclaration du module NRF
RadioPacket _radioData;//Déclaration du packet de données

void setup() {
  
    DMXSerial.init(DMXReceiver);
    DMXSerial.write(1, 0);  // 
    DMXSerial.write(2, 0); // 
    DMXSerial.write(3, 0); // 
    DMXSerial.write(4, 0); // 
   
 
  
  
     pinMode(rge, OUTPUT);
     pinMode(vert, OUTPUT);
     
 ////////////////////////////////////////////////////////////////
      
    if (!_radio.init(RADIO_ID, PIN_RADIO_CE, PIN_RADIO_CSN))//si l'initialisation du module n'est pas finie
    {
        
        digitalWrite(rge, HIGH);
        digitalWrite(vert, LOW);
        while (1); // Attend
    }
   
        digitalWrite(rge, LOW);
        digitalWrite(vert, HIGH);
        delay(200);
        digitalWrite(vert, LOW);
        delay(200);
        digitalWrite(vert, HIGH);
        delay(200);
        digitalWrite(vert, LOW);
        delay(200);
         digitalWrite(vert, HIGH);
        delay(200);
        digitalWrite(vert, LOW);
        delay(2000);

}



void loop() {
 
   digitalWrite(rge, HIGH);   // témoin module allumé
  
////////////////////////////////////////////////////////////  
  unsigned long lastPacket = DMXSerial.noDataSince();
    
    if (lastPacket < 5000) {    
   
       
      _radioData.Val1= DMXSerial.read(1); 
      _radioData.Val2= DMXSerial.read(2);
      _radioData.Val3= DMXSerial.read(3); 
      _radioData.Val4= DMXSerial.read(4);      
      } 
     
   else {   
      _radioData.Val1= 0; 
      _radioData.Val2= 0;
      _radioData.Val3= 0; 
      _radioData.Val4= 0;  
  
        } 
     
     
     _radio.send(DESTINATION_RADIO_ID, &_radioData, sizeof(_radioData), NRFLite::NO_ACK);  
  
  
}

et le récepteur :

/*

Radio    Arduino
CE    -> 9
CSN   -> 10 (Hardware SPI SS)
MOSI  -> 11 (Hardware SPI MOSI)
MISO  -> 12 (Hardware SPI MISO)
SCK   -> 13 (Hardware SPI SCK)
IRQ   -> Rien
VCC   -> En dessous de 3.6 volts
GND   -> GND

*/
#include <VarSpeedServo.h>
#include <SPI.h>
#include <NRFLite.h>

#include "AccelStepper.h" 
AccelStepper stepper(1 ,5, 6);    // 1 = Easy Driver interface
                                  // Nano Pin 2 connected to STEP pin of Easy Driver
                                  // Nano Pin 3 connected to DIR pin of Easy Driver

int rge = 4;
int vert = 3;

int valnew ;

VarSpeedServo myservo1;
VarSpeedServo myservo2;


const static uint8_t RADIO_ID = 0;       
const static uint8_t PIN_RADIO_CE = 9; 
const static uint8_t PIN_RADIO_CSN = 10;

struct RadioPacket // Packet de données envoyé,

{
    uint32_t Val1;
    uint32_t Val2;
    uint32_t Val3;
    uint32_t Val4;
   
};

NRFLite _radio; //Déclaration du module NRF
RadioPacket _radioData;//Déclaration du packet de données


void setup() {
  
  stepper.setAcceleration(2000);
  
  pinMode( rge , OUTPUT ); 
  pinMode( vert , OUTPUT );  
  myservo1.attach(A0); 
  myservo2.attach(A1); 
  
  myservo1.write(20, 30 , false);  // ici placement des servo au neutre 
  myservo2.write(20, 30 , false); 
  
  delay ( 3000 ) ;
   
  Serial.begin(9600);
    
    
    if (!_radio.init(RADIO_ID, PIN_RADIO_CE, PIN_RADIO_CSN))//si l'initialisation du module n'est pas finie
    {
        
        digitalWrite(rge, HIGH);
        digitalWrite(vert, LOW);
        while (1); // Attend
    }
   
        digitalWrite(rge, LOW);
        digitalWrite(vert, HIGH);
        delay(200);
        digitalWrite(vert, LOW);
        delay(200);
        digitalWrite(vert, HIGH);
        delay(200);
        digitalWrite(vert, LOW);
        delay(200);
         digitalWrite(vert, HIGH);
        delay(200);
        digitalWrite(vert, LOW);
        delay(2000);

}



void loop() {
 
    digitalWrite(rge, HIGH);   // témoin module allumé
 //////////////////////////////////////////////////////////////////////////////////////    

    while (_radio.hasData())//Tant que le module NRF a des données
    {
        _radio.readData(&_radioData); // lecture des nouvelles données 
      
        _radioData.Val1 = _radioData.Val1;
        _radioData.Val2 = _radioData.Val2;
        _radioData.Val3 =  map(_radioData.Val3 , 0 , 255 , 0 , 180 );
        _radioData.Val4 = _radioData.Val4;
      
       } 
   //////////////////////////////////////////////////////////////////////////////////////  
        myservo1.write(_radioData.Val3);  // deplaceme mvt DMx
        myservo2.write(_radioData.Val3);
  
  //////////////////////////////////////////////////////////////////////////////////////
    if (_radioData.Val4 >=63 && _radioData.Val4 <=255){                                   
        myservo1.write(20);   // position de départ
        myservo2.write(20);    
       
        delay(100); 

      myservo1.write(100, 15 , false);    // allé à 100 ° vitesse 15
      myservo2.write(100, 15 , false); 

        delay(1900); // attente pr allé à 100°

      myservo1.write(20, 24 , false);    // retour à 0 ° vitesse 24
      myservo2.write(20, 24 , false);  

      delay(1150); // attente pr retourner à 30°
                              
      _radioData.Val4 = 0 ;  
    } 

   Serial.println(_radioData.Val4);   // voir a enlever ????? ou déplacer !
  
  //////////////////////////////////////////////////////////////////////////////////////

 if (_radioData.Val1 < 127 && _radioData.Val1 > 0  )
{ stepper.move(-1000);}
  
 

if (_radioData.Val1 > 127 )
{stepper.move(1000);}


valnew = map(_radioData.Val2, 0, 255, 100, 3000); 


stepper.setMaxSpeed(valnew);  
stepper.run();
 
 
 
  
  
}

dans la loop, vous faites

  while (_radio.hasData())//Tant que le module NRF a des données
  {
    _radio.readData(&_radioData); // lecture des nouvelles données

    _radioData.Val1 = _radioData.Val1;
    _radioData.Val2 = _radioData.Val2;
    _radioData.Val3 =  map(_radioData.Val3 , 0 , 255 , 0 , 180 );
    _radioData.Val4 = _radioData.Val4;

  }

--> s'il y a plusieurs messages en attente vous les lisez tous et ne traitez que le dernier.

VarSpeedServo va utiliser des interruptions, tout comme AccelStepper ce qui risque de créer des contentions sur l'écoute du signal radio...

peut-être que vous passez trop de temps coincé dans ce while.

essayez avec un if au lieu du while pour voir ce que ça donne.

je n'ai pas regardé s'il y avait des conflits possibles au niveau des interruptions (je suppose que la librairie utilise un timer) et des PWM de commande. --> regardez bien la doc pour voir quels timers sont utilisés et quel impact cela peut avoir sur certaines PIN


PS:

c'est quoi ces commentaires ?

AccelStepper stepper(1 , 5, 6);   // 1 = Easy Driver interface
// Nano Pin 2 connected to STEP pin of Easy Driver
// Nano Pin 3 connected to DIR pin of Easy Driver

S'il sont corrects, les pins ne sont pas correctes, s'ils sont faux pourquoi les mettre ou les garder...


le programme ne prendra pas plus de place si vous ne parlez pas en langage SMS...

int rge = 4;
int vert = 3;

de plus pour des N° de pins, autant prendre des constante de type byte. ça occupera moins de mémoire (en fait pas du tout) alors que là vous mangez 4 octets pour rien.Un truc du genre serait mieux donc:

const byte pinRouge = 4;
const byte pinVerte = 3;

bonjour et encore un grand merci pour ta précieuse aide !
j'ai suivi tes conseils , et effectué la modif de changer WHILE par IF , mais pas de changement notable
par contre j'ai rajouté dans cette boucle while , un RUN et j'ai gagné un peu en vitesse , mais encore assez rapide !!!
je sais bien que le moteur pas à pas n'st pas réelement fait pour atteindre de grande vitesse , mais pour mon projet j'ai besoin d'avoir à controler la position exact du moteur
c'est une sorte de Cable Cam pour le spectacle que je réalise ...
et je sais qu'un Nema 23 peu aller plus vite , je vais continuer mes tests peu etre avec la méthode de controler un P à P sans bibliotheque ....etat low et hight du pin step

par contre peux tu me confirmer que la fonction '' MOVETO '' de ACCel stepper est limité car
pour le déplacement de mon moteur sur le cable , j'ai l'impression d'etre limité au bout d'une certaine valeur !

voici le code récepteur actuel :

/*

Radio    Arduino
CE    -> 9
CSN   -> 10 (Hardware SPI SS)
MOSI  -> 11 (Hardware SPI MOSI)
MISO  -> 12 (Hardware SPI MISO)
SCK   -> 13 (Hardware SPI SCK)
IRQ   -> Rien
VCC   -> En dessous de 3.6 volts
GND   -> GND

*/
#include <VarSpeedServo.h>
#include <SPI.h>
#include <NRFLite.h>

#include "AccelStepper.h" 
AccelStepper stepper(1 ,5, 6);    // 1 = Easy Driver interface
                                  // Nano Pin 5 connected to STEP pin of Easy Driver
                                  // Nano Pin 6 connected to DIR pin of Easy Driver

int rouge = 4;
int vert = 3;

int valnew ;

VarSpeedServo myservo1;
VarSpeedServo myservo2;
VarSpeedServo myservo3;  // panoramique



const static uint8_t RADIO_ID = 0;       
const static uint8_t PIN_RADIO_CE = 9; 
const static uint8_t PIN_RADIO_CSN = 10;

struct RadioPacket // Packet de données envoyé,

{
    uint32_t Val1;
    uint32_t Val2;
    uint32_t Val3;
    uint32_t Val4;
   
};

NRFLite _radio; //Déclaration du module NRF
RadioPacket _radioData;//Déclaration du packet de données


void setup() {
  
  stepper.setAcceleration(3000);
  
  pinMode( rouge , OUTPUT ); 
  pinMode( vert , OUTPUT );  
  myservo1.attach(A0); 
  myservo2.attach(A1); 
  myservo3.attach(A2); 
  
  myservo1.write(20, 150 , false);  // ici placement des servo au neutre 
  myservo2.write(20, 150 , false); 
  
  myservo3.write(20, 150 , false); 
  
 
   
  Serial.begin(9600);
    
    
    if (!_radio.init(RADIO_ID, PIN_RADIO_CE, PIN_RADIO_CSN))//si l'initialisation du module n'est pas finie
    {
        
        digitalWrite(rouge, HIGH);
        digitalWrite(vert, LOW);
        while (1); // Attend
    }
   
        digitalWrite(rouge, LOW);
        digitalWrite(vert, HIGH);
        delay(200);
        digitalWrite(vert, LOW);
        delay(200);
        digitalWrite(vert, HIGH);
        delay(200);
        digitalWrite(vert, LOW);
        delay(200);
         digitalWrite(vert, HIGH);
        delay(200);
        digitalWrite(vert, LOW);
        delay(2000);

}



void loop() {
   
    digitalWrite(rouge, HIGH);   // témoin module allumé
 //////////////////////////////////////////////////////////////////////////////////////    

    while (_radio.hasData())//Tant que le module NRF a des données // remplacement du while par IF !!!
    {
        _radio.readData(&_radioData); // lecture des nouvelles données 
      
        _radioData.Val1 = _radioData.Val1;
        _radioData.Val2 = _radioData.Val2;
        _radioData.Val3 =  map(_radioData.Val3 , 0 , 255 , 0 , 180 );
        _radioData.Val4 = _radioData.Val4;
        
        stepper.run();
       } 
   //////////////////////////////////////////////////////////////////////////////////////  
        myservo1.write(_radioData.Val3);  // deplaceme mvt DMx
        myservo2.write(_radioData.Val3);
        
        myservo3.write(_radioData.Val2);    // deplacement du panoramique 
  
  //////////////////////////////////////////////////////////////////////////////////////
    if (_radioData.Val4 >=63 && _radioData.Val4 <=255){                                   
        myservo1.write(0);   // position de départ
        myservo2.write(0);    
       
        delay(100); 

      myservo1.write(180, 80 , false);    // allé à 100 ° vitesse 15
      myservo2.write(180, 80 , false); 

        delay(600); // attente pr allé à 100°

      myservo1.write(0, 140 , false);    // retour à 0 ° vitesse 24
      myservo2.write(0, 140 , false);  

      delay(700); // attente pr retourner à 30°
                              
      _radioData.Val4 = 0 ;
    
     
    } 

  
  
  //////////////////////////////////////////////////////////////////////////////////////

 if (_radioData.Val1 < 127 && _radioData.Val1 > 0  )
{ stepper.move(-1400);}
  
 

if (_radioData.Val1 > 127 )
{stepper.move(1400);}


valnew = map(_radioData.Val2, 0, 255, 500, 2500); 


stepper.setMaxSpeed(valnew);  
stepper.run();
 
 
 
  
  
}

OK

run() ne fait qu'un pas au maximum par appel donc si vous avez vu une amélioration peut-être il faut prévoir d'en avoir ailleurs, là où vos calculs prennent du temps. Vous pourriez essayer de mesurer en combien de temps la boucle tourne, ça vous permettra de voir si vous êtes loin du compte par rapport à la vitesse que vous voulez ou pas.

la fonction moveTo() prend un long comme paramètre donc elle est limitée bien sûr mais c'est un grand chiffre entre -2147483648 et +2147483647, donc ça en fait des pas :slight_smile:

"Nema 23" ça définit la dimension physique du bloc moteur, pas sa performance. Il faut regarder dans la spec combien de pas par seconde il est capable de faire et quelle alimentation il faut pour cela

Autant que ça pour la fonction Move TO !!!
J’ai l’impression de plafonner au delà de la valeur 6000 !!!
Je suis sur mon driver à 400 pas par tour , et la longueur de ma corde sera de 80 mètres Max ,
Je croyais que la fonction Move To était la position absolu , la valeur 0 le point de départ et la valeur Max le nombre de pas pour ce déplacer
Je suis étonné de voir une plage avec une valeur négative !
Je vais re tester
J’ai une déclaration particulière à faire dans ma fonction pour ma valeur « Move To « ?
Merci à toi
Cordialement
Pour le type de batterie
J’utilise une batterie Yuasa 12 volts 2,1 ampères heure

hum pas sûr de comprendre, il n'y a qu'un seul paramètrevoid AccelStepper::moveTo(long absolute) c'est une position absolue par rapport à l'état du système à l'allumage.

une valeur négative dis de tourner dans l'autre sens.

voici un petit code d'exemple qui doit osciller entre +1000 et -1000

#include <AccelStepper.h>

AccelStepper stepper; // par défaut FULL4WIRE (4 pins) sur les pins 2, 3, 4, 5

void setup()
{  
  stepper.setMaxSpeed(100);
  stepper.setAcceleration(20);
  stepper.moveTo(1000); // position absolue 1000 pas plus loin
}

void loop()
{
    stepper.run();

    if (stepper.distanceToGo() == 0) // si on est arrivé au bout des 1000 pas
      stepper.moveTo(-stepper.currentPosition()); // on va à -1000 (et le coup d'après -(-1000) = +1000
}

je viens d'essayer le bout de code que tu as envoyé , en changeant qq valeur de l'exelaration et nombre de pas à faire
et ce code je dirais que le moteur va au moins 2 fois plus vite , donc il est capable
mais n'arrive pas à voir ce qui me '' bloque '' sa performance

#include <AccelStepper.h>

AccelStepper stepper(1 ,5, 6); 


void setup()
{  
  stepper.setMaxSpeed(5000);
  stepper.setAcceleration(2000);
  stepper.moveTo(5000); // position absolue 1000 pas plus loin
}

void loop()
{
    stepper.run();

    if (stepper.distanceToGo() == 0) // si on est arrivé au bout des 1000 pas
      stepper.moveTo(-stepper.currentPosition()); // on va à -1000 (et le coup d'après -(-1000) = +1000
}

il se peut qu'avec les servo en plus ça mette pas mal de pression sur le système ...

regardez tous les appels bloquants et essayez de voir combien de temps prends

    while (_radio.hasData())//Tant que le module NRF a des données // remplacement du while par IF !!!
    {
        _radio.readData(&_radioData); // lecture des nouvelles données 
      
        _radioData.Val1 = _radioData.Val1;
        _radioData.Val2 = _radioData.Val2;
        _radioData.Val3 =  map(_radioData.Val3 , 0 , 255 , 0 , 180 );
        _radioData.Val4 = _radioData.Val4;
       }

quand vous avez des données