Bipolar motor with DIR0035 TMC260 DRIVER shield

Hello everyone,

I am facing difficulties to control a stepper motor with an ARDUINO MEGA 2560R3 with a a stepper motor driver shield DIR0035 TMC260.

Even with the example in the followed link it doesn't work properly. The motor turned weirdly.
First I am not sure about the wiring of the shield. I only wired the motor and the power supply and plug the shield on the mega.

I want to control the motor with STEP/DIR mode:.

In the board overview in the link below, they are talking about :
1:DIR => already connected if I understand well
2:STEP=> IDEM
3:Enable => It didn't wire this pine but I don't understand how it's works. In the example we don't have to define any pine for the enable and if we start the code the motor turns so the enable is done automatically. Is it an OUTPUT?
4:SG=> is it only an output
5:CS(D9-D6) =>Only if you are using SPI but it's not my case
6: SPI=> not my case.

So I am wondering if i am missing something here.

Besides one stuff is calling me in the example on the link below :

</>
//we have a stepper motor with 200 steps per rotation, CS pin 2, dir pin 6, step pin 7 and a current of 800mA
TMC26XStepper tmc26XStepper = TMC26XStepper(200,6,4,5,800);
</>

the number of the pin doesn't match with the pine described in the comments. So maybe there is an error here...

If my wiring is Ok I will put my program code later.

Thank you in advance.

Hi,
If you post your schematic and your code it will be most helpful.

What are you using as a power supply for the steppers?
Can you please post link to specs/data of the stepper?

Thanks.. Tom... :smiley: :+1: :coffee: :australia:

Yes I understand :slight_smile: Thank you for helping

This is my code. (sorry comments are in french):

#include <SPI.h>
#include <TMC26XStepper.h>

TMC26XStepper tmc26XStepper = TMC26XStepper(200,6,4,5,800);
const int bouton = 51;
const int capteur_zero = 49;
const int pompe = 22;
const int agitateur = 24;
const int liquide1 = 28;
const int liquide2 = 30;
const int liquide3 = 32;
const int verin = 36;
const int eau = 38;
const int piston = 34;
const int nettoyage = 40;
const int vidange =42;
const int voyant = 26;
const int capteur_simule = 45;

long tps_erreur_mot = 30000; //en ms
bool etat_systeme = LOW;

/*-----------------------------------------------------------------------------
-----------------------INITIALISATION--------------------------------------------
-------------------------------------------------------------------------------*/
void setup() {

 /*ici on declare nos entrées/sorties*/
    pinMode(bouton, INPUT);
    pinMode(capteur_zero, INPUT);
    pinMode(pompe, OUTPUT);
    pinMode(agitateur, OUTPUT);
    pinMode(liquide1, OUTPUT);
    pinMode(liquide2, OUTPUT);
    pinMode(liquide3, OUTPUT);
    pinMode(verin, OUTPUT);
    pinMode(eau, OUTPUT);
    pinMode(piston, OUTPUT);  
    pinMode(nettoyage, OUTPUT);
    pinMode(vidange, OUTPUT); 
    pinMode (voyant, OUTPUT);
    pinMode (capteur_simule, OUTPUT);
    Serial.begin(9600);
    Serial.println("==============================");
    Serial.println("TMC26X Stepper Driver Demo App");
    Serial.println("==============================");
    //set this according to you stepper
    Serial.println("Configuring stepper driver");
    //char constant_off_time, char blank_time, char hysteresis_start, char hysteresis_end, char hysteresis_decrement
    tmc26XStepper.setSpreadCycleChopper(2,24,8,6,0);
    tmc26XStepper.setRandomOffTime(0);
    
    tmc26XStepper.setMicrosteps(128);
    tmc26XStepper.setStallGuardThreshold(4,0);
    Serial.println("config finished, starting");
    Serial.println("started");
    etat_systeme=initialisation(); 
    if (etat_systeme==HIGH) //Si il y a une erreur lors de l'init
    {
      while(1) //on entre dans une boucle infinie il faut redemarrer
      {
        Serial.println("erreur lors de l'init");
      }
    }
    
}

/*-----------------------------------------------------------------------------
---------------------------------MAIN--------------------------------------------
-------------------------------------------------------------------------------*/

void loop() 
{
    int i=0;
    // put your main code here, to run repeatedly:
/*debut de sequence 1*/
    agiter(1, 2000);//on lance la fonction agiter pendant 1min
    digitalWrite(verin, LOW); //attention carte relais desactivee
    Serial.println("on monte le vérin");
    delay(15000);
    Serial.println("on attend 15s");
    vidanger(10);//on vidange pendant 10s
/*fin de sequence 1, debut de sequence 2*/
    digitalWrite(liquide1, LOW); //on ouvre liquide1 //attention carte relais desactivee
    avance_moteur(200); // on injecte 200uL par puits
    Serial.println("injection liquide1");
    delay(15000); //on attend que le moteur soit en position
    digitalWrite(liquide1, HIGH); //on ferme liquide1 //attention carte relais desactivee
    etat_systeme=remise_a_zero();
    if (etat_systeme==HIGH) //Si il y a une erreur lors de la remise a zero
    {
      while(1) //on entre dans une boucle infinie il faut redemarrer
      {
        Serial.println("ERREUR");
      }
    }
    digitalWrite(verin, HIGH); //attention carte relais desactivee
    Serial.println("on descend le vérin");
    agiter(1, 500);//on lance la fonction agiter pendant 1min
    digitalWrite(verin, LOW); //attention carte relais desactivee
    Serial.println("on monte le vérin");
    delay(15000);
    vidanger(10);//on vidange pendant 10s
/*fin de sequence 2, debut de sequence 3*/  
    digitalWrite(liquide2, LOW); //on ouvre liquide2 //attention carte relais desactivee
    avance_moteur(150); // on injecte 150uL par puits
    Serial.println("injection liquide2");
    delay(15000); //on attend que le moteur soit en position
    digitalWrite(liquide2, HIGH); //on ouvre liquide2 //attention carte relais desactivee
    etat_systeme=remise_a_zero();
    if (etat_systeme==HIGH) //Si il y a une erreur lors de la remise a zero
    {
      while(1) //on entre dans une boucle infinie il faut redemarrer
      {
        Serial.println("ERREUR");
      }
    }
    digitalWrite(verin, HIGH); //attention carte relais desactivee
    Serial.println("on descend le vérin");
    agiter(2, 500);//on lance la fonction agiter pendant 2min
    digitalWrite(verin, LOW);  //attention carte relais desactivee
    Serial.println("on monte le vérin");
    delay(15000);
    vidanger(10);//on vidange pendant 10s
/*fin de sequence 3, debut de sequence 4*/  
    digitalWrite(liquide3, LOW); //on ouvre liquide3  //attention carte relais desactivee
    avance_moteur(800); // on injecte 800uL par puits
    Serial.println("injection liquide3");
    delay(15000); //on attend que le moteur soit en position
    digitalWrite(liquide3, HIGH); //on ouvre liquide3 //attention carte relais desactivee
    etat_systeme=remise_a_zero();
    if (etat_systeme==HIGH) //Si il y a une erreur lors de la remise a zero
    {
      while(1) //on entre dans une boucle infinie il faut redemarrer
      {
        Serial.println("ERREUR");
      }
    }
    digitalWrite(verin, HIGH); //attention carte relais desactivee
    Serial.println("on descend le vérin"); 
    agiter(3, 500);//on lance la fonction agiter pendant 2min
    digitalWrite(verin, LOW); //attention carte relais desactivee
/*fin de sequence 4, debut sequence de nettoyage*/
    int etat_bouton = digitalRead(bouton); //on attend le go de l'utilisateur
    while(etat_bouton!=HIGH)
    {
      etat_bouton = digitalRead(bouton);
          digitalWrite (voyant, LOW); //on fait clignoter le voyant pour que l'utilisateur sache qu'il faille faire une commande
          delay(500);
          digitalWrite (voyant, HIGH);
          delay(500);
    }
    agiter(1, 500);
    digitalWrite(pompe, LOW);  //attention carte relais desactivee
    digitalWrite(vidange, LOW); //attention carte relais desactivee
    digitalWrite(eau, LOW); //attention carte relais desactivee
    digitalWrite(vidange, HIGH); //attention carte relais desactivee
    for (i=0; i=8; i++)
    {
      delay(4000);
      vidanger(4);
      
    }
    digitalWrite(eau, HIGH); //attention carte relais desactivee
    i=0;
    etat_systeme=remise_a_zero();
    if (etat_systeme==HIGH) //Si il y a une erreur lors de la remise a zero
    {
      while(1) //on entre dans une boucle infinie il faut redemarrer
      {
        Serial.println("ERREUR");
      }
    }
}

/*-----------------------------------------------------------------------------
-----------------------SOUS FONCTIONS--------------------------------------------
-------------------------------------------------------------------------------


-----------------------SF_INITIALISATION--------------------------------------------

On initialise le banc electroniquement et mencaniquement.*/


bool initialisation()

{//On initialise toutes les sorties
    Serial.println("debut init");
    bool erreur =LOW;
    digitalWrite(pompe, HIGH); //car inversé dans la carte relai => HIGH = relai desactivé
    digitalWrite(agitateur, HIGH);
    digitalWrite(liquide1, HIGH);
    digitalWrite(liquide2, HIGH);
    digitalWrite(liquide3, HIGH);
    digitalWrite(verin, HIGH);
    digitalWrite(eau, HIGH);
    digitalWrite(piston, HIGH);
    digitalWrite(nettoyage, HIGH);
    digitalWrite(vidange, HIGH);
    digitalWrite(voyant, HIGH);
    digitalWrite(capteur_simule, HIGH);
//On initilise le pousse-seringue
    int etat_capteur_zero;
    etat_capteur_zero=digitalRead(capteur_zero);
    unsigned long debut =millis(); //on compte le temps
    tmc26XStepper.setSpeed(500);    //Set speed at 500
    unsigned long temps =0;
    while((etat_capteur_zero==LOW)&&(temps<tps_erreur_mot))
    {
      tmc26XStepper.step(-1);     //on recule d'un pas
      tmc26XStepper.un_start();         //start stepper   
      etat_capteur_zero=digitalRead(capteur_zero);  
      temps=millis();
      temps =temps-debut;
      delay(1000);
      Serial.println(temps);
      digitalWrite(capteur_simule, HIGH);
      
    }
    if (temps>tps_erreur_mot)
      {
        erreur=HIGH;
        digitalWrite(voyant, LOW);
      }
    Serial.println("initialisation terminéee");
    return (erreur);

}

/*-----------------------SF_AVANCE_MOTEUR--------------------------------------------*/

/*On va convertir la quantité en uL en nombre de tours: 
Sachant qu'il faut deja remplir le circuit qui fait 4.9mL. Donc quantité à envoyer est de 4.9mL+ 4*qté voulue par puits. 
La seringue 10mL envoie 0.4mL en 1.8mm de deplacement donc il faut deja faire 22.05mm (4.9/0.4*1.8) de deplacement pour remplir le circuit.
Ensuite qté mm = qtémL/0.4*1.8.
Un tour moteur fait 2mm (vis trapézoidale 2mm) donc Nombre de tours = Nombre de mm/2. 
Donc (22.05+qté mm)/2 = Nombre de tours à effectuer
*/

void avance_moteur(int qte_uL)
{
      float nbr_tr;
      int nbr_stp;
      nbr_tr=(22.05+(((qte_uL/1000)/0.4)*1.8))/2;
      tmc26XStepper.setSpeed(80);    //Set speed at 80 RPM
      nbr_stp =round(nbr_tr*200); // moteur a 200pas par tour
      tmc26XStepper.step(nbr_stp);     
      tmc26XStepper.un_start();         //start stepper
       
}

/*-----------------------SF_REMISE A ZERO--------------------------------------------*/

/*Dans cette fonction on vient remettre le pousse seringue a zero et vider les circuits*/

bool remise_a_zero()
{    
  bool erreur =LOW; 
  digitalWrite(pompe, LOW); //on active pompe à vide, inversé sur la carte relais
  digitalWrite(nettoyage, LOW); //on active le distributeur pour aspirer ce qu'il y a dans le reseau
  unsigned long debut =millis(); //on compte le temps
  tmc26XStepper.SPI_setSpeed(500);    //Set speed at 500 RPM
  int etat_capteur_zero =digitalRead(capteur_zero);
  unsigned long temps =0;
  while(capteur_zero==LOW&&temps<tps_erreur_mot) //si on mets plus de 30s à atteindre la position on considère qu'il y a une erreur
  {

      tmc26XStepper.SPI_step(-1);     //on recule d'un pas
      tmc26XStepper.spi_start();         //start stepper 
      etat_capteur_zero =digitalRead(capteur_zero);
      temps=millis();
      temps =temps-debut;
  }
      if (temps>tps_erreur_mot)
      {
        erreur=HIGH;
        digitalWrite(voyant, LOW);
        Serial.println("erreur lors de la remise Ă  zero");
      }
   temps =temps-debut;
   while(temps<15000) //on attend 15s d'aspiration
   {
    Serial.println("on attend 15s");
    delay(1000);
    temps=millis();
    temps =temps-debut;
    }
    digitalWrite(nettoyage, HIGH); //on ferme le distri inversé sur la carte relais
    digitalWrite(pompe, HIGH); //on eteint la pompe inversé sur la carte relais
    Serial.println("remise à zero terminée");
    return (erreur);
  }
  
/*-----------------------SF_AGITER--------------------------------------------*/

/*Dans cette fonction on vient lancer l'agitation selon un temps defini des que l'utilisation lance le go par l'appui du bouton (comme il y a des reglages manuels a faire)*/

void agiter(long temps_agitation, int intervalle)//temps_agitation minute
{
  Serial.println("debut_agitation");
  long temps;
  digitalWrite(agitateur, LOW);
  int etat_bouton =digitalRead(bouton);
  Serial.println(etat_bouton);
  while (etat_bouton!=HIGH) //on attend le go de l'utilisateur
  {
    Serial.println("attente commande utilisateur");
    etat_bouton =digitalRead(bouton);
    digitalWrite (voyant, LOW); //on fait clignoter le voyant pour que l'utilisateur sache qu'il faille faire une commande
    delay(intervalle);
    digitalWrite (voyant, HIGH);
    delay(intervalle);
        //on ajoute un truc d'erreur si on attend trop longtemps? UN VOYANT??
  }
  temps=temps_agitation*60*1000;
  Serial.println("agitation en cours");
  delay(temps);
  digitalWrite(agitateur, HIGH); //on desactive l'agitateur  inversé sur la carte relais
  Serial.println("agitation terminée");
}

/*-----------------------SF_VIDANGER--------------------------------------------*/

/*Dans cette fonction on vient lancer la vidange des puits*/

void vidanger(int temps_vidange) //temps_vidange seconde
{
  long temps;
  digitalWrite(pompe, LOW); //on active pompe Ă  vide
  digitalWrite(piston, LOW); //on mets les pistons en position basse
  digitalWrite(vidange, LOW); //on ouvre circuit vidange
  temps =temps_vidange*1000;
  delay(temps);
  digitalWrite(pompe, HIGH); //on active pompe Ă  vide
  digitalWrite(piston, HIGH); //on mets les pistons en position basse
  digitalWrite(vidange, HIGH); //on ouvre circuit vidange 
}

When I launched the code I have the strange behaviour following (if the stepper is not powered), i saw that in the monitor :

16:54:14.220 -> ==============================
16:54:14.260 -> TMC26X Stepper Driver Demo App
16:54:14.300 -> ==============================
16:54:14.340 -> Configuring stepper driver
16:54:14.380 -> config finished, starting
16:54:14.380 -> started
16:54:14.420 -> debut init
16:54:15.340 -> 0
16:54:16.340 -> 1001
16:54:17.340 -> 2001
16:54:18.340 -> 3001
16:54:19.340 -> 4001
16:54:20.340 -> 5001
16:54:21.334 -> 6002
16:54:22.336 -> 7002
16:54:23.364 -> 8003
16:54:24.360 -> 9002
16:54:25.360 -> 10003
16:54:26.336 -> 11003
16:54:27.336 -> 12003
16:54:28.376 -> 13004
16:54:29.376 -> 14003
16:54:30.341 -> 15004

=>seems to work properly.

But if I powered ON :

co⸮==============================
TMC26X Stepper Driver Demo App

Configuring stepper driver
config finished, starting
started
debut init
0
=========================}====
TMC26X Stepper Driver Demo App

TMC26X Stepper Driver Demo Aconfig f⸮nished, starting
started
debut init
0
49
==================z===========
TMC26X Stepper Driver Demo App

Configuring stepper driver
c⸮

=> as if it's restart again and again

Here the schematic

Sorry my schematic is false it's not the good shield but the wiring is similar

Sorry, i forgot the stepper : it's a Nema 17.
i also tried with a 103H5208-5240 from SANYODENKI same results

Hi,
I looked through the schematic in the link that you had posted.
The /EN line is active low. Looking at the diagram in your link, it appears that the Enable LED should light up when the Enable pin is low.

Could you please describe the behaviour or the motor in a little more detail?

Do you have a multimeter? If so, you could check the voltages at the /EN pin (the bar over the EN means active low).
But more importantly, also check to see if the voltage provided by the power supply is correct both at rest and when you are running the motor.

Hi,

So the led /EN is light up.
I measured 0.4V.

I have 24VDC at the power supply

When i lauched the example code in the link :
/EN light up all the time
24VDC all the time
0.4VDC all the time
even when the motor is running
SG led blinked when motor is running.

With my code the motor is never runnnig but with the example code it's running roughly. (start a few, stop then restart a little...stop for a while then restart...)

I have this on the monitor :

=============================
TM⸮26X Stepper Driver Demo App
==============}===============
⸮onfiguring stepper driver
config finished, starting
started
settin⸮ speed to 100
Go⸮ng 1000 steps
Stall Guard: 863
Stall Guard: 0
Stall Guard: 0
Stall Guard: 225
Stall Guard: 508
Stall Guard:0 Stall Guard: 0 Stall G⸮a======== =============}================ Configur⸮ng stepper drive⸮ config finished\ starting started setting speed to 100 Going 1000 steps Stall Guard: 821 ⸮tall Guard: 0 Stall Guardt 0 Stall Guard: 682 Stall Guard: 50 Stal⸮ Guard: 0 Stall Guard: 0 Stall Guard: 52 Stall Guard: 405 Stall G⸮ard: 0 Stall Guard: 35 Stall Guard: 0 St⸮ll Guard: 0 Stall Guard:
Stall Guard: 256
Stall Guard: 0
Stall Guard: 0
Stall Gu⸮rd: 361
Stall Guard: 604
Stall Guard: 0
Stall Guard: 0
Stall Guardv 0
Stall Guard: 0
Stall Guard: 334
Stall@Guard: 0
Stall Guard: 0
Stall Guard: 592
Stall Guard: 709
Stall Guard: 60
Stall Guard: 0
Stall Guard: 0
Stall Guard: 79
Sta⸮l Guard: 382
Stall Guard: 0
Stall Guard: `
Stall Guard: 0
Stall Guard: 0
Stall Guard: 144
⸮tall Guard: 0
Stall Guard: 0
Stall

That seems good.

I looked up the Trinamic web site for the chip used by your motor driver TMC260C

From what I can gather, the SG_TST is connected to the Stall Guard module inside the TMC chip. If that LED comes on, it is likely that the TMC is signalling an overload condition.

This may be solved by using a higher current limit in the constructor.
According to your motor data sheet:
Courant 1 A
It may be that the current limit that you have set is a little too low.

Also, the above constructor seems odd to me. I know it is what is written in the documentation, but please try to change that line to this, and see if it makes a difference:

TMC26XStepper tmc26XStepper(200,6,4,5,800);

Here is a link to the chip itself:

Hello again,

Thank you for helping.
So I tried with your modification (for me "tmc26XStepper" doesn't appears red in the program like in yours) and with a higher current limit but there is the same results:
Motor move, then stop, then move again, with random delay between two runnings.

Besides on the arduino monitor I see that the message of the beginning of the program appears many times, as if the program restart to 0. But normally the motor should run continuously right?

I am wondering if I should tiry to change some of the configurations datas :

  tmc26XStepper.setSpreadCycleChopper(2,24,8,6,0);
  tmc26XStepper.setRandomOffTime(0);

  tmc26XStepper.setMicrosteps(128);
  tmc26XStepper.setStallGuardThreshold(4,0);

But I don't really understand their purpose (except microsteps).

Hi,
Can you please post some pictures of your project so we can see your component layout?

Thanks.. Tom... :smiley: :+1: :coffee: :australia:

It's enough?

The more and more I test and the more and more I think that the library furnished by the constructor of the shield is bad...

Even if I put just a print message in the loop function, the program restart many time...and the program write the setup message again and again and with some errors in it and more and more errors each time. I don't know what happen to create this behaviour.

After some testing I found an other strange behaviour.
Maybe someone could tell me if it's normal or not :

If I launch the followed simple code just with USB wired on the ARDUINO, it's work properly and I saw the 0-5V to my pin:

void setup() 
{
    pinMode(4, OUTPUT);
    pinMode(5, OUTPUT);
    Serial.begin(9600);
    Serial.println("SETUP_END");

}

void loop() 
{
    Serial.println("GO");
    digitalWrite(4, HIGH);
    digitalWrite(5, HIGH);
    delay(200);
    digitalWrite(5, LOW);
    delay(200);
}

But if I put the power 24VDC on the shield + 12VDC on the ARDUINO, I've got the same pbl of program rebooting all the time...

I really don't understand what's happening....

When this happens, what is your 5V on the Arduino showing?

Thanks.. Tom.... :smiley: :+1: :coffee: :australia:
PS, Check that the gnd of the 12V supply is a good connection to the Arduino gnd.

Ok so the solution was : growing up the 24VDC Power Cable Gauge. :sweat_smile:

The rebooting was due to a power collapsing maybe.
Now with the example the motor is running.
Maybe I have to work to have a smooth moving but It's working

1 Like

Hello TomGeorge,

So I found the solution but I do not understand really why.
Is that because the smaller cable warm up too much and activate a security in the arduino?

Thank you.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.