Odd results modulating PWM

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
jstoner
 
Posts: 22
Joined: Tue Dec 11, 2012 11:10 pm

Odd results modulating PWM

Post by jstoner »

I am trying to do sort of PWM within PWM. I have a thread running, calling PWM.start() and PWM.stop() on a pin. Here's the simplest version of my code:

Code: Select all

import Adafruit_BBIO.PWM as PWM
from time import sleep

while True:
    PWM.start('P9_14', 50, 3)
    sleep(2)
    PWM.stop('P9_14')
    sleep(2)
I have it set up with a test LED. I expect it to modulate and show six flashes, and then pause two seconds, and repeat ad infinitum. What I actually see is six flashes, and then a two second pause, and then a single flash, and then a few seconds, and then another single flash, and the single flashes repeat.

I have seen other unpredicted behavior with more sophisticated code--long periods on instead of flashing, that sort of thing, but when I boil it down to something basic, this is what I see. Ultimately I am planning to go to 100,000Hz, modulated over a period of an hour, with this application.

Anyone got any ideas? I imagine people doing servo control run into something similar.

User avatar
jstoner
 
Posts: 22
Joined: Tue Dec 11, 2012 11:10 pm

Re: Odd results modulating PWM

Post by jstoner »

OK, got a little more complicated. Connected my LED circuit back to P9_12 and listened for falling events, thinking I wanted to be sure I was leaving PWM in the off state.

Code: Select all

import Adafruit_BBIO.PWM as PWM
import Adafruit_BBIO.GPIO as GPIO

from time import sleep
from threading import Thread

GPIO.setup('P9_12', GPIO.IN)

class AsyncStop(Thread):
    """docstring for AsyncStop"""
    def run(self):
        try:
            GPIO.wait_for_edge('P9_12', GPIO.FALLING)
        except RuntimeError:
            pass
        PWM.stop('P9_14')

while True:
    PWM.start('P9_14', 50, 3)
    sleep(2)
    thread = AsyncStop()
    thread.start()
    sleep(2)
But I get the same results. Now, if I comment out the wait_for_edge and the surrounding try/catch, I get four runs of six flashes and then it goes to single flashes. So there's some timing issue happening. Hm.

User avatar
jstoner
 
Posts: 22
Joined: Tue Dec 11, 2012 11:10 pm

Re: Odd results modulating PWM

Post by jstoner »

This does work:

Code: Select all

import Adafruit_BBIO.PWM as PWM
from time import sleep

while True:
    PWM.start('P9_14', 50, 3)
    sleep(2)
    PWM.set_duty_cycle('P9_14', 0)
    sleep(2)
Though I still think PWM.stop() should work.

User avatar
drewfustini
 
Posts: 944
Joined: Sat Dec 26, 2015 1:19 pm

Re: Odd results modulating PWM

Post by drewfustini »

I ran the test code you posted:

Code: Select all

import Adafruit_BBIO.PWM as PWM
import Adafruit_BBIO.GPIO as GPIO

from time import sleep
from threading import Thread

GPIO.setup('P9_12', GPIO.IN)

class AsyncStop(Thread):
    """docstring for AsyncStop"""
    def run(self):
        try:
            GPIO.wait_for_edge('P9_12', GPIO.FALLING)
        except RuntimeError:
            pass
        PWM.stop('P9_14')

while True:
    PWM.start('P9_14', 50, 3)
    sleep(2)
    thread = AsyncStop()
    thread.start()
    sleep(2)
I noticed this warning about the PWM duty cycle:
root@beaglebone:~# python john-test.py
[ 3030.000072] ehrpwm 48302200.ehrpwm: Duty is larger than period
[ 3034.275995] ehrpwm 48302200.ehrpwm: Duty is larger than period
[ 3039.330709] ehrpwm 48302200.ehrpwm: Duty is larger than period
[ 3042.617165] ehrpwm 48302200.ehrpwm: Duty is larger than period
The frequency seems to be 3 Hz:
PWM.start('P9_14', 50, 3)
Did you intend for that?

User avatar
drewfustini
 
Posts: 944
Joined: Sat Dec 26, 2015 1:19 pm

Re: Odd results modulating PWM

Post by drewfustini »

With frequecny set to 1kHz, PWM.stop() does work ok.

Code: Select all

import Adafruit_BBIO.PWM as PWM
from time import sleep

while True:
    PWM.start('P9_14', 50, 1000)
    sleep(2)
    PWM.stop('P9_14')
    sleep(2)

User avatar
jstoner
 
Posts: 22
Joined: Tue Dec 11, 2012 11:10 pm

Re: Odd results modulating PWM

Post by jstoner »

Yeah, higher frequencies seem ok, but lower ones are useful for testing. It's useful to start at 3Hz and be able to verify visually that it's showing the right frequency. Especially when you have complicated application code leading up to the call to PWM.start() or whatever. I'd rather test the same code I'm going to use.

I've never seen any error messages related to the frequency being lower than the duty cycle. That seems odd. I don't see anything erroneous about a square wave at 3Hz with a 50% duty cycle.

I have switched my code over to PWM.set_duty_cycle(pin, 0). That seems to leave the pin i a state that I can change at will.

User avatar
jstoner
 
Posts: 22
Joined: Tue Dec 11, 2012 11:10 pm

Re: Odd results modulating PWM

Post by jstoner »

OK, navigating constraints.

There are times when I need a short cycle (<1s), and times when I need a long cycle (up to minutes). Sometimes I want PWM within PWM and sometimes I don't.

I can address a pin as either GPIO or PWM. If I want to switch between the two, I can go from GPIO to PWM at will, but PWM to GPIO fails. As in

Code: Select all

>>> import Adafruit_BBIO.PWM as PWM
>>> import Adafruit_BBIO.GPIO as GPIO
>>> GPIO.setup('P8_13', GPIO.OUT)
>>> GPIO.output('P8_13', GPIO.HIGH)
>>> PWM.start('P8_13', 50, 1000)
>>> PWM.stop('P8_13')
>>> PWM.cleanup()
works but the reverse fails silently. No signal, no error message. The only way I have found to switch back is to reboot. Which doesn't work when I am trying to wrap this in a service that can be controlled by end users, that can run with minimal involvement from me.

So I try dispensing with GPIO and do PWM with a duty cycle of 100. Call it a degenerate case of PWM within PWM.

Code: Select all

import Adafruit_BBIO.PWM as PWM
from time import sleep

while True:
    PWM.start('P8_13', 100, 1000)
    sleep(2)
    PWM.stop('P8_13')
    sleep(2)
This works... on the first cycle. On subsequent cycles, I see an odd flash and then nothing, over and over. When I look in the filesystem I see

Code: Select all

0s  #> cat /sys/devices/ocp.3/pwm_test_P8_13*/duty
0
I don't see this problem with a 50% duty cycle.

If I try

Code: Select all

while True:
    PWM.start('P8_13', 100, 1000)
    sleep(2)
    PWM.set_duty_cycle('P8_13', 0)
    PWM.set_frequency('P8-13', 1000)
    sleep(2)
It works... for about twenty minutes.

If I try

Code: Select all

while True:
    PWM.start('P8_13', 100, 1000)
    sleep(2)
    PWM.start('P8_13', 0, 1000)
    sleep(2)
It works... for about ten minutes.

In both cases I see a 0 in /sys/devices/ocp.3/pwm_test_P8_13*/duty as above, when it should be 100.

Ideas? Why would this be?

User avatar
jstoner
 
Posts: 22
Joined: Tue Dec 11, 2012 11:10 pm

Re: Odd results modulating PWM

Post by jstoner »

... and I just tried unexporting the PWM cape and got a kernel panic. I've heard of that happening in Angstrom, but I am running Debian Wheezy. Hm.

User avatar
jstoner
 
Posts: 22
Joined: Tue Dec 11, 2012 11:10 pm

Re: Odd results modulating PWM

Post by jstoner »

aaaand, back to the original problem:

Code: Select all

import Adafruit_BBIO.PWM as PWM
from time import sleep

while True:
    PWM.start('P8_13', 75, 1000)
    sleep(2)
    PWM.stop('P8_13')
    sleep(2)
fails (as earlier), and

Code: Select all

import Adafruit_BBIO.PWM as PWM
from time import sleep

while True:
    PWM.start('P8_13', 50, 60)
    sleep(2)
    PWM.stop('P8_13')
    sleep(2)
also fails as earlier. 60Hz is not a test frequency for me. We use that.

And when I restart the process it begins ok for a varying number of loops, and then goes back to the odd flash and then nothing. So it's not outliving the process.

Locked
Please be positive and constructive with your questions and comments.

Return to “Beagle Bone & Adafruit Beagle Bone products”