2016年4月28日 星期四

仁寶待十年了.......


累積到第二張牌了.
這回是壓克力的...

遙控變色燈

相信很多人去逛IKEA都對這蠟燭台很有印象,感覺很好看,但又不知道買了要做啥.
顏色還很多種可以挑選呢.燭台.感覺有點危險,

或許拿來當營燈也不錯,網路上有很多達人都改裝成不同的LED.
要是跟大家都一樣,創意算是抄襲的.
所以囉.來點不一樣的.我的版本是遙控變色LED燈


材料如下:
IKEA蠟燭台,
Arduino Nano控制板,
3.7V手機電池,
5V升壓板,
AT89S52 315M遙控模組,
NeoPixel LED Ring,
泡棉一塊....


預計規劃的功能如下
當按下遙控器按鈕A 開啟紅燈,再次按下則關閉紅燈.
當按下遙控器按鈕B 開啟藍燈,再次按下則關閉藍燈.
當按下遙控器按鈕C 開啟綠燈,再次按下則關閉綠燈.
藉由ABC三個按鈕的交叉組合可以出現以下七種顏色變化
如按鈕D啟動, 則呈現DEMO展示,呈現彩虹色環的旋轉變化
程式碼的部分直接使用Adafruit_NeoPixel的DEMO code.小改一下很快就完成了.

剩下就是買零件組合.
這回要利用廢棄的手機電池當作電源的來源,需要是3.7V轉5V的電源供應機制.
如果不想用手機電池,其實可以用三顆1.2V的充電電池搭配電池盒與升壓板組合.
但考慮到只有狹小的燭台頂部空間可以收納這些零件.還是使用手機電池好了.

以下是直接修改DEMO code的文件 加入AT89S52 315M的控制於PIN8/9/10/11.
NeoPixel的控制接在PIN6,總計目前使用五個訊號端.
不過.目前手上還有一個G Sensor.可以考慮一下放進去.如果燈發生搖晃時.發生閃爍嗎?不過Arduino的I2C我還不懂.這可以當作下回的練習.



#include 

#define PIN 6

// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, PIN, NEO_GRB + NEO_KHZ800);

// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
// and minimize distance between Arduino and first pixel.  Avoid connecting
// on a live circuit...if you must, connect GND first.

// defines pins numbers
const int PinD0 = 8; // D8 link to AT89S52 315M AVR D0
const int PinD1 = 9; // D9 link to AT89S52 315M AVR D1
const int PinD2 = 10; // D10 link to AT89S52 315M AVR D2
const int PinD3 = 11; // D11 link to AT89S52 315M AVR D3
const int Pulses = 200; //Define delay time 1000 = 1 sec
int BTN_A = 0;
int BTN_B = 0;
int BTN_C = 0;
int BTN_D = 0;
int VAL_R = 127;
int VAL_B = 127;
int VAL_G = 127;
int Color_R;
int Color_B;
int Color_G;

void setup() {
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  Serial.begin(9600);
  Serial.println("Hello! I'm Arduino LED Ring.\n");
  // Sets the 4 pins as Input from AT89S52 315M
  pinMode(PinD0, INPUT);
  pinMode(PinD1, INPUT);
  pinMode(PinD2, INPUT);
  pinMode(PinD3, INPUT);
}

void loop() {
  BTN_A = digitalRead(PinD0);
  BTN_B = digitalRead(PinD1);
  BTN_C = digitalRead(PinD2);
  BTN_D = digitalRead(PinD3);
  // Some example procedures showing how to display to the pixels:

  if (BTN_A == 1) { // Red enable
    Color_R = VAL_R;
  }
  else {
    Color_R = 0;
  }
  if (BTN_B == 1) { // Blue enable
    Color_B = VAL_B;
  }
  else {
    Color_B = 0;
  }
  if (BTN_C == 1) { // Green enable
    Color_G = VAL_G;
  }
  else {
    Color_G = 0;
  }
  if (BTN_D == 1) { // DEMO mode
    rainbow(20);
    rainbowCycle(20);
    theaterChaseRainbow(50);
  }
  else { // Normal mode
    colorWipe(strip.Color(Color_R, Color_G, Color_B), 20)
    theaterChase(strip.Color(Color_R, Color_G, Color_B), 50);
  }

  //  colorWipe(strip.Color(255, 0, 0), 50); // Red
  //  colorWipe(strip.Color(0, 255, 0), 50); // Green
  //  colorWipe(strip.Color(0, 0, 255), 50); // Blue
  //  // Send a theater pixel chase in...
  //  theaterChase(strip.Color(127, 127, 127), 50); // White
  //  theaterChase(strip.Color(127,   0,   0), 50); // Red
  //  theaterChase(strip.Color(  0,   0, 127), 50); // Blue

}

// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  for (uint16_t i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, c);
    strip.show();
    delay(wait);
  }
}

void rainbow(uint8_t wait) {
  uint16_t i, j;

  for (j = 0; j < 256; j++) {
    for (i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for (j = 0; j < 256 * 5; j++) { // 5 cycles of all colors on wheel
    for (i = 0; i < strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

//Theatre-style crawling lights.
void theaterChase(uint32_t c, uint8_t wait) {
  for (int j = 0; j < 10; j++) { //do 10 cycles of chasing
    for (int q = 0; q < 3; q++) {
      for (int i = 0; i < strip.numPixels(); i = i + 3) {
        strip.setPixelColor(i + q, c);  //turn every third pixel on
      }
      strip.show();

      delay(wait);

      for (int i = 0; i < strip.numPixels(); i = i + 3) {
        strip.setPixelColor(i + q, 0);      //turn every third pixel off
      }
    }
  }
}

//Theatre-style crawling lights with rainbow effect
void theaterChaseRainbow(uint8_t wait) {
  for (int j = 0; j < 256; j++) {   // cycle all 256 colors in the wheel
    for (int q = 0; q < 3; q++) {
      for (int i = 0; i < strip.numPixels(); i = i + 3) {
        strip.setPixelColor(i + q, Wheel( (i + j) % 255)); //turn every third pixel on
      }
      strip.show();

      delay(wait);

      for (int i = 0; i < strip.numPixels(); i = i + 3) {
        strip.setPixelColor(i + q, 0);      //turn every third pixel off
      }
    }
  }
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  if (WheelPos < 85) {
    return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if (WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
    WheelPos -= 170;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}

2016年4月23日 星期六

Linkit-7688 duo & Arduino IDE Error.

Linkit-7688 duo可以使用 Arduino IDE操作使用,用法就跟Arduino完全一樣
但事前的準備可多囉,首先是IDE的部分要追加LinLit 7688的資料庫(細節可以參考以下網址)
http://oranwind.org/linkit-7688-linkit-smart-76887688-duo-ji-chu-jiao-xue/
直到能夠出現以下畫面的操作參數,方可將程式碼上傳,


如操作這一部分應該只用到MCU(Microcontroller Unit),也就是ATmega 32U4.
跟7688的強項完全無關,只能說是Arduino的附身.

但要上傳Code可能會出現很可怕的錯誤訊息.可能看不懂對吧
https://labs.mediatek.com/forums/posts/list/4392.page
其中有個描述
USBCore.cpp: In function 'int USB_RecvControl(void*, int)':
這段描述就直接指出USBCore.cpp這個檔案中的描述有問題

總之得要手工微調檔案內容了.先找到檔案位置.
C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino
開啟USBCore.cpp這個檔案.
找到第430以及435行,將Auto改成int後存檔
就可以解決這個問題了.


2016年4月21日 星期四

Arduino lightsaber Debug

終於等到材料了實際運作上有幾個問題

1.購買的LED尺寸規格小於預期, 48顆LED的長度才能達到60公分.因此全部的Digital pin都要用於LED使用.所以要用於作業的LED串就需要一點勞作的實力了.

一整包的LED要如何排排站好呢?用手抓,別鬧了.烙鐵溫度300度,

至於要如何快速又簡單的將LED串接起來,首先就要先設計製具,
以下直接找個瓦楞紙盒,先規劃好距離,針對LED的位置開孔.
接著貼上一層鋁箔.散熱使用,避免烙鐵直接將瓦楞紙燒毀.

瞧,排隊整齊劃一,輕輕一點錫就接合焊好,輕鬆愉快.

速度快的話20分鐘就弄出這麼多組啦.


2. MP3 module未能如期發出聲音來.可能是程式碼有問題,或是IC的使用上還需要花點時間認識.最後重新改寫控制,先刪除MP3 player的部分,並追加新的LED控制pin,以及一分鐘無任何震動後關閉的設定.


#include 
int LEDstatus = 0; //定義變量為LEDstatus
int Touchstatus = 0;
int hum[4];
int sensorValue;
int prevValue;
int StopCount;
const int LEDdelay = 20;  //定義延遲0.020秒進行一次LED升降50FPS
const int BreatheStep = 5;
const int PowerSW = 0; // A0
const int WaveSW = 1; // A1
const int LEDMartix[12] = {13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2} ; //設定LED Martix
const int PWMpin[12] = {0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0}; // PWM: 3, 5, 6, 9, 10, 11. Provide 8-bit PWM output with the analogWrite() function.

int CheckTouch(int AnalogPin) {
  prevValue = sensorValue;
  sensorValue = analogRead(AnalogPin);
  if (sensorValue >= 1023 && sensorValue >= prevValue) {
    return 1;
  }
  if (sensorValue < 1010 & prevValue  <=  1010) {
    return 0;
  }
}

void SaberInital() {
  for (int i = 11; i >= 0; i--) {
    digitalWrite(LEDMartix[i], LOW);
  }
  LEDstatus = 0;
  StopCount = 0;
}

void SaberON() {
  for (int i = 0; i <= 11; i++) {
    digitalWrite(LEDMartix[i], HIGH);
    delay(LEDdelay);
    LEDstatus = 1;
  }
}

void SaberOFF() {
  for (int i = 11; i >= 0; i--) {
    digitalWrite(LEDMartix[i], LOW);
    delay(LEDdelay);
    LEDstatus = 0;
  }
}

void SaberFlickON() {
  for (int j = 0 ; j <= 100; j++) {
    for (int i = 0; i <= 11; i++) {
      if (i != 11) {
        digitalWrite(LEDMartix[i], LOW);
      }
      if (i != 0) {
        digitalWrite(LEDMartix[i - 1], HIGH);
      }
    }
    delay( LEDdelay / 2); //定義延遲0.01秒進行
  }
  LEDstatus = 1;
}

void SaberBreatheON() {
  for (int j = 255 ; j >= 0   ; j - BreatheStep) {
    for (int i = 0; i <= 11; i++) {
      if (PWMpin[i] == 0) {
        if (i != 11) {
          digitalWrite(LEDMartix[i], LOW);
        }
        if (i != 0 || PWMpin[i - 1] != 1 ) {
          digitalWrite(LEDMartix[i - 1], HIGH);
        }
      }
      if (PWMpin[i] == 1) {
        analogWrite(LEDMartix[i], j);
      }
    }
    delay( LEDdelay);  //定義延遲0.02秒進行
  }
  for (int j = 0 ; j <= 255   ; j + BreatheStep) {
    for (int i = 0; i <= 11; i++) {
      if (PWMpin[i] == 0) {
        if (i != 11) {
          digitalWrite(LEDMartix[i], LOW);
        }
        if (i != 0 || PWMpin[i - 1] != 1 ) {
          digitalWrite(LEDMartix[i - 1], HIGH);
        }
      }
      if (PWMpin[i] == 1) {
        analogWrite(LEDMartix[i], j);
      }
    }
    delay( LEDdelay);  //定義延遲0.02秒進行
  }
  LEDstatus = 1;
}

void setup () {
  pinMode(2, OUTPUT); //設定D2為輸出端,劍尾端
  pinMode(3, OUTPUT); //設定D3為輸出端
  pinMode(4, OUTPUT); //設定D4為輸出端
  pinMode(5, OUTPUT); //設定D5為輸出端
  pinMode(6, OUTPUT); //設定D6為輸出端
  pinMode(7, OUTPUT); //設定D7為輸出端
  pinMode(8, OUTPUT); //設定D8為輸出端
  pinMode(9, OUTPUT); //設定D9為輸出端
  pinMode(10, OUTPUT);  //設定D10為輸出端
  pinMode(11, OUTPUT);  //設定D11為輸出端
  pinMode(12, OUTPUT);  //設定D12為輸出端
  pinMode(13, OUTPUT);  //設定D13為輸出端,劍首端,接近劍柄
  pinMode(A0, INPUT);  //LED啟動開關接腳在A0,為輸入端
  pinMode(A1, INPUT);  //設定震動開關接腳在A1,為輸入端
  SaberInital();
}

void loop() {
  if (LEDstatus == 0 && CheckTouch(PowerSW) == 1) { //當有開關觸發LED亮
    SaberON();
  }
  if (LEDstatus == 1 &&  CheckTouch(PowerSW) == 1) { //當有開關再次觸發LED暗
    SaberOFF();
  }
  if (LEDstatus == 1) { //當光劍啟動時紀錄震動開關觸發狀態
    for (int i = 0; i < 4; i++) {
      hum[i] = CheckTouch(WaveSW);
      delay(250);
    }
    if ((hum[0] != 0 && hum[1] != 0 && hum[2] != 0 && hum[3] != 0) || (hum[0] != 1 && hum[1] != 1 && hum[2] !=  1 && hum[3] != 1)) {
      SaberFlickON();
      StopCount = 0;
    }
    else {
      StopCount = StopCount + 1;
      if (StopCount >> 2400) {
        SaberOFF();
      }
    }
  }
}

2016年4月5日 星期二

599小孩沙龍(洗加剪)

夏天的腳步 終於到來了 長髮女孩的煩惱就是 洗頭 吹頭很麻煩
為了減輕負擔 伴哄半騙的 終於肯去剪頭髮了
老大惜髮如金, 這回告訴他是去洗頭. 天啊~~這太誇張了吧!! 沒錯.


安穩的坐在位子上 準備要開始剪了. 竟然沒哭.


洗頭很舒服的樣子,這表情 我都想去試看看了

2016年3月27日 星期日

第一次挑戰兒童樂園

一個問題,請問兒童樂園的英文是?
Children's Paradise Park 嗎?
逐字翻譯可以選Paradise 這單字嗎?

結果兒童樂園英文為Children's Amusement Park.
我猜錯了.

這次的新挑戰是帶兩位小孩 三歲以及兩歲,身高未滿100公分的女兒前往兒童新樂園
現在的交通非常發達,過去前往士林夜市的公車R9有經過.
一班車可抵達20分鐘內可到,比上班還快.交通不成問題.

天氣好,一開始姐姐配合度很高,興致非常高.

妹妹不知道為啥,鬧脾氣堅持一定要抱著水瓶,整天都很在乎水瓶的存在.
但還是很配合的跟摩天輪來個合照了.表情就不在乎了.


園內設施蠻多的,用餐區美食街的座位也很多.
但很多設施都有設限,所以身高不超過100公分去兒童樂園 只能玩
1.Carousel 旋轉木馬..(海馬 海豚),玩了兩次,畢竟連總統都愛(註)


剛開始還笑得很開心,一會開始跑了,妹妹就怕了.

2.Ferris wheel 摩天輪,運氣很好 搭到少女最愛的粉紅草莓車廂.

但當爸爸的相當怕高,這張照片笑得很緊張.

3.Garden Train  遊園軌道車.搭起來感覺跟捷運很像,不知樂趣在哪?

4. 兒童樂園最紅的玩具竟然是 溜滑梯,但人多到擠不進去.

因為有參與園遊會活動.還有額外的四個闖關遊戲
最讓我女兒有成就感的就是釣鴨子.夜市的遊戲真的有其不敗的歷史定位

妹妹還搞不清楚到底要如何操作,姐姐已經釣到了鴨子了.姐姐的領悟力真高,好厲害.

天氣好到這裡帶小孩子走走,看她們玩累了,也是件很開心的事.
但累到睡著,倒楣的就是要揹他們回家的爸媽,截至現在.當爸媽的肩膀還在貼痠痛藥膏.

註.早點到的好處是,意外遇到總統逛樂園.整個維安小組包圍旋轉木馬.

滿滿的攝影機 繞著一圈 看來當總統一點娛樂的機會都沒有.
話說排我後面的粉紅衣妹妹,申手跟總統握手,他的家人跟隨伴同齡小孩也瞬間被維安包圍.
傳說中的武林高手嗎?維安小組是八極拳高手嗎?

2016年3月21日 星期一

Arduino lightsaber upgrade

上網找了一下,應該要用更小規格的LilyPad Arduino

規格如下,不過看了價格.....還是 Nano有優勢.
MicrocontrollerATmega168 or ATmega328V
Operating Voltage2.7-5.5 V
Input Voltage2.7-5.5 V
Digital I/O Pins14
PWM Channels6
Analog Input Channels6
DC Current per I/O Pin40 mA
Flash Memory16 KB (of which 2 KB used by bootloader)
SRAM1 KB
EEPROM512 bytes
Clock Speed8 MHz
上回的code把全部的digital pin都用掉了,剩下的pin為Analog,不用上就可惜了.
以下圖為Touch Switch的接法,經測試,不接5V以及PNP電晶體,也是可以有一樣的功能.

重新改寫Code,採用sub function的方式撰寫,方便有興趣的朋友進行修改.
追加一段閃爍控制,主要功能是用來強化LED 揮舞時出現閃爍的感受
追加Analog Touch SW的sub function.實際功能等想到再規畫吧!

效果要實際測試調整delay的速度.
Code展開如下.


#include "softwareserial.h"
#include "dfplayer_mini_mp3.h"

int LEDstatus = 0; //定義變量為LEDstatus
int Touchstatus = 0;
bool hum[4];
int sensorValue;
int prevValue;
const int LEDdelay = 20;  //定義延遲0.020秒進行一次LED升降50FPS
const int BreatheStep = 5;
const int PowerSW = 12;
const int WaveSW = 13;
const int LEDMartix[10] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2} ;  //設定LED Martix
const int PWMpin[10] = {1, 1, 1, 0, 0, 1, 1, 0, 1, 0}; // PWM: 3, 5, 6, 9, 10, 11. Provide 8-bit PWM output with the analogWrite() function.

int CheckTouch(int AnalogPin) {
  prevValue = sensorValue;
  sensorValue = analogRead(AnalogPin);
  if (sensorValue >= 1023 && sensorValue >= prevValue) {
    return 1;
  }
  if (sensorValue < 1010 & prevValue  <=  1010) {
    return 0;
  }
}

void SaberInital() {
  for (int i = 9; i >= 0; i--) {
    digitalWrite(LEDMartix[i], LOW);
  }
  LEDstatus = 0;
}

void SaberON() {
  for (int i = 0; i <= 9; i++) {
    digitalWrite(LEDMartix[i], HIGH);
    delay(LEDdelay);
    LEDstatus = 1;
  }
}

void SaberOFF() {
  for (int i = 9; i >= 0; i--) {
    digitalWrite(LEDMartix[i], LOW);
    delay(LEDdelay);
    LEDstatus = 0;
  }
}

void SaberFlickON() {
  for (int j = 0 ; j <= 100; j++) {
    for (int i = 0; i <= 10; i++) {
      if (i != 10) {
        digitalWrite(LEDMartix[i], LOW);
      }
      if (i != 0) {
        digitalWrite(LEDMartix[i - 1], HIGH);
      }
    }
    delay( LEDdelay / 2); //定義延遲0.01秒進行
  }
  LEDstatus = 1;
}

void SaberBreatheON() {
  for (int j = -255 ; j <= 255   ; j + BreatheStep) {
    for (int i = 0; i <= 10; i++) {
      if (PWMpin[i] == 0) {
        if (i != 10) {
          digitalWrite(LEDMartix[i], LOW);
        }
        if (i != 0 || PWMpin[i - 1] != 1 ) {
          digitalWrite(LEDMartix[i - 1], HIGH);
        }
      }
      if (PWMpin[i] == 1) {
        analogWrite(LEDMartix[i], abs(j));
      }
    }
    delay( LEDdelay);  //定義延遲0.02秒進行
  }
  LEDstatus = 1;
}

void setup () {
  Serial.begin (9600);
  mp3_set_serial (Serial); //set Serial for DFPlayer-mini mp3 module
  mp3_set_volume (10);
  pinMode(2, OUTPUT); //設定D2為輸出端,劍尾端
  pinMode(3, OUTPUT); //設定D3為輸出端
  pinMode(4, OUTPUT); //設定D4為輸出端
  pinMode(5, OUTPUT); //設定D5為輸出端
  pinMode(6, OUTPUT); //設定D6為輸出端
  pinMode(7, OUTPUT); //設定D7為輸出端
  pinMode(8, OUTPUT); //設定D8為輸出端
  pinMode(9, OUTPUT); //設定D9為輸出端
  pinMode(10, OUTPUT);  //設定D10為輸出端
  pinMode(11, OUTPUT);  //設定D11為輸出端,劍首端,接近劍柄
  pinMode(PowerSW, INPUT);  //設定LED啟動開關接腳在D12,為輸入端
  pinMode(WaveSW, INPUT);  //設定震動開關接腳在D13,為輸入端
  SaberInital();
}

void loop() {
  if (LEDstatus == 0 && digitalRead(PowerSW) == HIGH) { //當有開關觸發LED亮
    mp3_play (random(6, 8));  //先將光劍啟動的音效檔定為0006.mp3 或0007.mp3, 藉由亂數處理任意播放
    SaberON();
    delay (1000 - LEDdelay * 9); //播放1秒音效
  }
  if (LEDstatus == 1 &&  digitalRead(PowerSW) == HIGH) { //當有開關觸發LED暗
    mp3_play (random(9, 11)); //先將光劍關閉的音效檔定為0009.mp3 或0010.mp3, 藉由亂數處理任意播放
    SaberOFF();
    delay (1000 - LEDdelay * 9); //播放1秒音效
  }
  if (LEDstatus == 1 && CheckTouch(A0) == 1) {
    mp3_play (2);  //播放揮光劍的音效檔定為0002.mp3
    SaberBreatheON();
    delay (2000 - LEDdelay * 255 / BreatheStep * 2);
  }
  if (LEDstatus == 1) { //當光劍啟動時紀錄震動開關觸發狀態
    for (int i = 0; i < 4; i++) {
      hum[i] = digitalRead(WaveSW);
      delay(250);
    }
    if ((hum[0] != 0 && hum[1] != 0 && hum[2] != 0 && hum[3] != 0) || (hum[0] != 1 && hum[1] != 1 && hum[2] !=  1 && hum[3] != 1)) {
      mp3_play (1);  //播放揮光劍的音效檔定為0001.mp3
      SaberFlickON();
      delay (1000 - LEDdelay * 9 / 2);
    }
  }
}

2016年3月17日 星期四

Arduino lightsaber DIY


光劍的題材很多人在做,比如說 泡棉光劍..有音效 可對打不怕重傷 又有藍芽控制 真的好棒.
想要當原力武士要打造一把自己專屬光劍,只要會Arduino,靠網路上的分享文章就可以DIY了,
以下文章的資源大部分都來自於網路上的分享.

如想要簡單的光劍,揮舞有音效,開啟以及關閉時會有光線升降的效果
  • 就材料上單晶片挑選Arduino nano當控制板,一來小二來便宜.
  • 音效需要MP3 player. Mini MP3 module *1, 稍嫌貴了些...
    音效coding的部分可參考DFPlayer Mini MP3的範例
  • TF card *1 用來存放MP3檔案,MP3的音效檔可以到The Force Net尋找Lightsaber sound的MP3
  • 劍身先找壓克力燈管 直徑23mm左右的.先把燈管做出來
  • 劍柄的部分找3D印表機列印囉.
  • 電源的部分,可以找單顆18650電池的行動電源提供5V的DC輸出
  • 開關的部分 需要微動開關作為Power ON/OFF的切換
  • 水銀開關作為晃動時的Audio ON/FF的判斷
  • LED數顆,光劍的LED串接可以參考超炫IoT光劍自製HowTo完全公開!
    (以下相關LED連接的圖片都擷取自上述連結)

但使用上 就要規劃一下,看一下如果想要有10段光線升降,會用掉D2~D11 pin
超炫IoT光劍自製的文章中採用的是6段光線升降,用的是3.3V的DC,

可能實際上要考慮一下Arduino是5V的DC
至於5V能並聯幾顆LED,串聯電阻多大,可以先參考一下這篇文章,
為什麼LED需要串聯的電阻值是220 ohm?
也可利用以下連結直接在線上作計算.
LED限流電阻值-線上計算器


針對Arduino的pin define先規劃一下




D0~D1連接Mini MP3 player
D2~D11連接LED Matrix控制LED燈管
剩下的D12 / D13當電源控制開關的訊號囉.
Pin define的規劃如下.剩下就是coding跟買材料來組裝.

Arduino Nano
DFPlayer Mini MP3
Speaker
LED 
N/A
SPK_1
RED Line
 
N/A
SPK_2
Black Line
 
TX/D1
RX
 
 
RX/D0
TX
 
 
RST
 
 
 
GND
GND
GND
GND
D2
 
 
LED matrix 1
D3
 
 
LED matrix 2
D4
 
 
LED matrix 3
D5
 
 
LED matrix 4
D6
 
 
LED matrix 5
D7
 
 
LED matrix 6
D8
 
 
LED matrix 7
D9
 
 
LED matrix 8
D10
 
 
LED matrix 9
D11
 
 
LED matrix 10
D12
 
 
LED On/OFF
D13
 
 
Audio On/OFF
3V3
 
 
 
AREF
 
 
 
A0
 
 
 
A1
 
 
 
A2
 
 
 
A3
 
 
 
A4
 
 
 
A5
 
 
 
A6
 
 
 
A7
 
 
 
5V
VCC
 
VCC
RESET
 
 
 
GND
 
 
 
VIN
 
 
 





就以上的規劃coding的展開如下,剩下就是debug囉.!


#include "SoftwareSerial.h"
#include "DFPlayer_Mini_Mp3.h"

const int LedMartix1 = 2;     //設定LED Martix1接腳在第2pin
const int LedMartix2 = 3;     //設定LED Martix2接腳在第3pin
const int LedMartix3 = 4;     //設定LED Martix3接腳在第4pin
const int LedMartix4 = 5;     //設定LED Martix4接腳在第5pin
const int LedMartix5 = 6;     //設定LED Martix5接腳在第6pin
const int LedMartix6 = 7;     //設定LED Martix6接腳在第7pin
const int LedMartix7 = 8;     //設定LED Martix7接腳在第8pin
const int LedMartix8 = 9;     //設定LED Martix8接腳在第9pin
const int LedMartix9 = 10;      //設定LED Martix9接腳在第10pin
const int LedMartix10 = 11;     //設定LED Martix10接腳在第11pin
const int PowerON = 12;     //設定LED啟動開關接腳在第12pin
const int AudioON = 13;     //設定水銀開關接腳在第13pin
const int LEDdelay = 30;      //延遲0.03秒進行一次LED升降
int LEDstatus = 0;      //定義變量為LEDstatus=0

void setup () {
  Serial.begin (9600);
  mp3_set_serial (Serial); //set Serial for DFPlayer-mini mp3 module
  mp3_set_volume (10);
  pinMode(AudioON, INPUT);          //設定水銀開關為輸入端
  pinMode(PowerON, INPUT);          //設定LED啟動開關為輸入端
  pinMode(LedMartix10, OUTPUT);     //設定LED Martix10為輸出端
  pinMode(LedMartix9, OUTPUT);      //設定LED Martix9為輸出端
  pinMode(LedMartix8, OUTPUT);      //設定LED Martix8為輸出端
  pinMode(LedMartix7, OUTPUT);      //設定LED Martix7為輸出端
  pinMode(LedMartix6, OUTPUT);      //設定LED Martix6為輸出端
  pinMode(LedMartix5, OUTPUT);      //設定LED Martix5為輸出端
  pinMode(LedMartix4, OUTPUT);      //設定LED Martix4為輸出端
  pinMode(LedMartix3, OUTPUT);      //設定LED Martix3為輸出端
  pinMode(LedMartix2, OUTPUT);      //設定LED Martix2為輸出端
  pinMode(LedMartix1, OUTPUT);      //設定LED Martix1為輸出端
  digitalWrite(LedMartix10, LOW);    //設定LED Martix10預設LOW
  digitalWrite(LedMartix9, LOW);    //設定LED Martix9預設LOW
  digitalWrite(LedMartix8, LOW);    //設定LED Martix8預設LOW
  digitalWrite(LedMartix7, LOW);    //設定LED Martix7預設LOW
  digitalWrite(LedMartix6, LOW);    //設定LED Martix6預設LOW
  digitalWrite(LedMartix5, LOW);    //設定LED Martix5預設LOW
  digitalWrite(LedMartix4, LOW);    //設定LED Martix4預設LOW
  digitalWrite(LedMartix3, LOW);    //設定LED Martix3預設LOW
  digitalWrite(LedMartix2, LOW);    //設定LED Martix2預設LOW
  digitalWrite(LedMartix1, LOW);    //設定LED Martix1預設LOW
}

void loop() {
  if (LEDstatus == 0 && digitalRead(PowerON) == HIGH) { //當有開關觸發LED亮
    mp3_play (random(6, 8));     //先將光劍啟動的音效檔定為0006.mp3 或0007.mp3, 藉由亂數處理任意播放
    delay (1000);    //播放1秒音效
    for (int i = 2; i <= 11; i++) {
      digitalWrite(i, HIGH);
      delay(LEDdelay);
      LEDstatus = 1;
    }
  }
  if (LEDstatus == 1 && digitalRead(PowerON) == HIGH) { //當有再次開關觸發LED暗
    mp3_play (random(9, 11));     //先將光劍關閉的音效檔定為0009.mp3 或0010.mp3, 藉由亂數處理任意播放
    delay (1000);    //播放1秒音效
    for (int i = 11; i >= 2; i--) {
      digitalWrite(i, LOW);
      delay(LEDdelay);
      LEDstatus = 0;
    }
  }
  if (LEDstatus == 1) { //當光劍啟動時紀錄水銀開關觸發狀態
    for (int i = 0; i < 4; i++) {
      hum[i] = digitalRead(AudioON);
    }
    if ((hum[0] != LOW && hum[1] != LOW && hum[2] != LOW && hum[3] != LOW) || (hum[0] != HIGH && hum[1] != HIGH && hum[2] !=  HIGH && hum[3] != HIGH)) {
      randNumber = random(1, 5);
      mp3_play (randNumber);     //先將揮光劍的音效檔定為0001~0004.mp3, 藉由亂數處理任意播放
      delay (randNumber * 1000);
    }
  }
}

名古屋行前準備

旅行先預訂了機+酒;不能讓這件旅遊的任務失敗.行前準備要做好 名古屋5天4夜家庭旅行計畫 ( 根據Grok的建議) 2026年1月30日 - 2月3日(2大2小,一個家庭) 行程採用 QFN思考模式 ,確保父母(45-50歲)執行力與小孩(6-12歲)樂趣兼顧: Quality(...