家庭自动化系统日益普及,如今通过使用一些简单的控制机制(如继电器或开关)来打开和关闭某些设备变得很容易,我们之前使用继电器构建了许多基于 Arduino 的家庭自动化项目。但是有许多家用电器需要控制这种交流电源,而不仅仅是打开或关闭。现在,进入交流相位角控制的世界,这是一种简单的技术,您可以通过它控制交流相位角。这意味着您可以控制吊扇或任何其他交流风扇的速度,甚至可以控制 LED 或白炽灯泡的强度。
虽然听起来很简单,但实际实现的过程非常困难,所以在本文中,我们将借助555 定时器构建一个简单的交流相位角控制电路,最后我们将使用 Arduino生成一个简单的PWM 信号来控制白炽灯泡的强度。正如您现在可以清楚地想象的那样,使用此电路,您可以构建一个简单的家庭自动化系统,您可以使用单个 Arduino控制风扇和交流调光器。
什么是交流相角控制,它是如何工作的?
交流相位角控制是一种我们可以控制或斩波交流正弦波的方法。开关器件的触发角在过零检测后发生变化,导致平均电压输出与修正的正弦波成比例变化,下图描述了更多信息。
如您所见,首先我们有交流输入信号。接下来,我们有过零信号,它每 10ms 产生一个中断。接下来是门极触发信号,一旦我们得到一个触发信号,我们等待一定的时间再给触发脉冲,我们等待的时间越长,我们越能降低平均电压,反之亦然。我们将在本文后面讨论更多的主题。
相角控制的挑战
在我们查看原理图和所有材料要求之前,让我们先谈谈与这种电路相关的一些问题以及我们的电路如何解决这些问题。
我们的目标是在微控制器的帮助下控制交流正弦波的相位角,用于任何类型的家庭自动化应用。如果我们看下图,你可以看到黄色是我们的正弦波,绿色是我们的过零信号。
当我们使用 50Hz 正弦波时,您可以看到过零信号每 10ms 出现一次。在微控制器中,它每 10 毫秒产生一次中断。如果我们要放置除此之外的任何其他代码,则其他代码可能由于中断而无法工作。我们知道在印度听到的线路频率是 50Hz,所以我们正在使用 50Hz 的正弦波,为了控制电源交流,我们需要在一定的时间范围内打开和关闭 TRIAC。为此,基于微控制器的相位角控制电路使用过零信号作为中断,但这种方法的问题是除了步速角控制代码之外,您无法运行任何其他代码,因为在某种程度上它会中断循环周期和其中一个代码将不起作用。
让我用一个例子来澄清一下,假设你要做一个项目,你需要控制白炽灯泡的亮度,同时你还需要测量温度。要控制白炽灯泡的亮度,您需要一个相位角控制电路,还需要读取温度数据,如果是这种情况,您的电路将无法正常工作,因为 DHT22 传感器需要一些时间给出它的输出数据。在这段时间内,相位角控制电路将停止工作,即如果您将其配置为轮询模式,但如果您将过零信号配置为中断模式,您将永远无法读取 DHT 数据因为CRC校验会失败。
为了解决这个问题,您可以为不同的相位角控制电路使用不同的微控制器,但这会增加 BOM 成本,另一种解决方案是使用我们的电路,该电路由 555 定时器等通用组件组成,成本也更低。
交流相角控制电路所需材料
下图显示了用于构建电路的材料,因为它是由非常通用的组件制成的,您应该能够在当地的爱好商店中找到所有列出的材料。
我还在下表中列出了组件的类型和数量,因为它是一个演示项目,所以我使用单通道这样做。但电路可以根据需要轻松扩展。
交流相角控制电路图
交流相位角控制电路原理图如下图所示,该电路非常简单,使用通用元件来实现相位角控制。
交流相角控制电路——工作
该电路由非常精心设计的组件组成,我将逐一介绍并解释每个模块。
过零检测电路:
首先,在我们的列表中,过零检测电路由两个 56K、1W 电阻器以及四个 1n4007 二极管和一个 PC817 光耦合器组成。该电路负责向 555 定时器 IC 提供过零信号。此外,我们已经对相位和中性信号进行了录音,以便在 TRIAC 部分进一步使用它。
LM7809 稳压器:
7809稳压器是用来给电路供电的,电路负责给整个电路供电。此外,我们使用了两个 470uF 电容和一个 0.1uF 电容作为 LM7809 IC 的去耦电容。
NE555定时器控制电路:
上图显示了 555 定时器控制电路,555 配置为单稳态配置,因此当来自过零检测电路的触发信号击中触发器时,555 定时器开始借助电阻器对电容器充电(一般来说),但我们的电路有一个 MOSFET 代替电阻器,通过控制 MOSFET 的栅极,我们控制流向电容器的电流,这就是我们控制充电时间的原因,因此我们控制 555 定时器的输出。 在许多项目中,我们使用555 定时器 IC来制作我们的项目,如果您想了解更多关于这个主题的信息,您可以查看所有其他项目。
TRIAC 和 TRIAC 驱动电路:
TRIAC 作为实际打开和关闭的主开关,从而控制交流信号的输出。驱动TRIAC的是MOC3021光可控硅驱动器,它不仅驱动TRIAC,还提供光隔离,0.01uF 2KV高压电容,47R电阻组成缓冲电路,保护我们的电路免受高压尖峰的影响当它连接到感性负载时会发生这种情况,开关交流信号的非正弦特性是造成尖峰的原因。此外,它还负责功率因数问题,但这是另一篇文章的主题。此外,在各种文章中,我们将TRIAC作为我们的首选设备,如果您感兴趣,可以查看这些文章。
低通滤波器和 P 沟道 MOSFET(作为电路中的电阻器):
82K 电阻和 3.3uF 电容组成低通滤波器,负责平滑 Arduino 产生的高频 PWM 信号。如前所述,P 沟道 MOSFET 充当可变电阻器,控制电容器的充电时间。控制它的是被低通滤波器平滑掉的PWM信号。在上一篇文章中,我们已经清除了低通滤波器的概念,如果您想进一步了解该主题,可以查看有关有源低通滤波器或无源低通滤波器的文章。
交流相角控制电路的 PCB 设计
我们的相位角控制电路的 PCB 设计在单面板上。我使用 Eagle 来设计我的 PCB,但您可以使用您选择的任何设计软件。我的电路板设计的 2D 图像如下所示。
足够的接地填充物用于在所有组件之间建立正确的接地连接。12V DC 输入和 220 V AC 输入位于左侧,输出位于 PCB 右侧。Eagle 和 Gerber 的完整设计文件可以从下面的链接下载。
手工PCB:
为方便起见,我制作了我手工制作的 PCB 版本,如下所示。
用于交流相角控制的 Arduino 代码
一个简单的 PWM 生成代码用于使电路工作,代码及其解释如下。您还可以在此页面底部找到完整的代码。首先,我们声明所有必要的变量,
常量 int 类比输入引脚 = A0;// 电位器连接到的模拟输入引脚
常量 int 模拟输出引脚 = 9; // LED 连接到的模拟输出引脚
int 传感器值 = 0; // 从锅中读取的值
int 输出值 = 0; // 值输出到 PWM(模拟输出)
变量用于声明 Analog 引脚、analogOut 引脚,其他变量用于存储、转换和打印映射值。接下来在setup()部分,我们将 UART 初始化为 9600 波特,以便我们可以监控输出,这就是我们如何找出能够完全控制电路输出的 PWM 范围。
无效设置(){
// 以 9600 bps 初始化串行通信:
序列号.开始(9600);
}
接下来,在loop()部分,我们读取模拟引脚 A0 并将值存储到传感器值变量中,接下来我们将传感器值映射到 0 -255 因为 atmega 的 PWM 定时器只有 8 位,接下来我们使用 Arduino的analogWrite()函数设置PWM 信号。最后,我们将值打印到串行监视器窗口以找出控制信号的范围,如果您按照本教程进行操作,最后的视频将使您对该主题有更清晰的了解。
sensorValue = analogRead(analogInPin);// 读取模拟输入值:
outputValue = map(sensorValue, 0, 1023, 0, 255); // 将其映射到模拟输出的范围:
模拟写入(模拟输出引脚,输出值);// 改变模拟输出值:
Serial.print("传感器 = "); // 将结果打印到串行监视器:
Serial.print(sensorValue);
Serial.print("t 输出 = ");
Serial.println(outputValue);
测试交流相角控制电路
上图显示了电路的测试设置。12V 电源由 12V SMPS 电路提供,负载在我们的例子中是一个灯泡,它可以很容易地替换为像风扇这样的电感负载。另外你可以看到我已经连接了一个电位器来控制灯的亮度,但它可以用任何其他形式的控制器代替,如果你放大图像,你可以看到电位器连接到Arduino 的 A0 引脚和 PWM 信号来自 Arduino 的 pin9。
如上图所示,输出值为84,白炽灯泡的亮度很低,
在这张图片中,您可以看到该值为 82,并且白炽灯泡的亮度增加了。
经过多次失败的尝试,我能够想出一个实际工作正常的电路。有没有想过当电路不工作时测试台的外观?让我告诉你它看起来很糟糕,
这是我之前设计的电路。我不得不将它完全扔掉并制作一个新的,因为前一个有点不起作用。
进一步增强
对于这个演示,电路是在手工制作的 PCB 上制作的,但是电路可以很容易地构建在质量好的 PCB 上,在我的实验中,由于元件尺寸,PCB 的尺寸确实很大,但在生产环境中,它可以通过使用廉价的 SMD 元件来减少,在我的实验中,我发现使用 7555 定时器而不是 555 定时器可以大大增加受控者,此外,电路的稳定性也增加了。
常量 int 类比输入引脚 = A0;// 电位器连接到的模拟输入引脚
常量 int 模拟输出引脚 = 9; // LED 连接到的模拟输出引脚
int 传感器值 = 0; // 从锅中读取的值
int 输出值 = 0; // 值输出到 PWM(模拟输出)
无效设置(){
// 以 9600 bps 初始化串行通信:
序列号.开始(9600);
}
无效循环(){
sensorValue = analogRead(analogInPin);// 读取模拟输入值:
outputValue = map(sensorValue, 0, 1023, 0, 255); // 将其映射到模拟输出的范围:
//outputValue = map(sensorValue, 0, 1023, 0, 255); // 将其映射到模拟输出的范围:
模拟写入(模拟输出引脚,输出值);// 改变模拟输出值:
Serial.print("传感器 = "); // 将结果打印到串行监视器:
Serial.print(sensorValue);
Serial.print("t 输出 = ");
Serial.println(outputValue);
延迟(2);// 在模数转换的下一个循环之前等待 2 毫秒
}