YFROBOT创客社区
标题: 光立方原理图 制作过程V1.4,arduino驱动光立方,灯塔搭建,驱动函数,动画演示 [打印本页]
作者: aosini 时间: 2014-1-14 08:16
标题: 光立方原理图 制作过程V1.4,arduino驱动光立方,灯塔搭建,驱动函数,动画演示
视频地址:http://v.youku.com/v_show/id_XNjc4MDMyMzY0.html
http://v.youku.com/v_show/id_XNjc4MDMyMzY0.html
因版本不同,驱动板外观有所区别,但灯塔的搭建方式是相同的。
亲自动手制作一个光立方,将能够给你带来无穷乐趣,做好后,还可以把他放在房间里,当作一盏小灯,每到夜晚,光彩夺目。
[attach]768[/attach]
光立方
1 光立方V1.3介绍
目前市面上大部分的光立方产品都是基于STC的51单片机来控制的,如果你擅长51单片机,这将都不会是问题,但如果你是Arduino用户,或者你精通STM32、MSP430或者其他控制器,那么无形中就会有很多的局限性。我们的推出的光立方,只需要3个IO引脚就能实现对512个LED的控制,也就是说不管你用什么控制器(当然像初级的51是不可以的,内存还是速度都跟不上),你都可以使用。即使你更换新的控制器,你同样可以使用它。光立方的控制非常的简单,对于很多朋友来说,困难之处在于焊接,因为想要512个LED整齐排列,并焊接牢靠,对于一般的人来说并非易事,但事实上是,焊接远没有你想象中的困难。甚至我们不需要借助外部工具,你只需要准备常规的器件即可动手了。
驱动板从左往右,依次是电源开关、音频座、电源座、红外接收头、两个轻触按键、排针,排针引出的端口分别是VCC、GND(可以给外部提供5V电源);SER、RCK、SCK(驱动板驱动信号);L、R(左右声道模拟信号输出);IR(遥控信号输出);K1、K2(按键输出信号)。排针焊接时需要注意方向,尤其您使用光立方罩时。[attach]970[/attach]
图1 排针焊接方式
插件焊接时,根据下图所示焊接:[attach]973[/attach]
图2 插件焊接示意图
还需要一些其他的必备工具:
1:电烙铁1把,建议40元左右的,价格太便宜的烙铁不仅使用寿命短,温度也不能够保持恒定,最好带有静电保护的,降低灯珠被静电击穿的概率;
2:焊锡丝4米,经过我们实际操作,一个光立方焊好后差不多使用了0.8mm直径的锡丝3.5米;
3:斜口钳1把,主要用来剪引脚;4:口罩1只,为了自身的健康,这是比不可少的保护,因为这个工程也不是一两分钟的事儿。
2 光立方灯塔焊接
2.1 “点”
灯塔的焊接是从“点”开始,我们先把灯的引脚折弯,如下图所示。左边为Ⅰ型灯,只需要弯折一次,一共需要弯折448个灯珠;右侧为Ⅱ型灯,需要弯折两次,共需要64个灯珠。长脚为阳极,短脚为阴极。
[attach]756[/attach]
图3 灯引脚折弯(左为Ⅰ型,右为Ⅱ型)
2.2 “线”
512个灯珠安装上节要求弯折好后,我们将进行“线”的焊接,线的焊接非常的简单,不需借用额外的模具,我们的控制板就是很好的模具。如图4所示,先将30MM的铜柱安装在驱动板上。
[attach]757[/attach]
图4 30MM铜柱安装示意图
铜柱安装到位后,我们将7个Ⅰ型灯、1个Ⅱ型灯的阳极插入驱动板PIN孔中,插件顺序,如图5所示。
[attach]758[/attach]
图5 两种型号灯排列方式
之后,我们用列子将灯的阴极引脚排列整齐,用烙铁焊接,使引脚相连,如图6所示。焊接时间不可太久,防止灯珠损坏,焊接的烙铁我们建议使用带有静电保护的。
[attach]759[/attach]
图6 线的焊接
焊接好后,将灯从驱动板上取出,并整理灯的引脚,使引脚之间相互垂直或平行,如图7所示。就以这种方法,完成剩下的63条“线”。
[attach]760[/attach]
图7 焊接好的“线”
2.3 “面”
64条线焊接完成后,我们的工程已经完成一半了,先偷着乐乐吧。
在面焊接前,我们需要焊接一下驱动板上的芯片与圆孔PIN,焊接时,注意图8中的注意事项。4个5MM白发白氛围灯可以先不焊,等到面都焊接完成后在焊接,引脚暂时不剪。
[attach]972[/attach]
图8 驱动板焊接
圆孔PIN焊接需垂直于驱动板,这样可以保证灯塔搭建的美观。面的焊接我们就是利用焊好的圆孔PIN作为模板,就可以焊出完美的方格了,以这种方法依次焊好8个面。
[attach]762[/attach]
图9 面的焊接
8个面全部焊接好后,我们将对灯进行测试,找出坏“点”,及时更换,不然等体焊接好后将会带来更大的麻烦。测试很简单只需要一个3V左右的电源就可以了,当然,电压不能大于3.3V。神马!没有3V电源,嘿嘿。那我们氛围灯的引脚的用处就大大体现了。按照图10连接就可以进行测试了。经过我们的实际操作,没有灯不亮,当然,这不能保证所有。
[attach]763[/attach]
图10 测试
2.3 “体”
面都测试完成后,我们将进行体的拼装与焊接焊接。如果您觉得阳极的引脚有些长,或者您想给他建个“阳光房”,按照图11所示的方法,将灯的引脚剪齐。
[attach]764[/attach]
图11 修剪引脚
先将面的阳极引脚插入圆孔PIN中,插入时需稍微用力,并调整灯高度,使灯的高度保持一致。如图12所示:
[attach]765[/attach]
图12 插入引脚
将面与面之间连接的引脚焊好,焊接时保证面与面之间等距、平行,且垂直于驱动板,将多余的引脚剪去。如图13:
[attach]766[/attach]
图13 “体”完成
就差层控制线的焊接了,如图14所示:
[attach]767[/attach]
图14 层控制线焊接
将灰色细线线头剥皮,从H1圆孔的下方穿到上方,将露出的铜丝弯成钩形,焊接在第一层阴极引脚上,将光立方底向上,亲亲拉着细线,用烙铁直接去靠近焊盘与细线,将线的绝缘皮融化、上锡,将细线从根部剪断,这样一根层控制线就焊接完成,这样可以保证层控制线是笔直的,且非常美观。
3 光立方驱动板
光立方驱动板请移步下方下载,74hc595具体的使用方法请移步[url=读芯片手册及595串行实例全解 http://www.yfrobot.com/forum.php?mod=viewthread&tid=2389]读芯片手册及595串行实例全解[/url]。
建立“体”的空间坐标系,如图15:
[attach]773[/attach]
图15 坐标系
Z=0为第1层、Z=1为第2层、···Z=7为第8层,在每一层中有8束光(就是我们前面焊接的“线”),一个立方共有64束,我们将他们分别编号为0、1、2···63(图3.1.2),每束光由8个灯组成。例如,第一层,我们分别编号0、1、2、···7。在X=0这个面,有0、8、···56这8束光。
我们数组的编号方式正好对应着数组中数,one[0]控制这光束0上面的8个灯,a[0]=0x01,用二进制表示就是00000001,控制(0,0,0)这个灯被点亮。如果a[1]=0x88,用二进制表示就是10001000,控制灯(1,3,0)和(1,7,0)两个灯亮,这样编号的优点,您会在今后的编程过程中慢慢体会到。
例如一个数组
u8 one[]=
{
ox01, ox01, ox01, ox01, ox01, ox01, ox01, ox01,
ox01, ox01, ox01, ox01, ox01, ox01, ox01, ox01,
ox01, ox01, ox01, ox01, ox01, ox01, ox01, ox01,
ox01, ox01, ox01, ox01, ox01, ox01, ox01, ox01,
ox01, ox01, ox01, ox01, ox01, ox01, ox01, ox01,
ox01, ox01, ox01, ox01, ox01, ox01, ox01, ox01,
ox01, ox01, ox01, ox01, ox01, ox01, ox01, ox01,
ox01, ox01, ox01, ox01, ox01, ox01, ox01, ox01,
}
这个数组选择的是Y=0这个面的灯“同时”亮。“同时”我们加双引号,实际上在某一时刻只有一层灯是被点亮,对8层灯进行扫描,利用人眼的视觉停留效果,给人一种同时亮的错觉。
4 程序例解
我们的程序是建立在控制器为“YFstm32核心控制板V1.0”的基础上编写的,程序为C语言编程,有较强的移植性,只需部分修改,就可以在其他控制器中运行。完整程序请到此贴结尾处下载。端口定义函数:
#define SER PBout(8) //串行数据输入
#define RCK PBout(9) //上升沿,串行输出,并行输出并锁存
#define SCK PBout(10) //上升沿,输入到移位寄存器
根据端口设置,将控制器输出端口对应接到驱动板的SER、SCK、RCK上,控制板不驱动板用不同电源时,控制板上GND与驱动板上GND相连。
4.1 驱动函数
数据最先被写入U8,然后通过移位,将数据从U8移到U7···U1,最后被移入U9 ,U9中的数据为层选择信号。
下方贴出的程序为驱动函数:- //595串行接法驱动程序
- //层填充函数,控制某层灯点亮方式
- //Called By:void Frame(u8 *a,u8 speed)
- //Input:*a
- //Output:SER、SCK
- void Storey(u8 *a)
- {
- u8 i , j , num ;
- for(i = 0;i < 8;i++)
- {
- num = a[i]; //将数组中数输入寄存器
- for(j = 0;j < 8;j++) //串行数据输入
- {
- if(num&0x80)
- SER = 1; // SER串行输入端口
- else
- SER = 0;
- SCK = 0; //上升沿,输入到移位寄存器
- delay_us(1);
- SCK = 1;
- num <<= 1;
- }
- }
- }
- //帧控制函数
- //帧,就是影像动画中最小单位的单幅影像画面,相当于电影胶片上的每一
- //格镜头。一帧就是一副静止的画面,连续的帧就形成动画。
- //a是一帧编码起始地址
- //speed表示一帧画面扫描的次数,可以看作这帧显示的时间,这里我们理解为动画速度
- //Calls(被本函数调用的函数):void Storey(u8 *a)
- //Input:*a
- //Output:SER、SCK、RCK
- void Frame(u8 *a,u8 speed)
- {
- u8 i,j,num;
- while(speed--)
- {
- num = 0x01;
- for(i = 0;i < 8;i++) //层数层控制,选通某一层,
- //使得第1层到第8层,依次点亮
- {
- num <<= i;
- RCK = 0;
- for(j = 0;j < 8;j++) //串行数据输入,先写0
- {
- SER = 0;
- delay_us(1);
- SCK= 0; //上升沿,输入到移位寄存器
- delay_us(1);
- SCK = 1;
- }
- for(j =0;j < 8;j++) //串行数据输入,写入层控制数
- {
- if(num & 0x80)
- SER = 1; // SER串行输入端口
- else
- SER = 0;
-
- SCK = 0; //上升沿,输入到移位寄存器
- delay_us(1);
- SCK = 1;
- num <<= 1;
- }
- Storey(a+i*8);//层填充函数,控制某层灯点亮方式
- RCK= 1;
- num=0x01;
- delay_ms(2); // 层显示时间
- }
- }
- }
复制代码 帧——就是影像动画中最小单位的单幅影像画面,相当于电影胶片上的每一格镜头。一帧就是一副静止的画面,连续的帧就形成动画。
4.2 动画一- //动画内容是:侧面从左向右依次点亮
- void Face_LtoR(u8 speed)
- {
- u8 b[64]={0};
- u8 x,z;
- for(z=0;z<8;z++)
- {
- b[z*8]=0xff;
- }
- Frame(b,speed);//帧函数
- for(x=1;x<8;x++)
- {
- for(z=0;z<8;z++)
- {
- b[z*8+x]=0xff;
- b[z*8+(x-1)]=0;
- }
- Frame(b,speed);
- }
- All_Light_Off();
- }
复制代码 这里,先使编号为(z*8)+0的灯束全亮(0=<z<8),再使(z*8)+1的灯束都亮,这样就可以从从左往右依次点亮8个面的灯了。
4.3 动画二- const u8 dot_tab[64]=
- {
- 0x01,0x01,0x00,0x00,0x00,0x00,0x01,0x01,
- 0x01,0x01,0x00,0x00,0x00,0x00,0x01,0x01,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,
- 0x00,0x00,0x01,0x01,0x01,0x01,0x00,0x00,
- };
- //依次点亮00-1,01-1,02-1,03-1....63-1,笑脸
- void Dot(s8 time, u8 speed)
- {
- u8 b[64] = {0};
- u8 x, z;
- s8 t;
- Frame(b, speed);
- for(z = 0; z<8; z++)
- {
- for(x = 0; x<8; x++)
- {
- b[z * 8 + x] = 0x01;
- Frame(b, speed);
- }
- }
- for(z = 0; z<8; z++)
- {
- for(x = 0; x<8; x++)
- b[z * 8 + x] = dot_tab[z * 8 + x];
- Frame(b, 20);
- }
- t=time;
- while(t--)
- {
- Frame(b, 200);
- }
- }
复制代码 这里可以通过time的大小来设置笑脸显示时间长短。笑脸就是一个数组,通过不断的显示数组dot_tab[64]的内容,使光立方点亮“笑脸”。
经过我们的测试,灯全点亮2天两夜,共计48小时,光立方未出现异常。
“光立方V1.4资料”此文件主要包含:
1:驱动板原理图
2:芯片介绍
3:图片
4:光立方驱动程序V1.2--STM32控制
5:光立方--Arduino控制
6:新手理解FFT.pdf
7:基于单片机的音频频谱显示研究_FFT算法原理分析.pdf
8:光立方制作手册V1.3.pdf
9:FFT结果的物理意义.pdf
10:C语言实现FFT(快速傅里叶变换).pdf
[attach]866[/attach]
[attach]865[/attach]
光立方制作手册V1.4请点击下载
作者: aosini 时间: 2014-2-14 09:55
标题: 光立方按键中断调速
光立方按键中断调速。
视频地址:http://v.youku.com/v_show/id_XNjc4OTA2NDc2.html http://v.youku.com/v_show/id_XNjc4OTA2NDc2.html
这层楼,将介绍按键中断调速。调速!首先我们需要知道调哪个参数,可以改变动画速度,当然,第一个想到的就是变量speed,在很多的动画中我们都使用了这个变量,但是我们在显示每个动画的时候是不是都要检测speed的值?这样保证调速的实时性?主函数中,我们动画显示部分会不会很乱?好了,写了改变这个变量。我们就会对主函数动画部分进行大的改动。pass这个想法。
再看void Frame(u8 *a,u8 speed),因为我们知道,每个动画显示时都会调用此函数。
- void Frame(u8 *a,u8 speed)
- {
- u8 i,j,num;
- while(speed--)
- {
- num = 0x01;
- for(i = 0;i < 8;i++) //层数层控制,选通某一层,
- //使得第1层到第8层,依次点亮
- {
- num <<= i;
- RCK = 0;
- for(j = 0;j < 8;j++) //串行数据输入
- {
- SER = 0;
- delay_us(1);
- SCK= 0; //上升沿,输入到移位寄存器
- delay_us(1);
- SCK = 1;
- }
- for(j =0;j < 8;j++) //串行数据输入
- {
- if(num & 0x80)
- SER = 1; // SER串行输入端口
- else
- SER = 0;
- SCK = 0; //上升沿,输入到移位寄存器
- delay_us(1);
- SCK = 1;
- num <<= 1;
- }
- Storey(a+i*8);//层填充函数,控制某层灯点亮方式
- RCK = 1;
- num=0x01;
- <font color="#ff0000"> delay_ms(2); // 层显示时间</font>
- }
- }
- }
复制代码 是不是我们可以改变其它参数,间接的来改变动画速度,有的,请看红色字体那,层显示时间,我们改变它,也就间接的改变了每帧显示的时间,这样就达到了改变速度的目的。
在led.c函数中我们声明一个全局变量:u8 GEAR = 4。 将delay_ms(2)改为delay_us(500 + (8-GEAR) * 250)。
下面开始编写外部中断函数。
- #define KEY_DOWN PAin(6) //PA6 速度减
- #define KEY_UP PAin(7) //PA7 速度加
- void EXTIX_Init(void);//外部中断IO初始化
- //按键调速,共7个档位,调整光立方的运行数度
- //PA6,PA7外部中断输入端口,分别接驱动板的KEY1、KEY2
- //按下KEY1速度变慢,按下KEY2速度变快
- //外部中断服务函数
- void EXTI9_5_IRQHandler(void)
- {
- <font color="#ff0000"> delay_ms(1); //消抖</font>
- if(KEY_DOWN == 0) //按键1
- {
- if(GEAR > 1 && GEAR < 8)
- {
- -- GEAR;
- printf("%d\n",GEAR);
- }
- }
- else if(KEY_UP == 0)//按键2
- {
- if(GEAR > 0 && GEAR < 7)
- {
- ++ GEAR;
- printf("%d\n",GEAR);
- }
- }
- EXTI->PR = 1<<6; //清除LINE6上的中断标志位
- EXTI->PR = 1<<7; //清除LINE7上的中断标志位
- }
- //外部中断初始化程序
- //初始化PA6,PA7为中断输入.
- void EXTIX_Init(void)
- {
- RCC->APB2ENR |= 1<<2; //使能PORTA时钟
- JTAG_Set(JTAG_SWD_DISABLE);//关闭JTAG和SWD
- GPIOA->CRL &= 0X00FFFFFF;//PA6,PA7设置成输入
- GPIOA->CRL |= 0X88000000;
- GPIOA->ODR |= 1<<6; //PA6上拉
- GPIOA->ODR |= 1<<7; //PA7上拉
- Ex_NVIC_Config( GPIO_A, 6, FTIR);//下降沿触发
- Ex_NVIC_Config( GPIO_A, 7, FTIR);//下降沿触发
- MY_NVIC_Init( 2, 1, EXTI9_5_IRQChannel, 2);//抢占2,子优先级1,组2
- }
复制代码 通过上面的中断服务函数就可以实时改变GEAR的值了,需要注意的是消抖时间,这个时间不可很大,时间过长,按键中断时光立方就会出现“一闪”的现象。
作者: aosini 时间: 2015-5-13 13:41
请您浏览:http://www.yfrobot.com/forum.php ... =%B9%E2%C1%A2%B7%BD
作者: aosini 时间: 2015-5-14 14:18
都需要自定义的,需要用到模拟量采集端口,将采集的数据进行傅立叶变换,得到不同频率所对应的幅值,这样就可以做成频谱了,具体请看光立方V1.3资料中《FFT结果的意义》,及fft.c。
- for(i=0;i<65;i++)
- {
- dd[i].real=Get_Adc(ADC_CH0); //读取ad结果;
- dd[i].imag=0; //清零虚部
- }
复制代码 采集65个模拟值。
作者: aosini 时间: 2015-5-14 17:28
1楼底层 “光立方V1.3资料”,里面包含了程序,但是stm32的,需要修改。
给您介绍的帖子中有使用说明的,你可以先检查一下接线,然后尝试运行一个简单的动画,像全亮。
作者: YFRobot 时间: 2015-5-15 17:33
会影响显示的,不过可以在595驱动函数中更改一下扫描方式就可以了
作者: aosini 时间: 2015-5-18 08:21
会的,程序是根据硬件的连接方式来变成的,不同的连接方式,驱动函数也会不同,两者是相对应的。
作者: aosini 时间: 2015-5-20 07:58
程序需要根据不同单片机稍微改动的,也需要看一下主程序,命令了那些动作。
作者: aosini 时间: 2015-5-21 12:58
目前上位机支持arduino的。这个贴中有较详细的说明http://www.yfrobot.com/forum.php ... =%B9%E2%C1%A2%B7%BD
作者: aosini 时间: 2016-1-14 08:04
有的
作者: aosini 时间: 2016-1-15 08:13
不好意思,搞错了,现在更新为1.4了。4楼的回复中也有相关连接。
作者: aosini 时间: 2016-1-16 08:03
不好意思,这个还真的没有arduino的,不过资料里面有相关资料,您可以研究一下
作者: mindcontrol 时间: 2016-11-14 12:17
你好。按照1楼的方法搭建起来光立方了,也成功运行了。但是对arduino里的代码有些地方不是很清楚,请问有技术支持吗?谢谢
作者: aosini 时间: 2016-11-14 13:04
有的哦,您可以在这里直接提问的。
作者: 浩天、 时间: 2016-12-15 19:59
想问下楼主,图上接了六根线,一个VCC一个GND,SER、RCK、SCK还有一根是接的哪里?arduino uno实现以上动画的源码有吗,我按楼主的修改有有许多错误,麻烦楼主了
作者: aosini 时间: 2016-12-24 08:34
“光立方制作手册V1.4”中是有的哦,您下载看一下
作者: sammyckm 时间: 2017-3-30 11:10
學習中, 謝謝分享
欢迎光临 YFROBOT创客社区 (http://yfrobot.com.cn/) |
Powered by Discuz! X3.1 |