Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doesn't work with Robotdyn AC Dimmer #11

Closed
JAndrassy opened this issue Jun 1, 2019 · 22 comments
Closed

doesn't work with Robotdyn AC Dimmer #11

JAndrassy opened this issue Jun 1, 2019 · 22 comments

Comments

@JAndrassy
Copy link

JAndrassy commented Jun 1, 2019

With Robotdyn AC Dimmer (schematics) and basic_example.ino the light is full on and sometimes flickers.
I test with Arduino Nano.
I added some debug prints in ISR(TIMER1_CAPT_vect) after last_icr = ICR1:

  Serial.print(micros());
  Serial.print("\t");
  Serial.print(last_icr);
  Serial.print("\t");
  Serial.println(TriacDimmer::detail::period);

output is

1408	2793	2793
11420	22824	20031
12168	22824	0
21440	42855	20031
31460	62905	20050
32208	62905	0
40448	17381	20012
50464	37423	20042
51212	37423	0
60476	57439	20016
70500	11952	20049
80512	31984	20032
81260	31984	0
90540	52027	20043

sorry I rewrote this issue twice until I debugged the problem.
the problem is, there are some phantom zero crossings resulting in period 0 and brightness is calculated with this value

@JAndrassy
Copy link
Author

JAndrassy commented Jun 1, 2019

I added

ISR(TIMER1_CAPT_vect){
  static uint16_t last_icr = 0;
  if (ICR1 == last_icr)
    return;

now the compare match interrupt fires on time, but the light still doesn't dimm.

I left the interrupt on for the second match to print the micros(), and it run and the time is somehow OK (not 20 half-micros, but I had Serial.print there)

ZC	299504
CM	301004
CM	301332 
ZC	309512
CM	311116
CM	311444 

this doesn't look right in compare match interrupt

TCCR1A |= _BV(COM1A1); //clear OC1x on compare match

TCCR1A is set in capture interrupt as

TCCR1A |= _BV(COM1A0) | _BV(COM1A1) | _BV(COM1B0) | _BV(COM1B1); //set OC1x on compare match

with

  TCCR1A &=~ _BV(COM1A0); //clear OC1x on compare match

it started fading but randomly gets out of sync and flickers.
it is better with

	TCCR1A &=~ (_BV(COM1A0) | _BV(COM1B0));
	TCCR1C = _BV(FOC1A) | _BV(FOC1B); //ensure outputs are properly cleared

in capture interrupt (clear COM1A0 instead of COM1A1)
but it still flickers on fade-in

I give up with your library. Additionally I use pin 10 as slave select for Ethernet shield and your library doesn't have an option to use only one pin of Timer1.

@AJMansfield
Copy link
Owner

AJMansfield commented Jun 2, 2019

there are some phantom zero crossings

Probably the easiest solution is to add a small RC filter to debounce the pin. Put a small 220 Ω resistor between the zero crossing pin between Sync and arduino pin 8, and wire a 1 µF capacitor from pin 8 to ground; that should be enough to fix the issue entirely without introducing too large of a timing error. These values were determined with this handy debounce calculator and give a debounce time of 142 µs (a little over 1% of the half-wave period), but if you are able to measure the debounce time with an oscilloscope you can calculate your own component values if you want the timing to be tighter than that.


Note that your debug code may actually be causing additional problems.
On the default 9600 baud, 8 bits/char and 2 bits dead time, you can only print 960 characters per second or only 9.6 per 50Hz half-wave. Attempting to write more characters than that on average will result in the serial print buffer filling up, and once full any subsequent Serial.print or println calls will block until there's enough space in the buffer, preventing the interrupt from completing on time and blocking the other interrupts from firing. The 60476\t57439\t20016\r\n is 19 characters, well over the limit.

Try switching to a higher baud rate (like 115200) to give yourself some more breathing room. Even at 115200 you still only get 115 characters per half-wave, but as long as you're not using the serial for anything else alongside it that should be enough to prevent the debug code from interfering with the interrupt timing.


this doesn't look right in compare match interrupt

After looking at it I believe you are in fact correct. This is actually a pretty huge error, I have no idea why it even works at all for me. I'll fix this ASAP.

TriacDimmer.cpp:100 should read:

	TCCR1A &=~ _BV(COM1A0); //clear OC1x on compare match

and likewise TriacDimmer.cpp:112 should read:

	TCCR1A &=~ _BV(COM1B0); //clear OC1x on compare match

I've split this off as issue #12. If you want to PR this yourself to take credit for the fix I'd be glad to accept it, although I may get to it first.


your library doesn't have an option to use only one pin of Timer1.

Actually that's a good suggestion. I'll take a look at updating the library to support using only a single pin.

I've split this off as issue #13.

@JAndrassy
Copy link
Author

and TCCR1A &=~ (_BV(COM1A1) | _BV(COM1B1));?

@AJMansfield
Copy link
Owner

AJMansfield commented Jun 2, 2019

and TCCR1A &=~ (_BV(COM1A1) | _BV(COM1B1));?

Thanks, you're correct there too. The changes are in PR #14. Can you comment there if those changes work before I merge it to master?

@AJMansfield
Copy link
Owner

but it still flickers on fade-in

Are you using it with an LED or CF bulb? Triac dimmers don't work with those kinds of loads, they only really work with resistive loads like incandescent bulbs or heaters.

Otherwise, the instability is likely due to the fact that the triac isn't capable of holding itself on for a small portion of the phase near 0 volts, and if the 20 µs pulse occurs in that window it won't latch on.

There is a solution for this, it's just not implemented yet. Give me a bit and I'll add it.

I've split this issue off as issue #15.

@AJMansfield
Copy link
Owner

Ok, I've just merged the fixes for #12 and #15 (PRs #14 and #16) into the development branch. Can you test whether these changes fix the issue for you and let me know so I can make a new release and push the updated library to the arduino library list?

@JAndrassy
Copy link
Author

JAndrassy commented Jun 3, 2019

I use incandescent light bulb for test. In the project I control a heater.
With the first bug the triac gate stayed on. in capture interrupt the pin was cleared. On my dimmer it was too late. On yours maybe not. if you fix the first bug, the second did show up on my dimmer toggling the pin to set in capture interrupt. but it maybe too early on your dimmer and the triac doesn't latch

@AJMansfield
Copy link
Owner

Can you test if the version in the development branch works? I've added the fixes for the issues with the compare match behavior and changed the behavior so an early pulse stays high until a minimum amount of time from the zero cross (enough to ensure triggering but without saturating the gate).

@JAndrassy
Copy link
Author

volatile uint16_t TriacDimmer::detail::min_trigger; is missing in cpp
fade-out is nice, but it still flickers on fade-in

@AJMansfield
Copy link
Owner

Oh you're right; I've added the volatile uint16_t TriacDimmer::detail::min_trigger; bit to dev.

Can you elaborate on the flickering you're seeing? I don't actually have access to real hardware to test against at the moment, so I'm going to need you to describe what you're seeing in more detail.

What dimmer values result in flickering? And what do you mean by "fade-out is nice, but it still flickers on fade-in"? That makes it sound like the flickering is only happening while gradually increasing the dimmer value, but that decreasing it - even through the same dimming percentage - doesn't cause flickering, which seems unlikely (and if that is the case, I definately need to see the code you're using that causes this).

Do you have an oscilloscope you can use to probe the circuit?

@JAndrassy
Copy link
Author

JAndrassy commented Jun 4, 2019

the brightness increases, but on every change it flickers.

@AJMansfield
Copy link
Owner

Huh. I think what's happening is that the ch_X_dn is being updated to a value that's smaller than the current OCR1x, resulting in the system generating a much shorter pulse than required.
Probably the best solution is to add another variable to buffer the ch_X_dn values that's only updated in the ICR interrupt, give me a bit to add that.

@AJMansfield
Copy link
Owner

AJMansfield commented Jun 4, 2019

Ok, just added code to the dev branch that should buffer the negative edge offset to prevent this flickering. (Commit 8a1be9c)

Can you test it and report if this change fixes the flickering issue?

@AJMansfield
Copy link
Owner

I also just made another small change in dev to eliminate one other possible but unlikely source of issues due to non-atomic writes to the variables that control ISR behavior.

@AJMansfield
Copy link
Owner

@JAndrassy Does the code in the dev branch now work correctly on your hardware?

@JAndrassy
Copy link
Author

JAndrassy commented Jun 4, 2019

you should really compile before commit ch_B_dn_buf = TriacDimmer::detail::ch_b_dn (lower case b)

now the fading is smooth. brightness values less then 0.02 don't work. the light is on and flickers. at 0.0 too

@AJMansfield
Copy link
Owner

You're right, I should be compiling this before committing; the reason I haven't is mostly that I've been doing this from my phone. I'm back home now though so I should be able to work faster.

I'll work on implementing the channel disable functionality and minimum brightness threshold.

@AJMansfield
Copy link
Owner

Ok, I've implemented the channel disable functionality (by default each channel is disabled until you enable it by setting its brightness) and added parameters for the upper and lower thresholds outside which the pin will be either always on or always off.
The thresholds are configurable via the on_thresh and off_thresh parameters to TriacDimmer::begin(); by default on_thresh is disabled since it's not normally necessary, and off_thresh is set to 0.01. I've also added directions to the readme for how to adjust the parameters to eliminate flickering.

There's also been a handful of other tweaks to the code that should make it just a little bit more stable and/or performant (ensuring both edge offsets for a channel get updated atomically, basing the falling edge in the compare interrupts on last_icr in case the input capture is somehow retriggered, etc.).

@JAndrassy
Copy link
Author

now it fades nice (with off_thresh 0.03) . triac is on pin 9 and a 5 mm LED blinks on pin 10.
time for a release?

@AJMansfield
Copy link
Owner

Yes, yes it is. Thanks for the help finding and solving these issues.

@AJMansfield
Copy link
Owner

There we are, just packaged and released v1.1.0 incorporating all of the changes.

Thanks again for bringing up these issues and helping fix them.

@JAndrassy
Copy link
Author

5 minutes after release the new version is in Library Manager. thank you for your effort

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants