Arduino控制调光器

878,289

609.

1087年

Arduino可控调光器

我的职业是医生。在制药行业工作之后,我决定放慢脚步,做我喜欢的事情。除了我的业余爱好是在东南亚的草根医学。我有成矿……

等待! !在您决定构建这个之前,最好知道一个类似的调光器可以在阿里巴巴全球速卖通其成本难以超越(目前为2.70欧元)

警告:有些人尝试用过零的光耦合器来做这个因为这样更好,对吧?一些人甚至在电子产品商店被告知使用更好这样的光耦合器。错误的。这只会使用随机的火光Optocoupler:没有在Zerocrosing点燃是这个调光器的原理。

用Arduino开关交流负载非常简单:可以是机械继电器,也可以是带有光学隔离可控硅的固态继电器。(我说的是Arduino,但如果你使用8051或PIC16F877A微控制器,这里也有适合你的东西。)

变得更加棘手的如果一个人想和一个昏暗的AC电源灯arduino:只是限制如晶体管的电流是不可能由于大功率晶体管需要消散,导致热量也不是从一个能源使用效率的观点。

阶段削减
一种方法是通过可控硅的相位控制:可控硅然后完全打开,但只在部分窦性交流波。这叫做前缘切割。
人们可以让Arduino刚刚打开TRIAC,据一些微秒,但这是一个问题,即在三分子杆菌发生的鼻窦波段的哪个部分是不可预测的,因此调光水平是不可预测的。一个人需要在鼻窦波中的参考点。
为此需要零交叉检测器。这是一个电路,当鼻波通过零时,告诉Arduino(或另一个微控制器),因此在该窦波上给出了一个定义的点。
因此,在从零交叉开始的多个微秒延迟之后打开三端双向可控硅延迟给出可预测的调光程度。

脉冲跳过调制
另一种方法是脉冲跳变调制。使用PSM,一个或多个完整周期(正弦波)被转移到负载,然后一个或多个周期不被转移。虽然效果很好,但这并不是一种好方法,因为有闪烁的机会。尽管它可能是诱人的,在PSM中,人们应该总是允许一个完整的正弦波传递到负载,而不是半正弦,因为在这种情况下,负载将实际上从直流馈电,这对大多数交流负载不是一件好事。前缘切割和PSM的区别主要在于软件:在这两种情况下,都需要一个能检测过零和能控制可控硅的电路。

可以做到这一点的电路很容易构建:过零直接来自整流的市电交流线路——当然是通过光耦合器——并在每次波经过零的时候给出一个信号。因为正弦波首先经过双相整流,不管窦性波是通过零上升还是通过零下降,过零信号都是已知的。这个信号可以用来在Arduino中触发一个中断。

PWM调光
PWM调光,如LED在LED中没有经常使用AC负载进行多种原因进行。但是,但是。查看这是有指导意义的

不用说,Arduino这一边的东西和任何连接到电源的东西之间都需要有电流隔离。对于那些不理解“电分离”的人,这意味着“没有金属连接”,因此——>光耦合器。但是,如果你不理解“电分离”,也许你不应该建造这个。

图中的电路就是这样做的。市电220v电压通过两个30k电阻到桥式整流器,为4N25光耦合器提供双相整流信号。因此,光耦合器中的LED以100Hz的频率低电平,而集电极上的信号以100Hz的频率高电平,与主频网络上的正弦波一致。4N25的信号被馈送到Arduino(或其他微处理器)的中断管脚。中断程序将特定长度的信号馈送给一个I/O管脚。I/O引脚信号返回到我们的电路并打开LED和MOC3021,这将触发光晶闸管。与MOC3021串联的LED指示是否有电流通过MOC3021。请注意,在调暗操作中,光不会很明显,因为它的持续时间很短。如果您选择使用可控硅开关连续使用,LED将清晰地亮起。

请注意,只有普通的白炽灯才真正适合调暗。它也可以和卤素灯一起工作,但它会缩短卤素灯的寿命。它不能与任何节能灯一起工作,除非它们特别说明适合调光器。LED灯也是如此

注意!很有可能,取决于使用的LED,转向信号只是不切断它,你可能最终得到的灯只是闪烁,而不是平稳地调节。用线桥代替LED就可以解决这个问题。LED并不是必须的。然后将220欧姆电阻增加到470


停止:这个电路连接到110-220电压。如果你对自己正在做的事情没有信心,就不要建立这个。在接近PCB之前拔掉它。可控硅的冷却板附在电源上。操作时请勿触摸。把它放在合适的容器里。

等待:让我在这里添加一个更强烈的警告:如果只由知道自己在做什么的人构建和实现这个电路,那么它是安全的。如果你毫无头绪,或者你对你所做的事感到怀疑,那么你很有可能会死!
连接到电网时请勿触摸

材料
Zerocrossing
4机n25€0.25或H11AA1或IL250, IL251, IL252, LTV814(见下一步的文本)
电阻器10 k€0.10
桥式整流器400伏€0.30
2 x30k电阻1/2瓦特(电阻器可能会消散400mW最大每欧元0.30欧元
1连接器€0.20
5.1伏零压二极管(可选)

灯驱动程序
领导(注:可以用线桥代替LED,因为LED有时会导致灯闪烁,而不是平稳调节)
MOC3021.如果你选择另一种类型,确保它没有过零检测不要使用MOC3042
电阻器220欧姆€0.10(我实际上用的是330欧姆,而且还行)
电阻器470年Ohm-1k(我最终使用了560欧姆,工作得很好)
双向可控硅TIC206€1.20或BR136€0.50
1连接器€0.20

其他
一块PCB 6x3cm
安装电线

这是零件的约3欧元

步骤1:Arduino可控调光器:PCB

你会发现PCB的两张图片:我的第一张,我留在这里作为文档的目的和一个稍微改变的新一张。不同之处是,我省略了zenenerdiode,因为它不是真的必要,我给了LED itś自己的(1k)电阻:它不再与光耦合器串联,现在有一个470欧姆电阻。我通过直接调色剂转移制作了PCB,然后在盐酸/过氧化氢浴中蚀刻。有很多指导手册告诉我们该怎么做。您可以使用所附的打印设计来做同样的事情。填充打印非常简单。我用IC脚的光耦合器和桥式整流器。
下载打印在这里
注意:你需要弗里茨。对于直接调色剂转移,打印pdf文件的打印面,直接对着铜层进行转移。一旦它被转移,你就会从另一边看墨水,从而再次看到正常的文本。我在pcb上做了轻微的改变:我移除了zenenerdiode和LED不再与光耦合器串联。

我用的是TIC206。可以输出4安培的电流。记住,尽管PCB的铜轨道将不能承受4安培。对于任何严重的负载,在从可控硅到连接器的轨道和两个连接器之间的轨道上焊接一根铜安装线。

如果不清楚输入是什么:在第二幅图中从上到下:
+ 5伏
中断信号(arduino上的D2)
可控硅信号(来自Arduino上的D3)
地面

注意:
如果您拥有H11AA1OR IL 250,251或252光耦合器,则您不需要桥式整流器。这些具有两个抗覆盖层二极管,因此可以处理AC。它是与4N25兼容的销钉,刚刚在R5和+和R7之间弹出和焊接2线桥和 - 。LTV814不是PINCOMPATIBLE

第二步:感性负载:理论

本电路适用于白炽灯等纯电阻负载。
如果你想用它来感应负载,那么缓冲器电路是必要的。图中显示了用于电感负载的修改。请注意,这并不是我尝试过的,因为我只是想调暗灯光,但它是基于互联网上可用的例子和理论。您必须调整所提供的PCB
上面的图显示了调暗灯的电路。它的简单之处在于仅仅是一个电阻器,通过光耦合器中的交流电路触发门。1k的值可以根据前面的讨论进行改变。
下图给出了在感应负载中使用的无所不在的电路。

它由一个额外的电阻和电容组成。栅极电流低于15mA。如果你使用一个不太敏感的可控硅来控制感性负载,减少电阻2.4kΩ到1.2kΩ,提供更多的电流来驱动可控硅,并增加电容到200nF。这种缓冲电路是为了保护可控硅免受电感负载产生的高电压。这种反馈可能会对无感负载造成一些问题。小的泄漏量足以打开小负载(例如一盏灯)。

还有其他的缓冲电路,例如直接在负载上串联一个电阻和电容

步骤3:软件,一点理论

如果您可以不关心理论,但只需要软件,请转到下一步

一旦你了解了基础知识,使用AC调光器/渐变器的方法是非常简单的:

在交流电中,馈给灯的功率与正弦波的总表面直接相关,只要允许正弦波流过灯的可预测部分,灯就可以被调节。

因此,我们需要一个参考点上的窦,从那里我们计算灯必须打开。

使用最简单的参考点是所谓的“零交叉”:光线循环的那一刻。
在每个过零之后,有整整一半的正弦波可以通过灯。

所以软件需要做的是检测过零,然后在正弦波上等待一定的时间,打开可控硅开关。

2大栅极频率

在世界上:50Hz在欧洲和大多数亚洲和非洲和60 Hz的美国(以及加勒比部分)。世界上有2个主要电压:110-120V和220-240V,但它们对数学并不重要

为了方便使用,我将以50Hz频率为例:
50Hz每秒50波。
因此,每个正弦波需要1000ms/50=20ms(毫秒)
因为在一个波中有两个正弦峰,这意味着在每一个零检测之后有一个10毫秒的周期我们可以调节。
如果我们在开始时直接点火,灯将收到满功率,如果我们在结束时点火,灯将没有功率,如果我们在中途点火,灯将收到一半功率。
当我们使用可控硅时,软件需要做的是等待正弦曲线上的零点,注意这一点,然后在10ms的周期内等待指定的时间向可控硅发送脉冲。
如果它以5毫秒的速度发送脉冲,灯只会以一半的功率燃烧。

在该电路中,零检测由双相光耦完成,并可作为板上的x信号。
微控制器基本上有2种方式检测到该信号:
连续的“轮询”过零引脚
使用一个中断来告诉程序有一个过零
两者之间的主要区别在于,每次计算机通过它的主循环时,它需要检查引脚。如果您的程序忙于做大量其他事情,请检查零交叉引脚可能为时已晚,而使用中断时,程序繁忙的情况无关紧要。中断是“敲击肩膀上的”说“嘿外观,有些东西已经提出了你现在需要参加”。

在检测到过零后,程序需要等待指定的时间,然后接通可控硅。
同样在这里,等待有两种不同的方式
1-通过发出“等待”命令
使用定时器中断

同样,这两种方法都有他们的亲和骗局。“等待”命令(Arduino语言中的'延迟')字面意思是让计算机等待所需的时间,并且在平均时刻不能做任何其他事情。如果灯通过让计算机等待9ms以低功率燃烧,这意味着每10ms计算机被告知等待9ms:Ergo将闲置90%的时间。如果您的控制器仅用于控制灯泡,则这很好,但如果它需要执行其他东西,那么剩下时间很少。
使用计时器中断解决了这一点。基本上是该程序的表明是什么意思告诉计时器:¨hey,我刚刚听到我们有一个零横穿,我得做别的事情,但你才等待4.5ms,然后打开三端双向自动射行“所以这个程序继续下去Merry Way和4.5ms(例如示例)在发出通知后有一个0交叉,定时器开关三端双向可控硅。

轮询:(注意轮询例证的粗略示例,显然它需要一些增强)
int AC_LOAD = 3;//我们使用引脚3来点燃可控硅int状态;//将AC Load引脚设置为输出}void loop() {state=digitalRead(AC_LOAD);如果(state=1) {delayMicroseconds(5000);// = 5ms =half power digitalWrite(AC_LOAD, HIGH);//触发触发器
中断驱动
要使用中断,首先我们需要设置它。在arduino上如下:
void setup() {pinMode(AC_LOAD, OUTPUT);//设置AC Load引脚作为输出attachInterrupt(0, zero_cross_int, RISING);//从上面的表中选择零交叉中断}

它说的是,中断连接到中断0,它进入一个名为zero_crosss_int的函数,它对引脚上上升的侧翼做出反应。

在程序在中断后跳转到的Zero_cross_int函数中,我们确定了在触发可调式控制之前需要等待的时间。我们还将添加一些功能。我们不只是想要一个水平设置的灯点燃,我们将增加一些功能来调节光水平的步骤。
为此,我选择了完全任意的128步。这意味着每一步是10ms/128 = 10000us/128=75us(事实上是78,但我稍后会讲到)。总的调光时间从75x(1到128)计算。在1-128之间的数字,它决定了我们的调光级别,我们将整数“调光”赋值给变量

Void zero_crosss_int() //函数被触发在0交叉点昏暗光{int dimtime = (75*dimming);//对于60Hz =>65 delayMicroseconds(dimtime);//关闭周期digitalWrite(AC_LOAD, HIGH);//可控硅触发delayMicroseconds(10);//可调式传输延迟(对于60Hz使用8.33);// triac Off}


这里发生的情况是程序首先计算在触发三端双向可控硅之前等待DIMTime(=等待时间)

然后等待一定的时间,然后等待一定的时间,触发可控硅。可控硅将在以下的零位交叉点再次关闭,但我们将在可控硅引脚上写一个低电平,以避免在下一个循环中意外点火。然而,我们需要等一段时间,以确定TRIAC是打开的,所以我们等待10us。现在(10000-10)/128仍然是78,但我发现75工作得很好。尽管使用78。

在主程序中剩下要做的唯一一件事就是设置我们想让灯燃烧的电平:
Void loop() {for (int i=5;< = 128;我+ +){调光=我;延迟(10);}
以下情况是一个简单的循环,调节128步的灯泡。我选择了不在1开始,但在5级,因为在那个级别可能会有一些可能导致灯闪烁的时间问题。

上面的程序只是一个如何控制灯的例子,显然你想添加一些其他的功能,而不是仅仅让灯的亮度上升和下降。

使用一个计时器:
如果您希望您的程序是时间效率,您将需要使用一个中断的过零检测和一个计时器来确定等待的时间量。
程序大致如下所示:

初始化
设置您需要的各种常量和变量,并包括所使用的库(例如Timerone库)

设置
设置引脚和2个中断
过零中断指向一个函数,定时器中断也是如此

交叉functie
设置一个布尔值,指示是否发生了叉零

定时器功能
如果我们在128步骤中再次调节亮度,那么只要步骤传递的时间(例如75us)即可调用定时器函数,然后检查通过的步骤数等于设置的步骤数量。如果是这种情况,则转换三折

第四步:Arduino控制调光器:软件

正如前面理论页面所讨论的,该软件相当简单。
如果你想开发自己的软件,你需要做的就是:
等待零点
等待0到9090微秒之间的特定时间(9090 = 10.000-10)
打开可控硅开关
等待约10us(即你需要确保三脚转向的时间)
关闭yr的可控硅(事实上,你只移除触发信号到可控硅,可控硅将一直保持到下一个过零)

我只是简要介绍了我使用的程序的流程:

(请务必阅读下面的“说明”)

零位x信号产生一个中断。
在50Hz时,每10毫秒或10.000uS中断一次
在60Hz中,中断每8333毫秒或8333毫秒
然后,中断例程在特定时间后切换到TRIOC。那个时间在主程序循环中设置。
由于该程序在128步(这只是一个选择,也可以是100步)的调光从完全关闭,在50赫兹,我们需要步骤是75 uS,在60赫兹,他们需要65 uS

其工作原理如下:
中断函数“zero_crosss_int”在每次检测到过零时被调用,即100次/秒。它的唯一功能是将可控硅打开的时间设置为变量“调光”的值。
在程序的主循环中设置该变量的实际值

/* AC Voltage dimmer with Zero cross detection作者:Charith feranado改编自DIY_bloke许可证:Creative Commons Attribution Share-Alike 3.0许可证。附加模块的零交叉销Arduino外部中断销选择正确的中断#从下面的表(密码数字针,不是物理针:数字销2 [INT0] =物理销4和数字物理销销3 (INT1) = 5)检查:< a href = " http://arduino。cc / en /引用/ attachInterrupt中断”> < / >销| Interrrupt # | Arduino平台  --------------------------------------- 2 | 0 |所有,但它是达芬奇INT1 3 | 1 |所有,但它是达芬奇INT0 18 | 5 | Arduino大型只有19个| 4 | Arduino兆只有20 | 3 | Arduino兆只有21 | 2 | Arduino大型只有0 | 0 |莱昂纳多1 | 3 |Arduino Due没有标准的中断引脚,因为中断可以连接到几乎任何引脚。在程序引脚2中选择*/ int AC_LOAD = 3;//输出到Opto可控硅引脚int dimming = 128;//设置AC Load引脚为输出attachInterrupt(0, zero_crosss_int, RISING); //设置AC Load引脚为输出attachInterrupt(0, zero_crosss_int, RISING);/ /从上面的表中选择零交叉中断#}/ /中断函数必须不带任何参数和返回没有空zero_crosss_int() / /函数被解雇的零交叉昏暗的光线{/ /点火角计算:1满50赫兹波= 1/50 = 20 / /每zerocrossing因此女士:(50Hz)-> 10ms (1/2 Cycle) // For 60Hz => 8.33ms (10.000/120) // 10ms=10000us // (10000us - 10us) / 128 = 75 (approming) For 60Hz =>65 int dimtime = (75*dimming);//对于60Hz =>65 delayMicroseconds(dimtime); // Wait till firing the TRIAC digitalWrite(AC_LOAD, HIGH); // Fire the TRIAC delayMicroseconds(10); // triac On propogation delay // (for 60Hz use 8.33) Some Triacs need a longer period digitalWrite(AC_LOAD, LOW); // No longer trigger the TRIAC (the next zero crossing will swith it off) TRIAC } void loop() { for (int i=5; i <= 128; i++){ dimming=i; delay(10); } }

关于软件:理论上在循环中你可以让变量“i”从“0”开始。然而,由于中断中的计时有点近似,使用'0'(完全打开)可能会把计时搞砸一点。同样的道理也适用于128 (Full off),尽管这似乎不那么重要。无论“5”或“1”是你设置的极限是一个尝试的问题,你的范围可能从例2到126而不是0-128。如果有人有更精确的方法来设置插话时间,我很乐意听听。
当然没有必要与中断合作。还可以继续轮询零交叉引脚以进行0。

虽然软件工作与中断确定零跨越的时刻,它仍然不是那么有效,因为我们需要等待的时间(dimtime)零跨越后,在可控硅被触发是真正的“等待”在零跨越中断功能。

更有效的方法是设置一个计时器在正确的时间触发,这样arduino就可以做其他事情了。这样的程序可以在步骤6中找到

请注意

让我再次重申上面的声明:这个程序是如何控制调光器的演示。由于它在大部分时间等待时,这是不是和高效的程序。因此,与处理器的其他任务相结合是最适合的。如果您需要更有效的程序,请使用计时器而不是延迟

步骤5:Arduino可控调光器:软件II

我发现了另一块软件,允许通过串行端口控制灯。它在过零信号的下降沿触发,因此定时有点不同。

我还没有测试过自己,但我看到它不能工作的原因:据我可以看到它不接收串口输入数量,但收到的每个数字的ascii值类型的,所以“0”将被视为48

int ac_pin = 3; //引脚到Optroiac字节昏暗= 0;//初始亮度级别从0到255,随意更改!void setup(){serial.begin(9600);PINMODE(AC_PIN,输出);AttachtErterrupt(0,Light,落); //当Arduino引脚2从高到低电平落下时,运行光线步骤!} void light(){if(serial.available()){dim = serial.read();if(暗淡<1){//转动TRIAC完全关闭,如果DIM是0ignWWRITE(AC_PIN,LOW);}如果(DIM> 254){//将TRIAC完全打开,如果DIM是255迪网(AC_PIN,高);}}如果(dim> 0 && dim <255){//调光部分,如果暗淡不是0而不是255 delaymicroseconds(34 *(255-dim));DigitalWrite(AC_PIN,高); delayMicroseconds(500); digitalWrite(AC_pin, LOW); } } void loop() { }

注意:上面的软件不是我的。我认为最好将串行端口的检查排除在中断之外。另外,在可控硅关闭之前的500uS延迟可能有点长。

甚至更多的软件在这里

步骤6:Arduino可控调光器:软件

下面的代码使用了计时器功能而不是延迟,并已被证实对达芬奇也有效

第七步:MQTT调光器

如果您有WLAN连接,可以使用MQTT来控制调光器。在这个例子中,我使用Arduino UNO和Ethernetshield。
主题是“Home / Br / Sb”,有效载荷从0-100设置调光级别

#include  // Ethernet.h #include  // PubSubClient.h #include  //TimerOne.h #define CLIENT_ID "Dimmer" #define PUBLISH_DELAY 3000 String ip = "";bool startsend = HIGH;Uint8_t mac[6] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x07};不稳定的int i = 0;//使用volatile变量作为一个计数器,因为它是在一个中断volatile boolean zero_cross=0;//输出到Opto Triac int dim1 = 0;//调光电平0 = on, 100 = 0ff int inc=1;//向上或向下计数,1=向上,-1=向下int freqStep = 100;EthernetClient ethClient;PubSubClient mqttClient;长previousMillis; void zero_cross_detect() { zero_cross = true; // set the boolean to true to tell our dimming function that a zero cross has occured i=0; digitalWrite(AC_pin1, LOW); // turn off TRIAC (and AC) } // Turn on the TRIAC at the appropriate time void dim_check() { if(zero_cross == true) { if(i>=dim1) { digitalWrite(AC_pin1, HIGH); // turn on light i=0; // reset time step counter zero_cross = false; //reset zero cross detection } else { i++; // increment time step counter } } } void setup() { attachInterrupt(0, zero_cross_detect, RISING); // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection Timer1.initialize(freqStep); // Initialize TimerOne library for the freq we need Timer1.attachInterrupt(dim_check, freqStep); pinMode(4, OUTPUT); // setup serial communication Serial.begin(9600); while (!Serial) {}; Serial.println(F("dimmer")); Serial.println(); // setup ethernet communication using DHCP if (Ethernet.begin(mac) == 0) { Serial.println(F("Unable to configure Ethernet using DHCP")); for (;;); } Serial.println(F("Ethernet configured via DHCP")); Serial.print("IP address: "); Serial.println(Ethernet.localIP()); Serial.println(); ip = String (Ethernet.localIP()[0]); ip = ip + "."; ip = ip + String (Ethernet.localIP()[1]); ip = ip + "."; ip = ip + String (Ethernet.localIP()[2]); ip = ip + "."; ip = ip + String (Ethernet.localIP()[3]); //Serial.println(ip); // setup mqtt client mqttClient.setClient(ethClient); mqttClient.setServer( "192.168.1.103", 1883); // <= put here the address of YOUR MQTT server //Serial.println(F("MQTT client configured")); mqttClient.setCallback(callback); Serial.println(); Serial.println(F("Ready to send data")); previousMillis = millis(); mqttClient.publish("home/br/nb/ip", ip.c_str()); } void loop() { // it's time to send new data? if (millis() - previousMillis > PUBLISH_DELAY) { sendData(); previousMillis = millis(); } mqttClient.loop(); Serial.print("dim1 = "); Serial.println(dim1); } void sendData() { char msgBuffer[20]; if (mqttClient.connect(CLIENT_ID)) { mqttClient.subscribe("home/br/sb"); if (startsend) { mqttClient.publish("home/br/nb/ip", ip.c_str()); startsend = LOW; } } } void callback(char* topic, byte* payload, unsigned int length) { char msgBuffer[20]; payload[length] = '\0'; // terminate string with '0' String strPayload = String((char*)payload); // convert to string Serial.print("strPayload = "); Serial.println(strPayload); //can use this if using longer southbound topics Serial.print("Message arrived ["); Serial.print(topic); Serial.print("] ");//MQTT_BROKER for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); } Serial.println(); Serial.println(payload[0]); dim1=strPayload.toInt(); }

第八步:软件设置水平使用向上和向下按钮

在代码下方,用上下按钮设置光级别。它使用计时器检查触发TRIAC的时间所需的时间,而不是在延迟循环中等待

*/ #include  //可从http://www.arduino.cc/playground/Code/Timer1 volatile int i=0;//使用变量作为调光步骤的计数器。它是volatile的,因为它在volatile布尔值zero_cross=0的中断之间传递;int AC_pin = 3; //通过0//输出到Opto Triac int buton1 = 4;//第一个按钮在引脚4 int buton2 = 5;//第二个按钮在引脚5 int dim2 = 0;// led control int dim = 128;//调光电平(0-128)0 = on, 128 = 0ff int pas = 8;//计数的步骤; int freqStep = 75; // This is the delay-per-brightness step in microseconds. It allows for 128 steps // If using 60 Hz grid frequency set this to 65 void setup() { // Begin setup Serial.begin(9600); pinMode(buton1, INPUT); // set buton1 pin as input pinMode(buton2, INPUT); // set buton1 pin as input pinMode(AC_pin, OUTPUT); // Set the Triac pin as output attachInterrupt(0, zero_cross_detect, RISING); // Attach an Interupt to Pin 2 (interupt 0) for Zero Cross Detection Timer1.initialize(freqStep); // Initialize TimerOne library for the freq we need Timer1.attachInterrupt(dim_check, freqStep); // Go to dim_check procedure every 75 uS (50Hz) or 65 uS (60Hz) // Use the TimerOne Library to attach an interrupt } void zero_cross_detect() { zero_cross = true; // set flag for dim_check function that a zero cross has occured i=0; // stepcounter to 0.... as we start a new cycle digitalWrite(AC_pin, LOW); } // Turn on the TRIAC at the appropriate time // We arrive here every 75 (65) uS // First check if a flag has been set // Then check if the counter 'i' has reached the dimming level // if so.... switch on the TRIAC and reset the counter void dim_check() { if(zero_cross == true) { if(i>=dim) { digitalWrite(AC_pin, HIGH); // turn on light i=0; // reset time step counter zero_cross=false; // reset zero cross detection flag } else { i++; // increment time step counter } } } void loop() { digitalWrite(buton1, HIGH); digitalWrite(buton2, HIGH); if (digitalRead(buton1) == LOW) { if (dim<127) { dim = dim + pas; if (dim>127) { dim=128; } } } if (digitalRead(buton2) == LOW) { if (dim>5) { dim = dim - pas; if (dim<0) { dim=0; } } } while (digitalRead(buton1) == LOW) { } delay(10); // waiting little bit... while (digitalRead(buton2) == LOW) { } delay(10); // waiting little bit... dim2 = 255-2*dim; if (dim2<0) { dim2 = 0; } Serial.print("dim="); Serial.print(dim); Serial.print(" dim2="); Serial.print(dim2); Serial.print(" dim1="); Serial.print(2*dim); Serial.print('\n'); delay (100); }

步骤9:更多的中断驱动软件

步骤10:Arduino可控调光器:结果和扩展

只是一个快速的手机记录下了它的工作过程



3通道
该电路还可用于RGB混频器,尽管您需要两个额外的三端双向可控硅电路。你可以使用这个电路+印刷电路板但请确保使用随机循环光耦合器suah作为MOC3021。不要使用MOC3041等过零光耦合器。
现在我做了一个3通道Ibble.

零交叉电路仅需要一次。
也许这仍然是传统(称之为老式):圣诞树灯直接工作在220(或110)伏特。在树上挂三根不同颜色的灯弦,用这个电路扩展两个可控硅电路来调节灯弦

频率
根据网格频率(50或60),需要手动设置不同的步长值。然而,可以让软件在设置程序中确定频率,例如,通过测量两次过零之间的时间或计算在设定时间内过零的次数。

步骤11:8051受控调光器:软件

显然,可以使用8051系列微控制器来控制调光器。
正如我不再拥有8051个开发系统,我无法测试任何代码,但如果您想要为8051开发这个,以下示例可能是帮助:

// //用8051控制交流//未经测试的代码//用MicroC Pro编译8051 int调光;int x;int我;空白ex0_isr (void) iv IVT_ADDR_EX0 ics ICS_AUTO ilevel 0  { /*===================================================*/ int dimtime =(75 *变暗);/ / delay_us (dimtime);P0 = 0 xff;//设置整个端口0高,也可以使用例如P0_1 =1;delay_us (10);/ / propagationdelay P0 = 0 x00;} void delay(int maal){for (x=1; x< maal; x++) { delay_us(75); // 65 for 60Hz } } /*===================================================*/ void main() { /*------------------------ Configure INT0 (external interrupt 0) to generate an interrupt on the falling-edge of /INT0 (P3.2). Enable the EX0 interrupt and then enable the global interrupt flag. ------------------------------------------------*/ IT0_bit =1; // Configure interrupt 0 for falling edge on /INT0 (P3.2) EX0_bit = 1; // Enable EX0 Interrupt EA_bit = 1; // Enable Global Interrupt Flag P0 = 0x00; //all pin of PORT0 declared as output while (1) { for(i=5;i<128;i++){ dimming=i; delay(10);//arbitrary delay between steps } } }

我不能保证这个代码工作,因为我没有办法测试它。如果有人尝试它并有结果,我会很高兴听到它。
一个应用说明描述了一个风扇按同样的原理控制,可以在这里找到

第12步:PIC控制LightDimmer:软件

如果你想用PIC微控制器来使用这个电路,这个链接中的软件可以帮助你更进一步:
http://www.edaboard.com/thread265546.html

一篇关于零交叉检测和PIC的好文章可以在这里找到:

http://tahmidmc.blogspot.nl/2012/10/zero-crossing-..。

作者Syed Tahmid Mahbub提供了一种检测零交叉的基本程序,然后触发LED,延迟为20ms。
虽然我从来没有与PIC的工作之前,我不破解C编程。我决定看看我是否可以建立在他的程序和使它可能改变光强度,而不是仅仅给它一个值(20毫秒延迟)。
我很快发现CAULD_MS和DELAY_US函数在C中有点棘手,即它们不接受变量。在汇编时需要知道延迟时间,因为它很难编码。我看到了一些复杂的工作,但我认为一个更简单的解决方案是制作一个函数,它给出了75美元延迟的函数(让65次为60Hz),并用参数确定延迟循环循环的频率如何调用。
最大环路次数为128次。这是因为我随机选择了在128步中调暗灯(0是完全打开,128是关闭)。
虽然警告:我没有PIC程序员,我不是规划(又要)进入照片,因为我与Atmega和Tartiny系列一样快乐。因此,我无法测试该程序。我只能说它没有问题编译,如果要在图片上使用电路,它将有助于您开始。您还可以找到完整的项目,包括程序,在这里包括红外遥控器和这里
//---------------------------------------------------------------------------------------------------------
/ /程序员:DIY_Bloke
//强烈基于来自Syed Tahmid Mahbub的0-X程序
//编译器:mikroc pro for pic v4.60
/ /目标图片:PIC16F877A
//相位角度控制程序
//在引脚33 RB0/INT过零信号
//通过PIN 19 RD0 / PSP0通过220-470r将信号通信到MOC3021
/ /石英4 MHz
//---------------------------------------------------------------------------------------------------------
无符号字符FlagReg;
int x;
int maal;
// '20'只是一个例子。调光应该包含一个
// 0到128之间的值,可以从例如e.g.一种
//可变电阻或LDR或出来的值出来
sbit ZC at FlagReg.B0;

无效中断(){
if (INTCON.INTF){//INTF标志被触发,因此外部中断发生
佐= 1;
INTCON。INTF = 0;
}
}

空隙延迟(int maal){
(x = 1;x <出席;x + +) {
delay_us (75);// 65为60Hz
}
}

void main(){
PORTB = 0;
TRISB = 0 x01;//中断RB0输入
porta = 0;
ADCON1 = 7;/ /禁用ADC
trisa = 0xff;//使所有porta输入
PORTD = 0;
TRISD = 0;/ / PORTD所有输出
option_reg.intedg = 0;//在下降沿中断
INTCON。INTF = 0;/ /清除中断标志
Intcon.inte = 1;//启用外部中断
INTCON。给= 1;/ /启用全局中断

而(1){
if (ZC){//发生零交叉
延迟(暗);// '20'是一个例子
portd.b0 = 1;//发送脉冲
delay_us (250);
PORTD。B0 = 0;
佐= 0;
}
}
}

步骤13:问题

如果你造的电路不工作了,除了开始冒烟。
在你对电路做任何工作之前把它从电源上拔掉!!

主要有3件事可以发生:

灯在闪烁
这可能是你遇到的最常见的问题,可能有几个原因。
- a'dry'powersupply。
如果你的电源发出很多额外的尖峰,这些尖峰会出现在0X信号引脚上,扰乱干净的过零信号。尝试另一个电源。
——“时间”问题
使用光耦合器可以得到精确的过零信号,但不是非常窄。这个电路的脉冲宽度(50Hz)通常在600us (0.6ms)左右,听起来足够快了。问题是,在50Hz时,每个半周期只需要10ms (60Hz时为8.33ms),所以脉冲宽度超过了总周期的5%。这就是为什么大多数调光器只能声称范围为10%-90% -过零脉冲持续时间太长,允许更大的范围。解决办法是避免自上而下或自上而下的监管。增加或有时减少步长值(50Hz为75,60Hz为65)也可以解决这个问题。

灯总是亮着
这可能是一种软件或硬件问题,以及对其进行调整的最简单方法是确保微控制器未连接到电路。如果灯仍然存在,则具有粗略的4种可能性:
- 你以某种方式搞砸了电路,检查它是否确实可以,并且一切都连接到它连接的位置。
- MOC3021以某种方式接收正输入,确保没有焊料短路的零散滴,不应该短路的东西。把输入线和地线短路,看看灯是否不亮。
- MOC3021高压端短路将MOC3021从插座上移除,看看会发生什么:如果你的灯不亮,很可能是MOC3021出了问题。如果你的灯一直亮着,那你的可控硅可能有问题
- 你有一个有缺陷的三折。如上所述。然而,如果它确实具有正确的值,请检查栅极电阻,只是为了确保

灯总是关着
由于这也可能是一个软件或硬件问题,首先看看发生了什么arduino断开。
将输入连接到一个+ 5v的电源,测量光耦的初级侧的电压(你的电路不应该连接到市电)。如果是几伏电压,把你的电路连接到电源上,看看会发生什么。如果灯打开,说明输入信号有问题。如果它保持关闭,你可能有一个错误的光耦合器,一个错误的可控硅或你的电路没有连接到电源。另一种可能是LED上的电压降阻止了光耦合器打开,特别是当你使用3.3 V作为驱动电压时。确保你有一个低电压下降的LED或更换它的电线桥。

可以帮助你测试可控硅电路的一段代码是添加以下设置

无效的设置()
{
PINMODE(AC_LOAD,输出);//将AC负载设置为输出
for(int i = 0; i <10; i ++){
digitalWrite (AC_LOAD、高);/ /双向可控硅触发
延迟(1000);
digitalWrite (AC_LOAD、低);/ /双向可控硅关
延迟(1000);
}
}
这将首先点燃可控硅几次,所以你可以看到它是工作的

最常见的错到现在

从所有联系我的关于电路不工作的问题的人,最常见的故障是:接线错误:芯片放倒了,焊点不好,电线没有接对。

第14步:门电阻:一点理论

在互联网上浏览可控硅开关时,你可能会遇到一个很大的分流,门电阻值。我的选择通常是取最低的值,仍将保护门和光耦合器。
读者马里·拉古纳斯在选择栅极电阻器值的标准背后做了一些理论研究。我将复制如下:

当电阻器放置在这个电路中,将有两个主要的影响:
a)它将限制/提供进入可控硅门的电流(I_{GT})
b)可控硅开启时电压下降(V_R)

这个电阻的最低值(对于220v交流)是R=220*根号(2)/I_{TMS},其中I_{TMS}是在光电耦合器的光敏可控硅中允许的最大峰值电流。这些是波动值,因此它们是短暂的,在崩溃前有一个极限。因此,在电路中,R将是R=220*根号(2)/1=311.12或330欧姆,因为MOC3021的I_{TMS}=1A。这与TIC206的峰值栅极电流I_{GM}是一致的。在原理图中,你用1K来限制电流为311mA。

只有当光电引频接收到脉冲并且它能够传导I_ {gt}时,并且当然可以用于220 * SQRT(2)的线值。然后将在三端双向可控硅大门中累积电荷,直到v_ {gt}得到积累并且三折被激活。

在象限I中,(V_ {gt}和a1比a2更好),以便足够的充电达到主动力带入蜜岛的v_ {gt}达到蜜蜂,而TRIAC两端的电压必须等于V_R + V_ {TM} + v_ {gt}
当然v_r = i_ {gt} * r。通常,v_ {tm} + v_ {gt}均占约3V(数据表)。同时,电阻器必须为三端双向可控硅大门提供足够的电流,让我们说最少25 mA(三端双向可控硅的灵敏度),因此

马V_{双向可控硅}= 330欧姆* 25 + 1.3 v + = 10.65 v和1.1 v
V_{可调式}= 1k欧姆*25mA+1.3V+1.1V=27.4V(你电路中的值)

这是启动可控硅所需的电压。因此,电阻越小,主可控硅开关所需的电压就越小。接下来发生的主要是在A1和A2上有一个电压降,因此光敏可控硅电压和电流将下降,导致(光敏可控硅)关断状态。如果保持电流I_H被考虑,主可控硅将保持接通。当负载电流低于I_H时,主可控硅关闭,直到光电二极管再次发射脉冲,以使V_{GT}极化,并在下一个周期中建立所需的电荷。Q1和Q3是这个设置的象限。

步骤15:调暗:一点理论

作为这个教程的背景:有各种类型的调光器。这里介绍的是一个相位控制(又称“相位切割”)前缘(又称“正向相位”)可控硅调光器。

前沿调光器
在这种类型中,调光器实际上切断了正弦波的开始部分。这是最广泛使用的类型的调光器,因为它是适用于triac。毕竟,可控硅很容易接通,一旦过零,它就会自动断开,因为电流降至栅保持电流以下

后缘调光器
也称为“反相控制”调光器。后缘调光器是一个相当多的复杂电路。不再使用具有前沿类型的简单电路,因为大多数三端双向可控硅件不能关闭。存在门关闭(GTO)三端双向可控硅,但在照明所需的相对较小的尺寸中,更昂贵且不太常见。为了能够实现尾部调光器,使用称为零交叉检测器的电路,开关装置必须接通,因为交流波形通过零。在通过控制设定的预定时间之后,开关装置被关闭,并且负载不使用波形的剩余部分。

尾随边缘调光器通常使用MOSFET,因为这些都需要几乎没有控制电流并坚固耐用可靠。它们也相对便宜,随时可用,额定电压适用于电源运行。另一种选择是使用IGBT(绝缘栅双极晶体管),该IGBT(绝缘栅双极晶体管)结合了MOSFET和双极晶体管的优点。这些通常比MOSFET更昂贵。同样,波形是理想的,从图9所示的实际波形显而易见的是,存在显着的偏差 - 特别是在全功率上。这是由于复杂的电子设备需要一些电压来运行的所施加的一些施加的电压。

大多数后缘调光器还有另一个有用的功能——至少在白炽灯上使用时是这样的。该电路设计为“软启动”,相对缓慢地增加灯的电压。对于白炽灯,这几乎消除了“热冲击”,即在开关时的短暂时间内,灯的电流大约是正常工作电流的10倍。热冲击是大多数电灯早期故障的原因——白炽灯在亮着的时候确实很少出现故障。失败几乎总是在开关打开的那一刻。通过加入软启动功能,灯的寿命增加了。

步骤16:零交叉:有点理论

虽然我已经描述了Zerocrosing,但我会花更多的话。
我在这个项目中使用的“桥和光耦合器”电路的原理非常清楚:一个市电交流电压通过2个33k的电阻,并通过二极管桥进行整流。
该整流导致脉动直流电压,使光耦合器保持开放,将零源信号低至电压下降到“零”,在光电耦合器不再导通,零源信号被拉高,直到电压升高再次足以将光耦再次发送到传导,导致Zerocross引脚低。
过零脉冲的“质量”当然取决于许多因素,但主要取决于光耦合器的速度、集电极电阻的值,但与市电线路中两个电阻的值无关。

如果这个值太低,你的光耦合器将烧坏,但如果它太高,电压仍然有足够的电流通过光耦合器,以保持它的导电变得越来越高。这意味着,如果电阻值太高,光耦合器的开关将发生更高的上升和下降侧的正弦波,导致一个宽过零信号,这开始于实际过零之前,直到过零之后。
因此:电阻器的值应该尽可能的低。但在实践中,我发现2x 33k是一个很好的值,导致在实际过零之前产生一个大约200uS的脉冲。这是可以接受的。通过4N25的电流大约是3.33 mA。当然,我们可以提高一个档次,但这不是必需的。有了这些值,该电路的空闲使用估计为0.7瓦

与H11AA1的电路实际上相同。H11AA1的优点是,一个人不需要二极管桥,因为它具有两个反平行二极管。IL250系列或LTV814也是如此
可以达到与两个常规光耦合器(例如4n25)达到相同的效果,如图所示或用双光耦合器。

我还提供了一个可以调节过零脉冲宽度的电路。
如前所述,过零信号的宽度决定了在实际过零中断产生之前的距离。理想情况下,如果知道过零信号有多宽,就可以在软件中考虑到这一点。假设你的信号是600uS宽,并且这是一个均分的时间。然后你知道你的中断是在实际过零之前300uS产生的。您可以在每次中断之后等待这段时间,以便更精确地处理过零

30个人完成了这个项目!

建议书

  • 词干比赛

    词干比赛
  • 角色扮演游戏挑战

    角色扮演游戏挑战
  • 数控大赛

    数控大赛

1,087评论

0.
najeeb53fattah

问题2个月前第8步

在我写了这个程序在我的笔记本电脑上,并试图放松它在我的纳米arduino猫这是一个错误在虚空,我不明白是什么原因

0.
najeeb53fattah

问题3个月前第8步

我可以将电路Digram栅极设置为设置下按钮Arduino纳米二聚体真空吸尘器电机驱动器

0.
rashed3e47

4个月前

我看过你们的"使用上下按钮设置电平的软件"代码。
我想用NODE单片机在Blynk平台上做一个项目。我想用3个触摸传感器开关(TTP223)来打开和关闭3个灯和4个更多的触摸传感器开关(TTP223)(或1个TTP224,它在一个模块中有4个触摸传感器)来控制交流风扇速度(零交叉检测)。为了做到这一点,我使用3虚拟Pin (V1, V2, V3)和另一个虚拟Pin (V4)为滑块按钮控制风扇速度在Blynk应用程序。它可以控制与互联网(Blynk应用程序)或没有互联网(手动触摸传感器开关)。在blynk app中还有开关状态反馈系统。我的问题是我不能匹配滑块按钮(Blynk应用程序的)与物理4触摸传感器开关(以4步控制风扇速度,即0(关闭),然后1,2,3(全速))和零交叉检测器程序在我的代码。请您在这方面帮助我。我的通讯地址是rashed_3e47@yahoo.com谢谢

1
diy_bloke.

4个月前的回复

拉希德,很遗憾听说你在布林克的项目遇到了困难。恐怕我不是这项工作的合适人选,因为我总是避开布林克,因此没有这方面的经验。我希望有人能帮助你

0.
rashed3e47

4个月前的回复

谢谢你的回复。我已经读了你的文章,并采取了“步骤8:软件设置水平使用向上和向下按钮”的代码,尝试学习过程,并尝试转换/修改它按照我的要求。这项工作很困难,因为它必须添加wifi和blynk协议,并与默认的两个向上和向下按钮相关联。非常感谢你非常好的和信息丰富的文章,人们可以从你的文章中学到很多东西。

1
rashed3e47

4个月前

特别感谢作者,为这样一篇信息丰富的文章,真的是非常非常非常有帮助的理解这件事,以及不同的代码。再次感谢。

0.
diy_bloke.

4个月前的回复

感谢您的客气话

0.
Kuljinder.

问题8个月前

我只是想问一下,为什么没有针分配给电位器的引脚,用于在步骤6中调光控制。

0.
diy_bloke.

8个月前

因为第六步只是一个演示程序,演示如何用arduino来调暗灯泡。你可以让它对电位器做出反应,如果你愿意,但如果这就是你想要的,你根本不需要一个微控制器

0.
Kuljinder.

8个月前回复

我想用温度传感器来控制吊扇的速度。我可以这样做与提供的电路和作出一些改变的代码

0.
diy_bloke.

4个月前的回复

Kuljinder我迟早没有看到你的后续评论道歉。我希望现在你已经找到了一个答案。
你描述的是可行的,但有更简单的方法来做。只需使用经典调光器并将变形电阻更改为NTC。然而,这将是非常原油。如果您想要更多控制,那么您需要如组合中所述的调光器,例如,arduino。程序并不难。只需使用温度传感器的值来确定您的调光变量

0.
ageedgarr.

问题9个月前

为什么在第四步中,FOR CYCLE从未停止????
谢谢! !
0.
diy_bloke.

8个月前

因为我不希望它停止。
这是一个演示程序,它一直在运行

0.
BrunoPedro

10个月前

你好,
我不明白我在哪里连接pwm引脚和过零引脚?
我应该使用哪些代码来通过Arduino IDE串行监视器控制调光器?

0.
Benjaminl140

1年前

嗨,家伙。很棒的工作!
我买的一个专业设备和你的一样有问题。问题很简单:当通道状态关闭时,可控硅没有适当地切断电源,我的可调光LED仍然亮着,而它应该完全关闭。分析功率——我可以看到常规的功率短“峰值”(每秒3或4次)。我尝试添加一个电阻(22K 5W) -但没有成功。我联系了制造商,他们只说“尝试不同的灯泡”......还有其他建议吗?我希望能有一个真正的状态…
谢谢你的帮助。

0.
diy_bloke.

1年前的回复

我可以想象你喜欢它工作得很好,有很多可能的原因,但有一个我可能没有在文章中:零交叉是zerocross实际上不是,个队伍有几个工作,但首先尝试看看能不能玩的时间。我不确定你使用的是什么程序(Robotdynn有一个库),但如果你调用中断在falling_侧翼,尝试rising_侧翼或反之。看看这能不能帮到你。你能告诉我从220到桥式整流器的降压电阻的值是多少吗?

0.
Sachind34.

问题1年前

风扇速度可以用这个来控制吗?

0.
diy_bloke.

1年前的回复

如果是带罩极电机的风扇,通常可以

0.
注8.

1年前

嗨,你建议添加保险丝和一个mov吗?电路保护?

0.
diy_bloke.

1年前的回复

不是特别的,当然你可以加上这些