Adafruit Industries, Essential service and business: NYC – Executive Order 202.6 - Read more. Accepting essential orders - here's how.
0

Odd results modulating PWM
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Odd results modulating PWM

by jstoner on Wed Jun 15, 2016 11:30 am

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 | TOGGLE FULL SIZE
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.

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

Re: Odd results modulating PWM

by jstoner on Fri Jun 17, 2016 11:54 am

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 | TOGGLE FULL SIZE
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.

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

Re: Odd results modulating PWM

by jstoner on Wed Jun 22, 2016 6:01 pm

This does work:

Code: Select all | TOGGLE FULL SIZE
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.

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

Re: Odd results modulating PWM

by drewfustini on Thu Jun 30, 2016 12:16 am

I ran the test code you posted:
Code: Select all | TOGGLE FULL SIZE
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?

drewfustini
 
Posts: 920
Joined: Sat Dec 26, 2015 1:19 pm

Re: Odd results modulating PWM

by drewfustini on Thu Jun 30, 2016 12:24 am

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

Code: Select all | TOGGLE FULL SIZE
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)

drewfustini
 
Posts: 920
Joined: Sat Dec 26, 2015 1:19 pm

Re: Odd results modulating PWM

by jstoner on Thu Jun 30, 2016 3:10 pm

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.

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

Re: Odd results modulating PWM

by jstoner on Mon Jul 18, 2016 4:31 pm

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 | TOGGLE FULL SIZE
>>> 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 | TOGGLE FULL SIZE
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 | TOGGLE FULL SIZE
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 | TOGGLE FULL SIZE
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 | TOGGLE FULL SIZE
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?

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

Re: Odd results modulating PWM

by jstoner on Mon Jul 18, 2016 5:55 pm

... 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.

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

Re: Odd results modulating PWM

by jstoner on Tue Jul 19, 2016 1:08 pm

aaaand, back to the original problem:

Code: Select all | TOGGLE FULL SIZE
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 | TOGGLE FULL SIZE
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.

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

Please be positive and constructive with your questions and comments.