激光投影POV(下)(2015-10-01)
2015-10-01 23:30
471 查看
文章字数限制,分成三篇:
激光投影POV(上)(2015-10-01)
激光投影POV(中)(2015-10-01)
激光投影POV(下)(2015-10-01)
主程序展示(凑个字数哈)
制作步骤如下:
整理所需要的字符:整理了从空格到波浪号这一批常用ascii字符,它们的ascii码连续,方便编写程序
选择等宽字体,并且缩到最小显示效果也不错的字体,选择了“Courier New”字体,做成 8 个像素高的图片,可以发现每一个字符都是 7 个像素宽,这样就方便程序计算每一个字符的偏移量了
其中有一些字符的位置需要手工调整:
g j p q y 上移两个像素
所有的符号全体上移两个像素
j {} 还有微调(高度缩短了一个像素)
使用字模软件取模后,做成一个数组即可
编写函数根据输入的字符取得点阵信息
根据每个字符宽 7 个像素,即在数组中占 7 个元素,首位是空格,ascii 值为 32,从而程序很容易计算任何一个字符的点阵数据在数组中的位置为: (字符的 ascii 值 - 空格的 ascii 值) * 7,连续 7 个元素
附上像素图(请准备好放大镜哦:D)
激光投影POV(上)(2015-10-01)
激光投影POV(中)(2015-10-01)
激光投影POV(下)(2015-10-01)
程序源码
完整代码下载:点击下载附件主程序展示(凑个字数哈)
// ---------------------------------------------------------------------------- // 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[i]; delayMicroseconds(microDelay); } } // 串口中断 // 接收串口输入的字符串,更新显示缓冲区 // 输入以 \n 为结束符,结束输入后更新点阵显示缓冲区从而更新显示内容 // 注意:一次输入可能发生多次串口中断 void serialEvent() { static int i = 0; while (Serial.available()) { bufStr[i] = (char)Serial.read(); if (bufStr[i] == '\n') { bufStr[i] = '\0'; delete [] bufDot; bufDot = stringToDot(bufStr); colNum = strlen(bufStr) * asciiCharDotWidth; i = 0; break; } if (i >= MAX_BUF_SIZE) continue; ++i; } }
软件字库的制作
没有字库芯片,咱自力更生做软件字库制作步骤如下:
整理所需要的字符:整理了从空格到波浪号这一批常用ascii字符,它们的ascii码连续,方便编写程序
选择等宽字体,并且缩到最小显示效果也不错的字体,选择了“Courier New”字体,做成 8 个像素高的图片,可以发现每一个字符都是 7 个像素宽,这样就方便程序计算每一个字符的偏移量了
其中有一些字符的位置需要手工调整:
g j p q y 上移两个像素
所有的符号全体上移两个像素
j {} 还有微调(高度缩短了一个像素)
使用字模软件取模后,做成一个数组即可
编写函数根据输入的字符取得点阵信息
根据每个字符宽 7 个像素,即在数组中占 7 个元素,首位是空格,ascii 值为 32,从而程序很容易计算任何一个字符的点阵数据在数组中的位置为: (字符的 ascii 值 - 空格的 ascii 值) * 7,连续 7 个元素
附上像素图(请准备好放大镜哦:D)
视频欣赏
相关文章推荐
- 100个常用的linux命令
- Java核心技术第3章(8)
- 把windows窗口置顶--Windows on Top
- mysql中sql语句执行时间
- 我的IOS成长之路——by Swift
- 弱校联萌十一大决战之强力热身
- 重温经典之排序 java实现
- iOS项目总结-GCD
- JDBC中Statement接口提供的execute、executeQuery和executeUpdate之间的区别(转)
- 找数组中出现超过一半的数 JAVA
- 如何给我们的eclipse新建文件自动生成注释
- 我的感触和想法
- activity view 截图
- 压缩感知(compressed sensing)科普两则
- BZOJ 2730: [HNOI2012]矿场搭建( tarjan )
- 【Python之旅】第四篇(二):Python异常处理与异常捕捉
- 【Python之旅】第四篇(二):Python异常处理与异常捕捉
- iOS项目经验-创建线程的三种方式
- 激光投影POV(中)(2015-10-01)
- 爬虫入门——01