Shop OBEX P1 Docs P2 Docs Learn Events
Pointless exercise?, PWM object — Parallax Forums

Pointless exercise?, PWM object

Graham StablerGraham Stabler Posts: 2,510
edited 2011-02-15 10:17 in Propeller 1
I'm playing with PID motor control, got it working pretty well under spin but I need to go to assembly for a better sampling rate. I was using Phil's awesome 8 channel PWM driver but because I don't really understand how it works I was a bit unsure about how to integrate it into my code or interface with it via assembly. I only need two channels of PWM (or even one if I swap pins) so I thought I'd try and bit bang it.

Well despite Phil's warnings of the difficulty of bit banging true PWM (not the stuff the counters produce) with high resolution and frequency I thought I could beat the system with an idea I had.

For a single channel you have an on time and an off time and the ratio defines the duty, one will be larger than the other or both zero. So the idea was to base the PWM on waitcnt and do any processing such as reading the PWM value from hub ram in the longest of the two times, the minimum time I would have would be T/2 where T is the PWM period. Even at 20khz this is a long time. You can apply the same principle to 2-channel PWM where the min time is T/3.

Then I did a little bit of loop unwrapping to get the minimum on/off time down to about 5 instructions, not bad. But even so I cannot even get 8bit resolution at 10khz (Phil gets it at about 20khz). Well actually that is not quite true, I get better than that between the min on and off time values (almost 12bit at 20khz) because it is based on counting the system clock but that doesn't, err, count!

But I attach it anyway (a single channel version), it might be interesting to someone, and who knows there may be some clever improvements possible to the main loop to improve performance.

Now I will go and look at Phil's object again, at least I can remember how to code assembly now (my level anyway). It's not like I was up until 4:30 am or anything is it, I mean that would have been stupid, ha ha ha, oh god.

Graham

p.s. ignore the file names, it is a single channel object, oh and not a complete object either and it is running at a random frequency.

Comments

  • pjvpjv Posts: 1,903
    edited 2011-02-15 07:50
    Graham;

    In your attempt at PWM in general, and multiple PWM in particular, I can see how that approach makes it difficult to get the results you desire. Essentially you have a classic situation of needing multiple independently timed threads, and that is difficult (altough not impossible) to achieve without a muti-threading Scheduler. I have written such a thing, and it makes multiple PWM's a breeze. In fact, at present I am using the Scheduler to directly drive (through mosfets) the stepper motor that runs the CNC table I am developing.. only a single motor so far. It lets me simultaneously manage the power in the windings relative to speed, the acceleration, the direction, the maximum speed and the minimum speed of any one move. This is all accomplished in about 20 lines of assembler code plus of course the 60 or so lines for the scheduler. Adding more axes would add about the same 20 lines per axis, and co-exist happily with each other.

    Your approach would be much simplified if you can live with PDM (pulse density modulation) instead of the classic PWM. PDM does cause more switching transitions than standard PWM, so that is perhaps an undesirable feature, but the simplicity for multiple PWMs in on Cog just make it so much superior.

    With PDM, you simply take the Duty Value you wish, (at whatever resolution you choose), and at a constant time interval, add it to a Duty Accumulator. If the Duty Accumulator experiences an overflow (carry), you simply turn the output drive ON, and if there was no overflow (carry) you turn the drive off. The constant rate that this is repeated at is the sampling rate. In your case you could do each 3 instruction PDM calculation (an ADD DutyAccum,DutyVal; and an if_c OUTA ON; and an if_nc OUTA OFF) sequentially at the same sample rate.

    Using conventional PWM, it is much mor difficult to achieve high speed results without a Scheduler...... I can lend you one if you like; the current Scheduler version is not released for general consumption.

    Cheers,

    Peter (pjv)
  • JonnyMacJonnyMac Posts: 9,208
    edited 2011-02-15 08:18
    Graham,

    Phil is a wizard and I don't understand that code either, but I'm happy that Phil is so kind to provide it. What I do understand is that he is using the video generator to get a hardware assist which reduces the code.

    If you're only using two outputs you can use the counters to do the same. As an example, here's a bit of Spin code that I use for running the motors of a pan/tilt camera head:
    pri pwmx2(xpin, xpntr, ypin, ypntr) | sync                      ' launch with cognew()
    
    '' Runs fixed-frequency PWM on xpin and ypin
    '' -- pwm frequency set with system constant (PWM_TIX)
    '' -- reads duty cycle (in clock ticks) from longs at xpntr and ypntr
    '' -- runs in own cog
                                                                     
      ctra := (%00100 << 26) | xpin                                 ' PWM / NCO
      frqa := 1                                                     ' setup frq for pwm
      dira[xpin] := 1                                               ' make pin an output  
                                                            
      ctrb := (%00100 << 26) | ypin     
      frqb := 1              
      dira[ypin] := 1
    
      sync := cnt                                                   ' sync timing
      repeat
        phsa := -long[xpntr]                                        ' update x motor speed
        phsb := -long[ypntr]                                        ' update y motor speed
        waitcnt(sync += PWM_TIX)                                    ' let period expire
    

    Even in Spin I can get up to 30kHz output frequency (with a 6.25MHz clock and 16x PLL). This code ports very easily to PASM in which you would have a lot of time between setting PHSB and the end of the loop check -- you could do you PID sampling there.

    Forgive me if this is old news; it is in fact an adaption of one of the processes described in AN001.
  • Graham StablerGraham Stabler Posts: 2,510
    edited 2011-02-15 09:51
    Peter,

    I definitely want to use true PWM rather than PDM.

    Fundamentally there is a lot of free time during the on or off time to do processing but at the end of the day you often still have to do some small amounts of code between first setting the state of the pins and the first wait time. If I can reduce that then I have something that will work really well, I think it might be possible but I need to consider it further. I don't think I need to consider my multiple PWM outputs as separate threads as such, they are the same frequency so I do well to consider them together.

    Jon,

    Although they call that PWM it isn't, you merely change the density of really short pulses, not very efficient for motor control. I need a high update rate on my PID so I also need a high PWM frequency, that would make for a extremely high PDM frequency and a huge amount of loss.

    I've looked at Phil's object again and read the original forum post, the time to set up the PWM which is done in spin is going to be a limiting factor to the update rate I can achieve so I will continue on with this idea for a while at least, or downspec the project or use some hardware to do the PWM.

    Graham
  • JonnyMacJonnyMac Posts: 9,208
    edited 2011-02-15 09:57
    Although they call that PWM it isn't, you merely change the density of really short pulses, not very efficient for motor control.

    Look again, Graham. The counter takes care of setting the output high but the loop timing is what determines PWM frequency and it is FIXED. I needed this to control two DC motors at a specific frequency and it is working very well. Believe me, I confirmed the fixed-frequency output on a 'scope long before I connected motors to it (through an h-bridge, of course).

    In PASM the main loop would look something like this and if you're running ~20kHz you have a lot of cycles between setting PHSB and the end of the loop time to do PID stuff. This is in fact hardware assisted PWM.
    runmotors               rdlong  tmp1, m1spdpntr                 ' get m1 speed
                            neg     phsa, tmp1                      ' set it
                            rdlong  tmp1, m2spdpntr                 ' get m2 speed
                            neg     phsb, tmp1                      ' set it
    
                            ' other processes here
                            ' -- do not exceed loop timing (1 / pwm freq)
    
                            waitcnt sync, pwmtix                    ' let PWM period finish
                            jmp     #runmotors
    

    I wish the Propeller counters would allow for "set and forget" fixed-frequency PWM (like the SX48 does) -- for many apps this would eliminate the use of a cog for dual pwm.
  • Graham StablerGraham Stabler Posts: 2,510
    edited 2011-02-15 10:08
    I'm really sorry Jon, I just saw the counters and they seemed to be being used in a really straight forward way, hence "they could not possibly be doing anything clever". I also had real problems when I first started with the propeller because of the "duty" mode and the talk about PWM, probably clouded my judgement.

    That is a fantastic way of getting it to work, you just give a negative number and it trips the output once it has counted up. Wow, this makes things so much easier, I'm almost disappointed because I had an interesting problem to solve!

    I'll have a go and let you know how it turns out, this should kick butt!

    Graham
  • JonnyMacJonnyMac Posts: 9,208
    edited 2011-02-15 10:11
    BTW, this is the product that uses the Spin version of the dual motor PWM:
    -- http://www.cameraturret.com/pt20.htm

    The controller also measures motor current to accommodate cable drag and the weight of big lenses on the tilt axis.
  • Graham StablerGraham Stabler Posts: 2,510
    edited 2011-02-15 10:17
    Fantastic!!

    I'm actually really embarrassed I did not read your code more carefully now :(

    But extremely happy that you gave me a solution! My application is relatively hard work for the motor and the controller so it needs all the help I can give it. I need to get my coreless brushed DC motor oscillating with a precise sinusoidal profile over 120 degrees at about 20Hz. My guess is that if it can do that it will do most things nicely.

    Graham
Sign In or Register to comment.