最近没有什么产出,吓得 ZhengN 翻箱倒柜倒出一些小东西来发。下面分享一个 ZhengN 大二时候的一个小玩具,软硬件都分享给大家,有需要的小伙伴,文末获取。
这个小作品设计到了强电,不建议没经验的小伙伴上手,了解了解即可。
功能
用 STM32 控制一个普通灯泡的亮度,一路开关控制普通灯泡电源的通断,另外两路开关分别控制普通灯泡亮度的增加和减小。
调光控制器的原理
通过 STM32 控制双向可控硅的导通来实现白炽灯(纯阻负载)亮度的调整。双向可控硅的特点是导通后即使触发信号去掉,它仍将保持导通;当负载电流为零(交流电压过零点)时,它会自动关断。
所以需要在交流电的个半波期间都要送出触发信号,触发信号的送出时间就决定了灯泡的亮度。
调光的实现方式就是在过零点后一段时间才触发双向可控硅开关导通,这段时间越长,可控硅导通的时间越短,灯的亮度就越低;反之,灯就越亮。这就需要提取出交流电压的过零点,并以此为基础,确定触发信号的送出时间,达到调光的目的。
1、硬件
控制部分
:主控单元以 STM32F103RBT6 单片机为核心,交流电压过零点信号提 取电路中产生的同步信号 TB 接到 STM32F103RBT6 的 EXTI_Line0,此信号的下降沿将使 STM32F103RBT6 产生中断,以此为延时时间的起点。控制部分使用的是现有的最小系统板。
驱动部分
:驱动部分主要由可控硅组成。可控硅在电路中能够实现交流电的无触点控制,以小电流控制大电流。动作快、寿命长、可靠性高。所以这里选用的是可控硅。驱动部分使用的是自己绘制的电路板,电路原理图:
负载部分
:本电路智能控制纯阻负载白炽灯。
2、软件
要控制的对象是 50Hz 的正弦交流电,通过光耦取出其过零点的信号(同步信号),将这个信号送至单片机的外部中断,单片机接收到这个同步信号后启动一个延时程序,延时的具体时间由按键来改变。
当延时结束时,单片机产生触发信号,通过它让可控硅导通,电流过可控硅流过白炽灯,使灯发光。延时越长,亮的时间就越短,灯的亮度越暗(并不会有闪烁的感觉,因为重复的频率为 100Hz,且人的视觉有暂留效应)。由于延时的长短是由按键决定的,所以实际上就是按键控制了光的强弱。
经过实际调试得出,延时时间为 0~7ms 内的值。在程序中,我把 7ms 分割为 14 等份(实际上,分割的分数越大,调节的精度会更高,但是,为了有明显的现象,取 14)。对于按键的处理,采用查询法,并且采用按下一次就响应一次的方法,即长按不能连续调整。
主程序:
左右滑动查看全部代码>>>
int main(void)
{
GPIO_Configuration();
USART_Configuration();
EXTI_Configuration();
PrintfLogo();
Bright=14-z; // 亮度缺省值为 7(通过调 Z 间接得到 Bright)
printf("当前亮度 = % d \r\n", Bright);
while(1)
{
//S1(PC6) 调高灯的亮度
if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_6) == Bit_RESET)
{
delay_ms(5); // 消除抖动
if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_6) == Bit_RESET)
{
z--;
// 等待按键释放
while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_6) == Bit_RESET);
if(z==1)
{
z=14;
}
Bright=14-z;
printf("当前亮度 = % d \r\n", Bright);
}
}
//S2(PC7) 调低灯的亮度
if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_7) == Bit_RESET)
{
delay_ms(5); // 消除抖动
if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_7) == Bit_RESET)
{
z++;
// 等待按键释放
while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_7) == Bit_RESET);
if (z==14)
{
z=1;
}
Bright=14-z;
printf("当前亮度 = % d \r\n", Bright);
}
}
//S3(PC8) 调节灯的亮灭
if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_8) == Bit_RESET)
{
delay_ms(5); // 消除抖动
if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_8) == Bit_RESET)
{
/*S3_Num 为 S3 按下的次数,当按下的次数为奇数时灯灭
当按下的次数为偶数时,灯亮,并且亮度值为默认值 7*/
S3_Num=S3_Num+1;
// 等待按键释放
while(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_8) == Bit_RESET);
if(S3_Num%2==1)
{
__set_PRIMASK(1); // 关闭总中断,灯灭
printf("灯灭 \r\n");
}
else
{
__set_PRIMASK(0); // 打开总中断,灯亮
printf("灯亮,且亮度值为默认值% d \r\n", Bright);
}
}
}
}
}
外部中断函数:
void EXTI0_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line0)!=RESET)
{
delay_us(500*z); // 调节 z 的值来调节灯的亮度
GPIO_ResetBits(GPIOC,GPIO_Pin_11);
delay_us(100);
GPIO_SetBits(GPIOC,GPIO_Pin_11);
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
验证:
软硬结合是一件很酷的事情,虽然本公众号倾向于分享软件,但是 ZhengN 对硬件同样感兴趣。等到 ZhengN 软件学有所成之后再重新学习一些硬件知识,分享一些软硬结合的东西。玩嵌入式,是一辈子的事~