firmata / protocol

Documentation of the Firmata protocol.
991 stars 152 forks source link

Update Stepper to better fit common use cases #42

Open soundanalogous opened 8 years ago

soundanalogous commented 8 years ago

The current version of Stepper has a number of limitations. It should be updated to better meet common uses cases. A separate command byte (TBD) can be used to safely deprecate the old version.

soundanalogous commented 8 years ago

The existing (old) protocol is here: https://github.com/firmata/protocol/blob/master/stepper.md

dtex commented 8 years ago

Edited 9/22 to add Stepper zero and update command values

So here's my stab at a new protocol...

This adds support for enable pins, multiStepper and more stepper interface types.

In addition to step I've added to which allows a position to be passed (accelStepper keeps track for us). I've also added stop which will stop a stepper and report back the current position.

There was some talk in other threads about adding the ability to poll the current position. I don't want to add this, but I would like for firmata to reply with the current position when a move or to is completed, or when stop is called.

What limited steppers to 6 initially? Was it just a guess as to what Firmata could handle updating? I've bumped it to 10, but that's an arbitrary number.


Stepper Motor

Provides support for full 2 wire, full 3 wire, full 4 wire, half 3 wire, and half 4 wire stepper motor drivers (H-bridge, darlington array, etc) as well as step + direction drivers such as the EasyDriver. Current implementation supports 10 stepper motors at the same time (#[0-9]).

Includes optional support for acceleration and deceleration of the motor.

Also includes multiStepper support which allows groups of steppers to be simultaneously passed different to values and the duration of their movements will match. Up to five multiStepper groups can be created. The total number of steppers is still limited to 10.

Example files:

Protocol

Stepper configuration

Note: stepDelay is the the number of microseconds between steps. The default value is 1us. You can change the delay to 2us (useful for high current stepper motor drivers). Additional delay values can be added in the future.

0  START_SYSEX                          (0xF0)
1  Stepper Command                      (0x62)
2  config command                       (0x00 = config)
3  device number                        (0-9) (supports up to 10 motors)
4  stepDelay | interface                (upper 3 bits = step delay:
                                            000XXXX = default 1us delay [default]
                                            001XXXX = 2us delay
                                            other bits not yet used)

                                         (4th bit = hasEnable:
                                            XXX0XXX = no enable pin
                                            XXX1XXX = enable pin)

                                         (lower 3 bits = interface:
                                            XXXX001 = step + direction driver
                                            XXXX010 = two wire
                                            XXXX011 = three wire
                                            XXXX100 = four wire
                                            XXXX101 = unused
                                            XXXX110 = half three wire
                                            XXXX111 = half four wire)

5  minPulseWidth                          (0-127)
6  steps-per-revolution LSB
7  steps-per-revolution MSB
8  maxSpeed LSB                           (steps in 0.01*rad/sec  (2050 = 20.50 rad/sec))
9  maxSpeed MSB
10 motorPin1 or directionPin number       (0-127)
11 motorPin2 or stepPin number            (0-127)
12 [when interface >= 0x03] motorPin3     (0-127)
13 [when interface = 0x04
    or interface = 0x08] motorPin4        (0-127)
14 [when hasEnable = 0x01] enablePin      (0-127)
15 [optional] pins to invert              (lower 5 bits = pins:
                                           XXXXXX1 = invert motorPin1
                                           XXXXX1X = invert motorPin2
                                           XXXX1XX = invert motorPin3
                                           XXX1XXX = invert motorPin4
                                           XX1XXXX = invert enablePin)
16 END_SYSEX                              (0xF7)

Stepper zero

0  START_SYSEX                             (0xF0)
1  Stepper Command                         (0x62)
2  stop command                            (0x01)
3  device number                           (0-9)
14 END_SYSEX                               (0xF7)

Stepper step

0  START_SYSEX                             (0xF0)
1  Stepper Command                         (0x62)
2  step command                            (0x02)
3  device number                           (0-9)
4  direction                               (0-1) (0x00 = CW, 0x01 = CCW)
5  num steps byte1 LSB
6  num steps byte2
7  num steps byte3 MSB                     (21 bits (2,097,151 steps max))
8  speed LSB                               (steps per second)
9  speed MSB
10 [optional] accel LSB                    (acceleration in steps/sec^2)
11 [optional] accel MSB
12 [optional] decel LSB                    (deceleration in steps/sec^2)
13 [optional] decel MSB
14 END_SYSEX                               (0xF7)

Stepper to

0  START_SYSEX                             (0xF0)
1  Stepper Command                         (0x62)
2  to command                              (0x03)
3  device number                           (0-9)
4  num target byte1 LSB
5  num target byte2 MSB
6  speed LSB                               (steps per second)
7  speed MSB
8  [optional] accel LSB                    (acceleration in steps/sec^2)
9  [optional] accel MSB
10 [optional] decel LSB                    (deceleration in steps/sec^2)
11 [optional] decel MSB
12 END_SYSEX                               (0xF7)

Stepper enable

0  START_SYSEX                             (0xF0)
1  Stepper Command                         (0x62)
2  enable command                          (0x04)
3  device number                           (0-9)
4  END_SYSEX                               (0xF7)

Stepper disable

0  START_SYSEX                             (0xF0)
1  Stepper Command                         (0x62)
2  disable command                         (0x05)
3  device number                           (0-9)
4  END_SYSEX                               (0xF7)

Stepper stop

0  START_SYSEX                             (0xF0)
1  Stepper Command                         (0x62)
2  stop command                            (0x06)
3  device number                           (0-9)
14 END_SYSEX                               (0xF7)

Stepper stop reply

0  START_SYSEX                             (0xF0)
1  Stepper Command                         (0x62)
2  stop reply command                      (0x07)
3  device number                           (0-9)
4  position byte 1 LSB                            
5  position byte 2 MSB                            
6  END_SYSEX                               (0xF7)

MultiStepper configuration

0  START_SYSEX                              (0xF0)
1  Stepper Command                          (0x62)
2  config command                           (0x08)
3  group number                             (0-4) (supports up to 5 groups)
4  member device                            (0-9)
5  member device                            (0-9)
6  [optional] member device number          (0-9)
7  [optional] member device number          (0-9)
8  [optional] member device number          (0-9)
9  [optional] member device number          (0-9)
10 [optional] member device number          (0-9)
11 [optional] member device number          (0-9)
12 [optional] member device number          (0-9)
13 [optional] member device number          (0-9)
14 END_SYSEX                                (0xF7)

MultiStepper to

Note: You must pass a value for every stepper in the group.

0  START_SYSEX                              (0xF0)
1  Stepper Command                          (0x62)
2  multi to command                         (0x09)
3  num device 0 target byte1 LSB
4  num device 0 target byte2 MSB
5  num device 1 target byte1 LSB
6  num device 1 target byte2 MSB
7  [optional] num device 2 target byte1 LSB
8  [optional] num device 2 target byte2 MSB
9  [optional] num device 3 target byte1 LSB
10 [optional] num device 3 target byte2 MSB
11 [optional] num device 4 target byte1 LSB
12 [optional] num device 4 target byte2 MSB
13 [optional] num device 5 target byte1 LSB
14 [optional] num device 5 target byte2 MSB
15 [optional] num device 6 target byte1 LSB
16 [optional] num device 6 target byte2 MSB
17 [optional] num device 7 target byte1 LSB
18 [optional] num device 7 target byte2 MSB
19 [optional] num device 8 target byte1 LSB
20 [optional] num device 8 target byte2 MSB
21 [optional] num device 9 target byte1 LSB
22 [optional] num device 9 target byte2 MSB
23 END_SYSEX                                (0xF7)

MultiStepper stop

0  START_SYSEX                             (0xF0)
1  Stepper Command                         (0x62)
2  multi stop command                      (0x0A)
3  group number                            (0-9)
4  END_SYSEX                               (0xF7)

MultiStepper stop reply

0  START_SYSEX                             (0xF0)
1  Stepper Command                         (0x62)
2  multi stop reply command                (0x0B)
3  group  number                           (0-9)
4  device 0 position byte 1 LSB                            
5  device 0 position byte 2 MSB                            
6  device 1 position byte 1 LSB                            
7  device 1 position byte 2 MSB                            
8  device 2 position byte 1 LSB (if necessary)                            
9  device 2 position byte 2 MSB (if necessary)                            
10 device 3 position byte 1 LSB (if necessary)                            
11 device 3 position byte 2 MSB (if necessary)                            
12 device 4 position byte 1 LSB (if necessary)                            
13 device 4 position byte 2 MSB (if necessary)                            
14 device 5 position byte 1 LSB (if necessary)                            
15 device 5 position byte 2 MSB (if necessary)                            
16 device 6 position byte 1 LSB (if necessary)                            
17 device 6 position byte 2 MSB (if necessary)                            
18 device 7 position byte 1 LSB (if necessary)                            
19 device 7 position byte 2 MSB (if necessary)                            
20 device 8 position byte 1 LSB (if necessary)                            
21 device 8 position byte 2 MSB (if necessary)                            
22 device 9 position byte 1 LSB (if necessary)                            
23 device 9 position byte 2 MSB (if necessary)                            
24 END_SYSEX                               (0xF7)
soundanalogous commented 8 years ago

I think the step to function in AccelStepper is blocking for the duration of the sequence, which is the reason I never used that library in the first place. However it's been a while since I've looked over the code so perhaps the authors made it non-blocking in a more recent release.

dtex commented 8 years ago

runToNewPosition blocks, but I think moveTo does not. I had planned on using the latter.

soundanalogous commented 8 years ago

Finally had time to review your proposal. Here are a few comments:

  1. Is this comprehensive for stepper motor interface types? If not it should get it's own byte to ensure it will scale:
(lower 3 bits = interface:
                                            XXXX001 = step + direction driver
                                            XXXX010 = two wire
                                            XXXX011 = three wire
                                            XXXX100 = four wire
                                            XXXX101 = unused
                                            XXXX110 = half three wire
                                            XXXX111 = half four wire)
  1. Regarding the multi-stepper commands, would a user ever want to control the motors in a random order. If so we may need to add an index byte for each motor rather than relying on the order in which the motors were defined in a group. I do like the brevity of not needing to specify an index, but just want to be sure that does not make this feature more difficult to use.
  2. We also need a message at the end of the step sequence, or does the stop reply also cover that (this was also missing from the original stepper protocol, but it was implemented and unfortunately I never included a command for it, it just reported the index so that needs to be fixed in the updated protocol)?
  3. There were some requests a couple years ago for a homing/limit capability. This could be done without any additional protocol updates by using a switch and using digital input to determine when the switch is triggered, then call the stop command on the stepper, but that incurs latency when conducted over the Firmata transport. Maybe it's useful to add a command that enables the user to identify when a specified pin (or multiple pins) has changed to a specified state (or states if multiple pins), then stop the motor (if D7 == HIGH then stop and report position). I'm not sure if just a digital input is sufficient or if there is an analog use case as well (if A0 > 127 then stop and report position). Could easily be added later as well.
  4. Maybe start the multistepper commands at a value of 0x20 to allow some space for new commands to the single stepper configurations without having to add numbers after the multistepper sequence.
dtex commented 8 years ago

Is this comprehensive for stepper motor interface types?

No, it is not. I will give it its own byte.

would a user ever want to control the motors in a random order

I'm skeptical. The time between commands to the steppers would be very small and a little unpredictable. I think it's more likely that a user would want to move only some members of a MultiStepper group and indices would give us the ability to do that too so I think it's a good addition but for a different reason.

We also need a message at the end of the step sequence

The stop reply command can cover that. I'll make sure to document that.

Maybe it's useful to add a command that enables the user to identify when a specified pin (or multiple pins) has changed to a specified state

That seems like a good idea (and matches my use case) but we will need the ability to add two digital pins (limits at either end) or one analog pin (potentiometer) with a range passed in.

start the multistepper commands at a value of 0x20

:+1:

I'll submit as a PR next.

soundanalogous commented 7 years ago

Done in Stepper 2.0: https://github.com/firmata/protocol/blob/master/stepper-2.0.md

soundanalogous commented 7 years ago

Reopening for comments.

soundanalogous commented 7 years ago

Here is the AccelStepper API for reference: http://www.airspayce.com/mikem/arduino/AccelStepper/classAccelStepper.html

These are current limitations according to what the library provides:

troywweber7 commented 7 years ago

My comments are numbered and in bold below to make them easier to identify/respond to.

Stepper Motor 2.0

Provides support for full 2 wire, full 3 wire, full 4 wire, half 3 wire, and half 4 wire stepper motor drivers (H-bridge, darlington array, etc) as well as step + direction drivers such as the EasyDriver.

1. EasyDriver is great, but I'd like to recommend that it also support the BigEasyDriver. I'd like to note that it only adds 1 more micro-step pin to the configuration, which allows 1/16 micro-stepping mode. The likelihood of ever needing smaller resolution than this is minimal, however.

Current implementation supports 10 stepper motors at the same time (#[0-9]).

Includes optional support for acceleration and deceleration of the motor.

Also includes multiStepper support which allows groups of steppers to be simultaneously passed different to values and the duration of their movements will match. Up to five multiStepper groups can be created. The total number of steppers is still limited to 10.

Example files:

  • Version 2.0 of the stepper protocol has not yet been implemented.

Protocol

Stepper configuration


0  START_SYSEX                                (0xF0)
1  Stepper Command                            (0x62)
2  config command                             (0x00 = config)
3  device number                              (0-9) (Supports up to 10 motors)

2. Minor comment: I was always kind of concerned about what would happen if the device numbers weren't sent in the proper order. Is there a way (perhaps using linked lists or something) to allow the device numbers to be set up out of order if necessary?

4 interface (upper 3 bits = wire count: 000XXXX = driver 010XXXX = two wire 011XXXX = three wire 100XXXX = four wire)

3. Bit packing is nice. Can you save on bits by counting 00 = driver, 01 = two-wire, 10 = three wire, 11 = four wire? Might be useful to have an unused bit in case there is ever need to add more features in the future...

                                          (4th - 6th bits = step type
                                            XXX000X = whole step
                                            XXX001X = half step
                                            XXX010X = micro step)

4. This seems odd to me. Micro-step seems to cover 1/4, 1/8, and 1/16 step. Is this intentional? Why not explicitly provide for each? If this is intentional, I would just use 2 bits to convey the information: 00 = whole step, 01 = half step, 10 = micro-step. If 3 bits are going to be used, then 000 = whole step, 001 = half step, 010 = quarter step, 011 = eighth step, and 100 = sixteenth step, etc...

                                          (lower 1 bit = has enable pin:
                                            XXXXXX0 = no enable pin
                                            XXXXXX1 = has enable pin)

5. Please note there is also a sleep pin. I think the enable is more useful, but if it were me, I'd include the sleep pin functionality just in case. If sleep were included (and the 6th bit were freed up), you could make the 6th bit be "has enable pin" and the 7th bit be "has sleep pin".

5 minPulseWidth (0-127 measured in us) 6 num steps-per-revolution LSB 7 num steps-per-revolution MSB 8 maxSpeed LSB 9 maxSpeed MSB

6. I might suggest 3 7-bit bytes here for max speed. See my comments lower down... What about max acceleration and deceleration?

10 motorPin1 or directionPin number (0-127) 11 motorPin2 or stepPin number (0-127) 12 [when interface >= 0x0110000] motorPin3 (0-127) 13 [when interface >= 0x1000000] motorPin4 (0-127) 14 [when interface && 0x0000001] enablePin (0-127) 15 [optional] pins to invert (lower 5 bits = pins: XXXXXX1 = invert motorPin1 XXXXX1X = invert motorPin2 XXXX1XX = invert motorPin3 XXX1XXX = invert motorPin4 XX1XXXX = invert enablePin) 16 END_SYSEX (0xF7)


**Stepper zero**

0 START_SYSEX (0xF0) 1 Stepper Command (0x62) 2 stop command (0x01)

7. Is this a typo? There is a "stop command" here and in the stepper stop function...

3 device number (0-9) 4 END_SYSEX (0xF7)

8. I'm excited to see the addition of this this stepper zero function and the fact that we are now tracking position on the arduino side. However, I would have this be stepper set position so you can set the position to anything you like.

9. Also, obviously someone will eventually run into some position overflow issues. I'd like to propose another function: stepper normalize. The idea is that this can be used to normalize the tracked position to remain within 0-steps/rev. If a stepper motor has 200 SPR, a position of 200 would become 0, 300 would be come 100, - 30 would become 170. I think the formula is something like (position % stepsPerRev + stepsPerRev) % stepsPerRev. Devices that turn over (such as a carousel) would benefit from this greatly. There could even be a configuration value sent to tell it when to turn over instead of having to call stepper normalize manually all the time.

Stepper step

10. Minor suggestion: this is commonly referred to by ME's as a "relative move".


0  START_SYSEX                             (0xF0)
1  Stepper Command                         (0x62)
2  step command                            (0x02)
3  device number                           (0-9)
4  direction                               (0-1) (0x00 = CW, 0x01 = CCW)
5  num steps byte1 LSB
6  num steps byte2
7  num steps byte3 MSB                     (21 bits (2,097,151 steps max))
8  num speed LSB                           (steps per second)
9  num speed MSB

11. What happened to the optional acceleration/deceleration bytes? I think it useful to allow them here as a temporary override to the configured default speed/acceleration/deceleration values.

12. Also, I was running into max speed/speed overflow issues with only 2 significant bytes. I think I calculated out that a 200 step/rev stepper motor connected to a 8 mm lead screw would max out at 4 cm/s or something like that. If you can, throw in a 3rd byte (for speed and acceleration/deceleration) and I doubt we'll ever hit those theoretical limits. Of course, we are probably limited by the AccelStepper class as to the actual max/min. I haven't looked.

10 END_SYSEX (0xF7)



**Stepper to**

13. Minor suggestion: this is commonly referred to by ME's as an "absolute move".

Sets a stepper to a desired position based on the number of steps from the zero position.


0  START_SYSEX                             (0xF0)
1  Stepper Command                         (0x62)
2  to command                              (0x03)
3  device number                           (0-9)
4  num target byte1 LSB
5  num target byte2 MSB

14. You probably want to go with 3 bytes here. You use 3 bytes in the stepper move relative command above. Why limit yourself here? You might even throw in a 4th byte to allow moving to positive or negative positions in case someone decides position 0 is at the center of their mechanical design...

6 speed LSB (steps per second) 7 speed MSB

15. Can we get 3 bytes here?

8 [optional] accel LSB (acceleration in steps/sec^2) 9 [optional] accel MSB

15. And 3 bytes here?

10 [optional] decel LSB (deceleration in steps/sec^2) 11 [optional] decel MSB

15. And 3 bytes here?

12 END_SYSEX (0xF7)


**Stepper enable**

0 START_SYSEX (0xF0) 1 Stepper Command (0x62) 2 enable command (0x04) 3 device number (0-9) 4 device state (HIGH | LOW) 4 END_SYSEX (0xF7)

16. Just want to point out that if we include sleep pin, we would need a stepper sleep function as well.

Stepper stop

17. Yes, yes, and yes! I'm so glad this is going to be a feature. Just something to think about though: will the default behavior be to halt, or to use acceleration to stop? Or we could offer both options: stepper halt and stepper brake, which immediately stop and use deceleration to stop respectively.

0  START_SYSEX                             (0xF0)
1  Stepper Command                         (0x62)
2  stop command                            (0x05)
3  device number                           (0-9)
4  END_SYSEX                               (0xF7)

Stepper report position (sent when a move completes or stop is called)

18. How about being able to report position at any point in time? We could have a stepper get status: it can return more than one piece of information: is it moving, current position, where in the move is it (accelerating, constant speed, or decelerating)?. etc.

0  START_SYSEX                             (0xF0)
1  Stepper Command                         (0x62)
2  stop reply command                      (0x06)
3  device number                           (0-9)
4  position byte 1 LSB
5  position byte 2 MSB
6  END_SYSEX                               (0xF7)

Stepper limit When a limit pin (digital) is set to its limit state, movement in that direction is disabled.

19. This is a cool feature! I wouldn't say it is absolutely necessary. The design model my company has been using is to think of a stepper motor as a single class and a limit switch as a separate class. Then, we have an abstraction layer above that which uses a motor object and zero or more limit sensor objects to create a new class which has all the concepts of the stepper class as well as storing configured position IDs (such as the IDs on a carousel), allowing for homing functions, allowing user to think in inches/revolutions/mL/whatever, etc.

0  START_SYSEX                             (0xF0)
1  Stepper Command                         (0x62)
2  stop limit command                      (0x07)
3  device number                           (0-9)
4  lower limit pin number                  (0-127)
5  lower limit state                       (0x00 | 0x01)
6  upper limit pin number                  (0-127)
7  upper limit state                       (0x00 | 0x01)
8  END_SYSEX                               (0xF7)

Stepper set acceleration

20. I presume this would be used if not supplied during a stepper to or stepper step command? I see an inconsistency between this and other areas where acceleration/deceleration is used: are we limiting it to a single value for acceleration and deceleration (as implied here)? Or are we allowing both to be set individually (as in the functions above)?

Sets the acceleration/deceleration in steps/sec^2.

0  START_SYSEX                             (0xF0)
1  Stepper Command                         (0x62)
2  set acceleration command                (0x08)
3  device number                           (0-9) (Supports up to 10 motors)
4  accel LSB                               (acceleration in steps/sec^2)
5  accel MSB
6  END_SYSEX                               (0xF7)

21. I don't have any comments for the below other than what is already commented above and that I'm excited to see how this will work!

MultiStepper configuration Stepper instances that have been created with the stepper configuration command above can be added to a multiStepper group. Groups can be sent a list of devices/positions in a single command and their movements will be coordinated to begin and end simultaneously. Note that multiStepper does not support acceleration or deceleration.

0  START_SYSEX                              (0xF0)
1  Stepper Command                          (0x62)
2  config command                           (0x20)
3  group number                             (0-127)
4  member 0x00 device number                (0-9)
5  member 0x01 device number                (0-9)
6  [optional] member 0x02 device number     (0-9)
7  [optional] member 0x03 device number     (0-9)
8  [optional] member 0x04 device number     (0-9)
9  [optional] member 0x05 device number     (0-9)
10 [optional] member 0x06 device number     (0-9)
11 [optional] member 0x07 device number     (0-9)
12 [optional] member 0x08 device number     (0-9)
13 [optional] member 0x09 device number     (0-9)
14 END_SYSEX                                (0xF7)

MultiStepper to

0  START_SYSEX                              (0xF0)
1  Stepper Command                          (0x62)
2  multi to command                         (0x21)
3  group number                             (0-127)
4  member number                            (0-9)
5  num member target byte1 LSB
6  num member target byte2 MSB

*Optionally repeat 4 through 6 for each device in group*

33 END_SYSEX                                (0xF7)

MultiStepper stop

0  START_SYSEX                             (0xF0)
1  Stepper Command                         (0x62)
2  multi stop command                      (0x23)
3  group number                            (0-127)
4  END_SYSEX                               (0xF7)

MultiStepper report positions (sent when a move completes or stop is called)

0  START_SYSEX                             (0xF0)
1  Stepper Command                         (0x62)
2  multi stop reply command                (0x24)
3  group  number                           (0-127)
4  member number                           (0-9)
5  device 0 position byte 1 LSB
6  device 0 position byte 2 MSB

*Optionally repeat 4 through 6 for each device in group*

33 END_SYSEX                               (0xF7)
soundanalogous commented 7 years ago
  1. This can be handled outside of the interface using the existing firmata message. A client library can include this in it's stepper API for convenience.

  2. This is tricky and is more about the details of the implementation than the specification of the interface. In the existing stepper implementation I allocate device numbers in ascending order as new Stepper instances are created. I want to avoid dynamic memory (at least for the Arduino implementation) going forward (because it is risky with low ram microcontrollers) so in order for this scheme to work, memory for 10 stepper instances would need to be allocated regardless of the number of stepper motors used. The device number would then correspond to the index of the array. We also need to determine how much memory 10 stepper instances will consume and if that is too high, we may need to limit the count based on the microcontroller's RAM.

  3. I agree with your comment. We need to enable this to scale so freeing up a bit would be helpful. @dtex thoughts?

  4. With AccelStepper, these values only apply to the 3 and 4 wire drivers, not to the 2 wire drivers, so that is one issue. Regarding 2 wire drivers, the step selection should be set using a digital message and does not belong in the firmware interface. It can be specified in the client stepper API for convenience.

  5. Should use digital message and can be specified in the client stepper API for convenience. Doesn't really belong in the firmware, unless it's ever added to AccelStepper (or other similar library).

  6. Let's figure out exact resolution, specified as 8, 16, 32 or 64 bit int and then specify the number of 7 bit bytes required to carry that value. Update in the Stepper 2.0 description, lets specify as uint8, int8, uint16, int16, uint32, int32, uint64, int64.

  7. Most likely a typo

  8. AccelStepper (or any similar open-loop based controller library) cannot accurately track position because there is no feedback from the motor so it doesn't know if a step was missed or not. It may be close, but not exact.

  9. I'm open to this. @dtex thoughts?

  10. SGTM, let's add it in parens

  11. The way AccelStepper works is accel/decel values are global. You set them once in the config message and they remain set for the duration of the application. You actually can't undo them either (no way to reset to no accel/decel). This is an unfortunate behavior of the AccelStepper library IMO (that and the fact that you can only a single value that is applied to both acceleration and deceleration, you can't specify them independently). This is actually nearly a deal-breaker with AccelStepper the more I think about it. Update You can set the accel/decel (single value) in the constructor or separately in a setAcceleration method.

  12. Same as #6 - lets figure out exact resolution necessary... someone needs to do the math here.

  13. SGTM, let's add it in parens

  14. lets figure out the exact resolution necessary

  15. lets figure out the exact resolution necessary

  16. No plans to add sleep, but as said earlier this can be achieved using digital message.

  17. Good suggestion, but with AccelStepper if you specify acceleration in the config message, then I think you'll always stop with deceleration. If you don't specify it you'll stop instantly.

  18. We could add this query. However there is no guarantee the count is accurate, although under most circumstances it should be fairly accurate. However there is latency involved depending on serial baud rate or other type of transport (Wi-Fi, Ethernet, BLE, etc).

  19. @dtex and I discussed this. The advantage of handling this in the stepper interface is to eliminate latency. If we relied on digital messages in this case and a motor has a relatively high angular velocity, we will respond too late.

  20. This is due to the way AccelStepper works. You can set acceleration outside of the constructor but once you set it you can't unset it, however you can change it, just not back to "none".

soundanalogous commented 7 years ago

AccelStepper has its short comings, but the advantage of using it for the Arduino implementation of Stepper 2.0 is it's actively supported and fairly well-featured (although falls short of Stepper 2.0 in some areas). I don't plan to continue supporting the simple FirmataStepper library I cobbled together as I don't use stepper motors very often and have enough to work on in the greater Firmata scheme as it is.

soundanalogous commented 7 years ago

I'll open a new PR for the edits, will be easier to add any additional comments in context.

dtex commented 7 years ago

Hey wow! Lots of good comments here. I honestly won't be able to give them the attention they deserve until Monday night. I'm out of town, doing the Christmas thing.

soundanalogous commented 7 years ago

for acceleration/deceleration values we need to work out what the max value is:

steps/sec^2 * 1000

We need to multiply by 1000 since we can't sent floats directly, so we multiply and cast to either a 16-bit int or a 32-bit long. Do we need a long here or is an int sufficient?

soundanalogous commented 7 years ago

Lets move this conversation over to this PR: https://github.com/firmata/protocol/pull/79/files

troywweber7 commented 7 years ago

I thought of one other idea that might be useful (though it probably can't be supported because AccelStepper probably doesn't support it): It would be neat if you could pause in the middle of a move and then choose either to resume or cancel the move entirely.

It would probably require a wrapper around AccelStepper though. I wish I had more time to look into these things... I could probably write a good stepper wrapper that cements the abstract concept of a stepper and then uses whatever library is best to achieve those goals on the Arduino side. I'm probably speaking gibberish here.

soundanalogous commented 7 years ago

By pause in the middle of a move, do you mean in the middle of a step or in the middle of a series of steps. I'd think you could accomplish the later already sending the stop message, but the former would be nearly impossible to achieve due to latency.

dtex commented 7 years ago

The stop message changes the target value. Perhaps you could just set the speed to 0 to make it pause?

troywweber7 commented 7 years ago

I do mean in the middle of a series of steps. If you can set the speed and it affects the current move, then yes, that will work sufficiently as a pause, I think.

Strophe27 commented 7 years ago

OMG !! Amazing ! There is all I need ! Just a message to encourage you all, unfortunately I cannot help you on coding, but for my needs I will keep on forking Maxuino to implant all those new features. I don't understand if stepper 2.0 is implemented yet, and if is not, if I can start to work around with some code you are working on, or maybe it will dramatically change again... Anyway, even if it's not the right place, thanks again for all that.

blackballer commented 6 years ago

I've been looking at the maxuino tutorial video, I tried Max/msp+Maxuino+Easydriver+arduino+nema17, and run normal。 now i will try biger stepper motor nema 23 with Maxuino, which motor driver can i use? i tried TB6600, the motor is fixed, but the motor can not be rotated by using maxuino. Thanks!!!

dtex commented 6 years ago

Ya, the TB6600 isn't supported. Can you link to the specific stepper motor you are using? Nema 23 is just the frame size. If the current draw is low enough you should still be able to use the Easy Driver. There is also the Big Easy Driver which can handle higher loads.

blackballer commented 6 years ago

thank you! I will use Stepper Motor Nema 23 - 3Nm, like this https://www.hardware-cnc.nl/en/shop/stappenmotoren/stepper-motor-nema-23/stepper-motor-nema-23-3nm-detail I want to build only XY CNC, like this https://www.hardware-cnc.nl/en/shop/cnc-frame-machines/cnc-bench-3d-4046-pro-detail and 2m*2m I want to use Max and Maxuino to control the two stepper motors.

panchalmanish2208 commented 4 years ago

Is it possible to control multiple stepper motors using pymata or any python libraries ? pls give some example