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

stepper motor library feedback to pc #2

Closed
soundanalogous opened this issue Apr 19, 2015 · 23 comments
Closed

stepper motor library feedback to pc #2

soundanalogous opened this issue Apr 19, 2015 · 23 comments

Comments

@soundanalogous
Copy link
Member

From @FineLineAutomation on March 23, 2014 20:8

Is there a mechanism in the stepper motor library to communicate back to the PC how many steps the stepper motor has moved? Trying to implement a live updated DRO on the PC side.

Copied from original issue: firmata/arduino#125

@soundanalogous
Copy link
Member Author

Nothing that specific. There is a callback that is called when the step sequence is completed: https://github.com/firmata/arduino/blob/configurable/utility/StepperFirmata.cpp#L151. This returns the id of the stepper that finished it's sequence. Updating on each step could be possible by adding another optional parameter to the Stepper constructor that would return the step count for each stepper motor. However this would be a lot of data to transmit to the PC when stepping at hight speeds.

@soundanalogous
Copy link
Member Author

From @FineLineAutomation on March 23, 2014 22:9

What about a command that would allow the PC to pull the data instead of the stepper pushing it back? Or limiting the return rate on the count to one packet every 1/2 second or so? I am thinking a half second sample rate is more than enough for my needs because I am just displaying it to the user.

@soundanalogous
Copy link
Member Author

That could work. The easiest would be to return it at a multiple of the sampling interval. The sampling interval is 19ms by default but can be updated by sending a command from the Firmata client. With configurable firmata, adding a report method to a feature class will result in that method being called at the sampling interval. The stepper count could then be reported every n iterations. However the trick is adding the multiplier to the firmata stepper implementation in a backwards compatible way. If you look at the protocol you'll see why that will be difficult because the last 2 parameters are optional (motor pins 3 and 4) and there aren't enough free bits available to pack a large enough multiplier value into.

@soundanalogous
Copy link
Member Author

From @ntruchsess on March 23, 2014 22:29

I'm using the callback Jeff mentioned for that. OK, that doesn't give you feedback while the motor moves. For that some 'reporting'-feature would be usefull. Nevertheless, this kind of feedback is not about the absolute position of the stepper as is might skip some steps. If you need reliable feedback you'd have to add e.g. a incremental rotary-encoder.

@soundanalogous
Copy link
Member Author

From @FineLineAutomation on March 23, 2014 23:42

Yeah. I see that. This isn't absolutely critical, so I am ok if we leave it as is. It falls into the category of a very nice to have feature.

@soundanalogous
Copy link
Member Author

From @DomAmato on January 10, 2015 8:43

Again a bit late to the party here but from my understanding the stepper implementation @soundanalogous made has a step counter which I used to get the current position though it zeros itself with a new move command. It works for what I needed to do since i was moving in 16th steps so missing a few wasn't the end of the world.

https://github.com/DomAmato/Robust-Firmata

@soundanalogous
Copy link
Member Author

One option here would be to add a Stop message to the Stepper protocol but that would be too slow to call externally in most cases (still a convenience none the less). Another ammendment to the protocol would be to provide a pin number to watch and an edge transition (high to low or low to high). If the edge changes as specified on that pin then call stop() (to be added) on the stepper internally. The feedback pin would need to be added after the optional motor pins. I could then add additional interface values to indicate step + direction + feedback, two wire + feedback or four wire with feedback. That would then indicate that the last specified pin is the feedback pin.

@soundanalogous
Copy link
Member Author

Just realized I had changed the upper bits of the Interface command to set the step delay (to support high current drivers that need a 2us delay rather than the standard 1us delay between steps). I need to update this in the Stepper protocol. That leaves me to find another place to indicate if there are feedback pins...

@soundanalogous
Copy link
Member Author

From @DomAmato on January 10, 2015 21:34

Yeah my implementation wasn't particularly pretty, I think it should probably check the length of argc too to make sure that all the values are actually given. perhaps adding to the interface where 8 means feedback and then & 0x07 to figure out the interface type something like this:

enum Interface {
    DRIVER = 1,
    TWO_WIRE = 2,
    FOUR_WIRE = 4,
    HAS_FEEDBACK = 8
};

so that

if(interfaceType & 0x08)
   we have feedback pins
  if(interfaceType & 0x07 == Stepper::DRIVER) ...
else {
   we don't have feedback pins
}

@soundanalogous
Copy link
Member Author

The issue here is that only the lower 3 bits of that byte are available. I'm using the upper 4 bits to specify the step delay. I had forgot to add that to the protocol, but it's there now. However there are free bits in bytes 2 and 3 (CONFIG and DEVICE_NUMBER) so the hasFeedback flag could go there. This protocol is going to get messy. It really needs to be done differently but I got very little feedback on it when I first created it a couple of years ago (few people were watching Firmata at that time). Now there are at least 3 popular Firmata client libraries using the Stepper protocol so to break compatibility may be a bigger mess than butchering the existing protocol.

@soundanalogous
Copy link
Member Author

Also the INTERFACE command is the only byte that had bits available that gets passed all the way through to FirmataStepper so the stepDelay has to be OR'd with that byte since it needs to be set within the FirmataStepper library constructor. CONFIG and DEVICE_NUMBER are handled at the next higher layer (AdvancedFirmata, RobustFirmata, ConfigurableFirmata) so that would be a better place for the hasFeedback flag since you would handle it at that level.

@soundanalogous
Copy link
Member Author

I guess I could reserve the 7th bit of interface for the hasFeedback flag. It would limit the number of stepDelay values that can be set in the future to 2 bits (4 values). It's ugly but the Interface byte could be split like this:

bits 0-3: INTERFACE
bits 4-5: STEP_DELAY
bits 6: HAS_FEEDBACK

This would maintain backwards compatibility with existing Stepper implementations.

@soundanalogous
Copy link
Member Author

correction, it would look like this:

bits 0-2: INTERFACE
bits 3-5: STEP_DELAY
bit 6: HAS_FEEDBACK

Which leaves 8 values for step delay.

@soundanalogous
Copy link
Member Author

From @DomAmato on January 11, 2015 1:49

Works for me, since the step delay is just a floor value unless I am misinterpreting that. There could be a separate protocol to set a max speed. I was looking at accelStepper though actually liked your library better for its brevity but the step delay would be then used like this right:

_step_delay = max(_min_step_delay, _step_delay);

@soundanalogous
Copy link
Member Author

The step delay value is used here: https://github.com/soundanalogous/FirmataStepper/blob/master/FirmataStepper.cpp#L381-L388. It only applies to step + direction type drivers. Some high current drivers need at least a 2 microsecond delay. There may be other variants needed in the future as well, but so far the 2us delay has fixed any reported issues with high current drivers.

@soundanalogous
Copy link
Member Author

Re accelStepper, I was originally considering wrapping that library but it had too many features and consumed too much memory - at least when you need to support a bunch of other potential features simultaneously. I think it also had a few lengthy delay calls in the code which I am keen to avoid for Firmata features. accelStepper is a much better written library than FirmataStepper though. I implemented FirmataStepper based on a white paper I came across. I still don't fully understand all the math involved. Someday I hope some much smarter than me picks it up and improves it :)

@soundanalogous
Copy link
Member Author

Just took a look at accelStepper again for the first time in a long while. It's actually much simpler than I remember. Not sure why I chose to write FirmataStepper over just wrapping accelStepper. I must have had some reason a couple of years ago. I don't see any delays other than the step delay so that couldn't be the reason. I don't think it would consume much more memory than FirmataStepper either now that I'm looking over the code again. Strange.

@soundanalogous
Copy link
Member Author

From @DomAmato on January 11, 2015 3:39

I think you implement the formulas better though which I believe you got from this:
http://www.hwml.com/LeibRamp.pdf
which is based off of this:
http://fab.cba.mit.edu/classes/MIT/961.09/projects/i0/Stepper_Motor_Speed_Profile.pdf

@soundanalogous
Copy link
Member Author

I remember looking over the two papers you referenced, but ultimately I used this paper: http://www.atmel.com/Images/doc8017.pdf and the accompanying sample code also published by Atmel. All share some similar logic.

@soundanalogous
Copy link
Member Author

From @DomAmato on January 11, 2015 21:37

Yeah they all seem to be based off the same set of equations. I remember now why I ended up using FirmataStepper over the AccelStepper and it had to do with the run() and runSpeed(). Run was never able to go at the max speed or same speed that runSpeed() did even if the numbers were set the same. I probably should have investigated more as to why this was happening but at the time I needed results and defaulted to the one that was behaving as I needed it to. This was done with a Nema 17 and 23 type stepper using the A4988 stepper driver at 8th and 16th steps.

@soundanalogous
Copy link
Member Author

see #33

@soundanalogous
Copy link
Member Author

soundanalogous commented Dec 24, 2016

The Stepper 2.0 update supports a limit switch, but there is no support to query the position. The position is reported when the motor is stopped. A position query could be added in the future if it is something users feel is still missing among the new features added in 2.0.

@soundanalogous
Copy link
Member Author

The AccelStepperFirmata implementation includes the ability to query the current position.

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

1 participant