Shop OBEX P1 Docs P2 Docs Learn Events
Using a cog to control a motor? — Parallax Forums

Using a cog to control a motor?

ReiserificKReiserificK Posts: 24
edited 2008-11-19 23:56 in Propeller 1
Hi all, this is my first post.· I have searched around, but havent found anything.· I just ordered a Propeller proto board and have a few questions on controlling motors with it.· I have a DC motor controller that takes pulses just like a servo.· I would like to know if I need to devote an entire cog, just to sending pulses.· If so, does it make sense to use a BASIC stamp as a sub unit that talks to the propeller and sends pulses to the motor?

Thanks

Comments

  • Beau SchwabeBeau Schwabe Posts: 6,562
    edited 2008-11-10 15:52
    ReiserificK,

    Welcome aboard!

    In order to keep the timing correct for the servo pulse, you should use a dedicated cog. Using a Basic Stamp to handle communications with the Propeller and controlling a servo sort of defeats the purpose.

    There are a couple of Servo drivers you can use in the Object Exchange ( http://obex.parallax.com/objects/search/?q=servo )

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.
  • J. A. StreichJ. A. Streich Posts: 158
    edited 2008-11-10 16:01
    One cog can send control pulses to quite a number of servos. I think the max is 32(?) servos from a single cog. If you get your timing right, a cog controlling one or two motors with pwm can do other things, but I don't think it wasteful to use a cog to control a motor or two.
  • GavitronGavitron Posts: 3
    edited 2008-11-19 23:56
    To ReiserificK and anyone else that’s interested in controlling RC servomotors with the Propeller,

    This is actually my first post on the forum too. My goal is to help create a definitive reference for people that want to learn more about controlling RC servomotors with the Propeller. First, you can think of the propeller as being like eight separate basic stamps (“cogs&#8221[noparse];)[/noparse] wrapped up in one chip. The cogs all share the same 32 I/O pins and a central Hub RAM, but other than that they can run completely independently of each other (parallel processing). Therefore, the best way to make servo pulses is to dedicate one of the cogs to just creating servo pulses while the bulk of your code runs on another cog (or cogs). The propeller can be programmed in Spin (which is interpreted code like PBASIC) and runs at around 80,000 instructions per second or alternatively it can be programmed in Propeller assembly code, which runs at a blazing 20 million instructions per second on each cog (up to 160MIPS if all 8 cogs are running assembly) but is not nearly as easy to write. In order to get a high level of resolution accuracy, it makes sense to run assembly instructions on the cog that is creating the servo pulses.···

    To help people out, I have just uploaded a couple files on the Propeller object exchange that I’ve been experimenting with that demonstrate how to control RC servomotors fairly easily and efficiently using a separate cog on the propeller chip. I’ve posted five files zipped together under the name “RC_Servo_Control.” They are really demos (not objects that can be called by other methods) that show you how to use some of my servo control techniques in your own code.

    http://obex.parallax.com/objects/387/

    One thing that is important to keep in mind about analog servos (like the Parallax/Futaba Standard Servo) is that they only move for a brief amount of time after they receive a signal pulse. Therefore, they work best when they receive a steady, continuous stream of signal pulses. (In other words, you can’t just set them once and forget them or they won’t get to or hold their target positions.) When an RC servomotor receives a pulse, it converts the width of this pulse into an analog voltage level (by charging a capacitor) and compares it with the analog voltage coming out of its potentiometer (which is set up as a voltage divider and acts as a position encoder for the servo’s output shaft). The servo then briefly activates its motor to try to reduce the difference between the desired position (pulse width) and actual position (potentiometer voltage).

    If you are not interested in controlling an RC servomotor with very high position accuracy, then you can simply use Spin code as I’ve demonstrated in my Single_Servo_Spin program. ReiserificK, in your case, this program should work for your motor controller. However, if it does not require refreshing (e.g., the Parallax HB-25 does not) and you don’t need high resolution accuracy, you might just consider using some statements in Spin (like the following example that outputs a single ~1ms pulse on Pin 7) whenever you need to change the motor’s speed and not even bother with using a separate cog that creates a continuous train of servo pulses.
    PUB Demo | position                        'Define a method called "Demo" and declare "position" as a local variable
      position:=100                            
      dira[noparse][[/noparse]7]~~                                'Set the direction of Pin 7 to be an output
      outa[noparse][[/noparse]7]~~                                'Set Pin 7 high
      waitcnt((clkfreq/100_000)*position+cnt)  'Wait for the specified position (units = 10 microseconds) 
      outa[noparse][[/noparse]7]~                                 'Set Pin 7 low
    

    In my opinion, the best way to control a servo is to use some assembly code as I do in the Single_Servo_Assembly, Two_Servo_Assembly, and Three_Servo_Assembly demos. These take advantage of the 20MIPS speed of a single cog running assembly code to be able to output servo pulses with resolutions between 12.5-50ns. (As I understand it, the “waitcnt” command may not sync perfectly with the specified terminal count of system clock so it might take up to 4 clock cycles to stop the pulse after the specified count has been reached.) I wrote these to help others (and myself) bridge the gap between simply controlling a servo with Spin code (poor resolution) and using Beau's Servo32v3 program in the Propeller Library. I’m sure that many people will agree that while Beau’s code is very clever, it is not very easy for newbies to propeller assembly programming (like me) to decipher. When only trying to control a·couple of RC motors, I felt like using it was kind of like swatting a fly with a sledge hammer. If you are new to assembly programming and like to be able to fully understand and customize the code you are using, give this alternative RC servomotor control method a try.

    Single_Servo_Assembly shows you exactly how to control a single RC servomotor using a little assembly code. All you have to do is copy and paste my assembly program into the DAT section of your code, declare a “position” variable as a long (32-bits), and start the assembly program in a new cog. (You may also optionally change the servo signal’s output pin in the assembly program.) The assembly program then runs in parallel on a separate cog and continuously reads the value of the “position” variable from the main Hub RAM (which Spin or assembly code running on any other cog can change at any time) and outputs a servo signal high pulse that corresponds to the “position” number of system clock cycles. Two_Servo_Assembly and Three_Servo_Assembly show you how to control multiple RC servomotors using a similar technique. As their names suggest, these demonstrate exactly how to control 2 and 3 servos at a time. Once you figure out how these work, you could apply the same technique to control up to around ten servos simultaneously. If you need to control more than that, then you should probably step up to using the Servo32v3 object in the Propeller Library, which can be used to control up to 32 servos at once.

    Finally, I have included a program called Single_Servo_Counter that demonstrates how to use a cog’s built in counter to create a train of servo pulses. If someday you actually find that you are maxing out all of your Propeller’s capabilities in a particular application, you could try to use this technique and squeeze a few more lines of code in when the cog is not busy setting up its counter.

    I hope that this helps.

    -Gavitron
Sign In or Register to comment.