我想使用带有ESP8266的Micro Python控制交流调光器。我没有与此相关的任何库或示例。有人可以帮我吗 提前致谢!
答案 0 :(得分:1)
实际上,这取决于您使用哪种交流调光器。我期望像RobotDyn AC dimmer这样的东西:
在这种情况下,调节不像在标准DC PWM中那样容易(请不要让自己被PWM引脚弄糊涂,它不是真正的PWM)。此模块是标准的三端双向可控硅调光器,需要控制调光过程(请参见schematics)。
调节的工作方式基于以下事实:您知道交流正弦波何时变为零(每个周期两次)。因此有Z-C输入引脚。当电压过零时,您打开三端双向可控硅开关一段时间,并切断正弦波的一部分。那就是法规。
这就是调光驱动程序应该执行的操作。在micropython中,这并非易事,因为它需要涉及中断。您可以看到以下我在硬件上尝试过且“有效”的代码:
from machine import Timer, Pin
from micropython import alloc_emergency_exception_buf
from math import acos, pi
class Dimmer:
def __init__(self, pwm_pin, zc_pin, fpulse = 4000):
alloc_emergency_exception_buf(100)
self._cnt = 0
self._freq = 0
self._timer = Timer(2)
self._mode = Timer.ONE_SHOT
self._pwm = Pin(pwm_pin, Pin.OUT)
self._fpulse = fpulse
self._ppulse = 100.0 / fpulse + 0.11
self._zc = Pin(zc_pin, Pin.IN)
self._val = 1
self._zc.irq(trigger = Pin.IRQ_RISING | Pin.IRQ_FALLING, handler = self._zeroDetectIsr)
def _zeroDetectIsr(self, pin):
if 0 == self._freq:
self._pwm.on()
return
if 0 > self._freq:
self._pwm.off()
return
self._cnt += 1
if 1 == self._cnt:
self._timer.init(freq = self._freq, mode = self._mode, callback = self._dimmDelayIsr)
def _dimmDelayIsr(self, _timer):
if 1 == self._cnt:
self._pwm.on()
self._timer.init(freq = self._fpulse, mode = self._mode, callback = self._dimmDelayIsr)
else:
self._pwm.off()
self._cnt = 0
@property
def value(self):
return self._val
@value.setter
def value(self, p):
p = min(1, max(0, p))
if not self._val == p:
self._val = p
p = acos(1 - p * 2) / pi
if p < self._ppulse:
f = -1
elif p > 0.99:
f = 0
else:
f = 100 / (1 - p)
self._freq = int(f)
return self._val
请注意,与晶体管不同,三端双向可控硅开关元件保持打开状态直到其电压下降到0,因此您甚至可以仅使用短脉冲来打开它。
使用驱动程序非常简单:
from dimmer import Dimmer
dimmer = Dimmer(4, 2)
dimmer.value = 0.3
不幸的是,ESP32上的micropython经常锁定中断,因此只有在什么都没有发生的情况下,整个东西才起作用。最明显的问题在于print
函数周围,该函数有时能够阻止多个AC正弦周期,这导致可见灯泡闪烁。不幸的是,在WiFi通信的情况下,我希望会有类似的情况。
这里的结论是,最好的解决方案是使用一些便宜的基于AVR的板并用C ++编写代码,这将仅涉及调光,而仅此而已。该板可以通过I2C总线连接到ESP板上,并且ESP仅发送命令以设置调光器值。