NO7 自行车POV制作 (基本完结)

POV原理:

Persistence of vision是光对视网膜所产生的视觉,在光停止作用后,仍保留一段时间的现象,其具体应用是电影的拍摄和放映。原因是由视神经的反应速度造成的,其时值约是十六分之一秒,对于不同频率的光有不同的暂留时间。是动画、电影等视觉媒体形成和传播的根据。而装在自行车上,很多人将它称之为风火轮。就像小时候的偶像哪吒脚上踩的轮子。

制作步骤:

1、查找资料

视觉1:发现装在自行车上的POV国内商店有卖,但很少能自编程,显示自己想要显示的东西基本没可能。也基本都是安装在自行车上,单纯的显示一个圆圈,只知道跑起来后轮子会发光,炫彩的环形灯光。

(摘至淘宝)

视觉2:近来makefaire、kickstarter中出现的monkey light 256级全彩效果。绚丽的效果令人向往。可以显示JPG、GIF、PNG、AVI、MOV等格式图片或者3D效果。

(摘至kickstarter)

视觉3:过程中看到另外的低成本的POV,便宜的让人有点伤人,另一方面又肯定了中国制造的力量,无法阻挡。因为我觉得自己做出来肯定不止这个成本,伤心之余买了个回来玩玩。



拆开研究了下:一个16脚的打磨过的主芯片,产生信号,7个LED,三极管。光敏二极管,震动开关。光敏猜测是用来检测白天黑夜,白天的时候不需要点亮,因为效果不佳。震动开关,检测在静止时不点亮LED。纽扣电池··回来玩了下就爆开了一颗。

效果有点···那个就没有图了。有个喜欢的地方就是外壳的设计,防水,还可以直接安装在自行车气嘴上,真是好创意啊。

2、设计

别的始终是别的,自己做的才是自己的。所以我开始了,首先给自己定个位,256级全彩需要单片机刷新频率够高,硬件复杂度相对高,编程最好还要有单独的软件,不然会泪流满面。这样不适合我。而下面这不能自编程的就更没有兴趣了,所以我敲定了利用自己熟悉的ATmega328,arduino编程玩玩简单的,主要实现硬件上。

制作方案:

主要芯片:Atmega328、74HC595

LED:高亮发光二极管16只

位置检测:霍尔传感器3144

红外遥控:38K红外一体化接收头

简单阐释方案,利用驱动2片74HC595芯片级联驱动16个高亮LED显示动态单色图形。

PCB设计:

原理图:



华丽丽的布局画线结束后,效果图出来了····,



正面主芯片,稳压芯片(考虑散热),电源接口(为连接电池供电输入)。串口接,ICSP接口(下载程序)。LED开始考虑贴片高亮LED,后来用了高亮直插LED(正因为手上有这种,就节约了)将插针的两脚剪短,掰弯,焊在板子上。当然固定孔少不了。

来张背面,背面还添了两人在骑自行车的效果。大家觉得不丑吧·~·



漫长的等待后,PCB加工好,回来焊接测试



小手不抖,一次性QFP封装轻松焊上···



继续选择供电,供电我选择的可充电锂电池,一块3.7V、1400mah,两者串联起来,总电压7.4V。引出供电接口与充电接口。一支给POV板供电,一支用来充电。



通过固定孔将旋转POV用捆扎带绑在自行车钢丝上。

将磁铁固定在自行车轴上。用于检测一圈的速度。



程序:

[C++] 纯文本查看 复制代码


#include <util/delay.h>
int latchPin = 10;
int clockPin = 13;
int dataPin = 11;
int intPin=2;
/*********全局变量定义**********/
unsigned long int S=0;
unsigned int DelayN=80, //延时临时计数
DelayTime=80; //每次延时的周期个数
int flag;

byte a[]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x30,0x03,0x3F,0xFF,0x3F,0xFF,0x30,0x00,0x00,0x00,0x3F,0xC3,0x3F,0xC3,0x30,0xC3,
0x30,0xFF,0x30,0xFF,0x00,0x00,0x30,0xC3,0x30,0xC3,0x30,0xC3,0x3F,0xFF,0x3F,0xFF,
//1 ,2,3
0x01,0xFF,0x01,0xFF,0x01,0x80,0x1F,0xF8,0x1F,0xF8,0x01,0x80,0x00,0x00,0x00,0x00,
0x19,0xFE,0x19,0xFE,0x19,0x86,0x19,0x86,0x1F,0x86,0x1F,0x86,0x00,0x00,0x00,0x00,
//4,5
0x7F,0xFE,0x7F,0xFE,0x63,0x06,0x63,0x06,0x7F,0x1E,0x7F,0x1E,0x00,0x00,0x00,0x06,
0x00,0x06,0x00,0x06,0x00,0x06,0x7F,0xFE,0x7F,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,
//6,7
0x3F,0xFF,0x3F,0xFF,0x30,0xC3,0x30,0xC3,0x30,0xC3,0x3F,0xFF,0x3F,0xFF,0x00,0x00,
0x30,0xFF,0x30,0xFF,0x30,0xC3,0x30,0xC3,0x30,0xC3,0x3F,0xFF,0x3F,0xFF,0x00,0x00,
//8,9
};
byte a1[]={
0x01,0xF0,0x03,0xFC,0x07,0xFE,0x0F,0xFF,0x1F,0xFF,0x3F,0xFE,0x7F,0xFE,0xFF,0xFC,
0xFF,0xFC,0x7F,0xFE,0x3F,0xFE,0x1F,0xFF,0x0F,0xFF,0x07,0xFE,0x03,0xFC,0x01,0xF0,
0x01,0xF0,0x03,0xFC,0x07,0xFE,0x0F,0xFF,0x1F,0xFF,0x3F,0xFE,0x7F,0xFE,0xFF,0xFC,
0xFF,0xFC,0x7F,0xFE,0x3F,0xFE,0x1F,0xFF,0x0F,0xFF,0x07,0xFE,0x03,0xFC,0x01,0xF0,
0x01,0xF0,0x03,0xFC,0x07,0xFE,0x0F,0xFF,0x1F,0xFF,0x3F,0xFE,0x7F,0xFE,0xFF,0xFC,
0xFF,0xFC,0x7F,0xFE,0x3F,0xFE,0x1F,0xFF,0x0F,0xFF,0x07,0xFE,0x03,0xFC,0x01,0xF0,
0x01,0xF0,0x03,0xFC,0x07,0xFE,0x0F,0xFF,0x1F,0xFF,0x3F,0xFE,0x7F,0xFE,0xFF,0xFC,
0xFF,0xFC,0x7F,0xFE,0x3F,0xFE,0x1F,0xFF,0x0F,0xFF,0x07,0xFE,0x03,0xFC,0x01,0xF0,
0x01,0xF0,0x03,0xFC,0x07,0xFE,0x0F,0xFF,0x1F,0xFF,0x3F,0xFE,0x7F,0xFE,0xFF,0xFC,
0xFF,0xFC,0x7F,0xFE,0x3F,0xFE,0x1F,0xFF,0x0F,0xFF,0x07,0xFE,0x03,0xFC,0x01,0xF0,
0x01,0xF0,0x03,0xFC,0x07,0xFE,0x0F,0xFF,0x1F,0xFF,0x3F,0xFE,0x7F,0xFE,0xFF,0xFC,
0xFF,0xFC,0x7F,0xFE,0x3F,0xFE,0x1F,0xFF,0x0F,0xFF,0x07,0xFE,0x03,0xFC,0x01,0xF0,
} ;

void timer1_init()
{
cli(); //禁止所有中断
TCCR1A=0X00;
TCCR1B=0X04; //256分频
TCNT1H = 0x80;
TCNT1L = 0x80; //定时器赋初值
TIMSK1 |= 0x01;//中断允许
TIFR1=0X00; //置位溢出标志
sei();//开全局中断
}
void delayw(unsigned char n)
{
for(;n>0;n--){
DelayN=DelayTime;
while (DelayN);
{_delay_ms(4);}
}
}
void displayP()
{
for (flag= 0; flag <192;) {
digitalWrite(latchPin, 0);
shiftOut(dataPin, clockPin,MSBFIRST,0xff-a1[flag++]);
shiftOut(dataPin, clockPin,MSBFIRST,0xff-a1[flag++]);
digitalWrite(latchPin, 1);
delayw(1);
if(digitalRead(2)==0)
flag=0;
}
}
void setup() {
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(intPin,INPUT_PULLUP);
// attachInterrupt(0, blink, LOW); //外部中断使能
timer1_init();
}

void loop() {
if(digitalRead(2)==0){ //触发显示
DelayTime=S/160;
S=0;
displayP();
}
}

ISR (TIMER1_OVF_vect) //T0溢出中断服务程序
{
S++; //计数
if (DelayN!=0)
DelayN--;
}



更好显示没有时间和精力写了,大家见谅请别扔砖,POV板手上还有一个多余的,有兴趣愿意自己调程序的人可以联系我,可以免费送出。
视频就上个以前第一次拍的视频···视频地址:


via - arduino中文社区

标签: Arduino教程