激光投影POV-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 21564|回复: 22

激光投影POV

[复制链接]
发表于 2015-10-2 00:21 | 显示全部楼层 |阅读模式
前言
  参加社区比赛的制作,实在想不出什么点子,就做一个摇摇棒的激光版本吧。

电路原理
  
002304k36ag30bg92sddsg.jpg

制作步骤
  • 先看运行效果
    打个招呼:Hi, I'm seesea : )
    001324r5rmjdrddd0jo0d4.jpg
  • 做支架
    感谢奥松机器人提供的套件。
    001320hffalgodipqqfmll.jpg
  • 激光管组合
    原以为共阳的方便使用,后来发现不能用ULN2803驱动,但木已成舟。在面包板测试的图中可以看到ULN2003(没有2803只使用七个灯测试)用了上拉电阻,可是电阻太大带不动电阻太小了发烫,只好用三极管来驱动。所以最终的电路图里修正为共阴的接线方式。
    难 点在于每一个激光管的方向对齐,不然略远一点距离就会偏得很明显,真是应了成语:差之毫厘,谬以千里。调整很累:先整体用热熔胶粘好,然后点亮激光管,利 用胶枪头的热一个一个激光管化开慢慢调整位置,调整好一个后冷却定型后再调整下一个,而调整后一个的时候还会影响到前一个,所以特别难。没办法呀,最原始 的木作加美工“裁纸刀”呀……会3D的话同学用3D打印应该精度好一些。
    调整过程要盯着激光点看,很伤眼,提醒大家注意护眼
    经过好几晚的调整终于弄平整了,激光管可能受热有损坏,有一些亮度降了很多,最后的效果图可以看到中间几个亮度明显暗了,只是没有更换激光管的欲望了,这可真是苦差事。
    裁纸刀切三合板:
    001324gjgmpgb71j7to11k.jpg

    切成这样已经很不错了:

    001319i0u017cizu19u8ul.jpg
    试试大小:
    001319y75qiit71v3nip1q.jpg
    共阴焊接:

    001319pbqotzglotggntuz.jpg
    焊好:
    001319xzllwtus1n118tom.jpg

  • 安装上激光管组合
    001320w1sk1kb7b31frz3h.jpg
  • 制作反光镜
    塑料片贴反光膜做的反光镜效果不好,太软会变形,反光后激光散了不平行,如果有条形的真正的镜子就好了。找半天发现一些树莓派坏外壳的亚克力挺平整的,救星啊。
    超市送的山寨扇子,废物利用吧。
    001320heronsxpizopnksr.jpg
    裁好:
    001320w94yk3saaa5zzy56.jpg
    反光膜,六块包邮:
    001321o221i51iisbjv88s.jpg
    做好:
    001321z4y6zw3yub6nbd1e.jpg
    还是要硬点的,有坏的树莓派亚克力外壳:
    001321gdb3d5a139he33km.jpg
    没工具,用手折:
    001321lczrklualtl6ber0.jpg
  • 安装反光镜
    001322k9ae0bz01an1v9sg.jpg
  • 安装光敏电阻
    如果有合适的机械结构是要做成活动可以调整的,这样可以控制显示范围,可以根据显示内容的长短做调整。
    001322chiimbdnbzrzz8s5.jpg
  • 搭电路接起来
    原来使用 UNO,但为了方便成组操作8个激光管,需要使用一个整个端口,UNO 只有一个完整的端口 pin0 - pin7 => PORTD,但是又要用到两个外部中断,所以要请来 Mega2560 了……
    001322d9oorbtgtjzyuejc.jpg
  • 焊接功能板
    面包板测试完后,焊接电路固定好。
    001322n49dlrt693d5ut3x.jpg
    001323mc9g5c5amlial5a7.jpg
    001323jdvd12ld2bub1lry.jpg
    001323dwyl1u3yrc9qsc2w.jpg
  • 整机安装好
    001323tsnpevf3d3vw3r6s.jpg
  • 运行:亮灯和关灯效果
    默认显示LOGO:seesea,有点自恋啊。
    001324rz04vy3rfpmftpk3.jpg
    001324sx3hx25owi27xy2h.jpg
  • 支持串口改字
    串口支持了,就相当于支持了蓝牙和 wifi 等各种便捷接口啦。
    ArduinoCN:
    001324k0lzssc5c0l56c0c.jpg

程序源码
  • 完整代码下载:点击下载附件
  • 主程序展示(凑个字数哈)
    [mw_shl_code=cpp,true]
    // ----------------------------------------------------------------------------
    // povLaser.ino
    //
    // Created 2015-08-26
    // By seesea <seesea2517#gmail#com>
    //
    // 激光POV
    //
    // - 由于需要用到外部中断,又想要端口整体操作,所以用了 mega2560
    // - A0 - A7 为 PORTK 端口,接到八个激光二极管正极,激光二极管负极接地(原用 pin22 - pin29 PORTA 端口,但焊接电路不方便就改 PORTK 了)
    // - pin21 为外部中断 2,作为 POV 起点的光敏电阻检测引脚
    // - pin20 为外部中断 3,作为 POV 终点的光敏电阻检测引脚
    // - 光敏电阻一端接 VCC,另一端通过 10K 的可变电阻接到 GND,相接处引出接到 pin20 和 pin21
    //   通过调整可变电阻达到调整检测灵敏度的目的,以便在不同的亮度的环境下使用
    // - pin3 输出 PWM 通过 PNP 三极管控制电机转动,通过调整 PWM 值控制电机以合适速度转动
    // - 电机控制一个镜子转动,镜子反射激光,达到偏转光线的作用
    //
    // 原打算在电机轴上使用光栅和红外对管来检测起止位置,后来发现镜子的转动造成光线 2 倍于镜子的转动角偏转,不好用
    // 所以给发射部分增加一个激光管做为光线位置指示,用光敏电阻来检测就完全吻合了
    //
    // ----------------------------------------------------------------------------

    #include "asciiToDot.h"
    #include <avr/io.h>

    #define PORT_LASER  PORTK                               // 控制八个激光二极管的端口寄存器
    #define DDR_LASER   DDRK                                // 控制八个激光二极管的端口方向寄存器

    const char interruptNumStartSensor = 2;                 // 开始显示的光敏电阻的中断号
    const char interruptNumStopSensor  = 3;                 // 结束显示的光敏电阻的中断号
    volatile unsigned long ti          = 0;                 // 中断函数中用于记录时间的变量
    volatile unsigned long microDelay  = 0;                 // 扫描时激光二极管的点亮延时,在中断函数中更新值
    volatile bool flagDisplayOn        = false;             // 是否显示的标志,当开始光敏电阻检测到信号的时候置 true,结束光敏电阻检测到信号时置 false

    const unsigned char pinPwmMotor    = 3;                 // 电机 pwm 控制引脚号
    const unsigned char pwmMotor       = 150;               // 电机 pwm 值

    #define MAX_BUF_SIZE 50                                 // 串口接收最大字符数
    char bufStr[MAX_BUF_SIZE] = "seesea";                   // 默认显示字符
    byte *bufDot = stringToDot(bufStr);                     // 点阵缓冲区
    int  colNum  = strlen(bufStr) * asciiCharDotWidth;      // 点阵缓冲区大小

    // 开始显示的中断处理函数
    void ISR_displayOn()
    {
        ti = millis();
        flagDisplayOn = true;
    }

    // 结束显示的中断处理函数
    void ISR_displayOff()
    {
        microDelay = 1000 * (millis() - ti) / colNum;
        flagDisplayOn = false;
    }

    void setup()
    {
        DDR_LASER = 0xFF;

        pinMode(pinPwmMotor, OUTPUT);
        analogWrite(pinPwmMotor, pwmMotor);

        attachInterrupt(interruptNumStartSensor, ISR_displayOn,  RISING);
        attachInterrupt(interruptNumStopSensor,  ISR_displayOff, RISING);
        interrupts();

        Serial.begin(9600);
    }

    void loop()
    {
        int i = 0;

        if (! flagDisplayOn)
            return;

        for (i = 0; i < colNum; ++i)
        {
            PORT_LASER = bufDot;
            delayMicroseconds(microDelay);
        }
    }

    // 串口中断
    // 接收串口输入的字符串,更新显示缓冲区
    // 输入以 \n 为结束符,结束输入后更新点阵显示缓冲区从而更新显示内容
    // 注意:一次输入可能发生多次串口中断
    void serialEvent()
    {
        static int i = 0;
        while (Serial.available())
        {
            bufStr = (char)Serial.read();

            if (bufStr == '\n')
            {
                bufStr = '\0';
                delete [] bufDot;
                bufDot = stringToDot(bufStr);
                colNum = strlen(bufStr) * asciiCharDotWidth;
                i = 0;
                break;
            }

            if (i >= MAX_BUF_SIZE)
                continue;

            ++i;
        }
    }
    [/mw_shl_code]
软件字库的制作
  • 没有字库芯片,咱自力更生做软件字库
  • 制作步骤如下:
  • 整理所需要的字符:整理了从空格到波浪号这一批常用ascii字符,它们的ascii码连续,方便编写程序
  • 选择等宽字体,并且缩到最小显示效果也不错的字体,选择了“Courier New”字体,做成 8 个像素高的图片,可以发现每一个字符都是 7 个像素宽,这样就方便程序计算每一个字符的偏移量了
    其中有一些字符的位置需要手工调整:
    • g j p q y 上移两个像素
    • 所有的符号全体上移两个像素
    • j {} 还有微调(高度缩短了一个像素)
  • 使用字模软件取模后,做成一个数组即可
  • 编写函数根据输入的字符取得点阵信息
    根据每个字符宽 7 个像素,即在数组中占 7 个元素,首位是空格,ascii 值为 32,从而程序很容易计算任何一个字符的点阵数据在数组中的位置为: (字符的 ascii 值 - 空格的 ascii 值) * 7,连续 7 个元素
  • 附上像素图(请准备好放大镜哦:D)
    001933hu9riyztfptqtlcy.bmp
视频欣赏

  
1.jpg
2.jpg
3.jpg
4.jpg
5.jpg
6.jpg
7.jpg
8.jpg
9.jpg
10.jpg
11.jpg
12.jpg
13.jpg
14.jpg
15.jpg
16.jpg
17.jpg
18.jpg
19.jpg
20.jpg
21.jpg
22.jpg
23.jpg
24.jpg
knife.jpg
totalASCII.bmp
laserPOV.jpg

povLaser.zip

4.38 KB, 下载次数: 46

相关帖子

 楼主| 发表于 2015-10-2 13:22 | 显示全部楼层
发表于 2015-10-3 09:12 | 显示全部楼层
66666666666666666666666666666
绝对表白神器系列
 楼主| 发表于 2015-10-3 11:37 | 显示全部楼层
virtualwiz 发表于 2015-10-3 09:12
66666666666666666666666666666
绝对表白神器系列

啊,没想过这层应用……还有这功能啊。。。
 楼主| 发表于 2015-10-3 11:38 | 显示全部楼层
发表于 2015-10-20 10:21 | 显示全部楼层
可以当留言板啊,激光管能够直接显示字母吗?
 楼主| 发表于 2015-10-20 14:07 | 显示全部楼层
soarlucky 发表于 2015-10-20 10:21
可以当留言板啊,激光管能够直接显示字母吗?

这个装置可以串口直接改字~
发表于 2015-12-3 15:21 | 显示全部楼层
双反光面可以使间隔变小吗?谢谢!
 楼主| 发表于 2015-12-4 09:48 | 显示全部楼层
礱蘢蠪 发表于 2015-12-3 15:21
双反光面可以使间隔变小吗?谢谢!

哇,这个问题很有价值。
可以的,相当于无光的阶段被缩短了。由于手工制作的原因不容易制作双面反光,且单面的效果也还过得去,就没有深入研究了。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-30 23:56 , Processed in 0.233942 second(s), 23 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表