Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TMC 2209 reading stallguard values #87

Open
so999 opened this issue Oct 24, 2019 · 6 comments
Open

TMC 2209 reading stallguard values #87

so999 opened this issue Oct 24, 2019 · 6 comments

Comments

@so999
Copy link

so999 commented Oct 24, 2019

I would like to monitor the torque output of a stepper motor driven by TMC2209.
I tried to read the stallguard values from TMC 2209 using the provided example - StallGuard_TMC2209.ino.
However, these values never change. The driver.SG_RESULT() prints continuously zero, whatever the resisting torque is (even the motor is stalled).
It seems that the arduino uno is not receiving data from the driver when the motor spins. When the timer1/motor is stopped, I can read values from the driver.

I used software serial pins connected to PDN using a resistor (rx directly to PDN and tx via the 1kohm resistor to PDN).

Sorin

@alex72ru
Copy link

alex72ru commented Dec 2, 2019

Good afternoon everyone. I want to connect to this issue. I use a translator, so I apologize for my English.
Doing a project where I use a stepper motor , about 300 mA 12 v. It is necessary to control the motor to stop at the extreme points. DIGTREETECH TMC2209 V. 1.2 driver purchased in China, jumpers on Board by default . Arduino nano v3 controller. The program Arduino IDE v 1.8.10. I use an example from the library StallGuard_TMC2209, to communicate with the driver added the library SoftwareSerial.h . SERIAL PORT works-if I change the value of driver.microsteps then the motor speed changes. But when the engine stops at the endpoint of the value driver. SG_RESULT, driver.cs_actual does not change and the rotation of the engine does not stop. Please tell me what I'm doing wrong.

@csosaayala
Copy link

Same issue Here using watterot TMC 5160, Sg_result value does not change.

@nietaki
Copy link

nietaki commented Aug 30, 2020

Try swapping your UART RX and TX connections.

When I had them connected like this:

ESP32 UART RX <------> TMC2209 TX
ESP32 UART TX <------> TMC2209 RX

I could send UART commands to the driver and it did react to them right, but when I was trying to read the SG_RESULT value from the driver it was always 0.

When I swapped them around to be

ESP32 UART RX <------> TMC2209 RX
ESP32 UART TX <------> TMC2209 TX

Everything started working as expected and I can read the values out alright.

I think it has something to do with how the resistors are connected on the driver board, between the RX/TX pins and the UART pin of the driver.

Good luck!

@stmcculloch
Copy link

@so999 @alex72ru I was struggling with the same issue. I found the solution was to use the TMC2209's built-in velocity control. I was initially using an ISR based on a timer, but this resulted in 0 0 55 while the motor was turning, and then normal values while the motor was at rest.

Use
driver.VACTUAL(1000); for rotate in one direction
driver.VACTUAL(-1000); for rotate in the other
driver.VACTUAL(0);, for keeping motor at rest

@so999
Copy link
Author

so999 commented Feb 18, 2021

I didn't manage to figure out why the arduino uno is not working. It wasn't a communication problem, even I used a single driver pin for it (the UART pin PDN). The driver received other commands, and arduino uno was able to read driver registries as well.

Finally, I used another microcontroller - ESP32, and it worked. The communication with the driver was the same: the hardware serial port UART2 pins (16 and 17) of ESP32, were connected to the PDN pin of the TMC2209 (Tx via 1K resistor). Also, the enable and step pins of TMC2209 were connected to ESP32. The direction was changed via software and the DIR pin of TMC2209 was not used. The driver configuration was the same as in the provided example and the arduino uno test. It worked. I was able to read different SG_RESULT values according to different resisting torques.

The SG_RESULTS values were used in a robot claw application. The claw was moved by a stepper motor used with TMC2209. The TMC driver received pulses and commands from ESP32 microcontroller and this was commanded by a simple phone application. When a "grab command" or a "release command" is sent from the phone app, the ESP32 starts a timer/motor and also starts reading the SG_RESULT values. When the claw reaches an end or grabs objects of different sizes, the SG_RESULT values tells the microcontroller to stop the motor: [https://www.youtube.com/watch?v=0jgBc6uqsYw]

Here is the code:

#include <TMCStepper.h>

#define STALL_VALUE     20 // [0..255]

  
static uint32_t previous_load_measuring_time=0; //for timing the load measures
bool grabDirection=false;  //for reversing the direction of the claw
int LoadLimit=0;      //over a determined value the claw is stopped because it reached an end or it grabbed an object

int load_measures_counter=0; //10 load measures will be averaged
unsigned long accumulated=0; //this accumulates  the 10 load measures

bool MeasuringLoadStarted=false; //the measuring process is started only when a movement command of the claw is sent via Bluetooth
bool Grab=true; //the movement command

unsigned long ticks;       //used for setting the timer/speed of the motor
int prescaler=1;
volatile unsigned long countedPulses=0; //only to check how many pulses the stepper moved until reached an end, object etc.
   
#define EN_PIN           2 // Enable
#define STEP_PIN         BIT22 // Step

#define DRIVER_ADDRESS 0b00 // TMC2209 Driver address 
#define R_SENSE 0.11f 


#include <HardwareSerial.h>

//the claw is commanded via bluetooth
#include "BluetoothSerial.h"
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif

BluetoothSerial SerialBT;
HardwareSerial TMC_Serial_Port(1);


// Select your stepper driver type
TMC2209Stepper driver(&TMC_Serial_Port, R_SENSE, DRIVER_ADDRESS);

using namespace TMC2208_n;


byte BTdata[100];
byte counterBT=0;


volatile int state=LOW;
hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;

//the ISR for one esp32 hardware timer; here the pulses are sent to the driver
void IRAM_ATTR onTimer() {
  portENTER_CRITICAL_ISR(&timerMux);

  if(state==LOW)
  {
    state=HIGH;
    REG_WRITE(GPIO_OUT_W1TS_REG, STEP_PIN);//GPIO22 HIGH (set)
    countedPulses++;
  }
  else
  {
    state=LOW;
    REG_WRITE(GPIO_OUT_W1TC_REG, STEP_PIN);//GPIO22 LOW (clear) 
  }
  
  portEXIT_CRITICAL_ISR(&timerMux);
}





void setup() {
Serial.begin(9600);
TMC_Serial_Port.begin(115200, SERIAL_8N1, 16, 17); //the port used for communication with TMC2209 is UART2
                                                   //the pins 16,17=Rx,Tx were connected to the PDN pin of the driver
                                                   //Rx is connected directly to PDN pin and Tx is connected via a 1Kohm
                                                   //resistor to the same PDN pin of TMC2209
SerialBT.begin("");

pinMode(EN_PIN, OUTPUT);
digitalWrite(EN_PIN, HIGH);
delay(5000);

Serial.println("\nStart...");

//tmc driver config
  driver.begin();
  driver.toff(4);
  driver.blank_time(24);
  driver.microsteps(256);
  driver.en_spreadCycle(0);
  driver.intpol(1);
  driver.TCOOLTHRS(0xFFFFF); // 20bit max
  driver.semin(5);
  driver.semax(2);
  driver.sedn(0b01);
  driver.SGTHRS(STALL_VALUE);
  Serial.println(driver.CHOPCONF());
  digitalWrite(EN_PIN, LOW);
   
REG_WRITE(GPIO_ENABLE_REG, STEP_PIN);

prescaler=8;   // = 80 ticks in usecs
LoadLimit=180; //the determined load limit for this particular motor, epplication etc

driver.rms_current(800); // mA
double rps=1.0; //1 rotation per second
double PulseFreq=400*256*rps; //400 full steps per turn x 256 microsteps
double semiperiod=(1/PulseFreq)/2;
ticks=(unsigned long)(semiperiod*80000000.0/(double)prescaler); //the calculated frequency of the timer
Serial.println(ticks);
}



void loop() {

//if a grab or !grab command was sent
if(MeasuringLoadStarted==true)
{
  uint32_t ms = millis();

  if((ms-previous_load_measuring_time) > 10) 
  { //run every 0.1s
    previous_load_measuring_time = ms;
    load_measures_counter++;
    accumulated=accumulated+driver.SG_RESULT(); //the actual load measuring
  }

  if(load_measures_counter>=10)
  {
    double val=(double)accumulated/(double)load_measures_counter;
    load_measures_counter=0;
    accumulated=0;
    Serial.println((int)val);

    if(val<=LoadLimit) //under the load limit the motor is stopped; the value is chosen such as the object to be kept 
                       //by the claw; also the driver current in the stall mode is important; 
    {
        Serial.print("pulses:"); Serial.println(countedPulses);
        MeasuringLoadStarted=false;
        //stopping the timer/motor
        timerAlarmDisable(timer);
        timerDetachInterrupt(timer);
        if(Grab)
        {//the motion is stopped and the claw is closed
          SerialBT.print(":d#"); //the phone is informed about the state of the claw
        }
        else
        {//the motion is stopped and the claw is opened
          SerialBT.print(":i#");
        }
     } 
  }
}
  
//if there are Bluetooth data
byte inB;
while(SerialBT.available())
 {
   inB=SerialBT.read();
       if(SerialBT.available())
       {    
         BTdata[counterBT]=inB;
         counterBT++;

       } 
      else
       { 
          BTdata[counterBT]=inB;
          decodeCommand();     
       }  
 }




}





void decodeCommand()
{
  if((BTdata[0]==':') && (BTdata[counterBT]=='#')) //all commands starts with ":" and ends with an "#"
  {
     
    switch((char)BTdata[1])
    {
      {
      case 'a':   //Grab
        {
            countedPulses=0;
            Grab=true;
            driver.shaft(grabDirection);
            //starting the timer
            timer = timerBegin(0, prescaler, true); 
            timerAttachInterrupt(timer, &onTimer, true);
            timerAlarmWrite(timer, ticks, true); 
            timerAlarmEnable(timer);
            MeasuringLoadStarted=true;
        } 
      break;
      }




      {
      case 'l':   //! Grab
        {
            countedPulses=0;
            Grab=false;
            driver.shaft(!grabDirection);
            //starting the timer
            timer = timerBegin(0, prescaler, true); 
            timerAttachInterrupt(timer, &onTimer, true);
            timerAlarmWrite(timer, ticks, true); 
            timerAlarmEnable(timer); 
            MeasuringLoadStarted=true;         
        } 
      break;
      }


      
    }
 
  }

  
  memset(BTdata, 0, sizeof(BTdata)); //golim array-ul de date al BT - reinitializare pt o noua comanda
  counterBT=0; 
}

@JonathanWillms
Copy link

Hey, I had the same problem. I did find out that the TX and RX Pins on the TMC2209 (in my case V3.0) are both the same. They are both a complete uart. So to solve your problem (That the TMC isn't sending data to the Arduino) you need to only wire one of these pins to the RX Pin you defined on your Arduino, then grab a 1kOhm Resistor and wire it from the RX Pin, you defined on the Arduino, to the TX Pin, you defined on the Arduino.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants