2

I want to control AC Light Dimmer using Micro Python with ESP8266. I am not getting any libraries or examples related to this.Could anyone please help me with this Thanks in advance!

  • Have you thought of connecting a servo to the dimmer knob and just using some basic servo control – phil Apr 19 '19 at 08:02
  • Have you found an arduino example that outlines the hardware, wiring and the logic? If so, that should give you a starting point for your own design. – Patrick Mar 18 '20 at 21:32

2 Answers2

1

Actually, it depends on which type of AC dimmer you have. I would expect something like RobotDyn AC dimmer:

Robodyn AC dimmer

In this case the regulation is not so easy like in the case of standard DC PWM (please don't let youself being confused by PWM pin, it is not real PWM). This module is standard triac dimmer which needs controlled dimming process (see this schematics).

The way how regulation works is based on the fact that you know when AC sine goes through zero (twice per period). Therefore there is Z-C input pin. When voltage goes through zero, you open triac for a while and cut off part of sine. Thats about regulation.

Wave regulation image

And this is what your dimmer driver shall do. This is not easy task in micropython as it requires to involve interrupts. You can see following code which I tried on HW and which was "working":

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

Just note that unlike transistor, triac holds opened state till voltage on it drops to 0, so you can even use just short pulse to open it.

Use of driver is then simple:

from dimmer import Dimmer
dimmer = Dimmer(4, 2)
dimmer.value = 0.3

Unfortunately, micropython on ESP32 is locking interrupts quite often, so whole stuff works only when nothing is happening around. Most visible problems was around print function which was sometimes able to block for several AC sine periods, what caused visible bulb blinking. Unfortunately I would expect something similar in the case of WiFi communication.

The conclusion here is that the best solution is to use some cheep AVR based board and write code in C++ which will just care about dimming and nothing else. Such board can be connected to ESP board over I2C bus and ESP only sends command to set dimmer value.

OSi
  • 11
  • 2
0

Apart from the fact that this code is not very explanatory, it does not (immediately) work. The line:

self._zc.irq(trigger = Pin.IRQ_RISING | Pin.IRQ_FALLING, handler = self._zeroDetectIsr)

is confusing. What is meant (I suppose) is that the trigger = Pin.IRQ_RISING or trigger = Pin.IRQ_FALLING. So the line must be:

self._zc.irq(trigger = Pin.IRQ_RISING , handler = self._zeroDetectIsr)

or

self._zc.irq(trigger = Pin.IRQ_FALLING, handler = self._zeroDetectIsr)

In both cases this program works well.

See also my topic https://forums.raspberrypi.com/viewtopic.php?p=2118520&hilit=dimmer#p2118520

Tyler2P
  • 2,324
  • 26
  • 22
  • 31