15

单片机很好玩14,制作“人工向日葵”,自动寻光

 4 years ago
source link: https://blog.popkx.com/single-chip-computer-is-very-interesting-14-making-artificial-sunflower-automatic-light-seeking/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

上一节介绍了如何使用C语言编程单片机控制步进电机转动,在文章最后提到,只要再结合感光器件,我们就能够制作一个“人工向日葵”,如下图:

dd70a5e742a4472c97dde232442ef248

可以看出,单片机控制步进电机带着“箭头”始终指向光源,就好像向日葵一直跟着太阳一样。怎么做呢?

两项基本工作

这里仍然计划使用 51 单片机作为控制中心,那么要制作“人工向日葵”,需要先完成两项基本工作:一是获取光源的方向,知道光源在哪个方向后,还要有能力带着“箭头”转动,直到指向光源。完成这两项基本工作后,剩下的工作就简单了。

721f8a1e9987ec6ea71e0948293ca151.png

先来看看怎样带着“箭头”转动

还记得上一节介绍的步进电机吗?它就非常适合完成这些工作,将箭头粘在步进电机的转动轴上,单片机驱动步进电机转动就可以带动“箭头”转动了。关于单片机如何驱动步进电机,这里就不赘述了,感到陌生的朋友可以看看上一节的文章。

再来看看如何获取光源方向

对我们人类来说,要判断光源方向实在太简单了,看一看周围就知道了,基本上光线最强的方向就是光源的方向。那么,单片机该怎样判断光源方向呢?

参照人类判断光源方向的方法,单片机首先要能“看到”环境光线情况。如何让单片机“看到”环境光线,第 11 节和第 12 节已经介绍的比较清楚了。这里还是采用和之前一样的方法:借助于光敏电阻。

dd798ffa30aadd74f8fbfc213fef88ee.png

光敏电阻的阻值会随着照射在它表面的光纤强度的改变而改变,利用欧姆定律,很容易将这种阻值变化转换为电压值变化,再利用 ADC 模块,单片机就可以通过 ADC 采样值,间接感知环境的光线情况了。

158cad99ec273aee62f9a89ecddd8c21.png

现在单片机能看到环境光线了,那怎样判断光源方向呢?似乎可以采取这样的办法:将光敏电阻粘在步进电机的转动轴上,然后利用单片机驱动步进电机带着光敏电阻转动,先“看一看”四周的光线,沿途记录光强值,转完一圈后,光强最强的方向就是光源的方向,再驱动步进电机转回来。

可是这种方法有个比较大的缺陷:如果想始终控制“箭头”指向光源,步进电机是不能停的,它得不停的检测四周的光线强度。这时,我们从外界看,箭头的方向是哪里呢?其实没有方向,它一直在转动。

可能你会说:可以在找到光源以后,驱动步进电机带着箭头转回来之后,停一会不就行了吗?可是步进电机停下后,不就没法“始终”指向光源方向了吗?所以,采取一个光敏电阻很难达成目标。

只用一个光敏电阻,至少我想不到好办法,如果读者有什么好办法,可以在评论区回复,让我长长见识。

也是考虑了好一会儿,决定使用两个光敏电阻,中间使用隔板挡开,如下图。

8cbbbc2b52e264049ac98e18e1535b7f.png

正常情况下,除非正对着光源,否则总有一个光敏电阻接收的光线更强,而接收到更强光线的那个光敏电阻一般就在光源方向,这时驱动步进电机带着光敏电阻往光源方向转动就可以了。

当两个电阻接收的光线强度相差无几时,就可以停下了,一旦光强差较大,就继续驱动步进电机往光较强方向转动,这样就实现了“人工向日葵”的基本功能:始终指向光源方向。

但是这种方法要求两个光敏电阻有相同的光响应曲线,而世界上不可能有一模一样的东西,所以这里使用了可调电阻,如下图:

c7625a2fb9e42d65d84dadd8917142e6.png

通过调节可调电阻,可以尽力让两个光敏电阻的响应特性接近。

编写C语言程序,实现“人工向日葵”的设计

现在思路和设计都有了,写C语言代码就简单了,毕竟重在设计,写代码本身没有什么技术含量。ADC 模块的相关C语言代码,我们之前已经写过很多次了,这里需要说明的是,P1ASF 寄存器决定开启几个通道的 ADC,因为我们的设计需要两路,所以给 P1ASF 赋值为 0x03,表示使用单片机的 P1.0 和 P1.1 作为 ADC 采样输入口了。

void adc_init()
{
    P1ASF = 0x03;       
    ADC_RES = 0;
    ADC_CONTR = ADC_POWER|ADC_SPEEDLL;
    delay_about_100ms(2);
}

步进电机相关的C语言代码上一节已经介绍,这里不再赘述。主控程序的C语言代码如下:

void main()
{
    WORD res0 = 0, res1 = 0;

    adc_init();

    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);
    }
}
962ed69003386c02438b263e37b392d0.png

因为两个光敏电阻不可能完全一样,所以代码中有一个 20 的光强阈值,只有光强差超过 20 时,系统才认为需要转动步进电机调整箭头方向。而且,设定 20 作为阈值,也能防止因为电路噪声,或者光源不稳定导致的箭头抖动问题。

现在编译C语言程序,烧写到单片机,发现我们成功了。

dd70a5e742a4472c97dde232442ef248

现在有了“人工向日葵”,我们可以在此基础上再做一些好玩又有用的东西:比如一款追着光源跑的小车,再比如一个自动追着太阳方向的晒鞋器,甚至,可以用在现在非常火热的新能源光伏发电上,想想看,光能发电板始终正对着太阳,能提升多少发电效率啊


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK