Controlling the output power of a pin (dimming external LED)
Controlling the output power of a pin (dimming external LED)
So I'm new to microcontroller development as a whole, but after seeing this nice introductory board on kickstarter I decided to give it a try since I love python so much.
I'm trying to create a LED light show display using this board. I've gotten my hands on a few nice RGB LED lights, and I was able to write a little program to create a ribbon out of the 6 possible colors you can make with RGB. However, it's not quite good enough for me. I'm trying to create smooth blending colors via dimming each color channel. So far, all I could do is turn each color on/off, is there a way to control the output voltage for each pin (I assume that's the easiest way to dim an LED light) or will I have to use something extra to dim the LEDs?
Thanks for the help!
I'm trying to create a LED light show display using this board. I've gotten my hands on a few nice RGB LED lights, and I was able to write a little program to create a ribbon out of the 6 possible colors you can make with RGB. However, it's not quite good enough for me. I'm trying to create smooth blending colors via dimming each color channel. So far, all I could do is turn each color on/off, is there a way to control the output voltage for each pin (I assume that's the easiest way to dim an LED light) or will I have to use something extra to dim the LEDs?
Thanks for the help!
Re: Controlling the output power of a pin (dimming external
The normal way that control brightness of an LED is to use PWM.
PWM isn't properly supported on the pyboard, but this thread has a way to do it:
http://forum.micropython.org/viewtopic. ... t=210#p967
Also see here: http://forum.micropython.org/viewtopic. ... t=PWM#p982
PWM isn't properly supported on the pyboard, but this thread has a way to do it:
http://forum.micropython.org/viewtopic. ... t=210#p967
Also see here: http://forum.micropython.org/viewtopic. ... t=PWM#p982
Re: Controlling the output power of a pin (dimming external
And I thought I should mention, that the STM32F405 datasheet says that the max current for a single pin is 25 mA.
So if you're going to be driving more than a single LED, you should really consider using a transistor or a MOSFET to switch the LEDs on and off.
So if you're going to be driving more than a single LED, you should really consider using a transistor or a MOSFET to switch the LEDs on and off.
Re: Controlling the output power of a pin (dimming external
Thanks a lot!
So I added the pwm module to my controller, and the contents are (I'm assuming this is the latest version)
I then moved my LED lights to be X1, X2, and X3 [RGB] (as apparently not all pins work with PWM). However, when I open up REPL and perform
nothing happens. No matter what I set the value to, I can't get any response. I get the same result no matter what color I test. Any ideas what's going on?
So I added the pwm module to my controller, and the contents are (I'm assuming this is the latest version)
Code: Select all
import pyb, stm
#as pwm is configured 0-3.3v is 0-10000
# used to truncate to 0-255;
# change if you need finer resolution
RESOLUTION = 255
#for each pin name
# list of possible pwm available alt fn's
# and corresponding timer/channel
__PIN_TIMERS = { \
'A0': { 0b0010: ( 5,1) }, \
'A1': { 0b0001: ( 2,2), 0b0010: ( 5,2) }, \
'A2': { 0b0001: ( 2,3), 0b0010: ( 5,3), 0b0011: ( 9,1) }, \
'A3': { 0b0001: ( 2,4), 0b0010: ( 5,4), 0b0011: ( 9,2) }, \
'A6': { 0b0010: ( 3,1), 0b1001: (13,1) }, \
'A7': { 0b0010: ( 3,2), 0b1001: (14,1) }, \
'A8': { 0b0001: ( 1,1) }, \
'A9': { 0b0001: ( 1,2) }, \
'A10': { 0b0001: ( 1,3) }, \
'A11': { 0b0001: ( 1,4) }, \
'B0': { 0b0010: ( 3,3) }, \
'B1': { 0b0010: ( 3,4) }, \
'B3': { 0b0001: ( 2,2) }, \
'B4': { 0b0010: ( 3,1) }, \
'B5': { 0b0010: ( 3,2) }, \
'B6': { 0b0010: ( 4,1) }, \
'B7': { 0b0010: ( 4,2) }, \
'B8': { 0b0010: ( 4,3), 0b0011: (10,1) }, \
'B9': { 0b0010: ( 4,4), 0b0011: (11,1) }, \
'B10': { 0b0001: ( 2,3) }, \
'B11': { 0b0001: ( 2,4) }, \
'B14': { 0b1001: (12,1) }, \
'B15': { 0b1001: (12,2) }, \
'C6': { 0b0010: ( 3,1), 0b0011: ( 8,1) }, \
'C7': { 0b0010: ( 3,2), 0b0011: ( 8,2) }, \
'C8': { 0b0010: ( 3,3), 0b0011: ( 8,3) }, \
'C9': { 0b0010: ( 3,4), 0b0011: ( 8,4) }, \
'D12': { 0b0010: ( 4,1) }, \
'D13': { 0b0010: ( 4,2) }, \
'D14': { 0b0010: ( 4,3) }, \
'D15': { 0b0010: ( 4,4) }, \
'E5': { 0b0011: ( 9,1) }, \
'E6': { 0b0011: ( 9,2) }, \
'E9': { 0b0001: ( 1,1) }, \
'E11': { 0b0001: ( 1,2) }, \
'E13': { 0b0001: ( 1,3) }, \
'E14': { 0b0001: ( 1,4) }, \
'F6': { 0b0011: (10,1) }, \
'F7': { 0b0011: (11,1) }, \
'F8': { 0b1001: (13,1) }, \
'F9': { 0b1001: (14,1) }, \
'H9': { 0b1001: (12,2) }, \
'H10': { 0b0010: ( 5,1) }, \
'H11': { 0b0010: ( 5,2) }, \
'H12': { 0b0010: ( 5,3) }, \
'H6': { 0b1001: (12,1) }, \
'I0': { 0b0010: ( 5,4) }, \
'I2': { 0b0011: ( 8,4) } \
}
class PWM:
"""dirty Pulse Width Modulation class"""
def __init__(self, pin, afmode=None):
if not pin.name() in __PIN_TIMERS:
raise ValueError('Pin does not support pwm')
if afmode == None:
#select the first timer in the dictionary
pwm_afmode = list(__PIN_TIMERS[pin.name()].keys())[0]
else:
pwm_afmode = afmode
if not pwm_afmode in __PIN_TIMERS[pin.name()]:
raise ValueError('Pin does not support afmode {0}'.format(bin(afmode)))
self.pin = pin
self.gpio = eval('stm.GPIO{0}'.format(pin.name()[0]))
pwm_pin = int(self.pin.name()[1:])
pwm_timer_no = __PIN_TIMERS[self.pin.name()][pwm_afmode][0]
pwm_timer_ch = __PIN_TIMERS[self.pin.name()][pwm_afmode][1]
#setup gpio
#set alternate fn mode, before setting pin to alternate function
if pwm_pin < 7:
stm.mem32[self.gpio + stm.GPIO_AFR0] |= pwm_afmode << (pwm_pin * 4)
elif pwm_pin == 7:
#avoid potential overflow on 32nd bit being set
stm.mem8[self.gpio + stm.GPIO_AFR0 + 3] |= pwm_afmode << 4
elif pwm_pin < 15:
stm.mem32[self.gpio + stm.GPIO_AFR1] |= pwm_afmode << ((pwm_pin - 8) * 4)
elif pwm_pin == 15:
#avoid potential overflow on 32nd bit being set
stm.mem8[self.gpio + stm.GPIO_AFR1 + 3] |= pwm_afmode << 4
if pwm_pin < 15:
stm.mem32[self.gpio + stm.GPIO_MODER] |= 0b10 << (pwm_pin * 2)
stm.mem32[self.gpio + stm.GPIO_OSPEEDR] |= 0b10 << (pwm_pin * 2)
elif pwm_pin == 15:
stm.mem8[self.gpio + stm.GPIO_MODER + 3] |= 0b10 << 6
stm.mem8[self.gpio + stm.GPIO_OSPEEDR + 3] |= 0b10 << 6
#setup timer
#TODO: work out how to init timer directly, so can use reserved ones TIM3
pyb.Timer(pwm_timer_no).init(freq=5) #use pyb module to kickstart the timer
pwm_timer = eval('stm.TIM{0}'.format(pwm_timer_no))
self.__pwm_duty = pwm_timer + eval('stm.TIM_CCR{0}'.format(pwm_timer_ch))
stm.mem32[self.__pwm_duty] = 0 #make sure duty is 0
stm.mem32[pwm_timer + stm.TIM_ARR] = 9999 #replicate damiens's prescalar, period
stm.mem32[pwm_timer + stm.TIM_PSC] = 83 #gives 10,000 steps between 0 and 3.3v
stm.mem32[pwm_timer + stm.TIM_DIER] |= 0b1
stm.mem32[pwm_timer + stm.TIM_SR] |= 0b11110 #sets all channel interupt flags
if pwm_timer_ch <= 2:
stm.mem32[pwm_timer + stm.TIM_CCMR1] |= 0b01101000 << ((pwm_timer_ch - 1) * 8)
else:
stm.mem32[pwm_timer + stm.TIM_CCMR2] |= 0b01101000 << ((pwm_timer_ch - 3) * 8)
stm.mem32[pwm_timer + stm.TIM_CCER] |= 0b1 << ((pwm_timer_ch -1) * 4)
stm.mem32[pwm_timer + stm.TIM_DMAR] |= 0b1
def duty(self, value=None):
if value == None:
return int( stm.mem32[self.__pwm_duty] / 10000 * RESOLUTION )
else:
if value > RESOLUTION: value = RESOLUTION
if value < 0: value = 0
stm.mem32[self.__pwm_duty] = int(value / RESOLUTION * 10000)
I then moved my LED lights to be X1, X2, and X3 [RGB] (as apparently not all pins work with PWM). However, when I open up REPL and perform
Code: Select all
b = pwm.PWM(pyb.Pin.board.X3)
b.duty(255)
Re: Controlling the output power of a pin (dimming external
Fixed it!
Seemed like I needed to still put the pyb.Pin.OUT_PP as the second argument to PWM. Awesome!
Seemed like I needed to still put the pyb.Pin.OUT_PP as the second argument to PWM. Awesome!
Re: Controlling the output power of a pin (dimming external
Maybe I haven't fixed it. I'm curious now if this is a problem due to using the OUT_PP function, or if it's a problem with the LED/PWM setup.
My problem is, when a color channel is set at anything less than 255, it's not a solid light, it actually has a flicker to it. When it's sitting still, it's unnoticeable; but if you start waving the LED around, you can see that the flicker gets faster and faster as the intensity increases until it hits 255, at which point it's a solid beam. Normally this wouldn't bother me, but the point of my application is to be able to generate geometric patterns using the lights. It just doesn't look right when you adjust custom colors like [255, 100, 150], simply because the green and blue channels are flickering while the red sits at a solid beam. It looks really bad as a ribbon.
Any idea what could be causing this?
My problem is, when a color channel is set at anything less than 255, it's not a solid light, it actually has a flicker to it. When it's sitting still, it's unnoticeable; but if you start waving the LED around, you can see that the flicker gets faster and faster as the intensity increases until it hits 255, at which point it's a solid beam. Normally this wouldn't bother me, but the point of my application is to be able to generate geometric patterns using the lights. It just doesn't look right when you adjust custom colors like [255, 100, 150], simply because the green and blue channels are flickering while the red sits at a solid beam. It looks really bad as a ribbon.
Any idea what could be causing this?
Re: Controlling the output power of a pin (dimming external
Try changing freq=5 to a higher number (perhaps 100)
Re: Controlling the output power of a pin (dimming external
I assume you mean the line in the pwm module?
At 100, it doesn't work, the highest value that appears to work is 80, anything above and the LED doesn't turn on. I also don't notice any changes once I up the frequency. The lights are still flickering at the same rate (as far as I can tell).
Code: Select all
pyb.Timer(pwm_timer_no).init(freq=5)
At 100, it doesn't work, the highest value that appears to work is 80, anything above and the LED doesn't turn on. I also don't notice any changes once I up the frequency. The lights are still flickering at the same rate (as far as I can tell).
Re: Controlling the output power of a pin (dimming external
Correct me if I'm wrong (as I know next to nothing about hardware programming, LED programming, and PWM) but PWM stands for Pulse Width Modulation, and so I'm assuming it's dimming the LED by sending gradually slower and slower pulses of electricity into the pin. If this is the case, wouldn't that be the cause of the flickering effect I'm noticing while waving the LED around? I could be completely wrong, it's just me speculating and trying to problem solve.
Re: Controlling the output power of a pin (dimming external
There are 2 things that go together, frequency and duty cycle.
If you send a 50% duty cycle at 1000 cycles per second or 10 cycles per second you'll get about 50% brightness.
As you get slower you can see the frequency visibly.
If you send a 50% duty cycle at 1000 cycles per second or 10 cycles per second you'll get about 50% brightness.
As you get slower you can see the frequency visibly.