robo027 发表于 2018-9-20 02:09:05

烂尾项目投稿---RGB POV风扇

为了投稿https://mc.dfrobot.com.cn/thread-268482-1-1.html我特地百科了一下"烂尾"的含义.
烂尾:网络用语,指一部作品在情节尚未圆满的情况下中途夭折或草草收尾。
我对于"烂尾作品"的理解:创客们因为种种原因没有最终完成后被遗忘在某个角落吃灰的作品,或是因为一些原因而把一个曾经计划的很好的作品做的虎头蛇尾,在要不就是本以为很简单,但自己做起来就是各种阻挠各种困难,导致最终要么没做出来要么草草收尾.
接下来要介绍的这个作品:"RGB POV风扇"原本计划两周,但却耗我整个夏天.(夸张了点,工作原因实际上只有偶尔晚上在做)直到现在,充其量只能算的上一个实验品.所以我想把这个小项目的制作过程最主要是想把失败经验分享给大家.能带给大家一点笑料以及一些启发就好了.
来由
最初是我们组的主任看到同事带了一个网红风扇,

拿在手里扇扇风,扇叶转动的同时还会显现出一些字母,主任当时问我能不能做,其实很早就知道:"摇摇棒"这个经典项目,想想原理不就是把摇摇棒装到马达上而已.于是就答应了做一个出来.
POV
Persistence of vision意思是光对视网膜所产生的视觉,应用于电影的拍摄和放映.在这个项目上就是利用人眼视觉暂留的生理特点,把某个光点在快速移动中看成是一段光的轨迹这样一个现象,做成多光点在整体移动的同时用各自不同的闪烁频率来构图,在人眼前呈现画面感.用一张图来解释



根据instructables上找到的例子可以用UNO做个简单的摇摇棒实验



物料:
接线:
完成图:
代码:/*
Written by Ahmad Saeed on 22 August 2015

此代码能够显示以下字符;
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ .-_!%&#$,()@?
*/

//////////////////// 要自定义的消息   /////////////      //////
#define msgLength 11                                       ///
String msgBody = "Ahmad Saeed"; //(←显示)               ///
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////




#define delayInChar 3
#define delayBetweenChar 5
#define LED1 1
#define LED2 2
#define LED3 3
#define LED4 4
#define LED5 5
#define LED6 6
#define LED7 7

byte msgCode[(5 * msgLength) + 10];
boolean pintState;
int columnNum = -1;
String charToWrite;

void setup() {
msgBody.toUpperCase();
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
pinMode(LED3, OUTPUT);
pinMode(LED4, OUTPUT);
pinMode(LED5, OUTPUT);
pinMode(LED6, OUTPUT);
pinMode(LED7, OUTPUT);
}

void loop() {
//// 将 所有 文本转换 为二进 制数 组    ////////////////////////
if ( columnNum == -1 ) //这个块需要完成一次                //
{                                                         //
    for (int c = 0; c < (msgBody.length()); c++){         //
      //Separate the following character                  //
      charToWrite = msgBody.substring(c, c + 1);            //
      //Send the separated characted to addChar function    //
      addChar(charToWrite);                                 //
    }                                                       //
      //Add a little space after each character             //
    addChar(" ");                                           //
    addChar(" ");                                           //
}                                                         //
//////////////////////////////////////////////////////////////

////                              在编码所有字符后显示二进制数组//
for (int c = 0; c < (sizeof(msgCode)); c++){            //
    pintState = (msgCode / B1000000) % B10;                //
    digitalWrite(LED1, pintState);                            //
                                                            //
    pintState = (msgCode / B100000) % B10;               //
    digitalWrite(LED2, pintState);                            //
                                                            //
    pintState = (msgCode / B10000) % B10;                  //
    digitalWrite(LED3, pintState);                            //
                                                            //
    pintState = (msgCode / B1000) % B10;                   //
    digitalWrite(LED4, pintState);                            //
                                                            //
    pintState = (msgCode / B100) % B10;                  //
    digitalWrite(LED5, pintState);                            //
                                                            //
    pintState = (msgCode / B10) % B10;                     //
    digitalWrite(LED6, pintState);                            //
                                                            //
    pintState = msgCode % B10;;                            //
    digitalWrite(LED7, pintState);                            //
                                                            //
    delay(delayInChar);                                       //
    // 如果字母显示完毕, 关闭时间//
    if ((c + 1) % 5 == 0 ) {                                  //
      digitalWrite(LED1, LOW);                              //
      digitalWrite(LED2, LOW);                              //
      digitalWrite(LED3, LOW);                              //
      digitalWrite(LED4, LOW);                              //
      digitalWrite(LED5, LOW);                              //
      digitalWrite(LED6, LOW);                              //
      digitalWrite(LED7, LOW);                              //
      delay(delayBetweenChar);                              //
    }                                                         //
}                                                         //
                                                            //
////////////////////////////////////////////////////////////////
}   


void addChar(String y) {
if (y == "1") {
    addColumn(B0010001);
    addColumn(B0100001);
    addColumn(B1111111);
    addColumn(B0000001);
    addColumn(B0000001);
}
else if (y == "2") {
    addColumn(B0100001);
    addColumn(B1000011);
    addColumn(B1000101);
    addColumn(B1001001);
    addColumn(B0110001);
}
else if (y == "3") {
    addColumn(B0100010);
    addColumn(B1000001);
    addColumn(B1001001);
    addColumn(B1001001);
    addColumn(B0110110);
}
else if (y == "4") {
    addColumn(B0001100);
    addColumn(B0010100);
    addColumn(B0100100);
    addColumn(B1111111);
    addColumn(B0000100);
}
else if (y == "5") {
    addColumn(B1110010);
    addColumn(B1010001);
    addColumn(B1010001);
    addColumn(B1010001);
    addColumn(B1001110);
}
else if (y == "6") {
    addColumn(B0111110);
    addColumn(B1001001);
    addColumn(B1001001);
    addColumn(B1001001);
    addColumn(B0100110);
}
else if (y == "7") {
    addColumn(B1000000);
    addColumn(B1000111);
    addColumn(B1001000);
    addColumn(B1010000);
    addColumn(B1100000);
}
else if (y == "8") {
    addColumn(B0110110);
    addColumn(B1001001);
    addColumn(B1001001);
    addColumn(B1001001);
    addColumn(B0110110);
}
else if (y == "9") {
    addColumn(B0110010);
    addColumn(B1001001);
    addColumn(B1001001);
    addColumn(B1001001);
    addColumn(B0111110);
}
else if (y == "0") {
    addColumn(B0111110);
    addColumn(B1000101);
    addColumn(B1001001);
    addColumn(B1010001);
    addColumn(B0111110);
}
else if (y == "A") {
    addColumn(B0011111);
    addColumn(B0100100);
    addColumn(B1000100);
    addColumn(B1000100);
    addColumn(B1111111);
}
else if (y == "B") {
    addColumn(B1111111);
    addColumn(B1001001);
    addColumn(B1001001);
    addColumn(B1001001);
    addColumn(B0110110);
}
else if (y == "C") {
    addColumn(B0111110);
    addColumn(B1000001);
    addColumn(B1000001);
    addColumn(B1000001);
    addColumn(B0100010);
}
else if (y == "D") {
    addColumn(B1111111);
    addColumn(B1000001);
    addColumn(B1000001);
    addColumn(B1000001);
    addColumn(B0111110);
}
else if (y == "E") {
    addColumn(B1111111);
    addColumn(B1001001);
    addColumn(B1001001);
    addColumn(B1001001);
    addColumn(B1000001);
}
else if (y == "F") {
    addColumn(B1111111);
    addColumn(B1001000);
    addColumn(B1001000);
    addColumn(B1001000);
    addColumn(B1000000);
}
else if (y == "G") {
    addColumn(B0111110);
    addColumn(B1000001);
    addColumn(B1000001);
    addColumn(B1000101);
    addColumn(B0100110);
}
else if (y == "H") {
    addColumn(B1111111);
    addColumn(B0001000);
    addColumn(B0001000);
    addColumn(B0001000);
    addColumn(B1111111);
}
else if (y == "I") {
    addColumn(B0000000);
    addColumn(B1000001);
    addColumn(B1111111);
    addColumn(B1000001);
    addColumn(B0000000);
}
else if (y == "J") {
    addColumn(B0000000);
    addColumn(B0000010);
    addColumn(B1000001);
    addColumn(B1000001);
    addColumn(B1111110);
}
else if (y == "K") {
    addColumn(B1111111);
    addColumn(B0001000);
    addColumn(B0010100);
    addColumn(B0100010);
    addColumn(B1000001);
}
else if (y == "L") {
    addColumn(B1111111);
    addColumn(B0000001);
    addColumn(B0000001);
    addColumn(B0000001);
    addColumn(B0000001);
}
else if (y == "M") {
    addColumn(B1111111);
    addColumn(B0100000);
    addColumn(B0011000);
    addColumn(B0100000);
    addColumn(B1111111);
}
else if (y == "N") {
    addColumn(B1111111);
    addColumn(B0010000);
    addColumn(B0001000);
    addColumn(B0000100);
    addColumn(B1111111);
}
else if (y == "O") {
    addColumn(B0111110);
    addColumn(B1000001);
    addColumn(B1000001);
    addColumn(B1000001);
    addColumn(B0111110);
}
else if (y == "P") {
    addColumn(B1111111);
    addColumn(B1001000);
    addColumn(B1001000);
    addColumn(B1001000);
    addColumn(B0110000);
}
else if (y == "Q") {
    addColumn(B0111100);
    addColumn(B1000010);
    addColumn(B1000010);
    addColumn(B1000010);
    addColumn(B0111101);
}
else if (y == "R") {
    addColumn(B1111111);
    addColumn(B1001000);
    addColumn(B1001100);
    addColumn(B1001010);
    addColumn(B0110001);
}
else if (y == "S") {
    addColumn(B0110010);
    addColumn(B1001001);
    addColumn(B1001001);
    addColumn(B1001001);
    addColumn(B0100110);
}
else if (y == "T") {
    addColumn(B1000000);
    addColumn(B1000000);
    addColumn(B1111111);
    addColumn(B1000000);
    addColumn(B1000000);
}
else if (y == "U") {
    addColumn(B1111110);
    addColumn(B0000001);
    addColumn(B0000001);
    addColumn(B0000001);
    addColumn(B1111110);
}
else if (y == "V") {
    addColumn(B1111100);
    addColumn(B0000010);
    addColumn(B0000001);
    addColumn(B0000010);
    addColumn(B1111100);
}
else if (y == "W") {
    addColumn(B1111110);
    addColumn(B0000001);
    addColumn(B0000110);
    addColumn(B0000001);
    addColumn(B1111110);
}
else if (y == "X") {
    addColumn(B1100011);
    addColumn(B0010100);
    addColumn(B0001000);
    addColumn(B0010100);
    addColumn(B1100011);
}
else if (y == "Y") {
    addColumn(B1110000);
    addColumn(B0001000);
    addColumn(B0001111);
    addColumn(B0001000);
    addColumn(B1110000);
}
else if (y == "Z") {
    addColumn(B1000011);
    addColumn(B1000101);
    addColumn(B1001001);
    addColumn(B1010001);
    addColumn(B1000011);
}
else if (y == "Z") {
    addColumn(B1000011);
    addColumn(B1000101);
    addColumn(B1001001);
    addColumn(B1010001);
    addColumn(B1000011);
}
else if (y == " ") {
    addColumn(B0000000);
    addColumn(B0000000);
    addColumn(B0000000);
    addColumn(B0000000);
    addColumn(B0000000);
}
else if (y == ".") {
    addColumn(B0000000);
    addColumn(B0000011);
    addColumn(B0000011);
    addColumn(B0000000);
    addColumn(B0000000);
}
else if (y == "_") {
    addColumn(B0000001);
    addColumn(B0000001);
    addColumn(B0000001);
    addColumn(B0000001);
    addColumn(B0000001);
}
else if (y == "-") {
    addColumn(B0000000);
    addColumn(B0001000);
    addColumn(B0001000);
    addColumn(B0001000);
    addColumn(B0000000);
}
else if (y == "!") {
    addColumn(B0000000);
    addColumn(B0000000);
    addColumn(B1111101);
    addColumn(B0000000);
    addColumn(B0000000);
}
else if (y == "(") {
    addColumn(B0000000);
    addColumn(B0000000);
    addColumn(B0000000);
    addColumn(B0111110);
    addColumn(B1000001);
}
else if (y == ")") {
    addColumn(B1000001);
    addColumn(B0111110);
    addColumn(B0000000);
    addColumn(B0000000);
    addColumn(B0000000);
}
else if (y == "%") {
    addColumn(B1100010);
    addColumn(B1100100);
    addColumn(B0001000);
    addColumn(B0010011);
    addColumn(B0100011);
}
else if (y == ",") {
    addColumn(B0000000);
    addColumn(B0000101);
    addColumn(B0000110);
    addColumn(B0000000);
    addColumn(B0000000);
}
else if (y == "?") {
    addColumn(B0100000);
    addColumn(B1000101);
    addColumn(B1001000);
    addColumn(B0110000);
    addColumn(B0000000);
}
else if (y == "#") {
    addColumn(B0010100);
    addColumn(B0111110);
    addColumn(B0010100);
    addColumn(B0111110);
    addColumn(B0010100);
}
else if (y == "@") {
    addColumn(B0111110);
    addColumn(B1000001);
    addColumn(B1011101);
    addColumn(B1011101);
    addColumn(B0111000);
}
else if (y == "$") {
    addColumn(B0110010);
    addColumn(B1001001);
    addColumn(B1111111);
    addColumn(B1001001);
    addColumn(B0100110);
}
}

void addColumn(byte x) {
columnNum += 1;
msgCode = (x);
}
我最开始就是跟着这个例子做的,效果这里就不演示了.可以看看原作者的效果.
当然,这只能算一个摇摇棒,如果要做成风扇的叶子,那就要更小的板子,更小的电池等.还要考虑重心等问题.两边重量不平衡装在马达上会晃.
于是就准备使用ATTINY85做个5灯的版本.经过画板蚀刻后,就有了第一版,单色POV风扇,贴片电阻和3MMLED,和3.7V锂电,加充电板.
打个岔:我这里所说的ATTINY85是指的芯片,而使用这个芯片的小板子有Digispark,lilypad等,如果你正好有其中之一,那简单,用DIGISPARK专用的IDE下载以下代码即可
驱动以及IDE下载链接
如果你想让风扇更轻便,那给ATTINY85芯片编程就稍微麻烦点了,需要你做一下外围的电路,也就几个电子元件,跟着下面的步骤做即可
文字版链接
论坛以前还有位朋友发过一个视频教学视频版

原理图:
实物图:
代码int delayTime = 1; //子字符之间的延迟时间
int charBreak = 2.1;//不同字母之间的延迟
//应根据需要调整上述2个延迟时间。尝试更改它们,直到获得所需的显示,//增加delayTime将增加字母的每个部分的宽度,而增加charBreak将增加2个字母之间的空间。
int LED1 = 0;
int LED2 = 1;
int LED3 = 2;
int LED4 = 3;
int LED5 = 4;

void setup()
{
pinMode(LED1,OUTPUT);
pinMode(LED2,OUTPUT);
pinMode(LED3,OUTPUT);
pinMode(LED4,OUTPUT);
pinMode(LED5,OUTPUT);
}

int a [] = {1,6,26,6,1};//显示a
int b [] = {31,21,21,10,0};
int c2 [] = {14,17,17,10,0};
int d [] = {31,17,17,14,0};
int e [] = {31,21,21,17,0};
int f [] = {31,20,20,16,0};
int g [] = {14,17,19,10,0};
int h [] = {31,4,4,4,31};
int i [] = {0,17,31,17,0};
int j [] = {0,17,30,16,0};
int k [] = {31,4,10,17,0};
int l [] = {31,1,1,1,0};
int m [] = {31,12,3,12,31};
int n [] = {31,12,3,31,0};
int o [] = {14,17,17,14,0};
int p [] = {31,20,20,8,0};
int q [] = {14,17,19,14,2};
int r [] = {31,20,22,9,0};
int s [] = {8,21,21,2,0};
int t [] = {16,16,31,16,16};
int u [] = {30,1,1,30,0};
int v [] = {24,6,1,6,24};
int w [] = {28,3,12,3,28};
int x [] = {17,1,10,4,10,17};
int y [] = {17,1,10,4,8,16};
int z [] = {19,21,21,25,0};
//5个不同的整数对应于构成每个字母的5个时间帧。int eos [] = {0,1,0,0,0};int excl [] = {0,29,0,0,0};
int ques [] = {8,19,20,8,0};

void displayLine(int line)
{
int myline;
myline = line;
if(myline> = 16){digitalWrite(LED1,HIGH); myline- = 16;} else {digitalWrite(LED1,LOW);}
if(myline> = 8){digitalWrite(LED2,HIGH); myline- = 8;} else {digitalWrite(LED2,LOW);}
if(myline> = 4){digitalWrite(LED3,HIGH); myline- = 4;} else {digitalWrite(LED3,LOW);}
if(myline> = 2){digitalWrite(LED4,HIGH); myline- = 2;} else {digitalWrite(LED4,LOW);}
if(myline> = 1){digitalWrite(LED5,HIGH); myline- = 1;} else {digitalWrite(LED5,LOW);}
}
/*这是代码中最重要的部分,它解释了我们上面提到的所有数字的含义,例如,让x为整数。如果x大于或等于16,则LED1打开,我们从x减去16,现在如果(x-16)大于或等于8,LED2也会随LED1一//起打开,我们减去8 ,现在如果(x-24)大于或等于4,LED3与LED1和LED2一起打开,依此类推......如果在任何情况下它小于指定的数字,那么该LED关闭,我们继续前进到下一步而不减去任何数字。例如:现在它大于16,现在大于16,因此LED1打开,现在减去16我们有2,小于8所以LED2关闭,现在2小于4所以LED3关闭,现在2是大于或等于2,因此LED4打开,减去2时我们有0小于1,因此LED5关闭。以这种方式,我们可以根据需要分配不同的整数来打开和关闭不同的LED。*/ void displayChar(char c)
{
if(c =='a'){for(int i = 0; i <5; i ++){displayLine(a ); delay(delayTime);} displayLine(0);}
if(c =='b'){for(int i = 0; i <5; i ++){displayLine(b ); delay(delayTime);} displayLine(0);}
if(c =='c2'){for(int i = 0; i <5; i ++){displayLine(c2 ); delay(delayTime);} displayLine(0);}
if(c =='d'){for(int i = 0; i <5; i ++){displayLine(d ); delay(delayTime);} displayLine(0);}
if(c =='e'){for(int i = 0; i <5; i ++){displayLine(e ); delay(delayTime);} displayLine(0);}
if(c =='f'){for(int i = 0; i <5; i ++){displayLine(f ); delay(delayTime);} displayLine(0);}
if(c =='g'){for(int i = 0; i <5; i ++){displayLine(g ); delay(delayTime);} displayLine(0);}
if(c =='h'){for(int i = 0; i <5; i ++){displayLine(h ); delay(delayTime);} displayLine(0);}
if(c =='i'){for(int it = 0; it <5; it ++){displayLine(i ); delay(delayTime);} displayLine(0);}
if(c =='j'){for(int i = 0; i <5; i ++){displayLine(j ); delay(delayTime);} displayLine(0);}
if(c =='k'){for(int i = 0; i <5; i ++){displayLine(k ); delay(delayTime);} displayLine(0);}
if(c =='l'){for(int i = 0; i <5; i ++){displayLine(l ); delay(delayTime);} displayLine(0);}
if(c =='m'){for(int i = 0; i <5; i ++){displayLine(m ); delay(delayTime);} displayLine(0);}
if(c =='n'){for(int i = 0; i <5; i ++){displayLine(n ); delay(delayTime);} displayLine(0);}
if(c =='o'){for(int i = 0; i <5; i ++){displayLine(o ); delay(delayTime);} displayLine(0);}
if(c =='p'){for(int i = 0; i <5; i ++){displayLine(p ); delay(delayTime);} displayLine(0);}
if(c =='q'){for(int i = 0; i <5; i ++){displayLine(q ); delay(delayTime);} displayLine(0);}
if(c =='r'){for(int i = 0; i <5; i ++){displayLine(r ); delay(delayTime);} displayLine(0);}
if(c =='s'){for(int i = 0; i <5; i ++){displayLine(s ); delay(delayTime);} displayLine(0);}
if(c =='t'){for(int i = 0; i <5; i ++){displayLine(t ); delay(delayTime);} displayLine(0);}
if(c =='u'){for(int i = 0; i <5; i ++){displayLine(u ); delay(delayTime);} displayLine(0);}
if(c =='v'){for(int i = 0; i <5; i ++){displayLine(v ); delay(delayTime);} displayLine(0);}
if(c =='w'){for(int i = 0; i <5; i ++){displayLine(w ); delay(delayTime);} displayLine(0);}
if(c =='x'){for(int i = 0; i <5; i ++){displayLine(x ); delay(delayTime);} displayLine(0);}
if(c =='y'){for(int i = 0; i <5; i ++){displayLine(y ); delay(delayTime);} displayLine(0);}
if(c =='z'){for(int i = 0; i <5; i ++){displayLine(z ); delay(delayTime);} displayLine(0);}
if(c =='!'){for(int i = 0; i <5; i ++){displayLine(excl ); delay(delayTime);} displayLine(0);}
if(c =='?'){for(int i = 0; i <5; i ++){displayLine(ques ); delay(delayTime);} displayLine(0);}
if(c =='。'){for(int i = 0; i <5; i ++){displayLine(eos ); delay(delayTime);} displayLine(0);}
delay(charBreak);
}
/*代码的这一部分告诉arduino在延迟时间的情况下一个接一个地移动一个时间帧,并且从i = 0(时间帧1)到i = 4(时间帧5)循环显示每个整数,因为它继续运行。
*/
void displayString(char * s)
{
for(int i = 0; i <= strlen(s); i ++)
{
    displayChar(S );
}
}
//这告诉arduino从i = 0开始一个接一个地显示我们想要的所有字符,直到i =字符串长度(字符数)。
void loop()
{   
displayString(“hello world”);
}
/*
"hello world"是当前显示的内容,您可以将其更改为您想要的任何内容。只需确保没有太多字符,POV无法以给定的电机速度显示。如果增加电机速度并减少延迟时间,则可以显示更多字符。凭借我的电机和我使用的延迟时间,我总共可以显示12个字符,包括空格,所以"hello world"是完美的。
*/


=================================
彩灯版:

单色灯版的pov风扇顺利的做出来后,又发现了国外一些牛人做出了彩灯版的,

效果简直比单色的提升了一大档,当然,可想而知的是:制作难度应该也会更高了,本来还犹豫做不做.后来到ADA的官网看到了这个项目后就坐不住了.
回忆起<<万万没想到>>第一集中的桥段


......
坚定了做彩灯版的想法后就开始构思了

解释一下:最开始的想法就是把ws2812灯珠串起来,扇叶转动过程中,动端上的霍尔传感器与定端磁铁每相交一次相当于一次复位操作,扇叶在两次复位操作中消耗的时间为完成一次整幅图流程的时间.所以这样一来电机就不会因为供电不足转速下降而影响画面的显示.这样一来电机的转速要求也会相应宽泛一些.
至于特斯拉线圈,我至今还没有实验过.之所以这么想,原因是RGB灯珠的功率会大很多,而且数量也要求多一些 这就要单独供电才能正常工作,想想看,本应该轻薄的扇叶上又是Arduino,又是蓝牙模块,还得背两个电池...所以能用体积小的元器件模块尽量用小的.而且还得考虑扇叶平衡重心的问题,得合理得分配它们得位置.否则转起来就会晃的很严重.
这个无线供电的想法就留给感兴趣的朋友或自己以后有空在试试吧.
最开始我买的是SK6812灯珠5050封装,一颗一颗的在洞洞板(孔距2.0)上焊,本来以为自己应该能搞定的


因为这玩意最好是一次到位.要不然一点多余的操作就会让灯珠毁掉,第一次买的几乎全部焊废了.
还好记得以前看过一个彩灯棍子
可以买几个续接起来.买买买.
做好了后,问题又来了,这灯珠频率不行,做做环境氛围可以,但是要进行高速的切换亮灭及其颜色,就不行了
而且后来查了查资料才发现,人家多数是用APA102的灯珠做的.APA102参数如下

下面还有一些较主流型号的全彩灯珠之间的对比图


这次我又买了灯珠(不信邪),当然, 还是让老板带了一条灯带.
几天后,到货了.
取快递那天我的心情是这样的.
两天后,我的心情是这样的.是的,我又玩坏了几十个..
也许你要问:"不是还有灯带吗?"
对,灯带也玩坏了...
也许你又要问:"灯带怎么玩坏的...?"
是这样, 灯带到了后我发现我拍错了..一般灯带按每个灯珠的间隔大小来分类,有1米30珠60珠144珠,很显然这个项目要求灯珠之间的间隔越小越好,最后成图的分辨率才会高.
可...到的是一米30珠的.
当灯珠败完后,心情又毛,一怒之下把灯给一截一截剪了下来,横过来重新排列..
最后做是做好了,但是当时没拍图,后来也没保留,因为它实在是看不下去.越看越觉得丑.后面飞线飞到密密麻麻一塌糊涂. 拆了.
"LZ不做了!"这个念头多次闪现,当然对于我来说"闪现"得意义就是没意义.转瞬即逝.
又认认真真的拍了一米144灯的灯带
这回总算是做成功了.
整个项目分成三个部分:扇叶部分|||马达,与开关部分,|||风扇主体部分.
一个一个来介绍:
扇叶部分:

马达开关电路部分:

风扇主体部分:
我用了PVC管,加一个旧的话筒座(比较沉).加工起来比较轻松,主要是刚好找到了一个和PVC管孔径一样大的马达.而且只需要一个18650就能带的动风扇.
还是发出来吧.
代码和库以及更换图片的APP在文尾处下载.


使用方法:安装好APP后打开第一栏是用自带图片,第二栏的是用自己图片,用自己的图片时,要注意大小,尽量选分辨率低点的.后面有参数预估,超出是上传不了的.
在就是如果发现颜色不对就要调real colour那里.你的灯珠试RGB还是GBR还是BRG...一个一个试.总会找到的.

总结:
说真的做成现在这个样子和我想象中的还是存在一些差距,主要是灯珠,我用的是5050的,灯珠越大能够放置的数量就越少,图片颗粒感就重,相反,灯珠越小单位面积内放置的灯珠就多,那图片出来的效果也更清晰.后来看到有卖更小3535封装的APA102,想想自己的焊功...还是算了吧.还有一个值得注意的问题就是确保转轴是风扇叶的中心平衡点.要不然两边重量分布不均,马达转动时整个风扇就剧烈震动起来了.然而这也一点儿都不简单,又要照顾到板子上的元器件和开马达轴孔互不影响,还得保证两边重量的平均.最无奈的一点就是NaNo的内存有限,大一点的颜色多一点的图就不行.
如果你也想做一台,可以考虑自己设计pcb,用3535的灯珠.我也非常乐意一起参与设计.
如果你在制作过程中遇到有什么疑问可以跟帖留言给我
最重要的:安全 ,请一定注意安全.扇叶打到身上任何部位都不好受.

=============================================
代码以及库文件下载:



APP我传不了可以在这里下载
项目源自:https://www.persistenceofvisionproject.com/












LYon 发表于 2018-9-25 11:39:05

超详细的制作历程,我以前也做过一个ESP8266+WS2812的多功能炫彩LED棒项目,除了没手工焊灯珠外其他的坑我也都踩过,哈哈。
烂不烂尾不重要,创客之路上新的想法和目标永无止境,能实现了最初主要的目的,并在这个过程Get到新技能,就是成功!

gada888 发表于 2018-9-27 15:07:59

满不错的有深度的项目

板蓝根 发表于 2018-9-28 18:16:13

很有意思,感谢分享!

20060606 发表于 2020-8-10 05:15:14

对于烂尾的定义很好

发表于 2022-4-18 10:59:11

哟西~   
页: [1]
查看完整版本: 烂尾项目投稿---RGB POV风扇