Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 8 of 8

Thread: Teensy control of a stepper at high frequency, plus buffering and comms?

  1. #1

    Teensy control of a stepper at high frequency, plus buffering and comms?

    Whelp - got my DC servo motion controller working OK, with thanks to several forum members for their advice.

    Interrupt driven at 2KHz, handles its own buffering, announces its capabilities (well, the motor's) to the Mac so I've got sort of plug and play, and it's doing some sexy interpolation on the trajectory too. Made you guys a video - I figured you'd like nothing more than listening to two and a bit minutes of some tit waffling, so here you go:

    https://youtu.be/DIOxSClVAMk

    So, next I've got to make two more motion controllers - a lens one (shouldn't be a problem thanks to other people's hard work deciphering the Canon EF protocol) and more trickily, a stepper motor driver.

    Same protocol, buffering, interpolation (if necessary - but I don't think it'll be as critical as the DC servo) but very different control loop.

    Hmm. Step timing. While doing my other jobs too.

    Any suggestions, thoughts, info appreciated. I've used the AccelStepper library in the past, but that doesn't lend itself to my needs - I have a list of positions, one for every 25th of a second, coming from the Mac, and I need the stepper to get there as smoothly as possible. It's buffered, so I don't just know where I want the stepper to be in 1/25th of a second's time, I can also work out what velocity it should be at when it hits the mark too.

    But I'm a bit nervous about timings.

    What sort of frequency steppers have people played with here? (I mean, almost all my motors are 200steps/rev, but the drivers can handle ridiculous levels of microstepping which don't half help at slower speeds).

    Probably need to sit down with a napkin and a pen and work some figures out, but I thought I'd see what other people have achieved too

    PS Paul, thanks for making all my bloody arduinos and drawers full of atmegas and attinys and AVR programmers instantly feel slow and crap. Thanks, man. Real nice of you. Grrr. (yeah, so I've got 5 Teensy LCs on order now. I hope you're bloody happy)

  2. #2
    A step rate of up to 100kHz should be achievable if you are careful with your coding.

    For a servo, sending regular position set points makes sense, for a stepper not so much. I don't really see how it would work. If you have a bunch of points, then the firmware can interpolate a path through them, but if these points are generated by a host, then why not have the host send the velocity information as well?

    Of course, it's hard to develop a design without knowing the application. In some cases the exact path/velocity profile is important, not in others. For example in milling the head needs to follow a particular path, in pick and place it may not matter, just the start and end points need to be exact.

  3. #3
    100KHz - cool, bobc, that gives me a ballpark to think about.

    The application is motion-controlled filming, so accuracy isn't as critical as CNC, but the better the repeatability, the better, if you get me. Basically, I'm making a teensy-tiny (geddit?!) camera slider with a pan head and lens focus control. Rather than treat it as a monolithic project, I'm keeping things as adaptable as possible; you can plug in any number of drivers, whether servo, stepper, or hacked lens, and they can all be controlled together.

    The interpolation thing: I don't really know until I test things whether 25Hz updates will be enough for a stepper, but I've kept the code as modular as possible, so if I find later it benefits me to give my stepper driver updated position/velocity every 50Hz or 100Hz, the code's already there. I suppose the extremes are:
    - interpolate a new step delay for every single step (super smooth)
    - do no interpolation, just take the 25Hz trajectory setpoints and move at constant speed for every 25th of a second.

    I can certainly pre-calc velocities on the host, but as it's such a simple calculation I figured I'd let the Teensy do it (keeps the necessary serial bandwidth down for the sake of a DIV or two).

    I wonder whether there'd be a benefit to using two Teensys (or a Teensy and an Arduino) to split the work: one to handle comms and buffering, one to actually do the timing and produce the STEP/DIR pulses I need. Hmm. But then /they've/ gotta communicate somehow. Hmm.

  4. #4
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    24,452
    Why not use AccelStepper? Isn't this pretty much what it does?

    I suppose simply wanting to learn the process and do the speed & acceleration stuff yourself is plenty good enough reason. I'm just curious if there's some other (unknown to me) issue with AccelStepper, since that's what I usually recommend. If it has some important limitation or flaw, I'd really like to know?

  5. #5
    Whelp - the longer story (make yourself comfortable):

    Bought a controller-less robot arm a couple of months ago, with the idea I could stick a little camera on the end and use it for motion controlled filming. I'm a self-employed motion graphics / 3D artist/idiot and most of my work ends up being time consuming and expensive. If I can do all my swishy 3D camera moves for real, out here in meat-space, it'll open a new world of creative possibilities, and hopefully be a hell of a lot cheaper. So hopefully I can attract more work, smaller / quicker jobs, as well as do interesting new stuff.

    Spent a few weeks with the robot arm, learning about DC servos, PID, learning C++, writing a robot server for the Mac so I can use my 3D software (Blender) to do all the trajectory design / inverse kinematics. But I hit the limits of what the motor drivers I'd bought (Motion Mind 3s) could do: they'll do PID, but now I was learning about Jacobians and torque calculations and needing feedforwards... and besides, I've now found out that what I'm trying to achieve (particularly slow, smooth motions) is traditionally Rather Tricky. Nigh-on impossible with simple PID.

    One way or another I've gotta roll my own drivers. So the arm has gone on the back burner for a bit while I get some basics sussed. Even with a single servo and a Teensy acting as a driver, I can see how this is going to be fantastic: https://youtu.be/YnLd4EneKX0 . Once I'd got the turntable moving back and forth, it took about 2 minutes (minutes! I've been in the wrong business all this time) to take all those shots, and about 10 minutes to cut them together. I'm sold. Just think what I could do with nice lighting, more axes, compound moves...

    To use all this motorised paraphernalia well, though, is going to take careful orchestrating, hence using Blender to create the trajectories. Plus I love the idea that I can design a camera move in Blender, film it, and then use Blender to add 3D elements etc without needing to track the footage.

    It's got to be entendable, though; gotta be able to add and remove motors / actuators etc to the rig for different situations, which is why I'm trying to keep things modular - I can do any kind of pre-processing I want to the data, but it'll certainly help to use a common protocol throughout. Hence me starting out by delivering nice simple packets of 25 (int32_t) positions every second, and trying to handle interpolation and PID (servo) or step timing (stepper) on the driver.

    So to answer your question (finally) - no problem with AccelStepper, it's just that linear acceleration ain't enough for my needs. If I had the money I'd buy more servos, now I understand them a bit better, but until then I've got steppers I need to wrangle into obedience...

  6. #6
    Junior Member
    Join Date
    Apr 2014
    Posts
    7
    Hi,
    just thought i might add my 50c worth,

    I am a complete beginner in the world of micro controllers,
    however
    I have designed and built many motion control rigs over the years, and have always used a software/hardware system known as KUPER.
    Now this is as old as the hills, runs on DOS4GW and the cards need old 16bit ISA busses.
    However to date no one has really made a better system, (with the possible exception of Flair MRMC, similar age)

    What follows is an attempt to describe how pulse train generation is addressed in this
    system



    The way it treats the pulse train generation is really very simple.

    it divides the time line into data frames , there generally being 5 data frames per visual frame.
    so if you are filming at 25fps for example there will be 125 data frames per second.

    So a move file is merely a list of pulse counts for all the motors in use
    at every data frame
    if we were for example running at 100 data frames (25fps*4)
    so each interval is 10millisecs
    So say motor X should be at count 200 at data frame 31
    and at count 212 at data frame 32
    then there will be 12 pulses produced evenly spaced over the next 10millis.
    NO accell or decell
    and then it goes to the next data frame and produces a new pulse count over the next 10 mills,
    and so on.

    You might think that the step speed changes would make this unworkable, but in practice the use of micro stepping
    and highish pulse rates gives an extremely smooth response. The inertia of the motors masking any pulsing.

    It goes without saying however that this only works with a data sequence that is sensible, i.e. no major step changes
    and so the trajectory planning needs to take account of smoothing, starting, stopping, et al.

    So if you can generate from blender a move file giving X,Y,Z,Pan,Tilt,Roll, focus,zoom, etc in a sufficiently finely granulated manner

    then read that in , and simply produce the pulse trains as described it should work.

    Maybe a small library that just takes a number representing the pulse count
    a number giving the frame interval and spits out the relevant number of pulses plus direction toggle.
    fitting as many channels into a teensy as possible.
    A max frequency of at least 100k would be neccesary
    I imagine this would involve some (under the hood work with teensies timers)
    Perhaps someone else far more knowledgable might advise.

    Will be very interested to follow your progress as am playing around with other ideas in a similar vein
    Wish you well
    Harry Harrison

  7. #7
    Harry - thanks for the valuable intel. I've a tendency to over-engineer and over-think things, so it's incredibly useful to know what has worked elsewhere.

    My move file (or equivalent) is only 25fps but I can interpolate it smoothly (curve-fitting, rather than linear) to minimise jerk. Key things then: 125fps update rate, linear between them. Groovy. That I think I can do.

    The thing that's on my side in the battle is thanks to Paul: I can afford to dedicate a Teensy to each channel, which also makes it easier to create these actuators (pan, slide, lens_focus, or whatever) as separate modules, so as I make 'em, I can just plug 'em in. My RoboServer software (now on umpteenth re-write) can handle an arbitrary number of channels, linking them to Blender.

    I'll have to test to see what sort of frequency I can produce cleanly (ie with minimal aliasing / jitter); then I can grab a ballscrew and nut from eBay with a suitable lead on it. I've found you can get 10mm lead fairly easily (so, 200 pulses / one revolution of the screw pushes the camera 10mm) which may help; have to work out whether that's high enough "resolution" to ease out of slow moves nicely.

    Cheers!

  8. #8
    Well - I've got a single stepper working, doing a sine-wave motion (ie not just a plain ol' linear acceleration). The Teensy's spending between 12 and 16% of its time in the interrupt code, which is running at 100KHz. Maximum step frequency is probably best kept below half of that, I reckon, but it all seems fairly jitter free now. Stepper motors do at least let you know if your code ain't quite right - they shout ungodly harmonics at you. Wake the baby.

    In case anyone else finds themselves trying to do this: I'm following Harry's advice and treating each 10ms period as constant speed. To spread the pulses out evenly I'm using Bresenham's; treating time as the X axis and sending a step for every increment in Y. I was worried about what would happen at the end of one period and the start of the next - whether I'd lose "phase" and end up with steps on top of each other, but Bresenham's seems to be doing a nice job. Always seem to get half a step-delay at each end of the time period which leads perfectly into the next one.

    Next step: buffering and comms. That should be easy </sarcasm>

Posting Permissions

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