STC12C5A60S2 单片机,光敏电阻,步进电机,制作寻光器,始终指向光源
发表于: 2018-08-15 22:51:18 | 已被阅读: 31 | 分类于: 单片机
光纤传感专业的我转行做了嵌入式软件,可是心系光学专业啊。下班回来发现个 stc 的 51 单片机最小系统,是我之前做的,好久没碰了。正好手边有两个光敏电阻,结合着步进电机,琢磨着做一个寻光器
玩玩,让箭头始终指向光源。
总体思路
因为要寻找光源,所以需要一个能感知外界光线的器件,这里选择了
- 设计电路,将对光功率变化敏感的电阻信息转换为电压信息
- 设计单片机程序,驱动 STC12C5A60S2 的 AD 模块采集光敏电压信息
- 设计程序,驱动步进电机转动
- 设计算法,使步进电机时钟指向光源
将光敏电阻信息转换为光敏电压信息
这里直接使用了最简单的电路,如下图,就是一个可调电阻和光敏电阻串联,可调电阻的大小要与光敏电阻的常态接近。
STC12C5A60S2 的 AD 驱动程序
这个程序可参考:
步进电机驱动程序
我使用的是
\#include "reg51.h"
char motorIndex = 0;
unsigned char code beatCode[8] = {0xe,0xc,0xd,0x9,0xb,0x3,0x7,0x6};
void Delay2ms(unsigned int cnt)
{
unsigned int i = 2000;
while(cnt--)
while(i--);
}
void MotorTurn(unsigned int rounds)
{
while(rounds--){
P0 = beatCode[motorIndex];
motorIndex ++;
motorIndex = motorIndex&0x07;
Delay2ms(1);
}
}
void MotorTurnBack(unsigned int rounds) // 反转
{
while(rounds--){
P0 = beatCode[motorIndex];
if(motorIndex > 0)
motorIndex --;
else
motorIndex = 7;
Delay2ms(1);
}
}
寻光算法
算法也是考虑了很久,最后决定使用两个光敏电阻,两个光敏电阻的电路是相同的,都是上面介绍的电路。只不过,将两个电阻之间用隔光纸板隔开了,如下图
如果光源在左边,则左边的电阻接收光强比右边的大。如果光源在右边,则反之。如此一来,寻光算法就非常简单了,就是判断两边光强,那边强往哪边转。在实验之前,调节两个光敏电阻电路中的可调电阻,使两个光敏电阻在相同光强下,尽量输出接近的电压值。最后,总体程序如下:
void main()
{
WORD res0 = 0, res1 = 0;
InitADC();
while(1){
res0 = get_adc_res(0);
res1 = get_adc_res(1);
if(res0-20 > res1)
MotorTurnBack(100);
else if(res1-20 > res0)
MotorTurn(100);
}
}
可以看出,非常简单。单片机的 ADC 通道 0 和 通道 1 分别探测两个光敏电阻电路输出的电压值,只要两个电压值差值大于阈值,则驱动步进电机步进100个角度。
最终,寻光器的工作效果如下:
[video width="544" height="960" mp4="https://www.xrkzn.cn/wp-content/uploads/2018/08/寻光器.mp4"][/video]