Closed brunoudi closed 7 years ago
What do you mean by "stand-by"? Are you trying to use this in low power mode?
This is where you set up the timer. Passing in a 0 in the second parameter is supposed to tell it to not auto-rearm (you can verify in the hw_timer source since it does not pass in 'FRC1_AUTO_LOAD'). hw_timer_init(NMI_SOURCE, 0); hw_timer_set_func(dimTimerISR);
I'm not showing any odd issues with the timer on my ESP12.
You could have issues with any delays in the interrupt. I've seen issues where the ESP crashes or the wifi stack crashes (no wifi until reboot). 20us is pretty small so there may not be any issues. You'll have to test and see.
I'm not trying to use it in low power mode, when I said the NMI timer in 'stand by' mode I was referring that is not armed (wich happens in the ZC interrupt). For test this you can comment out the attach Interrupt for the ZC, and put a Serial.print in the NMI interrupt handler, you will see the Serial.print happens every 1.677.722 uS precisally.
My point is, considering the ZC handler is what arm the NMI timer, this not happens when brightness is 255 or the lamp is OFF (curBrightness = 0). Considering the NMI is handled 'automatically' every ~1,6 seconds, in those conditions the lamp will have a delay to Power On or Off. For example, 'if curBrightness = 255' the Power On/Off will delay ~1,6 seconds (worst case), and 'if (curBrightness < 255 && curBrightness > 0)' the turnOff happens instantally.
I found a better solution, than the suggestion in my first message:
void dimTimerISR() {
if (fade == 1) {
if (curBrightness > tarBrightness || (state == 0 && curBrightness > 0)) {
--curBrightness;
}
else if (curBrightness < tarBrightness && state == 1 && curBrightness < 255) {
++curBrightness;
}
}
else {
if (state == 1) {
curBrightness = tarBrightness;
}
else {
curBrightness = 0;
}
}
if (curBrightness == 0) {
state = 0;
digitalWrite(outPin, 0);
}
else if (curBrightness == 255) {
state = 1;
digitalWrite(outPin, 1);
}
else {
digitalWrite(outPin, 1);
delayMicroseconds(20); //included
digitalWrite(outPin, LOW); //included
}
zcState = 0;
}
void zcDetectISR() {
if (zcState == 0) {
zcState = 1;
if (curBrightness < 255 && curBrightness > 0) {
//digitalWrite(outPin, 0);
uint32_t dimDelay = 25 * (255 - curBrightness) + 700;
hw_timer_arm(dimDelay);
}
else {
hw_timer_arm(3000);
}
}
}
1) When curBrightness = 0 or 255, I arm the NMI timer with 3000. This value is because the ZC detection can happens due some noise and 3ms will disconsider it.
2) When dimmering, I believe that is because my components, the ZC is detected really near the real ZC (Vin < 5 V). So the 'turn off' of the outPin not happens in the same semicicle. The lamp was always in full bright. To solve that, in the NMI timer handler I change the outPin 'turn on' to just a pulse of 20us.
I was able to verify this behavior. I've added your updates to my code and haven't seen any side effects so they should be in the next push I do.
Thanks.
I implemented a dimmer based on the NMI timer, but I got a point:
In 'stand by', the NMI timer handle the interrupt repeatedly by intervals precisally of 1.677.722 uS (or ~1,67 s). This automatically interrupt can be disabled or changed the time interval?
When I implemented the NMI timer I got a delay on the turn ON and OFF, and studying the code I saw it happens because the change of state is handled by the "dimTimerISR" and not by the "zcDetectISR". To solve that I changed my code to this:
I actually dont know if it is OK use the 'delayMicroseconds(20);' inside the NMI handler. And I can't think a better algorithm to get the dimmer working without the delay to power ON and OFF. Any ideas or comments?