You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is a highly optimized TRIAC delayed-trigger compensation routine for ESP32(-S3).
It compensates the TRIAC trigger time so that the power delivered to resistive load is changing linearly when the original TRIAC trigger time is also changing linearly.
Input: Relative delay of TRIAC trigger (0: start of half-sine wave up to 1: end of half-sine wave) Output: Linearized relative delay (0 up to 1, 0 when input < 0, 1 when input > 1, NaN when input is NaN) Relative error of power delivered to resistive load: < 1e-5
Cycles: 14-186 (includes CALL8, close to upper bound most of the time unless special input cases mentioned above) Instructions: 10-142 (includes CALL8, close to upper bound most of the time unless special input cases mentioned above)
Comment:
The power delivered with TRIAC to a resistive load during a half sinewave is simply Integrate[Sin[x]^2, x], which yields x/2 - 1/4 Sin[2 x] (indefinite integral - needs to be converted to definite one from x to Pi).
Linearization eq.: Reduce[(Pi/2 - (x/2 - 1/4 Sin[2 x]))/(Pi/2) == 1 - y/Pi, {x, y}] yields y == x - Sin[2 x]/2. But InverseFunction[Function[x, x - Sin[2 x]/2]] will get you nowhere :/
That is why I created this simple and most importantly fast routine!
Ring up your prodigy mathematician acquaintances - maybe, they will be able to devise an infinite series for the inverse function and conveniently truncate it when the required precision is met.
I am attaching the sources. Use 7-Zip to extract them from the 7-Zip archive. Feel free to incorporate them into this project. Let me know if you need me to tweak the ASM source.
Added: PLin function - same as DComp, but the input is the required relative output power (from 0 to 1).
Added: Graphs for DComp and PLin compensation functions - see the tiny PDF files.
Added: C source for Xtensa GCC folks since the C -Ofast floating-point code is an unmitigated disaster. The ASM version as a whole is 2× faster than C -Ofast!!! This is thanks to the highly optimized floating-point code at the end of the ASM routine, which is more than 3× faster than C -Ofast!!! To conclude, the Xtensa GCC is pretty good at optimizing integer code - e.g. if(c<minc) minc=c; is translated into just 1 ASM instruction MIN, which is both apt and cool! On the other hand, GCC quickly runs out of floating-point registers and starts using the stack with dire consequences for speed. Please tell the Xtensa GCC folks this is the one area really deserving their attention!!! Thanks.
Added: ESP32(-S3) target and instruction count in ASM and C source comments
Updated: Cycle count in ASM source comments
The text was updated successfully, but these errors were encountered:
Why in assembly?
Is this compatible with all ESP32 platforms?
It looks like it is a big lookup table, so I can imagine it is fast.
But still that doesn't explain why it has to be in assembly code.
Also I guess it would be nice to have a bit more explanation about the actual use case and what makes this a requirement for that use case.
The ASM version is 2× faster than C -Ofast!!! Since it extensively uses Xtensa FPU, it is compatible with ESP32 and ESP32-S3. It is suitable for cases when you want to linearly control the power delivered to a load connected to AC mains or any sinus power source in general, which can have much higher frequency - hence the need for speed…
f4lc0n-asm
changed the title
SOLVED: TRIAC delayed-trigger compensation routine (DSP-119)
SOLVED: TRIAC delayed-trigger compensation routine for ESP32(-S3) (DSP-119)
Dec 6, 2023
This is a highly optimized TRIAC delayed-trigger compensation routine for ESP32(-S3).
It compensates the TRIAC trigger time so that the power delivered to resistive load is changing linearly when the original TRIAC trigger time is also changing linearly.
Input: Relative delay of TRIAC trigger (0: start of half-sine wave up to 1: end of half-sine wave)
Output: Linearized relative delay (0 up to 1, 0 when input < 0, 1 when input > 1, NaN when input is NaN)
Relative error of power delivered to resistive load: < 1e-5
Cycles: 14-186 (includes CALL8, close to upper bound most of the time unless special input cases mentioned above)
Instructions: 10-142 (includes CALL8, close to upper bound most of the time unless special input cases mentioned above)
Comment:
The power delivered with TRIAC to a resistive load during a half sinewave is simply Integrate[Sin[x]^2, x], which yields x/2 - 1/4 Sin[2 x] (indefinite integral - needs to be converted to definite one from x to Pi).
Linearization eq.: Reduce[(Pi/2 - (x/2 - 1/4 Sin[2 x]))/(Pi/2) == 1 - y/Pi, {x, y}] yields y == x - Sin[2 x]/2. But InverseFunction[Function[x, x - Sin[2 x]/2]] will get you nowhere :/
That is why I created this simple and most importantly fast routine!
Ring up your prodigy mathematician acquaintances - maybe, they will be able to devise an infinite series for the inverse function and conveniently truncate it when the required precision is met.
I am attaching the sources. Use 7-Zip to extract them from the 7-Zip archive. Feel free to incorporate them into this project. Let me know if you need me to tweak the ASM source.
Cheers!
f4lc0n
dcomp_v1.2.zip
Fixed: Function description in plin.s.
Added: PLin function - same as DComp, but the input is the required relative output power (from 0 to 1).
Added: Graphs for DComp and PLin compensation functions - see the tiny PDF files.
Added: C source for Xtensa GCC folks since the C -Ofast floating-point code is an unmitigated disaster. The ASM version as a whole is 2× faster than C -Ofast!!! This is thanks to the highly optimized floating-point code at the end of the ASM routine, which is more than 3× faster than C -Ofast!!! To conclude, the Xtensa GCC is pretty good at optimizing integer code - e.g. if(c<minc) minc=c; is translated into just 1 ASM instruction MIN, which is both apt and cool! On the other hand, GCC quickly runs out of floating-point registers and starts using the stack with dire consequences for speed. Please tell the Xtensa GCC folks this is the one area really deserving their attention!!! Thanks.
Added: ESP32(-S3) target and instruction count in ASM and C source comments
Updated: Cycle count in ASM source comments
The text was updated successfully, but these errors were encountered: