2015年12月31日 星期四

秋葉原的電子零件商店-1


大概去年(2015)第一次去去東京,主要是去看Tokyo Maker faire的時候,排了兩天逛秋葉原XD
然後這篇會是一些在秋葉原的電子零件商店簡介,全部的商店地圖在這
主要的資料來源是Tokyo Hackerspace對秋葉原的店家介紹(每家店的地點/影片集)
另外就是圖片太多,所以分成幾篇這樣

IV-18 Arduino Clock


這應該算是第二版了,這個版本改成控制板+顯示板,先來列一下特色
  1. 自動亮度控制
  2. Wifi 設定(校時,時區,鬧鐘,顯示風格,手動亮度控制)
  3. 蜂鳴器鬧鐘
  4. Build with Arduino Leonardo(Atmega32U4)
控制板主要有
  1. Atmega32U4 as MCU
  2. Linkit connect module to connect to Internet
  3. RTC (DS1307 or PCF8563) with CR1215 battery backup
  4. Buzzer 
  5. Four tact switch
  6. Photocell

顯示板主要有
  1. HV5812 VFD controller
  2. Attiny24 I2C VFD scanner
  3. build in Step-up
這次版本最重要的就是把我想很就的Wifi功能加了進去,主要就是為了NTP校正時鐘
所以先從這邊講起,
一般來說,時間校正(先不管計時機制),有下列這幾種
  1. 網路
  2. 無線電校時(大人的科學有電波鐘套件,就那種Type)
  3. GPS
  4. GSM(基地台會幫你校時)
以前Wifi模組還很貴的時候基本上都是用2或3,但是無線電台灣沒有開發射站了,所以只能收日本的,訊號很差,甚至還要用音源線+OOXXZZZ做簡易的發射源,太麻煩
GPS的問題也不是說訊號太弱,但是不是每個人都會把時鐘放在窗邊,至於GSM就無視吧
所以這三個在我以前做時鐘的時候都沒用
之前為了時鐘的準確度(懶得校時)所以就用了比較高級的RTC(DS3231),真的覺得不錯,一年下來差不到幾秒.

然後最近幾年,Wifi模組的價錢可以說是直接殺了下來,以前在櫥窗的那些Microchip貴桑桑的無線網路模組,現在只要台幣幾百塊錢,所以是時候把時鐘也連上網了.(我還可以宣稱是科技潮流的 I-O-T 喔喔喔喔喔)

這次用的Wifi模組是聯發科的MT7681模組
就一個標準的3.3V,UART無線網路模組.有Arduino 的範例也有接線圖https://github.com/will127534/7681-ATcmd
範例就是NTP time sync

好了,那已經有網路校時了,這Wifi模組還可以發揮甚麼功能?
顯示股票大跌,不準的公車預估到達時間,永遠掛0~9的新郵件數目
這些當然都很好,只是說Code不夠用......

所以就先把設定值搬到網路上

===========期末考完再來補...===============







2015年11月30日 星期一

High Altitude Ballooning with LoRa



好久沒有寫廢話了,Blog的草稿越疊越高,過陣子應該就有空補完,
不過這東西真的令人興奮,所以趕快貼上來

As title,這次是關於高空氣球.
左邊接收器,右邊要探空的
上圖是同一種電路板但是設定成不同功能,一個是探空儀,另一個是地面接收站
規格如下:

  • Atmega328 (就是用Arduino UNO)
  • RFM98    (LoRa模組)
  • Neo 6m    (GPS)
  • MPU9250 (姿態)
  • BMP180 ,但是之後換成MS5607 (氣壓計)
  • HDC1000
首先來講一下重點的無線模組,這次用的是LoRa,比傳統的FM那種來說,首先是Link Budget可以很高,而且可以藉由下調速度來換取更高的Link Budget,而換取更遠的距離

這次的速度設定有兩個,第一是GPS Channel,有鑑於這是最重要的一筆資料(與天線指向有關)
所以設定的速度很低,只有183.11bps, 參數是:SP:12,Band:125Khz,CR:4/8
而這個Link budget達到154dB
第二個則是Payload Channel,這次是裝了九軸計算出來的姿態,速度是21875bps
參數是SP:7,Band:500khz,CR:4/5,Link budget只有134dB

而這兩個的理論最低接收訊號強度為 -137和-117dBm

至於九軸這次選MPU9250主要的原因是因為體積,比起9150來說,周邊電路的零件減少一些
另外就是氣壓計,其實BMP180並不適合,因為最低氣壓只有300hPa,換算高度大概只有七公里
所以在第二次升空的時候改用MS5607,最低可以達到10hPa.

至於GPS模組就是單純找個能用的然後便宜,不過這有個Trick,還有個大魔王,下面會提到

我原先的發射流程是希望探空儀用GPS計時,之後就每分鐘切到GPS Channel後送一筆GPS位置和高度,其他時候每秒鐘送一次姿態+其他資料回來
然後地面站同步時間切頻道收資料,一種TDMA的概念

試了一下覺得沒問題就跑去升空



然後就出問題了,由於問題太多,所以決定用條列式的
  1. GPS高度資料是錯的
  2. Yagi天線也是錯的頻率
  3. 地面站的時鐘和GPS時間有誤差
  4. Python的Thread Handle也有問題
  5. 被大樓擋住
GPS高度錯誤這件事情真的讓我嚇到了,氣球上去之後看著他升空遠去,然後轉頭看著電腦的20m高.....然後就GG了,高度資料出問題的時候,天線指向的仰角會出問題,理論上這時候應該要切成壓高公式去計算(把靜力平衡和氣體方程式帶進去然後隨高度積分),但是一來,我沒有環境的溫濕度計,沒有辦法計算需要的平均虛溫,而且我也沒有寫這個副程式

於是只能用N小時前的探空資料去算大概的高度,免強追到25Km遠

這一切是因為我沒有設定成飛航模式,也就是讓GPS知道說我不在地面上.u-blox需要先由u-blox center設定後,才有高度可以用,而且還要加電池不然設定會消失.再來就是Yagi天線的問題,原先的設計是給400Mhz的Vaisala用的,然後我以為433應該也可以,計算證明根本.....至於地面時鐘,這大概無解,只能讓地面站也有GPS會比較好一點



可以看到的是RSSI基本上剛開始有點悲劇,後來用探空資料回推高度有好一些,但是之後還是GG了,而能夠慶幸的是電池電壓與內部溫度都沒有變低多少,不過高度只有404hPa

接下來是第二次測試,改進的點就是
  1. GPS模組補回備份電池,同時設定成Airborne <1g
  2. 接收機變成兩組,兩隻新的433Mhz Yagi天線,同時接收兩個Channel
  3. 地面接收站改版加了GUI
  4. GPS資料改成每10秒送一筆,而且多送外部溫度,氣壓資料

然後剛開始前先用一個小氣球和繩子測試GPS的高度資料正常,由於高度很低,所以用防靜電袋裝著就好

可以看到線的重量已經開始影響升力了

然後測試正常之後就換大顆的氣球來

雙接收器

地面接收站軟體,要注意的是外部溫度沒有接上

由於這次風向正確,所以沒被任何東西擋住,算是滿成功的接收到67Km遠,13km高的程度
可以看到的是,RSSI維持在-90附近,差不多是這次實測的極限
內部溫度則是達到了-6度,但是電池電壓依舊是沒啥太大的變化,

至於為啥最後會失效,從GPS和Payload同時掛掉來看應該不是因為訊號的問題
I2C lock 住也應該不是問題,因為我已經把TWI.c改過了一下,把所有的while loop都加了Timeout
電池電壓也明顯不是,這溫度應該還不到直接掛掉,Feq shift也不過150hz,理論上不成問題

所以目前打算的解法就是用Watchdog先撐著.....

這篇應該還會再補就是了,應該啦

=====Update=====
我後來想起來一個很好笑的事情,我用的LDO是LM1117-3.3v
用Li-poly很明顯得Vdrop太大,電壓應該下降了不少
所以我覺得很有可能是因為溫度下降之後,電池過LDO電壓掛掉
這次的電池電壓測量方法是用VCC當3.3v,也不是用內建的Bandgap
所以測出來穩定的4.2V其實很有問題






2015年8月15日 星期六

Attiny x5/x4 mix program shield

 簡單來說就是...兩種系列(Attiny24/44/84 Attiny25/45/85)都能用的燒錄座
電路並不是簡單的開關就好了,由於x4和x5的部分接角重疊,需要比較複雜一點的電路
然後就做成下面這種鬼模樣了...
就直接用了一顆有兩個Analog Switch的IC然後結束這回合

另外就是這有放LED燈XD


YM2413 8-bit FM Sound IC + Arduino

 話說八月初去秋葉原扭了兩個FM音校IC的扭蛋
一個是YMF276-M 另一個是YM2413,Google的時候發現有人做過YM2413的Arduino Shield
https://htlab.net/products/electronics/ym2413-shield-1/
於是就沿用他的Code,不過硬體的部分改了一下
這顆IC基本上就是用8-bit的匯流排去寫入要演奏的樂器/Feq這樣,然後同時兩個(這是Costdown的版本...)
從它的Application manual http://www.smspower.org/uploads/Development/chipsym2413am.pdf
可以看到如下的工作原理
基本上需要的是積分電路,Mixer 還有LPF,最後就耳擴或是個簡單的OPA,我用的是LM386,
放大200倍大概就破音了...


Update:
改用Arduino Leonardo之後,改用acore的USB MIDI Device Stack
就變成USB MIDI Player了,影片放Youtube

2015年7月4日 星期六

Wifi Arduino (Leonardo + Linkit connect module)


簡單來說,就是Arduino Micro pro內建 MT7681的開發版本
用的是Sparkfun的Micro pro 3.3V的版本改來的,然後兩排Pin多了三個是MT7681自己的GPIO這樣

不過這Layout還是有點問題就是說,MT7681的Reset和Arduino的Reset是接在一起的,所以當Wifi出了問題的時候,我就不能單獨Reset,另外一個問題就是...

3.3V和VCC我沒接上去...

我在改電路圖的時候沒發現到3.3V和VCC還是分開來的,結果就是焊接完發現怎麼不會動的時候才發現到這問題,幸好供應VCC的LDO就在3.3V的Pin旁邊,一個大坨的焊錫就解決惹
PCB:https://github.com/will127534/Linkit-connect-with-arduino

2015年6月12日 星期五

Linkit one 上面常見的問題

一樣,整理一下作為筆記使用

1.Conctructure 不能再Setup以前使用

      EX: Adafruit MAX31855 library當中,硬體的設定是在constructure裡面設定的
             Linkit one 會出問題,但是把這段code移動到setup就好

2.Timming 不準
      由於Linkit one 上面跑的是RTOS,對於Arduino的Code會被Driver中斷,所以要在Arduino code裡面做到us等級的delay是不準的(還是可以試試)
    
   EX:DHT11,22 用Adafruit的話需要改
          
                                           DHT dht(DHTPIN, DHTTYPE, 13);

       但是就算是改過了,出錯率還是很高,所以不建議Linkit one的Arduino code拿來刻時序要求很精準的通訊.(然後順便婊一下,DHTXX真的很爛,我的觀察啦,我不喜歡用

3.Analog速度的問題
     Linkit one上面Analog不快,大概20ms,所以也不建議拿內建的Analog pin做示波器等級的東西,但是SPI速度超級快(他的基頻高),所以真的要快速的ADC,Ti有很多選擇,用SPI接上就好

4.I2C一次只能送8byte
    如標題,就是在Start後面最多8 byte,但是可以送Repeat Start
5.delay(1)沒有作用
    因為底層的RTOS systick是4.12ms,所以delay(5)以下其實因為小數點的關係會變成delay(0)
    導致delay(1~4)沒有作用,解決辦法就是改用delayMicroseconds(1000)

還有的話這篇文會增加,有解決的話會附註


2015年6月7日 星期日

Bluetooth Sensor node

其實這東西就是LMX9838 + Atmega32U4,也就是Arduino Leonardo

之所以會用LMX9838其中一個理由是因為這東西很小,這一整組不過十元硬幣的大小,
再來就是為啥會用BT 2.0了,因為這個裝置的目標是快速地把資料採樣,所以BLE的速度太慢了,每20ms 20byte絕對不夠用的,所以用傳統的Bluetooth來傳資料.

另外這個東西還有鋰電池充電器,所以上面那個插頭可以直接接鋰電池然後用USB充電這樣,
PCB:https://github.com/will127534/LMX9838-Arduino-board




2015年5月8日 星期五

HDD Motor Driver

總之這是一個三相無刷馬達的控制器,和電變有點像,
不過有幾個地方不一樣:

1.我用的是DRV11873,最大電流2A,電壓12V
2.用Attiny直接輸出PWM

大概就這兩點不一樣,因為硬碟馬達沒有受力的情形下其實電流非常小(不到0.01A)
所以其實用不著買電變來用,自己做一個小小張的就可以了,順帶一提這PCB忘了接最重要的PWM....所以你可以看到有條飛線在那邊

至於為啥不用NE555來生PWM,理由是因為我懶得畫了XDDD
而且Attiny24一個10元買太多了要消耗掉一些才行






2015年5月7日 星期四

FDC1004 With Arduino (Linkit one)



        FDC1004是Ti出的 I2C 電容測量ADC,使用起來滿方便的,體積也很小
        之後應該會拿來做一些Project
       
        電路方面很簡單,I2C和電源(3.3V)接起來就好



我現在的設定是200 sample/s , 4ch , continuous sampling , no offset/gain
Code 如下:

#include <Wire.h> 


int FDAddress = B1010000;


void setup() 

Serial.begin(115200);         

Wire.begin();      

    initFD();    
Serial.println("Setup");


void loop() 
{
  Serial.println(" ===========================================");
       
  for(int i=0; i<4; i++){
        uint32_t cap = ((read2byte(0x00+i*2)<<16)+read2byte(0x01+i*2))>>8;

        Serial.print("Input ");
        Serial.print(i);
        Serial.print(" ==> ");
        Serial.print(cap,HEX);
        Serial.print(" ==> ");
        Serial.print(cap/65536.0,5);
        Serial.println(" pf");


}
   Serial.println(" ===========================================");
        delay(1000);  
}





void initFD(){
for(int i=0; i<4; i++){
    write2byte(0x08+i,0x1C00+0x2000*i);
}
 write2byte(0x0c,0x5F0);  //All enable rate = 100


}

uint16_t read2byte(uint8_t address) {

Wire.beginTransmission(FDAddress);
Wire.write(address);
Wire.endTransmission();
Wire.requestFrom(FDAddress, 2);
uint16_t data = Wire.read();
        data = (data<<8)+Wire.read();
return data;
}

void write2byte(uint8_t address,uint16_t data) {

Wire.beginTransmission(FDAddress);
Wire.write(address);
    Wire.write(data>>8);
    Wire.write(data);
Wire.endTransmission();

}




2015年4月28日 星期二

氣象站 3.1 Router (nrf24l01 router)

由於最近Rpi一代借出去了,目前沒有Server可以用,所以就把我的Wifi Arduino拿來用
基本上這個就是Leonardo + Linkit connect module

總之就是將nRF24l01接收到的資料打包之後,送到Xively上面(P.S Xively看來是很難在註冊了..)

完整的程式在這邊(待補)
底下因為Sublime Text 3 的字體+上色太好看了,所以我用截圖來說明

 首先是Setup,要做的就是設定nRF24l01,這邊使用的Library是Mirf,很方便使用的一個library,設定完通訊方式,接收地址,以及接收大小之後就可以了.
再來就是利用AT cmd讓MT7681模組Reset,之後等待RecoveryMode結束的左箭頭之後就連線到AP.
但是如果MT7681並沒有對Reset回應的話,就會用GPIO將Wifi Arduino整台Reset,因為我當初Layout的時候並沒有把MT7681的RST接上GPIO而是和Leonardo的接在一起.













Loop也很簡單,收到nRF的資料之後,就將資料放到Structure裡面,然後把Wifi 的資料送出去
另外我用WatchDog來防止整台因網路不通的關西而Freeze的狀況.

最後就是Linkit connect module library當中需要的callback了










Wifi送資料的部分,剛開始先準備好資料,將Structure內的各個資料轉成String,同時查詢api.xively.com的IP位置,最後連到Server送Http header與資料.


============================
PUT /v2/feeds/(feedID).csv HTTP/1.1
Host: api.xively.com
X-ApiKey: (API_key)
Content-Length: (datalength)
Content-Type: text/csv
Connection: close

Humidity,(humidity)
Temperature,(temperature)
============================
大概是這種感覺

順帶一提,一樣是為了防止網路連線出錯導致的Freezing,加了WDT作保護


連線到AP的大概就是這種感覺...

以上就是針對接收站的紀錄了~

2015年4月27日 星期一

Linkit connect module 使用

上圖就是Linkit connect module,使用的其實就是MT7681 Wifi Soc
最近在完成的Project其中一個有用到這個模組,所以留個筆記方便日後使用

首先就是Linkit connect module其實是一個可以獨立Program的Wifi module
SDK是Open出來的,在官方網站就可以抓到最新的SDK與說明文件

先從硬體開始,因為這個模組,Seedstudio有做了一個Open Hardware的開發版可以用,所以可以先從HDK上面下載Eagle Layout files,打開來之後就可以直接沿用他們的做好的Linkit connect module Library,順帶一提,在Eagle裡面要跨檔案的複製只需要再命令列打copy之後打paste就可以貼上了,直接用左邊那一欄的複製是不行的

Update:我把它拿出來做成Library了,在這邊下載
所以就可以很直接的整合到其他PCB當中,底下這是Linkit connect with Arduino的電路圖
再來就是軟體,因為我的使用方式是把模組當作Wifi模組使用,所以是Arduino控制的,這就需要在Linkit connect上面燒錄AT cmd 的韌體,網路上已經有人寫好了一套韌體可以拿來用,不過我有再修改過,在這邊,可以看到我是fork IOTPlayer來改的
把Arduino_sample底下的MT7681的資料夾整包放到Arduino 的 library資料夾就可以在Arduino裡面使用了.

燒錄方式如下:在官網下載好Linkit connect module SDK之後,找個Serial to USB(總之就是一個接上Linkit connect module 的 COM port)接上模組,SDK裡面有個資料夾叫做Uploader,開命令程式列並且把AT cmd的兩個韌體放到該資料夾之後打這串指令:
mt7681_uploader.exe -f MT7681_sta_header.bin -c COM7
這樣就燒錄好了

Update:我把Uploader從SDK拿出來放在Github了,在這邊下載

接下來就從範例開始
首先,修改這三行
LC7681Wifi wifi(&Serial1);   <=填入使用的Serial
            Uno的話因為只有一個Serial,所以把Linkit connect接上Serial之後,這邊填入Serial
            Leonardo的話因為本身有USB CDC的Serial,所以實體的Serial是Serial1,所以填                               Serial1而Due,與Mega等等具有多個Serial的就看你是接上哪一組就填哪一組

const char ssid[] = "";          
const char key[] = "";
                       以上兩行填入你想連接AP的SSID與Key

接下來接上模組,燒錄完就可以用了.




2015年4月24日 星期五

Nrf24l01 Sensor node (氣象站 3.1)

 這是繼氣象站3.0的後續版本,基本上因為前一版真的是頗悲劇的
前一版的主要問題在於耗電量與體積問題,還有Layout的各種錯誤

這次的版本基本上就是

  1. 核心 Arduino Atmega328
  2. 氣壓計 BMP085
  3. 溫溼度計 HDC1000 
  4. 無線模組 Nrf24l01

 可以看到上方的Nrf24l01模組與底下的BMP085和右邊的HDC1000以及被遮住的Atmega328
 這次重點就擺在耗電量了,上次做的那一版可能是LDO的耗電量吧,啥待機耗電量大成這樣(60uA),這次是CR2032直接接上系統電壓,所以基本上不會需要任何穩壓,降低耗電量,
同時把讀取的時序調整過了,我簡單說明一下:
通常Sensor在測量的時候都會需要點時間,但是Arduino的Library常常會將這點時間用delay帶過
這就造成Arduino長時間的閒置,徒增耗電量的概念,所以我把開始測量和讀取測量值分開,中間用待機,這樣就可以省掉滿多閒置時間的

文字說明似乎不夠,用圖來解釋好了.
這是測試方法,由於最高耗電量不到數百mA的等級,用一個10歐姆的電阻串在中間,然後拿個示波器量就好(待機耗電量依然需要用電表來測)
這是目前的耗電量曲線,可以看到剛開始有兩次高峰,分別是HDC1000和BMP085的溫度啟動測量,第二個就是把測量的值讀進來,然後啟動BMP085的氣壓和HDC1000的濕度測量,最後將資料計算完之後,啟動RF,把資料發射出去

如果沒有特別設定的話,從第一個高峰到最後一個通通都會耗電.
這是RF發射的詳細波形,可以看到基本上設定要發射之後Arduino就睡眠了,等到最後面在啟動看有沒有傳成功.
耗電量的計算,基本上就是算面積,小心估計出各個耗電的時間和耗電量之後(V=IR,所以示波器上面的電壓除以10(我用的電阻值)就是電流),加總起來算平均

我的計算出來大概.....我忘了,等等翻一下計算過程去哪裡.....= ___ =
只記得大概靠CR2032撐個一年
有發射器當然就要有個接收站,但是我手邊的Raspberry Pi 一代借出去了,所以拿我的Wifi Arduino來傳,這就下一篇來解釋了.

2015年4月10日 星期五

Arduino countdown timer

 好久沒有用洞洞板做東西了..
這次是一個Arduino 倒數計時器,只是比一般的計時器多了一個警告的控制,也就是說倒數到幾分鐘會亮黃燈,歸零就亮紅燈這樣,功能很簡單,
架構就是三個按鈕,上/下/開始(長按:設定警告分鐘),一個Reset(回到開始的設定),然後兩個LED與四個七段顯示器.另外因為Pin不夠用了,所以加了一個74HC595控制七段顯示器的abcdefg

很亂的配線...
程式方面比較複雜的有兩個,長按切換模式,以及四個七段顯示器的掃描

接線圖我就不畫了,反正把程式碼的各個Pin設定好就能用

#include <stdio.h>

byte digit[8] = {1, 3, 5, 6, 7, 2, 4, 0};
byte num[4] = {5, 6, 7, 4};
byte led[3] = {2, 3, A4};
byte button[3] = {A0, A1, A2};
int SER_Pin = 8;   //pin 14 on the 75HC595
int RCLK_Pin = 9;  //pin 12 on the 75HC595
int SRCLK_Pin = A3; //pin 11 on the 75HC595
int reset = 10;

#define number_of_74hc595s 1
#define numOfRegisterPins number_of_74hc595s * 8
boolean registers[numOfRegisterPins];
byte seven_seg_digits[10][7] = { { 1, 1, 1, 1, 1, 1, 0 }, // = 0
  { 0, 1, 1, 0, 0, 0, 0 }, // = 1
  { 1, 1, 0, 1, 1, 0, 1 }, // = 2
  { 1, 1, 1, 1, 0, 0, 1 }, // = 3
  { 0, 1, 1, 0, 0, 1, 1 }, // = 4
  { 1, 0, 1, 1, 0, 1, 1 }, // = 5
  { 1, 0, 1, 1, 1, 1, 1 }, // = 6
  { 1, 1, 1, 0, 0, 0, 0 }, // = 7
  { 1, 1, 1, 1, 1, 1, 1 }, // = 8
  { 1, 1, 1, 0, 0, 1, 1 } // = 9
};


void setup() {
  Serial.begin(115200);
  for (int i = 0; i < 3; i++) {
    pinMode(button[i], INPUT_PULLUP);
  }
  pinMode(reset, INPUT_PULLUP);
  for (int i = 0; i <= 3; i++) {
    pinMode(num[i], OUTPUT);
  }
  for (int i = 0; i < 3; i++) {
    pinMode(led[i], OUTPUT);
    digitalWrite(led[i], HIGH);
  }

  pinMode(SER_Pin, OUTPUT);
  pinMode(RCLK_Pin, OUTPUT);
  pinMode(SRCLK_Pin, OUTPUT);
  clearRegisters();
  writeRegisters();
}
int second = 0;
int minute = 0;
int lastth = 0;
int lastminute = 0;
uint32_t lastbutton = 0;
uint32_t counttime = 0;
uint32_t ledtime = 0;
bool counting = 0;
int state = 0;
bool settime = 0;//0=countdown 1=last
int th = 5;
void loop() {
  if (settime) {
    disp(th / 10, th % 10, 0, 0);
    digitalWrite(led[1], HIGH);
  }
  else if(0==digitalRead(reset)){
   settime=0;
   counting =0;
   minute = lastminute;
   th = lastth;
   second = 0;
 }
 else {
  disp(minute / 10, minute % 10, second / 10, second % 10);
  if (millis() - counttime > 1000) {
 
    if (counting == 1) {
      second--;
      if (second < 0) {
        minute--;
        second = 59;
      }
      if (minute < 0) {
        minute = 0;
        second = 0;
      }
      Serial.print(minute);
      Serial.print(",");
      Serial.println(second);
      if (minute < th) {
        digitalWrite(led[0], HIGH);
       // Serial.println("Alarm");
      }
      else {
        digitalWrite(led[0], LOW);
      }
      if (minute <= 0 && second <= 0) {
        digitalWrite(led[1], HIGH);
        //Serial.println("STOP");
      }
      else {
        digitalWrite(led[1], LOW);
      }
      state = !state;
      digitalWrite(led[2], state);
      //Serial.println(digitalRead(led[2]));
    }
    else {
        //Serial.print(digitalRead(led[0]));
        //Serial.print(digitalRead(led[1]));
        //Serial.println(digitalRead(led[2]));
       // digitalWrite(led[0], !digitalRead(led[0]));
       // digitalWrite(led[1], !digitalRead(led[1]));
     }
     counttime = millis();
   }
   else if (millis() - ledtime>200){
     if (counting == 0){
      digitalWrite(led[0], !digitalRead(led[0]));
      digitalWrite(led[1], !digitalRead(led[1]));
      state = !state;
        digitalWrite(led[2], state);  //ditry fix about digitalRead error on led2
        ledtime = millis();
      }
    }
  }
  scan();

}
void change(int i) {
  switch (i) {
    case 0:
    if (0 == settime) {
      if(counting){
        counting = 0;
      }
      else{
        counting = 1;
        lastminute = minute;
        lastth = th;
      }
    }
    else {
    }
    break;
    case 1:
    if (0 == settime && counting == 0) {
      minute++;
      second = 0;
      //Serial.println(minute);
    }
    else  if (1 == settime) {
      th++;
      //Serial.println(th);
    }

    break;
    case 2:
    if (0 == settime && counting == 0) {
      minute--;
      if (minute < 0) {
        minute = 0;
      }
      second = 0;
      //Serial.println(minute);
    }
    else if (1 == settime) {
      th--;
      if (th < 0) {
        th = 0;
      }

      //Serial.println(th);
    }
    break;
  }


}
void scan() {
  uint32_t start = 0;
  int flag = 0;
  for (int i = 0; i <= 2; i++) {

    if (0 == digitalRead(button[i])) {


      if (millis() - lastbutton > 150) {
        start = millis();
        while (0 == digitalRead(button[i])) {
          if (settime) {
            disp(th / 10, th % 10, 0, 0);
          }
          else {
            disp(minute / 10, minute % 10, second / 10, second % 10);
          }
          if (i == 0 && millis() - start  >= 500 && flag==0) {
            settime = !settime;
            //Serial.print("SET TIME:");
            //Serial.println(settime);
            flag = 1;
            lastbutton = millis();
         
          }
        }

        if(flag==0){
          change(i);
          lastbutton = millis();
        }
      }

      //Serial.println(millis() - start);
    }

  }

}
void disp(int a, int b, int c, int d) {
  int data[4] = {a, b, c, d};
  for (int dig = 0; dig <= 3; dig++) {

    for (byte seg = 0; seg < 7; ++seg) {
      setRegisterPin(digit[seg], !seven_seg_digits[data[dig]][seg]);
      // digitalWrite(digit[seg], !seven_seg_digits[data[dig]][seg]);
    }
    writeRegisters();
    digitalWrite(num[dig], HIGH);
    delayMicroseconds(100);
    digitalWrite(num[dig], LOW);
  }
}

//set all register pins to LOW
void clearRegisters() {
  for (int i = numOfRegisterPins - 1; i >=  0; i--) {
    registers[i] = HIGH;
  }
}


//Set and display registers
//Only call AFTER all values are set how you would like (slow otherwise)
void writeRegisters() {

  digitalWrite(RCLK_Pin, LOW);

  for (int i = numOfRegisterPins - 1; i >=  0; i--) {
    digitalWrite(SRCLK_Pin, LOW);

    int val = registers[i];

    digitalWrite(SER_Pin, val);
    digitalWrite(SRCLK_Pin, HIGH);

  }
  digitalWrite(RCLK_Pin, HIGH);

}

//set an individual pin HIGH or LOW
void setRegisterPin(int index, int value) {
  registers[index] = value;
}

void serialEvent(){
 
  minute = Serial.parseInt();
  second = Serial.parseInt();
  th = Serial.parseInt();
  counting = Serial.parseInt();
  settime = 0;
  while(Serial.available()){
      int dummy = Serial.read();// statement
  }


}

====Update:2016/08/28====
Video:

AFE4400 breakout ver3.0


 總之就是把東西整理好一點,加入了ADXL345,打算用加速度計把移動造成的干擾削掉...
然後Sensor改用DCM03,整合好了PN與雙波段的LED