Lamp fader
I made myself a dimmer that has has 239 steps (the filament responds best in this range) from dividing the clock by the numbers 121 to 360. I want more fine control than this over the lamp (more of a resolution). Since the propeller will not accept numbers like 139.41 what should I divide the clock by for a greater range? I tried numbers like 13941 but they did not work (lamp was at full brightness).
Here is the code:
I commented out the lines that turn my dimmer into a "light bulb fade off over time" program to test the dimmer at fixed brightnesses. The end result of the program will dim the lamp over a period of X minutes. The program, if the lines were not commented out, would lower the lamps brightness by one step per second. The problem with this is at the lower brightnesses you can see the filament stepping dimmer. I want a finer resolution so the fading would appear more analog.
Here is the code:
CON _xinfreq = 5_000_000 _clkmode = xtal1 + pll16x var word brightness long stack[noparse][[/noparse]20] PUB Main cognew(Subtract, @stack[noparse][[/noparse]0]) cognew(Dimmer, @stack[noparse][[/noparse]10]) PUB Subtract brightness := 360 'repeat while brightness > 121 ' brightness := brightness - 1 'waitcnt(clkfreq + cnt) PUB Dimmer dira[noparse][[/noparse]16] := 0 dira[noparse][[/noparse]8] := 1 repeat outa[noparse][[/noparse]8] := 0 repeat while ina[noparse][[/noparse]16] == 0 'Wait until zero cross fires waitcnt(clkfreq / brightness + cnt) outa[noparse][[/noparse]8] := 1
I commented out the lines that turn my dimmer into a "light bulb fade off over time" program to test the dimmer at fixed brightnesses. The end result of the program will dim the lamp over a period of X minutes. The program, if the lines were not commented out, would lower the lamps brightness by one step per second. The problem with this is at the lower brightnesses you can see the filament stepping dimmer. I want a finer resolution so the fading would appear more analog.
Comments
If the zero cross signal is narrow enough, you should use waitpeq instead of the repeat loop. waitpeq will be faster in continuing execution.
Don't use a division in the waitcnt. I'd rather give it a fixed variable. The subtract can take care of the value of this variable. If you divide 80_000_000 by 121 you get 661_157, if you divide by 360 you get 250_000. So, simply put any value in between in the variable and you have 411_157 steps.
To give you better advice it would be interesting to see what the cirquit to switch on the light looks like.
PS: As perception of light is not linear - plus the alternating currency will produce non linear brightness (in sense that it's not proportional to the switch on time), it makes sense to create a table of values which give the impression of a linear fade.
dat
fade long 250_000, 251_000, 252_000 ........ and so on (·~128 values would propably give a soft fade )
In your subtract you'd increase an index inside of that array and provide that value to dimmer.
Post Edited (MagIO2) : 11/23/2009 10:54:30 PM GMT
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Style and grace : Nil point
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Style and grace : Nil point
http://mouser.com/Search/ProductDetail.aspx?qs=sGAEpiMZZMt82OzCyDsLFGDf%2b07/%2bYgHW//tOw8Iy2o=
It contains two LED's wired in inverse parallel that couple to an NPN transistor. I have the two LEDs hooked up to the 110 line with two 10k ohm resistors in series.
FWIW, I'll be coding my dimmer to accept an input range of 0 (off) to 255 (full on) to accommodate DMX512. The user may do linear corrections in the high-level code (keeps the assembly simpler, and I've done this with an LED dimmer [noparse][[/noparse]see my BAM object in ObEx]).
[noparse][[/noparse]Edit] You might consider the H11AA1 opto-isolator as it gives you an output for each half cycle of the AC input. The attached circuit will give you high-going pulse at 120 Hz.
Post Edited (JonnyMac) : 11/23/2009 11:37:22 PM GMT
Is your code intended to pulse the power to the lamp as it makes P8 0 almost instantly after making it 1?
Have you considered:
Reverse phase control:
http://www.epanorama.net/documents/lights/lightdimmer.html
Fire the triac at the zero crossing, wait for a time and then turn off (a time less than a half cycle). You should be able to get plenty of resolution.
The other thing is that there is no reason to do a division just do:
waitcnt(brightness + cnt) but change your values of brightness accordingly, your resolution is then the clock time period (1/80000000) which I suspect is good enough.
Cheers,
Graham
Still not sure of the need for assembly.
Graham
Graham
Speed. PASM is on the order of 50 to 75x faster than Spin; by running at a faster speed you can get better resolution of control. If you're running a dimmer in a separate cog, anyway, it might as well be a PASM cog for the best performance. A program that simple is not difficult to code in Assembly and would be worth the effort.
No, it's based on the lamp you're controlling -- this is why my dimmer projects do not attempt to linearize at the low level; it's easy to create a translation table to take a straight linear input and apply a curve to it to get the best visual output. Again, see my BAM object for an example of this.
-- http://obex.parallax.com/objects/517/
So far I have this
org 0 'Set the program origin at mem position 0
mov dira, 8 'Set pin 8 to output
Now how do you specify a jnp command to wait for the ina <pin> register to go high?
As the perception of light is more sensitive to little changes in the dark, the SPIN code should be feasible as it switches on the TRIAC at the beginning of the half-periode which will not add much brightness. If you switch on at the end of the periode the light will be darker. That area is covered by the waitcnt with high resolution.
Exactly as MagIO2 says the resolution even in spin using waitcnt will be 12.5ns the only thing Spin will limit is the minimum time and it will mean you are a little late catching the crossing perhaps.
If you want to learn assembly here are some resources:
http://forums.parallax.com/showthread.php?p=668559
Which contains two wonderful PDFs by deSilva and Potatohead
http://forums.parallax.com/showthread.php?p=647408
Which is my own "assembly step by step" which contains 4 programs containing the basics to get you started.
It will become an object that can be started with start and have the brightness changed by setbrightness. Notice there is a pulse_time variable this is because in assembly I'm not sure the pin will pulse for long enough to turn on the triac, you may be able to remove the delay, I just guessed a value for that so you may need to change it.
Reading the comments may teach you plenty about assembly too.
Hope it works [noparse]:)[/noparse]
1.
The PASM code is very small ... so you have lots of place to put the array there that holds the waittimes to give the impression of a linear fade. So, the setbrightness would not set the time itself, but an index of that table.
PASM part then would not use that value directly, but do a lookup in that table and use what it finds there.
2.
rdlong could be done after the waitpeq. As a half periode is 1/120 second the value might have been changed between rdlong and end of wait by setbrightness. Ok ... wrong value would only be used for a half-periode, but you started with this 'more accurate'-thing ;o)
3.
Instead of adding pulse_time like you did it, you could use
waitcnt time, pulse_time
instead of
waitcnt time, 0
for the first waitcnt.
Then you don't need the second mov time, cnt and add time, pulse_time.
... just wanted to mention this for those who learn PASM.
2. Yes good idea (but it wasn't me who started the accuracy thing)
3. Nice optimisation, this thing will probably work for Mhz dimmer circuits [noparse]:)[/noparse]
Graham
Please check, I don't even have a prop with me.
Of course the look up table could be huge and should have proper values in it.
Graham
If cross_pin and trisac_pin are hardcoded anyway, it makes no sense to calculate the masks during runtime. And even if the values are not hardcoded you can get rid of mov cross_mask, #1 when initializing cross_mask with 1. Saves 2 longs of our valuable COG-RAM in this case.
In case you initialize all values, you save 4 longs.
;o)
[noparse];)[/noparse]
Post Edited (Graham Stabler) : 11/25/2009 8:49:02 AM GMT
Maybe someone else can now find a nice set of values for the lookup table and we have a nice driver to put into the Object Exchange.