teemuatlut / TMCStepper

MIT License
500 stars 195 forks source link

About using the DIAG pin #174

Open MakerLS opened 3 years ago

MakerLS commented 3 years ago

Hi.

First of all I apologize for my level of English, I probably have more than one fault.

Once the code "StallGuard_TMC2209: https://github.com/teemuatlut/TMCStepper/tree/master/examples/StallGuard_TMC2209" and the code "https://gist.github.com/metalinspired/dcfe07ed0b9f42870eb54dcf8e29c126" have been tested, I am trying to modify it so that when it detects a collision, (PIN_DIAG == HIGH) it changes the direction of rotation. To do this, I read the status of the DIAG pin. According to documentation once DIAG == HIGH, it is necessary to disable the TMC2209 (and I suppose to re-enable it) to keep it working. I can't figure out how to implement this code.

Once DIAG is positive, I can't get the TMC_2209 to work again. Somebody can help me. Thank you

MakerLS commented 3 years ago

This is my code:

#include <TMCStepper.h>
#include <AccelStepper.h>

#define STALL_VALUE     1 // [0..255]
#define TOFF_VALUE        4 // [1... 15]

#define EN_PIN           12 // Enable
#define SW_RX            8 // TMC2208/TMC2224 SoftwareSerial receive pin
#define SW_TX            9// TMC2208/TMC2224 SoftwareSerial transmit pin

#define DIR_PIN          11 // Direction
#define STEP_PIN         10 // Step
#define DIAG_PIN             7// Pin para detectar colision

#define DRIVER_ADDRESS 0b00 // TMC2209 Driver address according to MS1 and MS2
#define R_SENSE 0.11f // SilentStepStick series use 0.11

TMC2209Stepper driver(SW_RX, SW_TX, R_SENSE, DRIVER_ADDRESS);

AccelStepper stepper = AccelStepper(stepper.DRIVER, STEP_PIN, DIR_PIN);

using namespace TMC2209_n;

int32_t speed = 0;  //0 lo deshabilita

int steps_per_mm = 100;

void setup() {
  Serial.begin(115200);         // Init serial port and set baudrate
  while(!Serial);               // Wait for serial port to connect
  Serial.println("\nComenzamos...");

  //SERIAL_PORT.begin(115200);
  driver.beginSerial(115200);

  pinMode(STEP_PIN, OUTPUT);
  pinMode(DIR_PIN, OUTPUT);
  pinMode(DIAG_PIN, INPUT);
  pinMode(EN_PIN, OUTPUT);

  driver.begin();

  // Sets the slow decay time (off time) [1... 15]. This setting also limits
  // the maximum chopper frequency. For operation with StealthChop,
  // this parameter is not used, but it is required to enable the motor.
  // In case of operation with StealthChop only, any setting is OK.
  driver.toff(TOFF_VALUE);  //4

  // VACTUAL allows moving the motor by UART control.
  // It gives the motor velocity in +-(2^23)-1 [μsteps / t]
  // 0: Normal operation. Driver reacts to STEP input.
  // /=0: Motor moves with the velocity given by VACTUAL. 
  // Step pulses can be monitored via INDEX output.
  // The motor direction is controlled by the sign of VACTUAL.
  driver.VACTUAL(speed);

  // Comparator blank time. This time needs to safely cover the switching
  // event and the duration of the ringing on the sense resistor. For most
  // applications, a setting of 16 or 24 is good. For highly capacitive
  // loads, a setting of 32 or 40 will be required.
  driver.blank_time(24);

  driver.rms_current(400); // mA
  driver.microsteps(16);

  // Lower threshold velocity for switching on smart energy CoolStep and StallGuard to DIAG output
  driver.TCOOLTHRS(0xFFFFF); // 20bit max

  // CoolStep lower threshold [0... 15].
  // If SG_RESULT goes below this threshold, CoolStep increases the current to both coils.
  // 0: disable CoolStep
  driver.semin(5);

  // CoolStep upper threshold [0... 15].
  // If SG is sampled equal to or above this threshold enough times,
  // CoolStep decreases the current to both coils.
  driver.semax(2);

  // Sets the number of StallGuard2 readings above the upper threshold necessary
  // for each current decrement of the motor current.
  driver.sedn(0b01);

  // StallGuard4 threshold [0... 255] level for stall detection. It compensates for
  // motor specific characteristics and controls sensitivity. A higher value gives a higher
  // sensitivity. A higher value makes StallGuard4 more sensitive and requires less torque to
  // indicate a stall. The double of this value is compared to SG_RESULT.
  // The stall output becomes active if SG_RESULT fall below this value.
  driver.SGTHRS(STALL_VALUE);

  Serial.println(F("\nComprobando conexión con chip... "));
  uint8_t conexion = driver.test_connection();
   delay(500);
  if (conexion) {
    Serial.println(F("La conexion ha fallado. "));
    Serial.print(F("La causa mas probable es: "));
    switch (conexion) {
      case 1: Serial.println(F("El cableado de la conexión")); break;
      case 2: Serial.println(F("No hay alimentación")); break;
    }
    Serial.println(F("Corrige el fallo y reinicia el sistema"));

    // We need this delay or messages above don't get fully printed out
    delay(100);
    abort();
  }
  Serial.println("La conexion se ha establecido de forma correcta.");

  stepper.setMaxSpeed(50*steps_per_mm); // 100mm/s @ 80 steps/mm
  stepper.setAcceleration(1000*steps_per_mm); // 2000mm/s^2
  stepper.setEnablePin(EN_PIN);
  stepper.setPinsInverted(false, false, true);
  stepper.enableOutputs();

  while (digitalRead(DIAG_PIN) == HIGH)
  {
    // Espero a que el chip este operativo
    Serial.print(".");
  }
  Serial.println(".");
}

void loop() {

  boolean flag = false;

  while ((digitalRead(DIAG_PIN) == LOW) && flag == false)
  {
      if (stepper.distanceToGo() == 0) {
        Serial.println("Cargo 1mm");
        stepper.disableOutputs();
        delay(100);
        stepper.move(steps_per_mm); // Move 1mm
        stepper.enableOutputs();
      }

      if(digitalRead(DIAG_PIN) == HIGH){
        int cont = 1;
        Serial.println("Llego");
        for(int i=0; i<100; i++)
        {
          if (digitalRead(DIAG_PIN) == HIGH)
          { cont++;
            Serial.println("Detectado final" + cont);
          }
        }

        if (cont > 75)
        {
          Serial.println("Detectada colision");
          flag = true;

        }
      }else
        {
          stepper.run();
          Serial.println("Avanzo 1mm");
        }
   }

   Serial.println("He llegado al final");
  reactivateStepper ();
    Serial.println("Reseteo el driver");

    delay(5000);

    steps_per_mm = -steps_per_mm;
}

void reactivateStepper ()
{
  driver.toff(0);
  digitalWrite(EN_PIN, HIGH);
  delay(5000);
  driver.begin();
  driver.toff(TOFF_VALUE);  //4
  driver.VACTUAL(speed);
  driver.blank_time(24);
  driver.rms_current(400); // mA
  driver.microsteps(16);
  driver.TCOOLTHRS(0xFFFFF); // 20bit max
  driver.semin(5);
  driver.semax(2);
  driver.sedn(0b01);
  driver.SGTHRS(STALL_VALUE);

  digitalWrite(EN_PIN, LOW);

  Serial.println("Reactivado");
}
teemuatlut commented 3 years ago

The driver is disabled by pulling the enable pin high, like you're doing in reactivateStepper, but it doesn't forget all the previous configuration so you don't need to reconfigure everything.

It also seems like a conflict for you to be using both the accelStepper library with its Step and Dir lines, but you're also trying to use the internal step pulse generator (VACTUAL).

MakerLS commented 3 years ago

I was desperate from so much trial and error ... when logic (when my logic) fails, anything seems good. I have tried to keep the code as simple as possible for what I want to do:

#include <TMCStepper.h>
#include <AccelStepper.h>

#define STALL_VALUE     1 // [0..255]
#define TOFF_VALUE        4 // [1... 15]

#define EN_PIN           12 // Enable
#define SW_RX            8 // TMC2208/TMC2224 SoftwareSerial receive pin
#define SW_TX            9// TMC2208/TMC2224 SoftwareSerial transmit pin

#define DIR_PIN          11 // Direction
#define STEP_PIN         10 // Step
#define DIAG_PIN             7// Pin para detectar colision

#define DRIVER_ADDRESS 0b00 // TMC2209 Driver address according to MS1 and MS2
#define R_SENSE 0.11f // SilentStepStick series use 0.11

TMC2209Stepper driver(SW_RX, SW_TX, R_SENSE, DRIVER_ADDRESS);

AccelStepper stepper = AccelStepper(stepper.DRIVER, STEP_PIN, DIR_PIN);

using namespace TMC2209_n;

int steps_per_mm = 100;
int counter = 0;

void setup() {
  Serial.begin(115200);         // Init serial port and set baudrate
  while(!Serial);               // Wait for serial port to connect
  Serial.println("Comenzamos...");

  driver.beginSerial(115200);

  pinMode(STEP_PIN, OUTPUT);
  pinMode(DIR_PIN, OUTPUT);
  pinMode(DIAG_PIN, INPUT);
  pinMode(EN_PIN, OUTPUT);

  driver.begin();
  driver.toff(TOFF_VALUE);  //4
  driver.blank_time(24);
  driver.rms_current(400); // mA
  driver.microsteps(16);
  driver.TCOOLTHRS(0xFFFFF); // 20bit max
  driver.semin(5);
  driver.semax(2);
  driver.sedn(0b01);
  driver.SGTHRS(STALL_VALUE);

  testConection ();

  stepper.setMaxSpeed(50*steps_per_mm); // 100mm/s @ 80 steps/mm
  stepper.setAcceleration(1000*steps_per_mm); // 2000mm/s^2
  stepper.setEnablePin(EN_PIN);
  stepper.setPinsInverted(false, false, true);
  stepper.enableOutputs();
}

void loop() {

  //I advance until I reach an end "Extrem 1"
  while (digitalRead(DIAG_PIN) == LOW) {
    stepper.move(steps_per_mm); // Move 1mm
    stepper.run();
  }

  //stepper.setCurrentPosition(0); // When it has reached the extreme set position to 0 steps

  steps_per_mm = (-1*steps_per_mm); //Change direction
  reactivateStepper (); //¿Reset Enn?

  //I advance until I reach an end "Extrem 2"
  while (digitalRead(DIAG_PIN) == LOW) {
    stepper.move(steps_per_mm); // Move 1mm
    stepper.run();
    counter++;  //Counter = Travel (in milimetters)
  }
}

void testConection ()
{
  Serial.println(F("\nComprobando conexión con chip... "));
  uint8_t conexion = driver.test_connection();
  delay(500);
  if (conexion) {
    Serial.println(F("La conexion ha fallado. "));
    Serial.print(F("La causa mas probable es: "));
    switch (conexion) {
      case 1: Serial.println(F("El cableado de la conexión")); break;
      case 2: Serial.println(F("No hay alimentación")); break;
    }
    Serial.println(F("Corrige el fallo y reinicia el sistema"));

    delay(100);
    abort();
  }
  Serial.println("La conexion se ha establecido de forma correcta.");
}

void reactivateStepper ()
{
  stepper.disableOutputs();
  digitalWrite(EN_PIN, HIGH);

  delay(500);
  digitalWrite(EN_PIN, LOW);
  stepper.enableOutputs();

  Serial.println("Reactivado");
}

ReactivateStepper does not work. I have tried:

void reactivateStepper ()
{
  //stepper.disableOutputs();
  digitalWrite(EN_PIN, HIGH);

  delay(500);
  digitalWrite(EN_PIN, LOW);
  //stepper.enableOutputs();

  Serial.println("Reactivado");
}
void reactivateStepper ()
{
  stepper.disableOutputs();
  //digitalWrite(EN_PIN, HIGH);

  delay(500);
  //digitalWrite(EN_PIN, LOW);
  stepper.enableOutputs();

  Serial.println("Reactivado");
}
void reactivateStepper ()
{
  stepper.disableOutputs();
  digitalWrite(EN_PIN, HIGH);

  delay(500);
  digitalWrite(EN_PIN, LOW);
  stepper.enableOutputs();

  Serial.println("Reactivado");
}

And always DIAG equals HIGH. I cannot reset ENN and therefore the program does not go from there. Well the program passes, but the execution is wrong:

Comenzamos...

Comprobando conexión con chip... 
La conexion se ha establecido de forma correcta.
Reactivado
... infinity ...
Reactivado

The idea is to move a platform on a rail of length X. I want to use the stallguard function to detect X (start) and X (end).

ReTheoden commented 3 years ago

Hi, I have exactly the same problem. After a stall the DIAG pin should reset after sending an HIGH signal to EN_PIN but there is no way to clear it. Also the datasheet says this is the correct manner but nothing happens. Any Idea ?

teemuatlut commented 3 years ago

https://github.com/teemuatlut/TMCStepper/issues/191 Similar issue from a month ago. It may be enough to take a single step in order to properly reset the condition after reactivating EN line.

ReTheoden commented 3 years ago

Hi, solved the problem in the same way recommended by teemuatlut. After the lines that reset the DIAG pin and reactivate the driver:

digitalWrite(EN_PIN, HIGH);
delay(500); digitalWrite(EN_PIN, LOW);

it is mandatory NOT to check the DIAG pin immediately but only after a full step. Thank you.