Forum Rule: Always post complete source code & details to reproduce any issue!
Page 4 of 5 FirstFirst ... 2 3 4 5 LastLast
Results 76 to 100 of 101

Thread: New Stepper Motor Library

  1. #76
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    701
    I just released version 2 of TeensyStep on GitHub

    New features:
    • Improved rotational mode
    • Possibility to override speed and acceleration of a group of motors on the fly (rotational mode only)
    • Access to the current speed of the controllers
    • Callback when a target is reached
    • Additional examples


    I also started a small documentation page which can be found here: https://luni64.github.io/TeensyStep/

  2. #77
    Hi Luni
    I wonder if you could give me some advice on my project?
    I have a carriage on a 6m long guide. The carriage is pulled by a 8Nm stepper power by a 48v supply. The stepper has a 1:2 reduction and the looped belt has a ratio of 1:0.6. The carriage will move about 400mm per revolution of the motor.
    The objective:
    I have to accelerate the carriage in the first 2m to 8m/s then maintain that for 2m and then decelerate for the last 2m. This is done both ways.

    I am having problems conceptualizing how to use the library to achieve this. If the acceleration could be specified for a distance or a duration, then it could be done.
    Any suggestions will help please.

  3. #78
    Senior Member
    Join Date
    Aug 2014
    Posts
    165
    @luni — just wondering if the library will work with the new Teensy 4.0

  4. #79
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    701
    Sorry, not yet. The timers of the T4 behave differently from those of the T3s. So, I need to rethink a few concepts to utilize the speed of the T4 which will take some time.

  5. #80
    Senior Member
    Join Date
    Aug 2014
    Posts
    165
    Thanks @luni — I guess in real terms the library doesn’t really need the power of 4.0

  6. #81
    Junior Member
    Join Date
    Nov 2019
    Posts
    9
    Hello,

    sorry for my english. Im german.

    i have a problem with this library.
    i have a motor with 800steps/revolution
    i need 48khz (3600rpm) for output. this function is ok.
    But i can max set the setAcceleration(); to 10000
    I need 4-5seconds for full speed.
    Can i change the teensystep.h or others to make higher the acceleration


    can you me help?

    regards
    Stefan

  7. #82
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    701
    For an acceleration from 0 to 48kHz in 4s you need a setting of 48'000/4 = 12'000 stp/s^2. TeensyStep allows values from 1 to 500'000 so this should be no problem.

    But i can max set the setAcceleration(); to 10000
    This is very unlikely. Can you post an -ideally very short- sketch showing the effect?

  8. #83
    Junior Member
    Join Date
    Nov 2019
    Posts
    9
    this is the code

    Code:
    #include "TeensyStep.h"
    // stepper and  controller
    constexpr int stpPin = A8, dirPin = 1;
    Stepper motor(stpPin, dirPin);
    //StepControl controller;
    RotateControl controller;
    
    constexpr int stopPin = 2;
    const int ALARM = A5;
    const int ENA = A4; 
    int ENAstate=0;
    long frq;
    long acc;
    long rpm;
    
    // stopwatches 
    elapsedMillis displayStopwatch = 0;  // timing the display of the current position
    elapsedMillis blinkStopwatch = 0;    // timing the heartbeat LED
    elapsedMillis debounceTimer = 0;     // debouncing input pins
    
    int lastPos = 0;
    
    void handlePins();
    void handleCommands();
    
    void setup()
    {
        Serial.println("  m: move motor Pin A8");
        Serial.println("  r: RPM motor, r 1000");
        Serial.println("  a: acceleration, a 1000");
        Serial.println("  s: stop motor");
        Serial.println("  e: ENA motor Pin A4");            
        Serial.println("  x: emergency stop");
        Serial.println("  h: display this help");     
        motor.setMaxSpeed(1000);
        motor.setAcceleration(1000);
        pinMode(ALARM, INPUT_PULLUP); 
        pinMode(LED_BUILTIN, OUTPUT);
        pinMode(ENA, OUTPUT); 
        pinMode(stopPin, INPUT_PULLUP);  // touch the pin with GND to stop the motor
    }
    
    
    void loop()
    {
        
        // handle incomming commands on the serial interface ------------------
        handleCommands();
         
        // handle input from pins ---------------------------------------------
        handlePins();
    
        // the usual heartbeat ------------------------------------------------
        if (displayStopwatch > 2000)
        {
         controller.stopAsync();    
            displayStopwatch = 0;
        }
    }
    
    
    
    void handleCommands()
    {
        if (Serial.available() > 0)                 // skip if the serial buffer is empty
        {
          
           char cmd = Serial.read(); 
          displayStopwatch = 0;
          digitalWriteFast(LED_BUILTIN, 1);
          delay(10);
          digitalWriteFast(LED_BUILTIN, 0);
            switch (cmd)                            // ... and analyze it
            {
            case 'm':                               // move command
                if (!controller.isRunning())        // skip move command if motor is running already
                {
                    controller.rotateAsync(motor);
                    Serial.println("Started motor movement");
                }
                else
                {
                    Serial.println("Ignored, motor is already running");
                }
                break;
    
            case 's':                               // stop command
                controller.stopAsync();             // initiate stopping procedure
                Serial.println("Stopping motor");
                break;
                
           case 'a':                               // stop command
              while (Serial.available()) {
            String read = Serial.readStringUntil('\n');
             if (read.substring(0, 1) == " ") {
                acc = read.substring(1, read.length()).toInt();
                motor.setAcceleration(acc);
                Serial.println(acc);
            
            }
        } //end Serial.available
            break;
            case 'r':                               // stop command
            while (Serial.available()) {
            String read = Serial.readStringUntil('\n');
              if (read.substring(0, 1) == " ") {
                rpm = read.substring(1, read.length()).toInt();
                frq=rpm/0.075;
                motor.setMaxSpeed(frq);
                Serial.println(frq);
              }
        } //end Serial.available
               break;
            case 'x':                               // emergency stop command
                controller.emergencyStop();
                Serial.println("Emergency Stop");
                break;
    
            case 'e':                               // ENA  command
                controller.emergencyStop();
                ENAstate=!ENAstate;
                digitalWrite(ENA,ENAstate);
                delay(100);  
                Serial.println("ENA");
                break;
    
            case 'h':                               // help / usage command
            case 'u':
                Serial.println("\nUsage:");
                Serial.println("  m: move motor Pin A8");
                Serial.println("  r: RPM motor, r 1000");
                Serial.println("  a: acceleration, a 1000");
                Serial.println("  s: stop motor");
                Serial.println("  e: ENA motor Pin A4");            
                Serial.println("  x: emergency stop");
                Serial.println("  h: display this help");            
                break;
    
            default:
                break;
            }
        }
        
    }
    
    
    void handlePins()
    {    
        if (controller.isRunning() && !digitalReadFast(ALARM) && debounceTimer > 200)
        {
            debounceTimer = 0;                   
            controller.stopAsync();              // initiate stopping procedure
            Serial.println("Stopping motor");
                  ENAstate=!ENAstate;
                  digitalWrite(ENA,ENAstate);
                  delay(1000);
                  ENAstate=!ENAstate;
                  digitalWrite(ENA,ENAstate);         
                  delay(1000);            
                        controller.rotateAsync(motor);
        
        }
    }

  9. #84
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    701
    I tested your code and don't see a problem with acceleration.

    I changed the following for my tests:

    Code:
    void setup()
    {
      while(!Serial);                                      //<<<<<<<<<<<<<<<<<<<<<<<< Need to wait until the serial monitor is ready, otherwise the following text might not be displayed. 
    
      Serial.println("  m: move motor Pin A8");
      Serial.println("  r: RPM motor, r 1000");
      Serial.println("  a: acceleration, a 1000");
      Serial.println("  s: stop motor");
      Serial.println("  e: ENA motor Pin A4");
      Serial.println("  x: emergency stop");
      Serial.println("  h: display this help");
      motor.setMaxSpeed(48000);                     //<<<<<<<<<<<<<<<<<<  As you requested in the originial post
      motor.setAcceleration(100000);                //<<<<<<<<<<<<<<<<<<  Tested it with 10000, 20000 and 100000 all works as expected. 
      pinMode(ALARM, INPUT_PULLUP);
      pinMode(LED_BUILTIN, OUTPUT);
      pinMode(ENA, OUTPUT);
      pinMode(stopPin, INPUT_PULLUP); // touch the pin with GND to stop the motor
    }
    For testing I pressed "m" and recorded the signal on the STP pin. Here some screen shots:

    Acceleration 100000stp/s^2, you can clearly see the acceleration
    Click image for larger version. 

Name:	acc_100k_start.png 
Views:	9 
Size:	14.4 KB 
ID:	18283

    It should take t=v/a = 48000 / 100000 = 480ms to reach the speed of 48000 step/sec. Here a screenshot of the pulse sequence some 500ms after the start:
    Click image for larger version. 

Name:	acc_100k_t=500ms.png 
Views:	7 
Size:	20.5 KB 
ID:	18284
    Showing 48kHz

    As mentioned, I don't see anything strange.


    Remark: It is quite confusing to use the "A" pin numbers for digital pins. Technically it doesn't matter but it is much clearer to say
    Code:
    int stpPin = 22
    instead of
    Code:
    int stpPin = A8

  10. #85
    Junior Member
    Join Date
    Nov 2019
    Posts
    9
    Hello Luni.

    Thanks. I will test.
    and i will make a video when the test is not ok.
    what do you have for a osszi? :-) looks fine.

  11. #86
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    701
    what do you have for a osszi? :-) looks fine.
    https://www.az-delivery.de/products/...1681d4d4&_ss=r

  12. #87

  13. #88
    Junior Member
    Join Date
    Nov 2019
    Posts
    9
    now is ok.
    this was my failure.

    I had thought wrong.
    I thought the higher the value the longer the acceleration. This was not correct.
    lower value = longer acceleration

  14. #89
    Junior Member
    Join Date
    Dec 2019
    Posts
    4

    getCurrentSpeed() issues

    luni, thank you for your fabulous work on this library!

    I'm using a Teensy 3.5 and programming it with the Arduino IDE. I'm working on a project using the TeensyStep library which will be documented here. I've run into two library issues to bring to your attention:

    Issue 1
    getCurrentSpeed() reports non-zero values when the motor is stopped. Before rotation begins, it reports 1. After rotation has been stopped using stop() or stopAsync(), it reports 5. I would expect zero in both cases.

    Issue 2
    getCurrentSpeed() continues to return the last running speed after an emergency stop (it is not reset to zero). This prevents us from being able to test for issue 1 when using emergencyStop().

    The following example code can be used to demonstrate these issues. It also shows my crude initial method of deriving the motor RPM in real time, but I suspect my data types and math functions are not 100% optimal and probably cause rounding issues, hence the warning to prevent someone from blindly trusting this code for this purpose.

    Code:
    #include "TeensyStep.h"
    
    Stepper motor(2, 3);
    RotateControl ctrl(5, 5000);   // params are step pulse width (µs) and speed update period (µs) (defaults are 5,5000)
    
    float motorsteps = 200.0;  // motor steps per rotation
    float microstep = 1.0;     // match to DIP switch setting on microstep driver
    float rpm = 1500.0;        // desired initial speed setting in RPM
    
    int lastUpdateMillis = 0;
    int updateInterval = 250;  // (ms) interval between serial monitor updates
    
    void setup() {
      motor.setMaxSpeed((rpm / 60) * motorsteps * microstep);
      motor.setAcceleration(1000 * microstep);
      
      Serial.begin(9600);
      delay(1000);
      Serial.println("TeensyStep library: display current speed in serial monitor in PPS and RPM");
      Serial.println("(no need for an actual microstep driver or motor to be present)");
      Serial.println("(note that variable types and math functions are likely not ideal in this test code)");
      Serial.println("Send characters to cause events:");
      Serial.println(" 'r' to begin rotation with rotateAsync");
      Serial.println(" 'o' to override speed");
      Serial.println(" 's' for stopAsync (non-blocking)");
      Serial.println(" 'b' for stop (blocking)");
      Serial.println(" 'e' for emergency stop");
    }
    
    
    void loop() {
    
      if (millis() - updateInterval >= lastUpdateMillis)
      {
        lastUpdateMillis = millis();
        int calculatedrpm = ctrl.getCurrentSpeed() * 60 / motorsteps / microstep;
        Serial.printf("position: %d, pulses/sec: %d, rpm: %d\n", motor.getPosition(), ctrl.getCurrentSpeed(), calculatedrpm);
      }
    
      
      if (Serial.available()) 
      {
        char inChar = (char)Serial.read();
    
        if (inChar == 'r')  // rotate (initially to max speed specified)
          ctrl.rotateAsync(motor);
    
        if (inChar == 'o')  // change to a new speed
          ctrl.overrideSpeed(.5);
    
        if (inChar == 's')  // stop rotation with the non-blocking code
          ctrl.stopAsync();
    
        if (inChar == 'b')  // stop rotation with the blocking code
          ctrl.stop();
    
        if (inChar == 'e')  // emergency stop (instantaneous; no deceleration)
          ctrl.emergencyStop();
      }
    }

  15. #90
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    701
    Sorry, this is a known bug. See here for a simple workaround. https://github.com/luni64/TeensyStep...ment-499847557. You can also use the development branch (DevTimer) which fixed this and a couple of other things already. Hope to find some time soon to merge the fixes into the master branch. Too much projects at the same time...

  16. #91
    Junior Member
    Join Date
    Dec 2019
    Posts
    4
    I see; thanks! The underlying cause of not being able to set a timer to delay infinitely makes total sense, and that simple workaround addresses it perfectly.

    I noticed is that when the motor has been rotated and stopped, I can resume rotation using overrideSpeed(). If I have never started rotation using rotateAsync(), calling overrideSpeed() has no effect and the motor remains stopped.

    I also happened to notice that if I specify setAcceleration() a second time later in the program, it has no effect. This is not something that I expect will be necessary in my application, but I'm curious how tricky it would be to implement an overrideAcceleration() functionality. I imagine declaring the initial value does some fancy math that stores simpler values for repeated later efficient use, and recalculating on the fly would require more fancy math on the fly. I also expect that triggering a new acceleration ratio while the motor is currently accelerating would require being able to ramp smoothly from one acceleration rate to the new one, which would add a whole additional layer of complexity. Is this about right?

  17. #92
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    701
    I noticed is that when the motor has been rotated and stopped, I can resume rotation using overrideSpeed(). If I have never started rotation using rotateAsync(), calling overrideSpeed() has no effect and the motor remains stopped.
    Yes, OverrideSpeed(f) just changes the speed of a running motor by multiplying the set speed by the factor f. If you choose f to be zero the motor "runs" with speed 0. This is different from actually stopping the motor.

    I also happened to notice that if I specify setAcceleration() a second time later in the program, it has no effect. This is not something that I expect will be necessary in my application,
    All the "SetXX" functions only work with a stopped motor since they pre calculate all the parameters required for the move. As said above, overrideSpeed(0) will not stop the motor....

    I'm curious how tricky it would be to implement an overrideAcceleration() functionality.
    Not tricky anymore since it is already implemented in the development branch. This example https://luni64.github.io/TeensyStep/..._winder/winder makes heavy use of the feature when fine adjusting the pitch of a winding machine for violin strings.

  18. #93
    Junior Member
    Join Date
    Dec 2019
    Posts
    4
    Quote Originally Posted by luni View Post
    If you choose f to be zero the motor "runs" with speed 0. This is different from actually stopping the motor.
    As said above, overrideSpeed(0) will not stop the motor....
    Understood. Here's the nuance I'm seeing that can be demonstrated using the code I posted above: If I power up the Teensy so the program starts fresh (and I don't call a rotateAsync() command) and I call overrideSpeed(), the motor does not move. If I stop a running motor using stopAsync() or stop() or emergencyStop(), I can then use overrideSpeed() to cause the motor to begin rotating again (at the specified speed factor) even though it appears "stopped".

    So either the stop commands do not fully "stop" the motor in some manner, or rotateAsync() is capable of "starting" a stopped motor, but only if it has been called previously.

    I think I will want to set a fairly high max speed initially, but be able to start rotation at a lower speed. I plan to simply call rotateAsync() and then immediately call overrideSpeed() to the lower starting speed. There should be so little delay between the two calls that the output signal will behave as if the new lower speed was the only thing it has been given. (yet to be tested with hardware, but it seems plausible)

    Not tricky anymore since it is already implemented in the development branch. This example https://luni64.github.io/TeensyStep/..._winder/winder makes heavy use of the feature when fine adjusting the pitch of a winding machine for violin strings.
    Is he changing the acceleration on the fly, or merely the speed? (and the acceleration has been set once at the beginning)

    Either way, it sounds like I should figure out how to get the dev branch loaded onto my machine. ;-)

  19. #94
    Hey @luni

    2 Things

    1. I have noticed in your discussions and github pages you show some timing and signals in a GUI interface that looks to be running on a desktop computer. I was wondering what software you were running to debug the stepper motor timing to produce those images.

    2. Do you have an estimate for when the Teensy 4 will be supported?

    Thanks

  20. #95
    Junior Member
    Join Date
    Nov 2019
    Posts
    9
    Hallo,

    ich habe jetzt doch noch ein Problem mit dem Teensy (3.2,3.5).
    Ich schreibe jetzt auch auf deutsch weil man das besser erklären kann.

    Mein Programm funktioniert soweit nur habe ich das problem wenn ich die geschwindigkeit ändere stopt der motor und fährt dann von 0 auf die gewünschte geschwindigkeit. und nicht von 1000 auf 500.
    das problem ist noch das die rampe (acc) bleiben muss, also er sollte langsam von z.b. 1000 auf 500 runterfahren und nicht ruckartig von z.b. 1000 auf 500 wenn ich die ACC ausschalte.

    benutzte ich da vielleicht falsche befehle, async nehme ich.

    grüße
    Stefan

  21. #96
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    701
    IMHO, it is not a good idea to write German posts in an English forum. If you feel uncomfortable you can always use https://www.deepl.com which does a great job translating technical texts in both directions

    Hello,
    I have a problem with the teensy (3.2,3.5) now after all. I write now also in german because it can be explained better.

    My program works so far, but I have the problem that when I change the speed the motor stops and then goes from 0 to the desired speed. and not from 1000 to 500. The problem is that the ramp (acc) has to stay, so it should go down slowly from e.g. 1000 to 500 and not jerkily from e.g. 1000 to 500 when I switch off the ACC.

    I might use wrong commands, async I use.

    Greetings
    Stefan
    The main use case of TeensyStep is to move up to 10 motors per controller in such a way that the movement of the motors remains synchronized. If you would change the speed of a single motor, the synchronization would be lost. (The next version of the library will generate an error in such cases) Therefore, it is not possible to change the speed (or acceleration, or target position) of individual motors while moving.

    If you need to change the speed during operation, you can use the OverrideSpeed function of the rotation controller (https://luni64.github.io/TeensyStep/...rotateControl/). This will change the speed of all motors so that they keep their synchronization. (https://www.youtube.com/watch?v=HcaStXmkH2w)

  22. #97
    Junior Member
    Join Date
    Nov 2019
    Posts
    9
    ok. thanks. I will test.

    correct english forum, english write :-)

  23. #98
    Junior Member
    Join Date
    Nov 2019
    Posts
    9
    Hello,

    this is now a problem. I will have only for one Motor.

    i always want to change the speed of one motor when i start the seriel Input, for example with "r 1000" and then go higher with "r 2000", but it must change slowly.

    Do you have an idea?
    i am grateful for any help.

    do you have the code what i see in the video?

  24. #99
    Junior Member
    Join Date
    Nov 2019
    Posts
    9
    i have test with overide function.
    this is ok for my motor.

    can i set a range with override_speed?
    i need from 0 - 3600rpm and i will change +100rpm or -100rpm
    can only be changed in percent?

  25. #100
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    701
    OverrideSpeed multiplies the override factor by the speed you set at startup. So, you can as well set the speed at startup to 1 and use the override factor to set the required speed.

    i.e.

    Code:
    motor.setMaxSpeed(1);
    
    ...
    
    ctrl.overrideSpeed(5000);
    will set the actual speed to 5000stp/sec

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •