1 2 Previous Next 21 Replies Latest reply: Dec 23, 2013 11:20 AM by vsluiter RSS

Any ideas on how to count pulses and shut off a PWM

PaulMakesThings

TL;DR version: How do I count pulses with programmable digital and use the count to shut off 5 PWMs. The count to shut off and the frequency of the PWMs would have to be set in software for each iteration.

 

I'm trying to figure out a good way to use programmable digital of the PSoC 4 on the pioneer kit to do coordinated stepper moves. Setting up a PWM module was pretty easy, I just need something to shut it off after a set number of pulses. The black box description is this, the software sets the pulse frequency for several modules, 5 in this case, with the timing already calculated so that they will finish their pulses in the same amount of time, then it starts them at the same time, then they all shut off when they're done and signal (probably via interrupt) back to the software that the move is done and they are ready for the next. I'm thinking the architecture would use one PWM module as the master, if there are not timing glitches they would all finish together, it would stop them, and interrupt that the move was done.

 

So far I have found that I can easily set a PWM module for a certain frequency from the software, but I'm not sure how to make a counter shut it off. The algorithm is pretty simple for these moves, you have a known speed in pulses at which each axis can move given the electrical and mechanical limitations of the system, given the number of steps required for a move on each axis and that speed you can find which one will take the longest, and divide the number of pulses for all the others to make them happen in that amount of time. At that point most controllers just use timers to generate and count those pulses, I'd like to figure out a nice efficient way to do it in programmable digital. I think it should be pretty simple if I can just figure out how to count pulses with a counter, then I would have it trigger an interrupt and stop the PWMs when the target is reached, can someone show me how to do that? I'd also be interested in other hardware architectures that can do this.

 

As a note, this is for the smarter life challenge, I'm not really worrying about my competitors seeing my code. If I win I want it to be by making the coolest project, not because they got stuck.

 

Thanks for reading

  • 1. Re: Any ideas on how to count pulses and shut off a PWM
    DAB

    Hi Paul,

     

    I believe that you can set up counters and status registers inside the PSOC.

    I think that you can turn the PWM outputs on and off by using a status/control register from the software side.

    Inside the IDE, you should be able to activate the software S/C register to work off either interrupt or other triggers.

    You should be able to configure the output pins to provide inputs for PSOC counters.

     

    Note, I have read about this capability in the documentation, but I have not implemented it.  I bring it to your attention so you can check the documentation on interfacing the software side of the PSOC with the HW programmable side.

     

    DAB

  • 2. Re: Any ideas on how to count pulses and shut off a PWM
    saurocksall

    Hi Paul...

     

    You just need to count the number of pulses, and store the value in some integer and when that value reaches your desired value set a command to stop the PWM.. i have done this with Arduino and it works, i think that would also do the job for you.. best of luck..

  • 3. Re: Any ideas on how to count pulses and shut off a PWM
    PaulMakesThings

    Thanks Dab, I have something like that in mind, I was trying to do it largely in programmable digital to better use the psoc and offload some work from the mcu. I think a counter unit could do the job but I'm not sure how to count pulses, when I tried I seemed to be counting clock pulses and my cc didn't switch. I could certainly use a variable incremented in an isr, but if I just new how to set a counter device to do it, it would be so fast an efficient and it would be a way that no other Microcontroller could do it, so it would really showcase the psoc capabilities.

  • 4. Re: Any ideas on how to count pulses and shut off a PWM
    hlipka

    A PWM can be configured to have an enable input. This can be used for disabling it. Then use an additional counter for counting the pulses of the PWM. The compare output of the counter can then drive the enables signal to stop the PWM.

     

    Or, if the frequency of your PWM is not so high, you can trigger an interrupt at the end of each period and count there.

  • 5. Re: Any ideas on how to count pulses and shut off a PWM
    PaulMakesThings

    Exactly, this is what I've been trying to do, but for some reason it hasn't been working so I figured I was using the counter wrong. Since it's hard to debug what you don't have I'll clean up all the stuff I've added trying to make it work and post my best guess so hopefully someone can tell me what I'm doing wrong. I tested that the PWM was running with my O-scope, and I fed that into the count input on the counter, with the overflow output going to the LED, and it never turned off. I had the PWM running at 1 Hz, and the count overflow set to 10, so I could see it pretty easily, but the LED never changed. Anyway, I'll post what I try to make the problem more concrete, thanks for the help!

  • 6. Re: Any ideas on how to count pulses and shut off a PWM
    PaulMakesThings

    Apparently all I needed was assurance that this was the right way to go. I got it working with a bit more trial and error. To help anyone who is interested here's what I had wrong:

    1. The comp output switches when the value is higher than the value in the configure tab of the counter under "period" I thought it was the value set to "compare"
    2. The timer has to be started in software by the command TimerName_Start();   kind of obvious maybe, but for some reason I was just looking at the schematic

  • 7. Re: Re: Any ideas on how to count pulses and shut off a PWM
    hlipka

    Glad you got it working!

    1. no, it really is a compare. But since the counter starts at zero, a compare value of 5 means you needs 6 pulses...
    2. this is a general rule with PSoC - every component needs to be started before it works. (Only exception is core logic like gates and flip-flops)
  • 8. Re: Re: Any ideas on how to count pulses and shut off a PWM
    PaulMakesThings

    That's just what I thought the datasheet said, so I had the period set to 255 and the compare set to 10, and after 10 blinks of the PWM led nothing happened, then several minutes the compare LED finally came on. Since it had been about 4 minutes at 1 Hz, I figured that was probably the 255 tripping it. I set the period to 10, and sure enough on the 9th blink it came on. I must be using some improper setting or something.

    Untitled.png

     

    int main()

    {

        /* Place your initialization/startup code here (e.g. MyInst_Start()) */

     

     

        /* CyGlobalIntEnable; */ /* Uncomment this line to enable global interrupts. */

       

        //PWM Isr setup

        PWM_Start();

        PWM_isr_StartEx(PWM_isr);

        CyGlobalIntEnable;

       

        //counter setup

        Counter_1_Enable();

        Counter_1_Start();

       

        for(;;)

        {

            /* Place your application code here. */

        }

    }

     

     

    /* [] END OF FILE */

  • 10. Re: Re: Any ideas on how to count pulses and shut off a PWM
    hlipka

    Yes, you did configure it wrong. Look at the clock mode setting. Think about what 'down counter' means. Change it to 'up counter', then try again

    (And yes, I think this is a stupid default setting for a counter)

  • 11. Re: Re: Any ideas on how to count pulses and shut off a PWM
    PaulMakesThings

    That's another thing that was confusing me, I kept setting it to up and it changed back to down. It seems like it will only allow an up counter with greater than compare modes? Even then I set it and come back and it's down, but at least it will let me hit apply.

  • 12. Re: Re: Any ideas on how to count pulses and shut off a PWM
    hlipka

    Maybe just try to use "equal" as compare mode?

  • 13. Re: Any ideas on how to count pulses and shut off a PWM
    max.kingsbury

    My solution was to use a lower frequency clock to drive a PWM(acting as a counter) just to generate a time-base during which the other 4 PWMs could generate the required number of pulses. We then use a bunch of glue logic to gate the signals.

     

    I only show 2 PWMs below, to demonstrate how it will work with both fixed function PWMs and UDB PWMs.

    SmarterLifePulses.PNG

     

    #define CLOCK_RESET_KHZ             100     //the input clock for the reset PWM
    #define CLOCK_STEPPER_KHZ           12000   //the input clock for the stepper PWMs
    
    
    #define PULSE_INCREMENT_INTERVAL1   10      //increment pulse1 count by this each time around (minimum of ~10 with these clocks)
    #define PULSE_INCREMENT_INTERVAL2   5       //increment pulse2 count by this each time around
    
    
    #define PULSE_TRAIN_LENGTH_MS       50      //length of time for each co-ordinated move
    
    
    #define SW_DELAY_MS                 100     //delay by this much after starting the co-ordinated move
    
    
    uint8 newMoveFlag = 0xff;
    
    
    int main()
    {
        // Declare variables
        uint16 pulsesPerPeriod1 = 0;
        uint16 pulse1CounterPeriod;
        uint16 pulsesPerPeriod2 = 0;
        uint16 pulse2CounterPeriod;    
        uint16 resetCounterPeriod;
        
        // Start components
        PWM_Stepper1_Start();
        PWM_Stepper2_Start();
        PWM_Reset_Start();
        isr_PWM_Reset_TC_Start();
        
        // Set reset counter period (this could change at runtime also)
        resetCounterPeriod = (CLOCK_RESET_KHZ * PULSE_TRAIN_LENGTH_MS);
        PWM_Reset_WritePeriod(resetCounterPeriod);    
        
        CyGlobalIntEnable; /* Uncomment this line to enable global interrupts. */
        for(;;)
        {
            // Only update the configuration if a new co-ordinated move is desired. 
            // This flag is set in the PWM_Reset TC ISR
            if(newMoveFlag)
            {
                // Calculate the new PWM periods
                // Stepper 1
                pulsesPerPeriod1 += PULSE_INCREMENT_INTERVAL1;
                pulse1CounterPeriod = ((uint32)CLOCK_STEPPER_KHZ/CLOCK_RESET_KHZ)* resetCounterPeriod / pulsesPerPeriod1;
                if(pulse1CounterPeriod < 2) // Check for rollover
                {
                    pulsesPerPeriod1 = PULSE_INCREMENT_INTERVAL1;
                    pulse1CounterPeriod = ((uint32)CLOCK_STEPPER_KHZ/CLOCK_RESET_KHZ)* resetCounterPeriod / pulsesPerPeriod1;
                }
                // Stepper 2
                pulsesPerPeriod2 += PULSE_INCREMENT_INTERVAL2;
                pulse2CounterPeriod = ((uint32)CLOCK_STEPPER_KHZ/CLOCK_RESET_KHZ)* resetCounterPeriod / pulsesPerPeriod2;
                if(pulse2CounterPeriod < 2) // Check for rollover
                {
                    pulsesPerPeriod2 = PULSE_INCREMENT_INTERVAL2;
                    pulse2CounterPeriod = ((uint32)CLOCK_STEPPER_KHZ/CLOCK_RESET_KHZ)* resetCounterPeriod / pulsesPerPeriod2;
                }
                
                // Disable the counters
                Control_Reg_PulseEnable_Write(0x00);
    
    
                // Reset the counters
                Control_Reg_PulseReset_Write(0xff);
                Control_Reg_PulseReset_Write(0x00);
                
                // Set the period of the pulse counters
                // Stepper 1 (UDB PWM)
                PWM_Stepper1_WritePeriod(pulse1CounterPeriod);
                PWM_Stepper1_WriteCompare(pulse1CounterPeriod/2);
                PWM_Stepper1_WriteCounter(0);
                // Stepper 2 (Fixed Function TCPWM)
                PWM_Stepper2_WritePeriod(pulse2CounterPeriod);
                PWM_Stepper2_WriteCompare(pulse2CounterPeriod/2);
                PWM_Stepper2_WriteCounter(0);
                
                // Enable the counters. pulses start here.
                Control_Reg_PulseEnable_Write(0xff);
                
                // Clear the flag and wait for the next update
                newMoveFlag = 0x00;
            }
                
        }
    }
    
    
    /* [] END OF FILE */
    
  • 14. Re: Any ideas on how to count pulses and shut off a PWM
    PaulMakesThings

    Awesome, thank you! I'll dig into this when I get home. It looks great. First thing I'll need to do is read the datasheet on that SRFF component, I don't know what that is.

1 2 Previous Next