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

Issues with Zero Cross Detection #18949

Closed
5 tasks
cacengineering opened this issue Jun 24, 2023 · 56 comments · Fixed by #19211
Closed
5 tasks

Issues with Zero Cross Detection #18949

cacengineering opened this issue Jun 24, 2023 · 56 comments · Fixed by #19211

Comments

@cacengineering
Copy link

PROBLEM DESCRIPTION

See attached screenshots showing input AC waveform (GPIO34 set as counter4) and pwm out pin GPIO25 (tried as both PWM and PWM_i) - fundamentally testing the PWM feature with option99 set and PWM frequency set at 100Hz, zero crossing 50Hz rectified mains (100Hz) via optocoupler on GPIO34). (Zero crossing now seems to be mostly working - huge improvement).
Issues are:

  1. Screenshot Stutter,2 - The zero crossing detector is not catching every zero crossing. Not sure if we can rather set a rising or falling edge.The LED connected in lieu of thyrister is not smooth - but has an erratic flicker. Also not sure if triggering at zero or peak crossing ?

  2. PWM waveform - this is a pulse of around 5 - 10us - was expecting a PWM waveform with length set by the pwm slider (but the trigger is useable).

  3. Screenshots PWM trigger point - The trigger point should follow the setting of the slider allowing a full waveform to be created by triggering a thyristor or similar - I have tested with the slider on low (maybe 5%), middle and high (maybe 95%). The low setting trigger point would give full power, the middle point seems to be at random and the high seems to be at midpoint of the waveform. This would only give at best 50% power setting - not 100%.

REQUESTED INFORMATION

Make sure your have performed every step and checked the applicable boxes before submitting your issue. Thank you!

  • Read the Contributing Guide and Policy and the Code of Conduct
  • [x ] Searched the problem in issues
  • [x ] Searched the problem in discussions
  • [x ] Searched the problem in the docs
  • Searched the problem in the chat
  • [x ] Device used (e.g., Sonoff Basic): ESP32-WROOM-32D DEVKIT
  • Tasmota binary firmware version number used: 12.5.0.4 on ESP32_____
    • [ X] Pre-compiled
    • Self-compiled
  • [x ] Flashing tools used: Tasmota Web installer
  • [x ] Provide the output of command: Backlog Template; Module; GPIO 255:
  Configuration output here: (not sure if you wanted me to run the command above?)
09:28:38.844 CMD: Backlog Template; Module; GPIO 255
09:28:38.889 MQT: _Gr/Load-ctl/Tas_Testint_3EA07C/stat/RESULT = {"NAME":"Load-ctl","GPIO":[0,0,0,0,0,0,0,0,224,4896,225,4897,0,0,0,0,0,0,0,0,0,416,0,0,0,0,0,0,0,288,355,4706,4740,0,0,4707],"FLAG":0,"BASE":1}
09:28:39.096 MQT: 2_Gr/Load-ctl/Tas_Testint_3EA07C/stat/RESULT = {"Module":{"0":"Load-ctl"}}
09:28:39.325 MQT: Gr/Load-ctl/Tas_Testint_3EA07C/stat/RESULT = {"GPIO0":{"0":"None"},"GPIO1":{"0":"None"},"GPIO2":{"0":"None"},"GPIO3":{"0":"None"},"GPIO4":{"0":"None"},"GPIO5":{"0":"None"},"GPIO6":{"0":"None"},"GPIO7":{"0":"None"},"GPIO8":{"0":"None"},"GPIO9":{"0":"None"},"GPIO10":{"0":"None"},"GPIO11":{"0":"None"},"GPIO12":{"224":"Relay1"},"GPIO13":{"4896":"ADC CT Power1"},"GPIO14":{"225":"Relay2"},"GPIO15":{"4897":"ADC CT Power2"},"GPIO16":{"0":"None"},"GPIO17":{"0":"None"},"GPIO18":{"0":"None"},"GPIO19":{"0":"None"},"GPIO20":{"0":"None"},"GPIO21":{"0":"None"},"GPIO22":{"0":"None"},"GPIO23":{"0":"None"},"GPIO24":{"0":"None"},"GPIO25":{"416":"PWM1"},"GPIO26":{"0":"None"},"GPIO27":{"0":"None"},"GPIO32":{"0":"None"},"GPIO33":{"288":"Led1"},"GPIO34":{"355":"Counter4"},"GPIO35":{"4706":"ADC Input3"},"GPIO36":{"4740":"ADC Temp5"},"GPIO37":{"0":"None"},"GPIO38":{"0":"None"},"GPIO39":{"4707":"ADC Input4"}}
  • [x ] If using rules, provide the output of this command: Backlog Rule1; Rule2; Rule3:
    None
    Rules output here:
- [x ] Provide the output of this command: `Status 0`:
```lua
  STATUS 0 output here:
Status 0
(edited out detail)
09:30:31.588 MQT: ----Gr/Load-ctl/Tas_Testint_3EA07C/stat/STATUS = {"Status":{"Module":0,"DeviceName":"Tasmota","FriendlyName":["Tasmota","Tasmota2","Tasmota3"],"Topic":"Tas_Testint_3EA07C","ButtonTopic":"0","Power":7,"PowerOnState":3,"LedState":1,"LedMask":"FFFF","SaveData":1,"SaveState":1,"SwitchTopic":"0","SwitchMode":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"ButtonRetain":0,"SwitchRetain":0,"SensorRetain":0,"PowerRetain":0,"InfoRetain":0,"StateRetain":0,"StatusRetain":0}}
09:30:31.603 MQT: -----_Gr/Load-ctl/Tas_Testint_3EA07C/stat/STATUS1 = {"StatusPRM":{"Baudrate":115200,"SerialConfig":"8N1","GroupTopic":"tasmotas","OtaUrl":"http://ota.tasmota.com/tasmota32/release/tasmota32.bin","RestartReason":"Vbat power on reset","Uptime":"0T00:30:50","StartupUTC":"2023-06-23T22:59:41","Sleep":50,"CfgHolder":4617,"BootCount":19,"BCResetTime":"2023-06-13T10:36:03","SaveCount":116}}
09:30:31.614 MQT:-----_Gr/Load-ctl/Tas_Testint_3EA07C/stat/STATUS2 = {"StatusFWR":{"Version":"12.5.0.4(tasmota32)","BuildDateTime":"2023-06-22T21:59:17","Core":"2_0_10","SDK":"4.4.5.230614","CpuFrequency":160,"Hardware":"ESP32-D0WD-V3 rev.3","CR":"567/699"}}
09:30:31.624 MQT:---------- _Gr/Load-ctl/Tas_Testint_3EA07C/stat/STATUS3 = {"StatusLOG":{"SerialLog":2,"WebLog":2,"MqttLog":0,"SysLog":0,"LogHost":"","LogPort":514,"SSId":["xxx",""],"TelePeriod":15,"Resolution":"558180C0","SetOption":["00008009","2805C80001000600003C5A0A192800000000","20000080","00026000","00004000","00000001"]}}
09:30:31.658 MQT: _Gr/Load-ctl/Tas_Testint_3EA07C/stat/STATUS4 = {"StatusMEM":{"ProgramSize":1532,"Free":1347,"Heap":112,"StackLowMark":3,"PsrMax":0,"PsrFree":0,"ProgramFlashSize":4096,"FlashSize":4096,"FlashChipId":"16405E","FlashFrequency":40,"FlashMode":"DIO","Features":["00000809","9F9AD7CF","0015A001","B7F7BFCF","05DA9BC0","E0360DC7","480840D2","20200000","D4BC482D","000A80B1"],"Drivers":"1,2,3,4,5,7,8,9,10,11,12,14,16,17,20,21,24,26,27,29,34,35,38,50,52,59,60,62,63,66,67,68,82,86,87,88","Sensors":"1,2,3,5,6,7,8,9,10,11,12,13,14,15,17,18,19,20,21,22,26,31,34,37,39,40,42,43,45,51,52,55,56,58,59,64,66,67,74,85,92,95,98,103,105,127","I2CDriver":"7,8,9,10,11,12,13,14,15,17,18,20,24,29,31,36,41,42,44,46,48,58,62,65,69,76,77"}}
09:30:31.675 MQT: _Gr/Load-ctl/Tas_Testint_3EA07C/stat/STATUS5 = {"StatusNET":{"Hostname":"Tas-Testint-3EA07C-0124","IPAddress":"192.168.X.X","Gateway":"192.168.X.X","Subnetmask":"255.255.255.0","DNSServer1":"192.168.X.X","DNSServer2":"0.0.0.0","Mac":"40:22:D8:3E:x.x,"IP6Global":"","IP6Local":"fecxx07c","Ethernet":{"Hostname":"","IPAddress":"0.0.0.0","Gateway":"0.0.0.0","Subnetmask":"0.0.0.0","DNSServer1":"192.168.x.x","DNSServer2":"0.0.0.0","Mac":"00:00:00:00:00:00","IP6Global":"","IP6Local":""},"Webserver":2,"HTTP_API":1,"WifiConfig":4,"WifiPower":17.0}}
09:30:31.691 MQT: _Gr/Load-ctl/Tas_Testint_3EA07C/stat/STATUS6 = {"StatusMQT":{"MqttHost":"x.x.io","MqttPort":1883,"MqttClientMask":"xxxx-DVES_%06X","MqttClient":"xxxx-DVES_3EA07C","MqttUser":"DVES_USER","MqttCount":1,"MAX_PACKET_SIZE":1200,"KEEPALIVE":30,"SOCKET_TIMEOUT":4}}
09:30:31.704 MQT: _Gr/Load-ctl/Tas_Testint_3EA07C/stat/STATUS7 = {"StatusTIM":{"UTC":"2023-06-23T23:30:31","Local":"2023-06-24T09:30:31","StartDST":"2023-10-01T02:00:00","EndDST":"2023-04-02T03:00:00","Timezone":99,"Sunrise":"13:47","Sunset":"05:57"}}
09:30:31.868 MQT: _Gr/Load-ctl/Tas_Testint_3EA07C/stat/STATUS10 = {"StatusSNS":{"Time":"2023-06-24T09:30:31","COUNTER":{"C4":1184},"ANALOG":{"CTEnergy1":{"Energy":0.001,"Power":0,"Voltage":230,"Current":0.000},"CTEnergy2":{"Energy":0.000,"Power":0,"Voltage":230,"Current":0.000},"A3":0,"A4":449,"Temperature5":52.3},"ESP32":{"Temperature":53.3},"TempUnit":"C"}}
09:30:31.888 MQT: _Gr/Load-ctl/Tas_Testint_3EA07C/stat/STATUS11 = {"StatusSTS":{"Time":"2023-06-24T09:30:31","Uptime":"0T00:30:50","UptimeSec":1850,"Heap":113,"SleepMode":"Dynamic","Sleep":10,"LoadAvg":111,"MqttCount":1,"Berry":{"HeapUsed":3,"Objects":39},"POWER1":"ON","POWER2":"ON","POWER3":"ON","Dimmer":97,"Fade":"OFF","Speed":1,"LedTable":"ON","Wifi":{"AP":1,"SSId":"xxxx","BSSId":"EC:BE:DD:4A:x:x","Channel":11,"Mode":"11n","RSSI":72,"Signal":-64,"LinkCount":1,"Downtime":"0T00:00:03"}}}
09:30:34.911 MQT: _Gr/Load-ctl/Tas_Testint_3EA07C/tele/STATE = {"Time":"2023-06-24T09:30:34","Uptime":"0T00:30:53","UptimeSec":1853,"Heap":119,"SleepMode":"Dynamic","Sleep":10,"LoadAvg":167,"MqttCount":1,"Berry":{"HeapUsed":3,"Objects":39},"POWER1":"ON","POWER2":"ON","POWER3":"ON","Dimmer":97,"Fade":"OFF","Speed":1,"LedTable":"ON","Wifi":{"AP":1,"SSId":"xxx","BSSId":"EC:BE:DD:4A:x.x","Channel":11,"Mode":"11n","RSSI":74,"Signal":-63,"LinkCount":1,"Downtime":"0T00:00:03"}}
09:30:35.075 MQT: _Gr/Load-ctl/Tas_Testint_3EA07C/tele/SENSOR = {"Time":"2023-06-24T09:30:34","COUNTER":{"C4":1512},"ANALOG":{"CTEnergy1":{"Energy":0.001,"Power":0,"Voltage":230,"Current":0.000},"CTEnergy2":{"Energy":0.000,"Power":0,"Voltage":230,"Current":0.000},"A3":0,"A4":261,"Temperature5":138.3},"ESP32":{"Temperature":53.3},"TempUnit":"C"}

  • Set weblog to 4 and then, when you experience your issue, provide the output of the Console log:
  Console output here:
Ongoing issue

TO REPRODUCE

Steps to reproduce the behavior:
Ongoing issue

EXPECTED BEHAVIOUR

A clear and concise description of what you expected to happen.

  1. It is expected that the zero crossing detector would trigger consistently for every crossing. Might be noise on the waveform (top is a bit saturated) - but this is on a test bench and real implementation will be noisier. Can we do a rising or falling edge slightly out of the noise ? Falling might be better as allows a short delay before triggering of the next cycle for 100%.

  2. It is expected the PWM waveform will trigger consistently at a specific crossing point.

  3. It was expected that we get a pulse of a certain width from the PWM - but not a serious issue as all we really need is a correctly positioned pulse to trigger power circuitry which switches off at Zero crossing.

  4. Ideally at full power the pulse will start at the zero crossing, and at lower settings start later in the waveform reducing the on time.

  5. Very Low priority - Incidental to this exercise we have noticed the mains frequency swings a fair bit compared to the 100Hz of the PWM. If we implement with fixed triggering delays on variable freq mains the power out will vary. Ideally the triggering delays should be tied to the mains frequency - or % of time between zero crossings which should be accurate enough. Will also allow for auto detection of 50 or 60Hz mains.

SCREENSHOTS

If applicable, add screenshots to help explain your problem.
Two sets of screen shots. Note the scope is triggering on the rectified mains input - rising edge at about 1.7V. Any less and the scope battles to hold the trigger point.

Stutter - image
Stutter2 -
image

Triggering point
Low -
image
Medium -
image
High -
image

ADDITIONAL CONTEXT

Add any other context about the problem here.
We are using MQTT extensively - and are resetting the counter with every MQtt report - 15secs.

I am not really a programmer and only know enough to be dangerous ... but very happy to further test if you need testing done.

(Please, remember to close the issue when the problem has been addressed)

@cacengineering
Copy link
Author

I have inverted the scope trace for the trigger channel - into the ZC detector. This provides a better picture but also implies the trigger is triggering on peak crossing, not zero crossing. The below, with inverted trace would be ideal.

At low power - ideal as triggers in late part of cycle
image

At full power - ideal as triggers at beginning part of cycle.
image

@Jason2866 Jason2866 changed the title Various issues with PWM Issues with Zero Cross Detection Jun 24, 2023
@ehsan342
Copy link

Answer 1:
The input signal is not crossing zero cleanly. This could be caused by noise or distortion in the signal.
The zero crossing detector is not being triggered at the right time. This could be due to the wrong threshold voltage being used, or the detector could be too slow to respond to the signal.
The LED is not being driven properly. This could be due to a faulty LED, or the wrong resistor being used to limit the current.
Answer 2:
This is likely due to a setting in the software that is not being properly configured.
Answer 3:
1; Verify PWM Configuration: Double-check the configuration settings for the PWM module in Tasmota. Ensure that the correct GPIO pin is assigned for PWM output and that the frequency and other parameters are set correctly.
2:Adjust PWM Frequency: Experiment with different PWM frequencies to see if it affects the trigger point behavior. Sometimes, certain frequencies may result in unexpected trigger points. Try increasing or decreasing the PWM frequency to see if it aligns better with the desired trigger point.
3:Check Hardware Compatibility: Ensure that the GPIO pin you are using for PWM output supports PWM functionality and is compatible with the Tasmota firmware. Some GPIO pins may have limitations or restrictions on their PWM capabilities, so verifying compatibility is important.
4:Test Different Trigger Points: Instead of relying solely on the slider, try explicitly setting the trigger point using a specific value or calculation. This can be done by directly assigning a specific duty cycle value to the PWM output rather than relying on the slider.
5:Consider External Circuitry: If the above steps don't resolve the issue, you may need to consider using external circuitry, such as a dedicated PWM controller or additional components, to achieve precise trigger points and better control over the waveform.

@cacengineering
Copy link
Author

The front end has been redesigned with us now using two optocouplers - the one to generate a sharp Zero crossing pulse and the other to create a "cleaner" sinewave for voltage measurement. Mains power will however always be dirty.

There is no external ZC detector - the ESP32 Wroom is "meant to be" performing the job of detection using its internal ZC detection. This is what we are battling with.

"wrong threshold voltage" - We did not realise this was changeable - How does one change the threshold ? This would help. Not found anything in documentation.

"correct GPIO pin is assigned" - GPIO25 is used as it also has DAC capability- was seen as best option. Is there a better option ?

"GPIO pin you are using for PWM output" - Using GPIO34 - ADC GPIO. Any suggestions as to better one to use.

@ehsan342
Copy link

The ZC detector can be used to synchronize other operations with the mains voltage, such as switching on a load or taking a voltage measurement. The threshold voltage for the ZC detector can be changed by setting the ZC_THRESHOLD value in the user_config_override.h. The default value is 1.5V, but this can be changed to a higher or lower value depending on the needs of the application. There is no universal minimum or maximum value that applies to all cases. The GPIO pin that is assigned to the ZC detector can also be changed by setting the ZC_GPIO value in the console. The default pin is GPIO25, but this can be changed to any other GPIO pin that is available.
add this line into {user_config_override.h} #define ZC_THRESHOLD 1
Modify the value to your desired threshold voltage. For example, #define ZC_THRESHOLD 0.5 for a threshold of 0.5V.
check the screenshot
2023-06-28

  1. The ZC detector is not very sensitive, so it is important to use a clean mains voltage signal. If the signal is too noisy, the ZC detector may not be able to detect the zero crossing point reliably.
  2. The ZC detector can be used to synchronize other operations with the mains voltage, such as switching on a load or taking a voltage measurement. However, it is important to note that the ZC detector is not very accurate. The accuracy of the ZC detector is typically around 10-20 milliseconds.

The GPIO pin that is used for PWM output can also be changed in the console . The default pin is GPIO34, but this can be changed to any other GPIO pin that is available.

@cacengineering
Copy link
Author

Thanks - I have tried various options for ZC_GPIO - Set ZC_GPIO etc. All get unknown command error.

I am playing with the User_Config_Override file and will report back if I can use it to change the detection voltage. My feeling is the ZC voltage is set too high - which is why it is triggering around 50% of the cycle. Ideally it should also be on falling edge.

A full 50Hz wave has a period of 20ms. Do you mean microseconds ?

The modified front end circuitry is producing a much sharper ZC trigger and the device is now more stable. Also updated to 13.0.0.

@stefanbode
Copy link
Contributor

Let me bring some light into the discussion as I maintain this driver currently. First please do not add rules or other high CPU loads on the ESP8266 that is doing the dimmer. If you so there will be flickering because it just misses. The Zero-Cross signal coming to counter4 is an input signal. If this is not good or have problems than you need to change your hardware. There is nothing TASMOTA can do. I have good experience with the one shown in the documentation. The pulse on the TRIAC should have a defined length an is shifted a constant time away from the last zero-cross event. The lower the DIMMER value is the more far away it the TRIAC pulse. The PWMFREQUENCY and other stuff is not needed anymore. In the most recent development version the dimmer is using high frequency interrupts.

@stefanbode
Copy link
Contributor

Explanation: Why is it only a pulse and not a ON signal until the next zero-Cross?
The TRIACS typically use just need a pulse to fire and then stay ON until the next zero-cross. There is no need to keep the PULSE ON until the end. Doing this creates a problem at the end. If you do not go to OFF before the zerocross then then the complete next half sine wave will be ON. As said you can only switch a TRIAC ON. You cannot switch it OFF. This must be done though the total lost of voltage during the zero-cross.

@stefanbode
Copy link
Contributor

There are some debug messages regarding missed zero.cross events in the xdrv_68_zerocrossDimmer.ino. Line 223
AddLog(LOG_LEVEL_DEBUG, PSTR("ZCD: ZeroEnable %d -> %d, Alarm %d, intr: %ld, cycle time: %ld µs, missed zc %ld"),
give some nice debug to the logs if zc events where missed. This was always 0 at my desk.

@ehsan342
Copy link

Let me bring some light into the discussion as I maintain this driver currently. First please do not add rules or other high CPU loads on the ESP8266 that is doing the dimmer. If you so there will be flickering because it just misses. The Zero-Cross signal coming to counter4 is an input signal. If this is not good or have problems than you need to change your hardware. There is nothing TASMOTA can do. I have good experience with the one shown in the documentation. The pulse on the TRIAC should have a defined length an is shifted a constant time away from the last zero-cross event. The lower the DIMMER value is the more far away it the TRIAC pulse. The PWMFREQUENCY and other stuff is not needed anymore. In the most recent development version the dimmer is using high frequency interrupts.

we are using esp32

@stefanbode
Copy link
Contributor

It's the same with esp32. Same driver. Pls share some logs regarding the flickering. This should not be there.

@Jason2866 Jason2866 added the awaiting feedback Action - Waiting for response or more information label Jul 2, 2023
@cacengineering
Copy link
Author

Stefan - Firstly thanks for the driver. See it has come on in leaps and bounds over the last few months. To clarify:

  1. We are using ESP32 s3 based dev board - so while pushing processing, should still have enough head room for the complex operations we are attempting to run. Will however keep an eye on that.
  2. Ideally the pulse to the triac should be start'able at the Zero cross however we have used a "boost" work-around until the ZC pulse matures a bit more.
  3. I would love to be able to, in order of preference: a) Change the trigger point of the ZC, and even have it falling edge. b) Have an ability to increase the duration of the pulse - but understand the concerns that it will overlap the ZC for low settings. Will play with this in the hardware a bit.

Some further background - this is a device being built to comply with Australian certifications and is pretty complex. The triac is only one small component. Hope the community likes the outcome in the end !. Thanks once again.

@stefanbode
Copy link
Contributor

  1. agree should work easily
  2. if you start the pulse right after the zero-cross you get 100% load because the triac will not switch off even if you the the pulse to LOW somewhere
  3. a) you can change the trigger point by changing the counter definition. This can be configured on rising and falling edge. Search for CounterDebounceLow in the docs.
    b) you can change the duration with in line 7 of the driver: static const uint8_t GATE_ENABLE_TIME = 100; this is 100microseconds. You have to compile your own version

What you want to do is a falling edge dimmer. With a config option I would trigger the pulse just in the ZERO-CROSS detection. This is the fastet way to set it HIGH. The use the current function to set it LOW instead of HIGH. I assume these will be not more than 5 lines of code and a config option. If it is a compiler option then super easy, if you want to make a variable. we have to reserve a byte in the config holder to store the definition: rising/falling edge and a small function to change it.

@cacengineering
Copy link
Author

Thanks. The pulse is however starting too late after the zero cross. See screenshot. There is at least a 2ms delay with dimmer 99 (100 kills the pwm pulse). At 50Hz this is a material amount of power we are not able to harness - but we do have a work around so not critical now.

image

The three counterdebounce options look interesting but I need to get my head around them!. They seem to set a validation period after an edge change.

Not too keen on straying from standard Tasmota build - was thinking of using override. Any guidance appreciated! Off the top of your head - would a ZC trigger for a rule be AC#pulse ?

@stefanbode
Copy link
Contributor

image

I used the ZCDimmerSet command to get good controll over the trigger. Attached an image with 98%. The short yellow pulse from the PWM is still on the falling edge of the ZC-Pulse (blue). This is a 100% on. If going to 99% flickering starts because the pulse is to early. I need a voltage divider to connect to mains and also show the sinus. Maybe this evening.
With 1% this looks this way:
image

On a 10% the weblog4 shows
image
that about 7.7ms after ZC the trigger fire and after 7.8ms it goes off. The cycle time is about 10ms. This vary continuously because mains frequency is not stable by nature.

@stefanbode
Copy link
Contributor

I do not know why, but my testbench does not work with "dimmer 10" "dimmer 20" and so on. I got reboots and odd behaviour. There seems something wrong and different.
ZCDimmerSet 10 instead is working as it should do

@ehsan342
Copy link

ehsan342 commented Jul 5, 2023

Thanks. The pulse is however starting too late after the zero cross. See screenshot. There is at least a 2ms delay with dimmer 99 (100 kills the pwm pulse). At 50Hz this is a material amount of power we are not able to harness - but we do have a work around so not critical now.

image

The three counterdebounce options look interesting but I need to get my head around them!. They seem to set a validation period after an edge change.

Not too keen on straying from standard Tasmota build - was thinking of using override. Any guidance appreciated! Off the top of your head - would a ZC trigger for a rule be AC#pulse ?

Regarding your question about using a ZC trigger for a rule, in Tasmota, the AC#Pulse trigger was previously used for this purpose, but as mentioned earlier, it has been removed in newer versions. If you are using an older version of Tasmota, you can try using AC#pulse as the trigger for your rule. However, in the latest versions, alternative triggers such as MQTT, HTTP, or timers would need to be utilized.

@stefanbode
Copy link
Contributor

stefanbode commented Jul 5, 2023

No it works differntly. You connect COUNTER4 to the ZC-Signal. Inside the Trigger counter I have a hook that calls the ZC-Driver: xdrv_68_zerocrossdimmer.ino

The hook is in: xsns_01_counter.ino Line: 78ff

#ifdef USE_AC_ZERO_CROSS_DIMMER
      if (index == 3) ACDimmerZeroCross(time);
#endif //USE_AC_ZERO_CROSS_DIMMER

This is inside an IRAM CACHE function that has high priority. a rule gets called far to late and on an unregular base. This can NEVER work. Rules are on the IDLE Task. For ZC you need hard INTERRUPTS to be in sync. Thats the reason why the function:
void IRAM_ATTR ACDimmerZeroCross(uint32_t time) { is also in IRAM to get served in an interrupt. Pls can you check following configuration:
PWM1: to Dimmer
COUNTER4: to ZC-Signal
setoption99 1
after reboot: command: zcdimmerset 20 to set 20% power

Using latest dev build, but production build is also fine

@cacengineering
Copy link
Author

cacengineering commented Jul 6, 2023

I do not know why, but my testbench does not work with "dimmer 10" "dimmer 20" and so on. I got reboots and odd behaviour. There seems something wrong and different. ZCDimmerSet 10 instead is working as it should do

Both are working on my ESP32_Wroom-32 devkit. Dimmer does give a different console response - "Power on, %" whereas ZCdimmerset just gives % but seems to reduce triggering delay to 1ms. My system is stable either way.

@cacengineering
Copy link
Author

cacengineering commented Jul 6, 2023

No it works differntly. You connect COUNTER4 to the ZC-Signal. Inside the Trigger counter I have a hook that calls the ZC-Driver: xdrv_68_zerocrossdimmer.ino

The hook is in: xsns_01_counter.ino Line: 78ff

#ifdef USE_AC_ZERO_CROSS_DIMMER
      if (index == 3) ACDimmerZeroCross(time);
#endif //USE_AC_ZERO_CROSS_DIMMER

This is inside an IRAM CACHE function that has high priority. a rule gets called far to late and on an unregular base. This can NEVER work. Rules are on the IDLE Task. For ZC you need hard INTERRUPTS to be in sync. Thats the reason why the function: void IRAM_ATTR ACDimmerZeroCross(uint32_t time) { is also in IRAM to get served in an interrupt. Pls can you check following configuration: PWM1: to Dimmer COUNTER4: to ZC-Signal setoption99 1 after reboot: command: zcdimmerset 20 to set 20% power

Using latest dev build, but production build is also fine

Currently using prod build 13 - did not see many relevant changes in dev 13.0.0.1

  1. I am already using PWM1 to dimmer - in our case though we are controlling resistive power via a Triac. Using ZCDimmerset as opposed to dimmer seems to reduce the trigger delay to 1ms !!
  2. Counter4 is already being triggered by our ZC signal. I had to significantly sharpen the pulse in the hardware though to get it to trigger reliably.
    Option99 has already been set for our testing.

The below looks fine on the scope as well.
10:56:00.749 CMD: zcdimmerset 20
10:56:00.772 MQT: 27_/Load-ctl/Tas_Testint_7C/stat/RESULT = {"ZCDimmerSet1":20.00}

I have been given lots of useful feedback on triggering an ADC after a few ms (for a voltage read). Most of it boils down to "modify the code as rules are not quick enough". I am a "not-so-well-self-taught" coder and it will take me ages, but more to the point dont want to fork a custom of the code - and not even sure another driver will work in conjunction with your driver as using same ports etc. Basically need to read voltage every few cycles after some delay (14ms ?) after the ZC and average it to calculate power. Current measured by more traditional means. Any suggestions ? Shall I close this bug report ?

Thanks for the help. If you do need an occasional resource - happy to contribute.

@Jason2866 Jason2866 removed the awaiting feedback Action - Waiting for response or more information label Jul 6, 2023
@stefanbode
Copy link
Contributor

I did some more investigations on the delay. ZCDimmerset 0.3 is working with some rare one time flicker. The pulse start at 9.8ms and ends 9.9ms after ZC. The flickering happen when the pulse last longer than the 10ms. With 0.1ms accuracy this is mast we can get.
On the other hand ZCDimmerset 99 does not work. To often the impuls get killed by the end of the zero cross. As you can see in picture 1. The trigger is 0.5ms after ZC detect. Here the limit is 98.5 and this is 0.77ms after ZC and still some signals get lost due to immediate kill in the TRIAC. See image 2.

CounterDebounceHigh MUST be 0. Anything else give very strange behavior. Looks like the "message" zerocross is deferred by the amount of ms in CounterDebounceHigh.

Image1
image

Image2
image

Code changes I can offer:

  • falling edge dimmer. PWM Signal go high on ZC and LOW at specified time
  • keep PWM high and set LOW in the ZC detection

@stefanbode
Copy link
Contributor

I made following changes to better support your use case:

  • Signal keeps HIGH like PWM. No pule anymore
  • Setoption155 introduced. If set to 1 then after a reboot dimmer will be falling edge dimmer. Default is leading edge dimmer

Known issues:

  • Saving the data to flash will disturb the interrupt. Therefore one flash wen changing dimmer value or on restart several small flashes. Nasty workaround is "savedata 0", but in this case a reboot will always back to saved values.

@cacengineering
Copy link
Author

Much appreciated. Stuck out in the field today - but itching to get back and try. Assume download latest dev build ? Did try savedata0 when we were originally testing - nasty.

@stefanbode
Copy link
Contributor

In have an idea how to overcome the save issue. Let's test today.

@stefanbode
Copy link
Contributor

No need to hurry. The PR is currently not merged into development.

@cacengineering
Copy link
Author

Thanks - Just got in now after a long day. When do you think you will merge it with dev?. The other issue - still really keen on tiggering an ADC read every 2nd or third cycle to sample voltage - eg 14ms after zero crossing. How hard would that be to build into the driver ?

@stefanbode
Copy link
Contributor

14ms after zero cross is a strange request because the phase is just 10ms. At least with 50Hz here in Europe. I do not understand the ADC use case. Trimming every half-sine is the best you can do. If you do 50% you just go in when voltage is max.

@SteWers
Copy link
Contributor

SteWers commented Jul 12, 2023

Unfortunately there is no oscilloscope available, to provide any plot. The hardware is a Robotdyn with a D1 mini.
Yesterday I tested a bit more and found that the disco only occurs when the dimmer is set to zero. With larger values ​​everything is OK. Furthermore, the lamp flashes on every change of the dimmer and then the light is steady on the new value.

@stefanbode
Copy link
Contributor

The flash is caused by the savedata event. This messes around with the interrupts. I may ask Theo for a workaround here. Maybe not a problem anymore. The disco on 0 I will check. Havent seen this here with the same device. Will let you know soon

@SteWers
Copy link
Contributor

SteWers commented Jul 12, 2023

Hm, interesting. In the previous version there was no flashing and I think the savedata event was also in place. I thought, that the savedata problem was only on ESP32.

@cacengineering
Copy link
Author

Let me bring some light into the discussion as I maintain this driver currently. First please do not add rules or other high CPU loads on the ESP8266 that is doing the dimmer. If you so there will be flickering because it just misses. The Zero-Cross signal coming to counter4 is an input signal. If this is not good or have problems than you need to change your hardware. There is nothing TASMOTA can do. I have good experience with the one shown in the documentation. The pulse on the TRIAC should have a defined length an is shifted a constant time away from the last zero-cross event. The lower the DIMMER value is the more far away it the TRIAC pulse. The PWMFREQUENCY and other stuff is not needed anymore. In the most recent development version the dimmer is using high frequency interrupts.

@cacengineering
Copy link
Author

Stefan - any timeline for the latest version of the driver to make it to dev? I started setting up some new GPIO's and they have killed the pwm pulse. Might blow away and start afresh.

@stefanbode
Copy link
Contributor

It is already in

@stefanbode
Copy link
Contributor

@SteWers : I fixed the flashing during change of the brightness. do you use ZCDimmerSet to set the dimmer? In the past it also worked with the normal Dimmer command but this causes a reset currently in my setup.
On ZCDimmerset 0 I do not have any disco. The light is 100% off. At least with my version of the robodyn triac

@SteWers
Copy link
Contributor

SteWers commented Jul 13, 2023

Yes, I use ZCDimmerSet. And yes, I saw the restarts too, when using the Dimmer command.
And now it becomes crasy: I tested it with an other Robotdyn and 8266 device. There is also the disco on 0, but every other value seems to put the light fully on. That was both tested right now with the latest precompiled dev. The "old" version works in both setups. 🤔

@SteWers
Copy link
Contributor

SteWers commented Jul 13, 2023

I set up another test environment to see the output of the PWM. Therefore I configured PWM1 to the LED-GPIO. Nothing was connected to COUNTER4 (ZC). After setting SO99, I recognized that PWM still worked. I could change the brightness via the DIMMER command. ZCDimmerSet had no reaction. After providing a (pseudo) ZC signal, the LED indicates the unwanted behavior. Should be off on 0, but it flashes.
So my suggestion is, that the "normal" PWM interferes with impulses from ZC driver. Could that be the cause?

@stefanbode
Copy link
Contributor

stefanbode commented Jul 14, 2023

As you can see I just submitted a change hopefully fixing ALL issues you saw right now. The DIMMER command executed an analogWrite command on the PWM that interfere with the Zero-Cross implementation. This caused the HANG. The Savedata now does not disable the counterInterrupt if there is a Zero-Cross Dimmer enabled. I kill the HIGH signal on the GPIO not later than 99% of the cycle time. This should address the flicker issue. Even if I was not able to reproduce the flickering with my Robodyn. Maybe a different, more accurate version.

@cacengineering
Copy link
Author

Have upgraded to Dev 13.0.0.2 and so far looking good, other than a possible issue with a clash with relay ? I will download latest driver - has the change request been accepted ?.

@SteWers
Copy link
Contributor

SteWers commented Jul 14, 2023

Thank you very much. No restarts until now. Unfortunately I cannot do a real test before Monday. In my simulation it seems, that the PWM is stable, but high at 0. At 100 it is unstable. But lets wait until I tested it in real next week.

@cacengineering
Copy link
Author

cacengineering commented Jul 15, 2023

The post was initially started to look at Zero cross detection and subsequent trigger for attached Triac. I believe we have successfully resolved at least that issue and in the interests of a proper closeout of the issue provide screen shots for the use of the community. Note that there are two minor issues but core problems resolved. Minor issues are:

  1. Gui web button no longer turns PWM on or off - but note there might be an interaction with another relay button. Not in scope of this post.
  2. Am still getting significant number of missed zero crossings. Triggering on falling edge has improved. I have not tried to further "tune" the triggering. Trigger pulse is good and sharp.

Screenshots below show:

  1. ZCDimmerset 99%
    image
  2. ZCDimmerset 50%
    image
  3. ZCDimmersetr 20%
    image
  4. Screenshot showing logs and feedback on ZCDimmerset.
    image

Big thank you to @stefanbode. @SteWers - when you believe your issue is resolved we can close the post.

@cacengineering
Copy link
Author

One further critical issue: The trigger pulse for the Triac is reversed. I.e. it triggers at the ZC. Ideally it needs to trigger after the ZC. For ZCDimmerset 99% - immediately and for 50% half way into the waveform.... I thought pwm_i would resolve but not the case.

@SteWers
Copy link
Contributor

SteWers commented Jul 17, 2023

@stefanbode Let me report from my tests:
Nearly everything is perfect. No disco, no flashes on changing, no restarts when using the dimmer command.
On one device I'd to decrease the disable_time_us to 95% of the cycle time. I guess there is a latency of the ZC impulse. After that it is running fine. May be this value should be made configurable.
You may remember that we discussed restarts caused by the hardware watchdog. They are still there, when the dimmer is on (not zero). I removed the line 146 (ac_zero_cross_dimmer.actual_tigger_Period = tmin(ac_zero_cross_dimmer.actual_tigger_Period,tmax(5,ac_zero_cross_dimmer.enable_time_us[i] - time_since_zc));) to prevent the restarts. I don't know what it is caused by.
As you persist the ZCDimmerSet value, the are a lot of store cycles to the flash. In my setup is approximately one per second. With savedata 0 this could be switched off. Is there another way?
That are the only few things I have to remark and I thank you for the great work!

@stefanbode
Copy link
Contributor

There is a setoption I assume 151 that changes from a leading edge dimmer to a trailing edge dimmer. Both modes are supported now. Should be in the documentation.

@stefanbode
Copy link
Contributor

Savedata 1 should be the default and then it saves on my site only if changing the value. Will double check. The other option I have to review. The zero cross is not a time it is a period and therefore there must be some silence before and after to be reliable.

@stefanbode
Copy link
Contributor

stefanbode commented Jul 21, 2023

sable_time

If we have a leading edge dimmer (default) the HIGH will come somewhere during the half sine and kills the power at the next zero-cross. It is mandatory that the HIGH goes LOW before that zero cross. Hardcoded and not willing to change is 99% of time of a cycle. At 50Hz this is 9.9ms after ZC and 0.1ms before the next one. This kill should be fine because it is used for ALL ZCDimmerset. Very low values of ZCDimmerset will not work if the start time after the kill time. But we talk about zcdimmerset 0.2 or something stupid. dimmer 0 and dimmer 100 should work. At least here.

Here is "dimmer 1" 1%
14:17:38.142 ZCD: ZeroEnable 1 -> 0, Alarm 0, intr: 0, cycle time: 9997 µs, missed zc 0
14:17:38.143 ZCD: PWM[1] en: 9254 µs, dis: 9901 µs, fade: 14, cur: 14, end: 14, lastlight: 14, acc: 19
14:17:39.147 ZCD: ZeroEnable 1 -> 0, Alarm 0, intr: 0, cycle time: 10003 µs, missed zc 0
14:17:39.148 ZCD: PWM[1] en: 9258 µs, dis: 9900 µs, fade: 14, cur: 14, end: 14, lastlight: 14, acc: 18
14:17:40.151 ZCD: ZeroEnable 1 -> 0, Alarm 0, intr: 0, cycle time: 10000 µs, missed zc 0

--> 18micro seconds to late (quite ok, inside tollerance)
-- > switch on at 9.25ms, there is more than enough time to switch off at 9.9ms

dimmer 99
14:20:52.151 ZCD: ZeroEnable 1 -> 0, Alarm 0, intr: 0, cycle time: 10003 µs, missed zc 0
14:20:52.153 ZCD: PWM[1] en: 518 µs, dis: 9899 µs, fade: 14, cur: 14, end: 14, lastlight: 1013, acc: 17
14:20:53.141 ZCD: ZeroEnable 1 -> 0, Alarm 0, intr: 0, cycle time: 9997 µs, missed zc 0
14:20:53.142 ZCD: PWM[1] en: 517 µs, dis: 9899 µs, fade: 14, cur: 14, end: 14, lastlight: 1013, acc: 18

-- > switch on at 0.5ms all good.

regarding the watchdog: you cannot remove this line. this is absolut mandatory to get on esp8266 the accuracy of the dimmer. the normal INTERRUPT is 75microsec. This is a about: 1000/75 = 13 stops between two zero cross events. 0..100 percent at least require 100 stops. The trick is on esp8266 to change the interrupt time if you come near the "switch HIGH" event. I have no hardware watchdogs here. what is you zcdimmerset testing value. maybe related there.

@stefanbode
Copy link
Contributor

cacengineering

The webbuttons will work but only if you are in the "dimmer" mode. This does mean zcdimmerset 0. then you can control it with dimmer 0 to dimmer 100 and then also the webbutton work. in this mode there is no 5.5% only integer are allowed 5% or 6%. For the missed ZC events I'm very sorry. have no idea how to overcome this by software.

@SteWers
Copy link
Contributor

SteWers commented Jul 24, 2023

I think you're right. There is an electrical delay caused by my setup. The "normal" one works as designed.
The watchdogs, I'll investigate after my vacations. My ZCDimmerset changes nearly every second, so may be it happens on one special value. Because of me, this issue can be closed.

@stefanbode
Copy link
Contributor

I did a "long time run test" 48h with ESP8266 and had zero reboots and hangs. Something we CAN change is the minumum time for a interrupt. 75 micro second is the default. The highlighted line:
ac_zero_cross_dimmer.actual_tigger_Period = tmin(ac_zero_cross_dimmer.actual_tigger_Period,tmax(5,ac_zero_cross_dimmer.enable_time_us[i] - time_since_zc));
allows a minimum of 5micro seconds. This is very very short. I will check a different method for ESP8266 to ensure the last Interrupt has a reasonable time.

@cacengineering
Copy link
Author

cacengineering commented Jul 25, 2023 via email

@stefanbode
Copy link
Contributor

confirmed. The one in DEV is the one working well here.

@SteWers
Copy link
Contributor

SteWers commented Jul 29, 2023

As you said "5 µs is very short", I did a few tests and increased the minimal time from 5 µs stepwise to 30 µs. With 20 µs the reboots were already there, but with 30 µs they have gone. The device is now up for 4(!) days without any crash. For testing I changed the ZCDimmerSet from 0 to 100 and back continuously in 0.1 steps every 100 ms via script.
Another point to think about is the storage of the ZCDimmerSet and restore it after a power outage / reboot. This is very nice, when there is e.g. wall switch and the light is restored after switching it on again. But in other cases it is better to start with a defined value after an uncontrolled return of power. Therefore a mechanism like PowerOnState would be helpfull.

@stefanbode
Copy link
Contributor

Zcdimmerset should restore after power off if savedata 1 is set. This is default. The 30mirco second is a good catch. I already have a change here where I can guarantee accuracy and do not violate minimum time. Let me submit this later today. Can you check if zcdimmerset survive a reboot if savedata is correct?

@SteWers
Copy link
Contributor

SteWers commented Jul 29, 2023

Yes, ZCDimmerSet is restored with savedata 1. In my case, I want to start with ZCDimmerSet 0, when device starts. This is the case when savedata is 0. But when savedata is 0 there are other side effects. E.g. script is not (re)stored. So I think, that an option, which is independent from savedata, would be a good feature.

@stefanbode
Copy link
Contributor

Nice idea but not possible. I removed as many problems with savedata as possible. should not flicker anymore. #19211 just submitted to increase minimum interrupt time from 5mirco to 30 micro seconds. Be aware that zcdimmerset 0 raises the use of DIMMER. Therefore this must also be 0. Otherwise you see side effects. "savedata 1" is the default and should work. @cacengineering : my long run test did work witch 20micros but i changes to your proposed 30micro.

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

Successfully merging a pull request may close this issue.

5 participants