2015年7月29日 星期三

好書 : Arduino 自作專案大百科

今天在明儀看到 Cavedu 翻譯自 "Arduino Projects Handbook" 的新書 "Arduino自作專案大百科", 用塑膠紙封起來, 無法翻閱內容, 所以當下沒買, 回來查網路看看圖書館有沒有, 唉, 新書怎會有呢?

# [新翻譯書準備出版] Arduino 自作專案大百科

原文版網站 :

# https://arduinohandbook.wordpress.com/


書中用到的函式庫可由下列 url 下載 :

# https://arduinohandbook.wordpress.com/libraries-2/

下載 45 個專案的範例程式可從網頁上方的 Projects1-15, Projects 16-30, ... 等下載.

或者到碁峰網站有 ZIP 檔 :

http://books.gotop.com.tw/download/ACH017800

這本書第 36 章介紹 NOKIA 5110 液晶顯示器的用法, 不使用函式庫, 所以較能深入了解其操作方法.


2016-10-21 補充 :

今天在母校高應大圖書館借到這本書了, 啃食中 ...






★ ESP8266 WiFi 模組 AT command 測試

這是我今年四月以 $180 向露天賣家 XLAN 買的超小型 WiFi 模組 (現已降價為 $145), 採用上海樂鑫科技的 ESP8266 晶片, 板子型式是 ESP-01, 這是 Arduino 最經濟的 WiFi 方案, 因為目前買一塊內建 WiFi 的 Arduino Yun 至少都要 2200 元以上. 此款板子有拉出 ESP8260 的兩個 GPIO 埠, 對於只需要兩個輸出入埠以內的應用而言, 可以改燒錄 NodeMCU 韌體, 直接將 ESP-01 卡當作 MCU+WiFi 用, 採用 Lua 作為程式語言, 在簡單應用可取代 Arduino.

關於 ESP8266 與 NodeMCU 簡介參考 :

# ESP8266 WiFi 模組
# NodeMCU 物聯網開發平台
# 5美元的WiFi微控器ESP8266已可與Arduino相容

ESP8266 晶片實作 LWIP 的精簡型 TCP/IP 協定堆疊, 成本低效能高, 具有極佳競爭力. 如果是採用 TI 的 CC3000 構建的 WiFi 模組, 大約要 700 元以上 (CC3000 晶片就要 500 元左右) :

# 露天 : CC3000 WiFi IC 晶片 W10 $540
# 露天 : CC3000 Wifi Module for arduino (BB-CC3K) $695
# CC3000 WiFi Shield for Arduino R3 帶SD卡座 支持 MEGA2560 $950

而採用 W5100 的 WiFi 模組則比 CC3000 便宜些 :

# <微控科技> W5100 WIZnet 網路晶片 Arduino 8051 AVR ARM PIC 均可用 $185
# 2013最新版 Arduino Ethernet W5100 網路擴展板 板載mini SD 支持Mega328 $225
# 【方塊奇品】新款Arduino Ethernet Shield W5100 R3 附參考資料 網路擴展板 板載TF  $380
# W5100乙太網模塊 網絡模塊紅板 W5100乙太網模塊 電子積木 網絡 W42 (小板) $400

但是論價格, 論體積, CC3000 與 W5100 兩個都不是 ESP8266 的對手, 目前較便宜的 ESP-01 板子如下 :

# esp8266 esp-01 (含稅) $90
ESP8266 ESP-01 串口 WIFI 無線模組 WIFI $145
# blkbox.me嚴選 ESP8266 大陸製ESP-01 Wifi 無線模組 arduino可用 $150
#《iCshop2》ESP8266 ESP-01 串口WIFI 無線模組 (陶瓷天線) $165
# blkbox.me原裝㊣品 虎紋風格 ESP8266 Wifi模組 板載8Mb FLASH (BB-E01) $185

ESP8266 可規劃作為 AP, STA, 或者是 AP+STA 雙模.

AP 模式 : Access Point 模式, 即無線基地台模式, 接受其他 WiFi 終端連入
STA 模式 : Station 模式, 即無線網卡模式, 可連接到 AP, 不接受連入
SSID : Service Set IDentifier, 無線區域網路的名稱, 可由 AP 廣播出來
LWIP 協定 : 精簡化後的 TCP/IP 協定堆疊, 適用於嵌入式系統

# ESP8266 晶片的規格書 (中文)
# ESP8266 晶片的規格書 (英文)

以下我參考克里斯與 Proteus 的文章, 利用 PL2303HX 下載線連接電腦的 USB 與 ESP8266 板, 使用 RealTerm 軟體以 AT 指令與 ESP8266 通訊 :

【技術教學】打造Wifi遙控車(之一):使用 ESP8266進行 Wifi無線通訊
【技術教學】打造Wifi遙控車(之二):整合 ESP8266 與 Arduino
# 如何燒錄 ESP8266 無線模組的韌體
# ESP8266 control from a PC via USB-serial

克里斯使用 CP2102 USB-UART(TTL) 轉換板來將電腦的 USB 訊號轉成 ESP8206 的 UART 串列訊號, 而我用的是 PL2303HX 下載線, 參考前作 :

安裝 PL2303HX USB 轉 TTL 驅動程式
關於 PL2303HX 在 win8 無法驅動的問題

此 PL2303HX 下載線電路板被包覆在 USB 塑膠殼內, 拆開來可看到裡面有 3.3V 電源接線孔, 若需要輸出 3.3V 電源需自行焊線拉出去, 但根據克里斯經驗, 因為 EXP8266 會消耗 200~300mA 左右的電流, 而一般下載線即使有 3.3V 電源輸出, 但無法輸出這麼多電流, 所以無法推動 ESP8266.

我查了 PL2303HX 規格, 在 9.2.1 節提到其最大操作電流是 25mA, 也是不夠的, 所以其 3.3V 輸出不能用 (故不須接出來了), 必須使用麵包板電源模組的 3.3V 電源, 如下圖右上角處, 把跳線帽移到 3.3V 處, 旁邊的接點就是輸出 3.3V 了 :


注意, 雖然 PL2303HX 吃電腦 USB 的 5V 電源, 其信號輸出卻是 3.3V 準位 (實際測量是 3.8V), 所以其 TX/RX 可以直接與 ESP8266 的 UXRD/UXTD 相接.




PL2303HX 有四條線, 其中紅色的 +5V 不能用 (因 ESP8266 工作電壓 1.7~3.6V) :

PL2303HX       
+5V(紅線)  - 不可接 (會讓 ESP8266 燒毀)
GND(黑線)-  接 ESP8266 與 3.3V 電源板的 GND (三個 GND 共接)
TXD(綠線) -  接 ESP8266 的 URXD
RXD(白線)-  接 ESP8266 的 UXTD

ESP8266 的接腳圖如下所示, 針腳位於背面, 接線時比較有用 :

正面

背面

連線圖如下, 可見 PL2303HX 與 ESP8266 的 GND 都接到電源模組的 GND (都是黑線), ESP8266 的 CH_PD (黃線) 與 VCC (紅線) 都接到電源模組的 3.3V, 然後 PL2303HX 的 RX (白線) 接 EXP8266 的 UXTD, TX(綠線) 接 ESP8266 的 URXD.


接好後把 PL2303HX 插入電腦 USB 槽, 按下電源模組按鈕送電, 這時 ESP8266 板子晶振旁的藍色 LED 會閃一下 (有資料傳送時藍燈閃, 參考 ESP8266), 邊邊的紅色 LED 也會亮起來 (表示有電源) :


 

打開控制台/裝置管理員/連接埠, 可看到 Prolific USB-to-Serial Comm Port (COM4) 已正常被驅動, 如果出現黃色驚嘆號的三角形, 表示驅動程式有問題, 請參考下文先安裝 : 



連接埠沒問題的話, 啟動 Realterm 通訊軟體, 免安裝版可由此下載 :

# https://dl.dropboxusercontent.com/u/68794214/Realterm.zip
 
打開 port 頁籤, 設定鮑率 Baud 為 9600, 指定埠號 port 為 4 (因 PL2303HX 為 COM4), 資料格式為 Parity=None, Data Bits 為 8, Stop Bits 為 1 Bit, 這樣應該就可以跟 0.9.2 版韌體順利連線了, 這時上面會出現 ready :


如果是較舊的韌體, 可能預設 Baud rate 不是 9600, 而是115200 或 57600, 要試一下才行. 注意, 每次修改後必須按 "Change" 才會生效, 如果出現 ready 了, 但伴隨有亂碼, 請切到 Display 頁籤, 勾選  Display As 與 ANSI, 這樣以後下 AT 命令就不會有亂碼了 :


接下來就可以切到 Send 頁籤向 ESP8266 傳送 AT 指令了, 首先須在 EOL 框中勾選 LF 與 CR, 因 Windows 系統以 LFCR 當作跳行符號, 然後就可以輸入 AT, 按 Send ASCII 鈕, 連線順利的話 ESP8266 就會回傳 OK : 


各種 AT 指令參考 :

# ESP8266 AT Command Set (PDF)
# ESP8266 Reference (PDF)
espressif/esp8266_at
atproto/commands.md

例如 :
  1. AT+GMR : 取得韌體版本 :
    AT+GMR                                                                         
    0018000902-AI03                                                               
                                                                                   
    OK 
    可見目前版本是 0902.
  2. AT+RST : 重新起始 ESP8266
    AT+RST                                                                         
                                                                                   
    OK                                                                             
    7!aS?'??!G?R??                                                           
    [Vendor:www.ai-thinker.com Version:0.9.2.4]                                    
                                                                                   
    ready  
  3. AT+CIOBAUD?  : 查詢鮑率 (位元速率)
    +CIOBAUD:9600

    OK
  4. AT+CIFSR : 查詢 IP 位址

    AT+CIFSR                                                                       
    192.168.4.1                                                                    
                                                                                   
    OK

    注意, 作為 STA 時,  若尚未用 CWJAP 連線基地台, 則預設 IP 為 0.0.0.0, 連線後才會被指派一個 192.168.X.X 的 STA 區域 IP. 如果 ESP8266 是在 AP/BOTH 模式, 則下 CIFSR 會看到兩個 IP, 一個是 STA IP, 另為一個是基地台 SoftAP IP. 
  5. AT+CWMODE? : 查詢目前工作模式
    AT+CWMODE?                                                                     
    +CWMODE:2                                                                      
                                                                                   
    OK     
    可見目前是模式 2 (AP 基地台模式), 1=STA 網卡模式, 3=BOTH (AP+STA).
    注意, 下完 CWMODE 最好再用 CWRST 重啟, 以確認設定有完成.  
  6. AT+CWMODE=1 : 修改工作模式為 1 (STA) 網卡模式
    AT+CWMODE=1                                                                    
                                                                                   
    OK                                                                             
    AT+CWMODE?                                                                     
    +CWMODE:1                                                                      
                                                                                   
    OK   
    要修改為雙重模式就在等號後面指定為 3 即可. 注意, STA 與 AP 模式有各自的 IP, 在 STA 模式下未連線前 IP 為預設之 0.0.0.0, 連線後基地台會配發一個 192.168.X.X 的 IP; 改為 AP 或 BOTH 模式後, ESP8266 會自行配發 192.168.4.1 的 AP IP, 故 BOTH 模式下會有兩個 IP.

    AT+CWMODE=3

    OK
    AT+CIFSR
    192.168.4.1     (這是 ESP8266 當 AP 的 IP)
    192.168.2.105 (這是 ESP8266 當 STA 的 IP)
  7. AT+CWLAP : 列出附近偵測得到的基地台
    注意, 此指令只能在 STA (=1) 與 BOTH (=3) 模式下才會回應, 在 AP 模式下會出現 ERROR.
    AT+CWLAP                                                                       
    +CWLAP:(2,"edimax.setup",-71,"74:da:38:15:16:00",1)                            
    +CWLAP:(3,"bryan",-90,"78:54:2e:26:66:28",1)                                   
    +CWLAP:(3,"TP-LINK_33C1",-86,"c4:e9:84:66:33:c1",4)                            
    +CWLAP:(4,"ching",-84,"54:b8:0a:84:f4:70",5)                                   
    +CWLAP:(4,"HOME",-70,"04:8d:38:52:ea:f7",6)                                    
    +CWLAP:(4,"alex",-85,"fc:75:16:01:26:0c",6)                                    
    +CWLAP:(4,"andy",-85,"fc:75:16:02:61:60",6)                                    
    +CWLAP:(1,"JANE-WIRELESS",-94,"00:24:01:ad:a0:65",6)                           
    +CWLAP:(4,"RFTQAD",-93,"c8:d3:a3:5f:d8:fd",9)                                  
    +CWLAP:(3,"TP-LINK_601A04",-73,"e8:de:27:60:1a:04",10)                         
    +CWLAP:(4,"EDIMAX-tony",-44,"90:1f:02:2d:5a:9f",11)  我的基地台                    
    +CWLAP:(3,"CHT5668",-89,"d8:fe:e3:5c:c0:fb",11)                                
    +CWLAP:(3,"MOTOROLA-5N6F",-89,"f8:35:dd:74:d2:b6",11)                          
    +CWLAP:(3,"45-9",-91,"d8:fe:e3:e6:90:87",11)                                   
    +CWLAP:(3,"family",-89,"6c:19:8f:b7:9a:79",1)                                  
                                                                                   
    OK
    回應訊息的格式為 : +CWLAP:(ecn,ssid,rssi,mac,mode)
    第一個參數是加密方式 ecn :
    0 OPEN (不加密)
    1 WEP
    2 WPA_PSK
    3 WPA2_PSK
    4 WPA_WPA2_PSK
    第二個參數是服務設定識別碼 SSID (即基地台代號), 第三個是接收的射頻信號強度 (dBm), 均為負值, 越負信號越弱, 最大值是 0. 第四參數是實體位址 MAC, 第五參數據 "More AT Command Information Found" 說是連接模式, 0 為手動 (manual), 1 為自動 (auto). 但上面測試卻有 0, 1 以外的值. 據 "ESP8266 WiFi module" 這篇則說是 channel, 似乎較合理, 因為 CWJAP 指令也無法設定手動或自動啊!
  8. AT+CWJAP="SSID","PWD" : 連線指定之基地台 (Join AP)
    AT+CWJAP="EDIMAX-tony","123456789111"                                         
                                                                                   
    OK 
    連線成功後再下 AT+CIFSR 查詢新指派的 IP, 還沒下 CWJAP 連線前為 0.0.0.0  :                                                                           
    AT+CIFSR                                                                       
    192.168.2.105  
    這時可在相同網域的電腦 ping 此 IP, 檢查連線是否可傳送資料 :

    C:\Users\petertw89>ping 192.168.2.105
    Ping 192.168.2.105 (使用 32 位元組的資料):
    回覆自 192.168.2.105: 位元組=32 時間=110ms TTL=255
    回覆自 192.168.2.105: 位元組=32 時間=18ms TTL=255
    回覆自 192.168.2.105: 位元組=32 時間=35ms TTL=255
    回覆自 192.168.2.105: 位元組=32 時間=55ms TTL=255

    192.168.2.105 的 Ping 統計資料:
        封包: 已傳送 = 4,已收到 = 4, 已遺失 = 0 (0% 遺失),
    大約的來回時間 (毫秒):
        最小值 = 18ms,最大值 = 110ms,平均 = 54ms   
  9. AT+CWJAP? : 查詢目前連線到哪一個基地台
    AT+CWJAP?
    +CWJAP:"EDIMAX-tony"

    OK
  10. AT+CWQAP : 離開目前連線的基地台
    AT+CWQAP

    OK
    這時再下 AT+CWJAP? 查詢連線之基地台時就會回應 ERROR :
    AT+CWJAP?

    ERROR
    這時下 CWFSR 原來指配的 IP 192.168.2.105 會消失, 回到預設 0.0.0.0
    AT+CIFSR
    0.0.0.0

    OK
  11. AT+CIPSTART : 建立 TCP/UDP 連線
    AT+CIPSTART="TCP","www.google.com",80

    OK
    Linked
    這樣就與遠端主機建立 TCP 連線了.
    AT+CIPSTART="UDP","192.43.244.18",123

    OK
    這樣就與遠端主機建立 UDP 連線了.
  12. AT+CIPSTATUS : 查詢目前 IP 連線狀態
    AT+CIPSTATUS
    STATUS:3
    +CIPSTATUS:0,"TCP","74.125.203.101",80,0

    OK

    回應訊息格式 : +CIPSTATUS:id,type,addr,port,tetype
    id 為連線通道編號, 最後面的 tetype 為 ESP8266 角色, 0 為 client, 1 為 server.
    表示目前與 IP 74.125.203.101 的 80 port 已建立了 TCP 連線 (2 表示已取得 IP 尚未連線, 3 表示 Connected, 4 表示 disconnected). 回應中的 0 為 id. 
  13. AT+CIPCLOSE : 關閉 IP 連線
    AT+CIPCLOSE

    OK
    Unlink
  14. AT+CWSAP? : 查詢 SoftAP 的設定
    此指令只有當 ESP8266 工作於 AP/BOTH 模式時才有用, 在 STA 模式下此指令會得到 ERROR 回應.

    AT+CWMODE=3   先改為 BOTH 模式

    OK
    AT+CWSAP?
    AT+CWSAP:"ESP_9CBD07","",6,0    預設 ssid, pwd, ch, ecn

    OK

    回應顯示預設未設密碼, 最後一個參數為加密方式, 預設 0=未加密, 見 CWLAP 指令. 而 ssid 是 ESP8266 作為 AP 的網路識別, 後面是其 MAC 號碼. ecn 是加密方式.
  15. AT+CWSAP="ssid","pwd",ch,ecn : 更改 AP 的設定 (只在 AP/BOTH 模式有效)

    AT+CWSAP="MYESP","1234567890",6,4

    OK
  16. AT+CWLIF : 查詢有哪些 Client 連線至此 AP (只在 AP/BOTH 模式有效)
    AT+CWLIF
    192.168.4.100,74:e1:b6:0e:f5:67

    OK
  17. AT+CIPMUX? : 詢問目前 TCP/UDP 連線模式
    這是設定 ESP8266 與同一 WiFi 網路中其他裝置的連線模式, 預設為單一連線, 如果要讓 ESP8266 當伺服器用, 必須設為 1=多重連線.

    AT+CIPMUX?
    +CIPMUX:0       (多重連線關閉, 即單一連線模式)

    OK
  18. AT+CIPMUX=1 : 設定 TCP/UDP 連線模式為多重連線
    如果要讓 ESP8266 當伺服器, 讓網域中的客戶端進行 TCP/UDP 連線, 必須開啟多重連線.

    AT+CIPMUX=1

    OK
    如果要取消 ESP8266 的伺服功能, 恢復單一連線功能, 須將 CIPMUX 設為 0 :
    AT+CIPMUX=1

    OK
  19. AT+CIPSERVER=mode[,port] : 設定是否開啟 ESP8266 為伺服器
    用 CIPMUX=1 開啟多重連線後, 就可以用 CIPSERVER 設定 ESP8266 的伺服器功能. mode=1 為開啟伺服器, 必須指定 port; mode=0 為關閉伺服器, 不須指定 port. 在單一連線下開啟伺服器, 會得到 ERROR 回應.

    AT+CIPSERVER=1,8087

    OK

    這樣 ESP8266 伺服器就會傾聽 8087 埠, 這時就可在同網域的電腦連線 ESP8266 伺服器了. 我下載克里斯寫的 Connector-Test.air 安裝後選擇當 Client, 連線 ESP8266 的 STA IP, 連線成功且能雙向傳遞訊息. 用書上的 Java Client 網路程式來測試也 OK.

    重複開啟伺服器會回應 no change :

    AT+CIPSERVER=1,8081
    no change

    關閉伺服器後必須重啟 ESP8266 (AT+RST), 其回應為 :

    AT+CIPSERVER=0
    we must restart
  20. AT+CIPSTO? : 查詢伺服器逾時計時器設定值 (秒)

    AT+CIPSTO?
    +CIPSTO:180

    OK

    預設是 180 秒
  21. AT+CIPSTO=timeout : 設定伺服器逾時計時器 (0~7200 秒)

    AT+CIPSTO=200

    OK

    其實不管設定為多少秒, 它都回應 OK, 但實際最多只能計時到 7200 秒.
設定用的 AT 指令 (例如改變工作模式或連線某個 AP) 完成後會寫入 Flash 記憶體, 即使關機也不會消失, 重開機就會回魂了. 所以設定連線哪個 AP 就會一直鎖定該 AP, 無法像筆電那樣會記錄曾經連線過的 AP 資料, 自動找信好強的連線.

ESP8266 的板子工作時摸起來溫溫的, 我拿了體溫計放在板子上測量約 39 度. 另外也接了電壓電流表測量總耗電量, 顯示 0.02A (20mA) 左右 :


以上就是今晚的測試, 終於搞定了!

2015-07-29 補充 :

賣家 blackboxstudio 表示中國製 ESP-01 板不支援 GSLP 休眠指令, 試過 AT+GSLP=10000 (休眠 10 秒) 果真無法執行. 根據 "Low Power ESP8266 – Sleeping at 78 micro Amps" 這篇得知是因為 ESP-01 板的 XPD_DCDC (8) 腳沒有接到 reset 之故.

2015-11-16 補充 :

今天找到這個網頁, 介紹 AT 指令蠻詳細的, 特別是把 ESP8266 作為伺服器的部分 :

# WiFi Module ESP8266 – 2. TCP CLIENT /Server mode

2016-05-19 補充 :

注意唷! 上面這些 AT 指令必須恰恰好, 亦即, 不可以在後面傳送多餘空格, 例如 AT+CIPSTO? 總共 10 個字元, 如果在 ? 後面多按了一個空格字元就會發生錯誤.

其他參考資料 :

# 无线网卡AP模式和station模式 
# SSID, BSSID, ESSID 
# lwIP――TCP/IP協議棧的一種實現(1)
# lwIP――TCP/IP協議棧的一種實現(2)
# lwIP――TCP/IP協議棧的一種實現(3)
# New! Arduino Pro Mini 相容 16MHz 8MHz 任選 (BB-NPMx) $145
# 小型抽水機 水泵 抽水馬達 USB arduino 可用 水冷 水循環 過濾 $145
# 超大FLASH 4M的容量 ESP8266 UART WIFI 模組 ESP-12 $180
# IOT ESP8266 串口WIFI模塊 ESP-12 (附送底板+開發資料+諮詢) $180
# ESP8266 ESP-12 ESP-07 最小系統 最小測試版 5V直用 $200
# SP-12 ESP8266串口WIFI 工業級 穩定版 測試板全套 !全IO引出
App HTML5 開發板 WF8266R ESP8266 物聯網 IoT 智慧家電 WIFI Arduino $250
# Arduino教學-使用ESP8266 wifi模組+DHT 溫溼度感測器上傳thingspeak
如何用arduino来测试ESP8266 WIFI模块(wifi普及预热中)
# A Simple IoT Project with the ESP8266 WiFi module
# 5$ Arduino WiFi Module!? ESP8266 mini Tutorial/Review
# Cheap and Easy WiFi (IoT) Tutorial Part 1 - ESP8266 Setup/Intro
ESP8266 的「IoT 創意致富」課程規劃
# NodeMCU 物聯網開發平台
BitBastelei #132 - WLAN-Thermometer mit ESP8266 & DHT22
# ESP8266: testing deep sleep & interrupts !?
# Low Power ESP8266 – Sleeping at 78 micro Amps
# 無線基地台 SSID 中文化的設定方法
# Esp8266 firmware update

2015年7月28日 星期二

到訪人數 287287

早上準備完姊姊的早餐, 寫一下部落格, 突然發現到訪人數 287287, 又觸動了我的數字怪癖, 紀錄如下 :


其實我會認真寫部落格, 主要的原因是要利用 Google 強大的搜尋引擎幫我瞬間找到自己以前寫的筆記, 其次才是分享心得的 "大愛". 當我找不到自己以前研究過的心得筆記時, 就會有 "秘笈遺失恐慌症", 到處翻箱倒櫃暴力搜尋. 有了 Google 真方便.

Arduino 用的小機箱

最近在露天看到一個塑膠製的機殼 :

# 小機殼..機箱..塑膠機殼..70*90*28 $32

經繪製大略尺寸研判可以作為 Arduino 實驗電路板的機箱之用, 就買下僅剩的五個 (有要求賣家繼續進貨啦). 買回來之後發現剛好可以擺進一個 5cm*7cm 的洞洞板, 實在太速配了, 難道製造廠家就是為了能放進這尺寸的洞洞板而開模的嗎?


我是想將 PIR 紅外線人體移動偵測器 + ESP8266 WiFi 模組 + 鹼性電池放到此小機箱內, 這樣只要一有人經過就會記錄在網路伺服器上或透過代理 API傳送簡訊.

參考 :

# 電子儀器塑膠盒 儀器盒 工具盒 小接線盒 接受客製 arduino 可用 $88


2015年7月27日 星期一

第 31 周記事 : 風力發電機安裝 part 5

周六 7/25 菁菁跟阿姨她們一家去台東玩, 所以本周只有我與姐姐回鄉下. 週日下午小舅全家來採龍眼, 舅媽拿了梯子上樹, 把門前那棵龍眼樹幾乎摘個精光 (她說好多年沒爬樹了). 龍眼到這周最甜, 本周不採的話, 下周可能退甘. 下周換採路邊的那棵龍眼樹.

斷斷續續弄了好一陣子的風力發電機實驗, 本周終於完成安裝了. 周日早上起來後把風機拿到頂樓安裝, 本來姊姊要幫我的, 但她還在歐歐睏, 所以只好自己來, 只是鎖螺絲稍微吃力而已. 才日正當中就吹起西南風了, 一裝上去風機就狂轉, 基本上如以前所觀察到的, 以西南到西北兩個方向的風為主流, 大雨前的狂風才會東西南北都有.


滾珠軸承的腳架剛好鎖進兩支角鐵組成的ㄇ字型結構內 :


用小北買的花線 ($179) 把電接到鐵皮屋內, 連接直流電壓表, 空載時電壓測得 50V~70V :


接上 3W LED 聚光燈負載后, 降到 10V, 不知是否燈具內有穩壓二極體保護?


整個下午都呼呼地轉, 一直到晚上才停.


如果每天下午都這樣吹, 不知能在傍晚前充飽電瓶否? 下周買好電瓶再來試驗. 小舅說的沒錯, 現在都是屬於玩而已, 經濟效益是零. 但是每次腦海中浮現新點子時, 心裡就感到無比興奮, 希望趕快實作出來.

能玩自己想玩的, 就是最大的快樂.

2016-06-24 補充 :

# 0921315178 DIY簡易風力發電機製作 Wind-driven generator
# 0921315178 DIY迷你型風力發電機
# 0921315178風扇葉片 發電機測試 簡易的風力發電 diy
# 三相交流發電機 馬達 減速 電機 風力水力 $300
# 集電環 DIY 發電機 改造 馬達 實習 減速 電機 風力發電機 $200


2015年7月25日 星期六

關於 Arduino pro mini 的電源電壓問題

最近買了一批 12V 23A 鹼性電池, 就是用在車庫鐵捲門遙控器或汽車遙控器那種短小的乾電池, 因為體積小, 適合用在 Arduino pro mini 為主控器的人體移動偵測器上, 我想鹼性電池應該可以撐很久, 但是 pro mini 能用 12V 嗎?

可以的, 因為 pro mini 電源規格是 5v~12v, 一般是 5V, 有些板可跑 3.3V, 但大於 5V 的電源必須從 RAW 腳灌進去, 不能從 VCC 腳, 否則有燒毀之虞 :


參考下列文章 :

# How to power Arduino Pro Mini via VCC pin (12v input)

2015年7月24日 星期五

太陽能板市調

南部的夏天總是艷陽高照, 早上七點的太陽就開始讓人覺得灼熱, 一直到下午五點下班時, 騎車穿短袖還有被灼傷的感覺. 這樣一整天超過 10 個小時的陽光不拿來發電實在很可惜. 只要沒下雨, 它就是很穩定的每天十小時可發電, 反觀風力常常青黃不接有一頓沒一頓的, 太陽能要好多了.

這幾天對目前網路上的太陽能發電產品的價格與規格做了一番調查, 主要包括太陽能板,  充電控制器, 蓄電池, 以及高功率可能會用到的逆變器. 目前只是實驗階段, 所以想找低功率產品來 DIY 安裝看看, 主要目的是用來夜間點亮水圳邊洗衣服的地方, 以及推動小水泵將河水抽到菜園去澆水.

調查研究後, 決定用 10W 太陽能板搭配 7.2AH 的電瓶來進行初體驗. 因為以 7.2AH 蓄電池來說, 正常充電電流為容量的 1/10, 即 0.72A 左右, 而 10W 多晶矽最大輸出電流為 0.556A 還可以, 20W 能板峰值電流 1.16A 就太大一點, 雖然那是日正當中才可能達到, 但為了保護電池, 還是保守一點好, 所以先用 10W 能板實驗看看, 比價後選購下列廠家之產品 :

10W 12V 單晶 多晶 高品質太陽能板 可搭配 10A 12V 控制器 $429
太陽能板 充電 控制器 12V 10A 太陽能控制 顯示電池電量 省電節能 $259

運費 60 合計是 748 元, 若多買一個控制器給風機用, 合計 1007 元. 而蓄電池就近有三多與全電行 (長明街大林附近) 兩家可取貨 :

# 三多電池"附發票"LONG廣隆電池WP7.2-12=NP7-12規格 12V,7.2AH UPS不斷電系統蓄電池 (28W) $336
# ☆全電行電池快遞☆LONG WP 1.2-12 12V 1.2A $260

本來想買 1.2AH 的小電池的, 但看了 "太陽能應用的模組化電池系統" 這篇文章後, 覺得小電池可能半天就充飽了, 可能無法達到文中提到能板與蓄電池的匹配 :

"是太陽能電池的最佳負載取決於它所接收的日光量。只是簡單地固定在充電電池上並不能保證太陽能電池的負載最佳。實際上,電池兩端的電壓在電池充電時會不斷變化,所以在完全光照條件下,可能會有一些能量未傳輸到電池中。並且,未用於電池充電的能量會以熱的形式保留在太陽能電池中,使太陽能電池提早老化。"

所以, 還是選 7.2AH 的好了.

另外在 mobile01 我看到有人描述其家用太陽能的配置, 高達 4.6KW 的發電量, 與市電並聯後每月電費帳單只剩 200 元不到, 令人羨慕啊. 但粗估其成本光是太陽能板就要 80000~160000 左右, 如果每個月省 2000 元電費, 要 80 個月 (約 7 年) 才能回本, 總之太陽能要推廣, 作為主角的太陽電池必須降價一半才有誘因 :

"我家使用了230w的太陽能板20片, 每一片是24V的,所以我用串聯2片成48V, 後在用併聯每一個48V的, 用MPPT 80A控制器2台, 來充20顆的100AH深循環電池, 在使用12V轉110V正旋波轉變器3000W,來給家電使用, 全部的太陽能板用矽利康黏於屋頂的瓦片上, 大太陽一天進電1200-1400A, 我家的所有用電都靠它. 外面裝置4.6kwp要差不多50至60萬. 如果自己裝應該只有一半價格自家用的剛好,沒想要賣電, 兩個月電費不到200元, 看到電費帳單是很爽的."

據估計, 1KW 太陽能發電設備成本約 88000 元, 參考  :

http://www.greenhomelife.com.tw/solar/ 

以下是市調紀錄 :

太陽能板 :

# 10W 12V 單晶 多晶 高品質太陽能板 可搭配 10A 12V 控制器 $429
# 高品質英利電池片20W 太陽能電池板 $680
#【綠市集】20W18V多晶太陽能電池板 太陽能板 組件太陽能發電板D02 $690
#【光力能】20w太陽能電池板多晶太陽能板 12V太陽能發電板光伏系統發電板 $750
#【有陽光有能量】20w 多晶 太陽能板 $780
# 20W多晶太陽能板 800元 (免運費) $800
#【綠市集】20W多晶太陽能板 $900
# ~能量工坊~邊露營邊充電20W12V單晶太陽能大特價 $1100 
# 【綠市集】太陽能全新A類50瓦多晶太陽能電池板 $1690
單晶太陽能板100W 1片 只要3000元
日本原裝.夏普SHARP180W單晶太陽能板(單片4000元)一次購2片台北以南免運費

控制器 :

# 12V 3A 太陽能控制器 太陽能路燈控制器 太陽能戶用系統控制器 $230
#【有陽光有能量】太陽能控制器 12V3A 俱光控、可定時 $240
# 太陽能板 充電 控制器 12V 10A 太陽能控制 顯示電池電量 省電節能 太陽能 風力發電 可用 $259 淘寶 淘寶 同款
#【有陽光有能量】太陽能控制器 12v/24v 通用 10A 具光控與時控功能 $340
# 太陽能電池板 太陽能板 用12V 24V10A控制器太陽能路燈發電系統通用版 $340
# ☼陽光屋☼太陽能【151-3】太陽能控制器 10A 12V/24V 帶5V輸出USB接口 $350
#【綠市集】太陽能控制器 10A/12V/24V通用 自動識別 太陽能路燈控制器A0151 $350
# 【有陽光有能量】 太陽能控制器 12v/24v 10A (雙USB輸出 5V1A / 2A充電)$440
# 12V 24V 自動識別 10A 太陽能路燈控制器多時段半功率IP68 $482
#【綠市集】太陽能控制器 10A 12V/24V 帶5V雙輸出USB接口LCD液晶頻可調A0151-4 $490
#【綠市集】太陽能控制器 10A 48V 帶5V雙輸出USB接口LCD液晶頻可調A0151-4 $680

逆變器 :

# 12V轉110V 500W 變電器 逆變器 變壓器 汽機車電源轉換器 太陽能 風力 $700
# 高品質 藍科 300W 車載 逆變器 汽車電源轉換器 12V轉110V 充電器 100%足功率 帶USB 5V輸出 $720
# A044 正品SUVPR 黃金台DY-8103 200W 汽車電源12V轉110V 車載逆變器 $899
# 300W~6000W 純正弦波 逆變器 太陽能 露營車 電源轉換 $1680 (600w $3450)
# 300W 純正弦波 市電併聯器 DC 14– 28V/AC 110V for 12v 太陽能板系統 $2499
# 太陽能板專用 ~300W市電併網機~市電併聯機 12V系統 10.8~28DC轉110AC $2660
# 新博源 太陽能板 市電併聯轉換器~最新款市電併聯機600WP12~28DC 24~45DC轉110AC $3700
# 太陽能板市電併網機銷售專家! 600W24~45VDC轉110AC 太陽能板&電瓶判別 $3700
# 1500w 正旋波電源轉換器DC 12V TO AC 110V, 台商大陸廠生產, 外銷美國機種 $5999

套裝組合產品 :

#【有陽光有能量】10W 多晶太陽能板 太陽能充電組 $920
# 組合包12V太陽能板+12V充電控制器+12V 紅外線感應開關+12V 螺旋燈泡+12V 圓形燈座 $997
# 20W 多晶太陽能板發電 獨立型發電套裝組 含運只要1290元
#【有陽光有能量】20W 太陽能發電 獨立型發電套裝組 太陽能充電 $1300
# 50W多晶太陽能板(購2片送充電控制器10A) $3200
# 綠能節電入門組合.多晶太陽能板50W+市電併網機只要3999元
# 太陽能板100W發電~獨立系統~免用台電套裝組 4800元露營車 行動攤販 $4800
# 200W(100w*2片)多晶太陽能板+600W市電併聯轉換器 28-52V TO 110V $9000
# 台廠多晶170W太陽能板(單片3300元) 並網套裝組合只要9800元含運喔
# 太陽能板發電 可抵銷冷氣用電. 降低用電度. 屏東標準安裝 $40000

並聯防逆流二極體 FR207 : 

# 《icshopping_com》FR207 2A/1000V (5pcs)【3680107000379】快速回復二極體 $11
#  快速回復二極體 FR207 壹包10pcs $20

固定片/角鐵/支架 : 

太陽能板固定用側邊夾具 有兩種 便宜賣 $35
鋁舉夾具專用"L PIN" 太陽能板固定用 $40
# 太陽能板固定片 Z形鋁角鐵 安裝架 支撐架(小 Z 1組4片) $150
太陽能板固定座 $150
# 太陽能板專用支架(4個/組) 附螺絲 螺絲帽 $175
# 太陽能板固定座 $180
太陽能板固定片 Z形鋁角鐵 安裝架 支撐架(大 Z 1組4片) $210
# ~能量工坊~L型不鏽鋼太陽能板固定座特價250元

其他 :

# 【有陽光有能量】太陽能噴泉 直流6V~24V 無刷水泵 直流水泵 JT680 $560
# DIY族最省錢. 3.5mm雙心電覽線~7米 太陽能板連結線 $350

以下是從賣家回答中記下的一些有用知識 (忘了記來源網址) :

"220W*6片 可日發 6 度電, 抵銷冷氣 7 小時用電, 買1000W~3000W最多, 尤其是買 2000W幾乎為主力)跟台灣百樂100AH深循環電池."

"深循環電池跟車用電瓶差在 鉛酸合金不同,深循環精密 壽命長可用 6年以上,汽車電瓶壽命不超過 3年,兩者價差 30~40%,深循環電池放電比更低,可放電的時間更多一點,深循環電池儲放溫度不可超過 48度,所以不適合放引擎室."

"如果電池因上述因素造成需要充電,有兩種充電狀況,一是電池電壓在11.5V以上,為標準過度放電,二是電池電壓在11.5V以下,為深度過度放電。"

"電池電壓在11.5V以上的電池,若是規格為45AH(46B/55B),充電電流為十分之一,約用4A電流充電,60AH(55D/75D)充電電流為6A以此類推,充電時間依電池放電狀況,約為2-6小時。若電池電壓在11.5V以下,充電時間拉長,可能需要更高的充電電流刺激。"

省錢大作戰! 前進美濃太陽能社區

20160928 補充 :

# 請問南部高雄地區家中有人有用太陽能發電的嗎?



2015年7月23日 星期四

路過榮總

今天下班後去仁武拿網購的零件, 回程經過榮總, 突然想起, 今天是 7 月 23 日啊!

2015年7月22日 星期三

關於電源穩壓 IC

在 Arduino 應用中, 不論是 MCU 或感測器, 都可能會用到限用 3.3V 或 5V 電源的組件, 例如我最愛用的 Arduino Pro Mini, 在 5V 或 3.3V 供電下都可以運作; 但 ESP8266 就只能在 3.3V 下運作; 而 PIR 紅外線移動感測器模組必須供電 5V, 其輸出信號則為 3.3V. 也就是說, 供電必須考慮可能得同時提供 5V 與 3.3V.

我在阿呆的部落格看到 "LM2576T-5穩壓電路一號" 介紹 LM2576 這顆穩壓 IC, 似乎不錯, 但查了規格書發現其輸出電流可達 3A, 不適合 MCU 與感測器使用, 較適合用在機器人或遙控車上 :

http://www.ti.com/lit/ds/symlink/lm2576.pdf

後來在葉難寫的 "Arduino 範例分析與實作設計" 一書的第 9-5 節, 看到 LD1117V33 這顆 5V 轉 3.3V 線性穩壓晶片, 輸出可達 800 mA, 足以推動大部分的 Arduino 應用. 而且穩壓電路超簡單, 只要在輸入端加個 10uF 的電解電容, 輸出端加個 0.1uF 的鉭質電容即可. 此與 AMS1117 是同樣功能的穩壓 IC, 只是廠家不同而已. 其輸入電壓最高 12V, 輸出 3.3V :

#  http://www.advanced-monolithic.com/pdf/ds1117.pdf
# LD1117AL33 LD1117A-L33 SOT223 降壓3.3V 穩壓 $3
# LD1117AL-3.3V SOT-223 (全新 1PCS/1包) 1117 3.3V 線性穩壓 電源IC $6
# 《iCshop3》LD1117V33 TO-220【線性穩壓,3.3V,Voltage Regulator】 $59

不過因為找不到 LD1117 輸出 5V 的晶片, 這樣要製作 5V 與 3.3V 雙電源時就比較麻煩, 因為如果由 12V 或 9V 鉛酸電池或鹼性電池供電, 勢必 5V 與 3.3V 都須同時供應. 我後來在之前購買的麵包板電源模組上發現它使用一顆 AMS1117 穩壓晶片 :

# 【方塊奇品】麵包板電源模組  $52
# AMS1117-3.3V 電源模組 降壓模組 $19
# KSM098 AMS1117 3.3V電源穩壓模組 $25 (buyic)
# KSM098 AMS1117 5V電源穩壓模組 $25 (buyic)

當然用模組是很方便, 但是麵包板專用那個價格太高, 體積也大; 降壓模組那個只有 3.3V, 5V 的還是得張羅, 所以還是自己找零件實做為宜. 查了一下 AMS1117 的規格, 發現跟 LD1117 一樣可輸出 800mA, 而且最重要的是 AMS1117 輸入耐壓 12V 以上, 所以不管是 9V 方形電池, 還是 12V 23A 的 L1208 鹼性電池, 或者 12V 鉛酸電池都可以作為其輸入來源. 在露天 3.3V 與 5V 這兩種晶片都很好找, 也很便宜, 才 5, 6 塊錢而已 :

AMS1117 3.3V SOT-223 ( 1pcs /1包) 三端線性穩壓 $5
AMS1117 5.0V SOT-223 $6
icshopping_com》AMS1117-5.0 SOT-223 $7
#《iCshop1》LM1117S-3.3 SOT-223 $7

所以打算以後就用 AMS1117 作為 Arduino 應用的雙電源供電主角, 我的構想是這樣 :


這樣只要兩個 AMS1117 晶片加上四顆電容, 焊在萬用板上就可以滿足雙電源的需求了.

AMS1117 規格書詳見 :

http://www.advanced-monolithic.com/pdf/ds1117.pdf

2015-07-25 補充 :

我在下列網站看到輸入側電容用 10uF, 輸出側電容用 22uF :

# http://www.go-gddq.com/html/s225/2015-02/290541p3.htm



2015-07-29 補充 :

我在 Proteus 的 "萬物皆聯網-ESP8266 IoT(Internet of Things)入門學習套件" 一文中, 看到麵包板電源模組的電路圖, 他是將 AMS1117 5V 輸出饋給 AMS1117 3.3V 當輸出, 我覺得這種接法是比較好的.

2015-08-14 補充 :
找到 LD1117 3.3V 與 5V 供應商 :

# (100個一標) LD1117AL33 LD1117A-L33 SOT223 降壓3.3V 穩壓 $200
# (100個一標) LD1117AL50 LD1117A-L50 SOT223 降壓5V 穩壓 $200
LD1117AL33 LD1117A-L33 SOT223 降壓3.3V 穩壓 $3
# LD1117AL50 LD1117A-L50 SOT223 降壓5V 穩壓 $3

2015-08-21 補充 :

今天在露天看到這個 24L01 無線模組專用的轉接板, 同樣使用 AMS1117 當 3.3V 電源供應晶片, 可做為製作 ESP8266 轉接板的參考, 不過這裡的 10 PIN 排母要改成 8 PIN, 因 ESP8266 只有八支腳, 同時要加入兩顆 2N7000 MOSFET 替 TX/RX 轉換準位 :

# 無線模塊轉接板 3.3V 配套24L01無線模塊使用 智能小車機器人必備 $65
# 無線模塊轉接板 配套本店無線模塊使用 智能小車 機器人【8針】 $69




採購鋰電池與零件一批

今天採購了兩批零件 : 一是向嘉義的露天賣家 tmwc7  (此賣家兼賣五穀) 採購電池相關零組件一批如下, 合計 352 元, 超商取貨 :

# LED電池盒 燈條電池盒 12V電池盒 23A電池盒 $5*6=30
# 12V 23A 防盜鎖音樂門鈴發射器 23A 12V 卷閘門無線遙控器L1028電池 $6*5=30
# 特價接線端子 電線連接器 接線器接頭排柱快速彈簧按壓式對接兩位CH-2(二個5元) $2.5*20=50
# 特價批發全新18650 印刷3200MAH充電鋰電池 強光手電筒最佳搭配充電池 (無帶保護板) $32*2=64
# 4.2雙頭焊片 接線片 冷壓端子 線耳3片(一元3片) $1*10=10
# 特價南孚環高萬用18650/14500/10440/16340/CR123A鋰電池智能充電器 $42*1=42
# 四號轉三號 電池轉接桶 4號轉3號轉換套筒 AAA轉AA轉換器 磨砂材料 $12*3=36
# 特價CR123A 3.7V 充電鋰電池16340 充電鋰電池 1800mah 標示 $30*1=30

二是向仁武大灣的 IC995 購買 AMS1117 與紅外線模組, 合計 102 元自取 :

# AMS1117 3.3V SOT-223 ( 1pcs /1包) 三端線性穩壓 $5
AMS1117 5.0V SOT-223 $6
VS1838B 紅外線遙控接收頭 + 發射管 紅外線接收器 $12


2015年7月21日 星期二

Realterm 執行時出現存取 OLE 登錄錯誤問題

今天研究了克里斯這篇關於如何燒錄 ESP8266 韌體的文章 :

【技術教學】打造Wifi遙控車(之一):使用 ESP8266進行 Wifi無線通訊

他使用 Realterm 這個通訊軟體來與 ESP8266 送收 AT 指令, 所以我就去 SourceForge 下載 Windows 安裝版 :

# http://sourceforge.net/projects/realterm/files/latest/download

我下載的是Realterm_2.0.0.70_Signed_Wrapper_setup.exe 0 安裝檔, 但是安裝完後點桌面 icon 啟動程式卻出現下面錯誤畫面 (Exception EOleSysError in module realterm.exe at 0081A75, 存取 OLE 登錄時發生錯誤) :


查了網路才知, 原來必須以系統管理員身分執行才可以 :


我已將安裝後的檔案壓縮成 zip 放在 Dropbox, 方便免安裝執行 :

# https://dl.dropboxusercontent.com/u/68794214/Realterm.zip



Arduino 測試 : PIR 紅外線移動偵測 (一)

昨晚回到高雄後, 看到帶回去鄉下又原封不動帶回來的電子實驗工具箱, 突然想要彌補一下, 於是找出上回買的 PIR 人體紅外線偵測模組, 睡前來個電子實驗交代一下. 所謂 PIR 原文 Passive InRared Sensor (被動人體紅外線感測器), 稱為被動是因為此種感測器只被動接收紅外線, 以偵測是否有人或動物經過感測區, 本身不會發出紅外線訊號. 而電視的紅外線遙控器或紅外線測距儀會發射紅外線, 那就是主動式的紅外線.

可見光波長介於 380nm~780nm 間, 所謂紅外線是指波長在 780nm~100um 間的電磁波, 靠近 780nm 為近紅外線, 幾乎不會輻射熱能, 常用來作為遙控感測或通訊之用 (例如電視遙控器); 而靠近 100um 的是遠紅外線, 會傳遞熱能. 任何物體都有可能發射紅外線, 溫度越高, 發出的紅外線就越多. 人體或動物常溫下釋放的紅外線波長約為 10um (參見 "Arduino 互動設計入門 2" 第 12 章).

PIR 紅外線感測器通電後會先經過一小段時間作校正, 建立四周紅外線能量分布對應表, 並分成兩部分來偵測移動, 當物體停止時, 兩部分能量值平衡相抵銷, 但當人走動造成晶片上熱點移動, 兩邊的能量分布就會失衡而輸出 HIGH. 不過 PIR 只能偵測是否有物體在移動, 無法偵測移動的距離, 方向與位置等資訊.

關於 PIR 模組的深入介紹可參考高手 Proteus 的大作 :

# [PIR] 簡易人體紅外線感應 (PIR) 模組測試電路

我手上這個紅外線模組是今年 3/11 向露天 XLAN 買的, 當時買了 45 元, 現在便宜了, 約 30 元就可買到 :

# [X-LAN] 送光敏電阻 Arduino HC-SR501 人體紅外感應模塊 PIR(附範例) $45
# Arduino人體紅外線感應器 HC-SR501 $31
# 【盼盼36】 HC-SR501 人體紅外線感應器 PIR $32

此 PIR 模組正面有一個 PE (聚乙烯) 做的平凸透鏡外罩, 用來過濾 (波長 8um~14um) 與聚焦紅外線, 增加感測範圍. 紅外線難以穿越玻璃, 因此玻璃窗外的動靜無法偵測. PE 外罩裡面是一顆焦電型 (pyroelectric) 紅外線感測器 D203S, 負責將溫度變化轉成電子訊號. 如果需要以天色陰晴來控制觸發與否, 還可以加一顆光敏電阻, 以便控制在陰暗時才觸發偵測, 預設是沒有光敏電阻的.

模組背面則是 IC 與被動元件, 特別是可以調整觸發模式的跳接帽與可以調整感應距離 (即靈敏度) 與延時時間的可變電阻. 感應距離最遠 7 公尺, 範圍可達 110 度角. 由於紅外線感應晶片是透過兩個小窗口接收紅外線, 偵測左右方向紅外線到達的時間差, 以分辨是否有人移動, 故水平方向的移動較容易被偵測到, 垂直方向的移動則較不容易.


此模組電源輸入 5~26V, 輸出信號 3.3V (偵測到人體紅外線) 與 0V (未偵測到), 所以電平方面不一致, 如果能全部一律在 5V 或 3.3V 工作就很好規劃, 事實上不然, Arduino Nano/Pro Mini 雖可在 5V/3.3V 電源下工作, 但感測器模組就參差不齊了. 像我手上這個型號 HC-SR501 的 PIR 模組就必須在 5V 電源工作, 我試著調到 3.3V 就不會感應了. 看樣子在 Arduino 應用中, 降壓模組是少不了的, 基本供壓 5V 需要降壓模組供電給吃 3.3V 的感測器或模組 (例如 ESP8266 就必須吃 3.3V).

此模組的規格書 (PDF) 如下 :

# HC-SR501 PIR MOTION DETECTOR

從電路圖可知, 此模組由 7133-1 這顆電源管理晶片將電源降壓至 3.3V 後供應給訊號處理晶片 BIS0001, 其 PDF 規格書參考 :

30mA Low Power LDO : 7133-1 (耐壓 26V)
Micro Power PIR Motion Detector IC : BIS0001

此 PIR 模組功耗很低, 小於 50uA, 可用乾電池供電. 只有三支腳, 兩隻是 +VCC (5V~20V) 與 GND, 中間那支是 Output (3.3V/0V).  有些板子上可能還有三支針腳用來設定觸發模式, 預設是跳在連續觸發模式, 即當偵測到人經過時, 它會輸出 High, 然後保持一段時間 (延時時間), 若在這段時間內又有移動, 它就會一直輸出 High, 否則延時時間到了後就回到 Low. 而非重複觸發模式則是, 當移動偵測被觸發輸出 High 後, 在延時時間到期後一定回到 Low, 即使這段期間內持續偵測到移動, 也不會拉長延時計時器.但我手上這塊模組沒有焊這三隻腳, 而是直接在 PCB 上 Layou 成連續觸發模式, 如下圖右下角所示 :


另外每次觸發結束後 (即 High 變 Low), 會有一段閉鎖時間 (2.5 秒), 此期間內即使有觸發也不會被偵測到. 這個閉鎖時間由模組上的固定電阻與電容決定, 除非拔掉重焊否則無法改變.

以下是我從碁峰 "Arduino 最佳入門與應用" (楊明豐) 這本書第 8 章找到的範例, 但我使用 Arduino Pro Mini 來測試, 接線圖如下 :



PIR 偵測器的信號輸出 (中間腳) 接 Pro Mini 的 D2 (設為 Input), 而 LED 串接電阻後一端接地, 一端接 Pro Mini 的 D13 (設為輸出). 然後寫程式如下編譯後上傳 Pro Mini :

const int led=13;
const int PIRout=2;
void setup() {  //定義針腳輸出入
  pinMode(led,OUTPUT); 
  pinMode(PIRout,INPUT);
  }
void loop() {
  int val=digitalRead(PIRout);  //讀取 PIR 輸出
  if (val==HIGH) {   //PIR 有偵測到時 : LED 閃一下
    digitalWrite(led,HIGH);
    delay(50);
    digitalWrite(led,LOW);
    delay(50);
    }
  else {  //PIR 沒有偵測到 : LED 暗
    digitalWrite(led,LOW);
    }
}


測試結果 OK, 我只要一動, LED 就閃不停. 下一步我打算跟 WiFi 結合, 只要偵測到移動就發出訊息到 Twitter 或物聯網伺服器.



另外我在下面這個露天賣的紅外線感應開關模組使用 DIP 開關來設定頗具方便性 :

# 【優酷3C】12VDC感應模組,可調時,可調光,自動感應,紅外線人體感應器,12v 感應器 $280

2016-10-29 補充 :

更新 : Arduino 測試 : PIR 紅外線移動偵測 (二)


2015年7月20日 星期一

第 30 周記事

本周氣候不穩定, 下過雨後菜園都是水, 所以也沒辦法去除草. 週日早上天氣還不錯, 穿了雨鞋去巡看看胡瓜有沒有可收成的, 結果有四顆, 除了一顆較嫩外, 其他都有點老了, 必須用燜的. 而冬瓜有一顆藤已乾枯, 不摘不行, 因為被蜂叮咬過, 所以表面凹凸不平.


正要上市場時感覺烏雲開始聚集, 而且姐姐說她也要去, 所以必須開車, 平常只有我跟菁菁的話, 騎機車停車比較方便.

週六回到鄉下時,小舅已到我家多時, 因小舅媽跟日文班同學赴日自助旅行, 所以只有一個人回來, 呵呵, 他說現在也是孤獨老人. 趕緊去煮晚餐招待小舅.

昨日下午把晚餐要燜的菜與湯準備好後, 把側門那間儲藏室整理一番, 媽以前很多東西捨不得丟, 塞了非常多小東西, 要用時找得到的話很好用, 問題是我們通常找不到. 我們家的哩哩扣扣的東西必須問媽放在哪才可能找到, 但現在已問不到了, 只好大清倉尋寶, 已經不能用的就丟. 其實我可能比媽還念舊, 很多還是丟不下手, 整理了老半天, 空間是增加了, 但沒想像中大. 

原本預計整理完去大馬路那邊採龍眼, 回高雄時順路帶去給二阿姨, 沒想到雨越下越大, 風颳得跟颱風時差不多. 到了四點看風雨較小了, 料想到傍晚可能停不了, 叫醒菁菁與姐姐幫我摘龍眼, 爸用竹竿, 我用長梯, 摘了兩大桶. 這周龍眼甜度剛好, 不採的話, 我擔心下禮拜可能過熟而退甘.



2015年7月18日 星期六

關於 Corona SDK 與 Lua 開發工具 Koneki

前天去河堤分館還書時, 看到這本博碩出版的 "遊戲自己做-Corona SDK 跨平台 App 開發設計實戰", 感覺似曾相識, 好像以前借過, 但當時還不知道 Lua 的妙用, 覺得還要學另一種語言很累, 所以翻一翻就還了. 最近因為 NodeMCU 的關係突然注意到 Lua, 發現其實 Lua 很簡單易學呀! 所以又再借回來看.

仔細翻閱後發現, 原來 Corona 主要是設計 Android 與 iOS 遊戲之用. 但拿來設計一般 App 也當然是可以的. 而且 Corona 整合了許多 API, 可以調用各種功能來實現手機平板的應用程式, 加上 Lua 簡單易學, 遠比用原生碼或 HTML5+Javascript 辛苦 coding 要快速簡單多了.

使用 Corona 開發跨平台 App 需先下載 Corona SDK, 請先到 Corona 網站以 Email 註冊, 收取認證信點擊認證超連結後即可登入下載頁面 :

http://developer.coronalabs.com/user/login?destination=downloads/coronasdk

按右上方的 Download 即可下載, 目前是 2015.2646 版本的安裝檔 CoronaSDK-2015.2646.msi (約 53M), 執行時預設安裝位置為 C:\Program Files (x86)\Corona Labs\Corona SDK\, 為了設定方便, 建議修改為 D:\Corona\Corona SDK. 我的 Inhon 筆電因為整個 SSD 都給 C 碟, 沒有 D 碟, 而創見 64G 插卡是 E 碟, Corona SDK 必須安裝在 Local Drive, 所以只好裝在 C 碟.


安裝完畢會在桌面出現一個 Corona Simulator, 點擊執行會先彈出登入視窗, 必須先輸入先前註冊之 Email 與密碼才能進入模擬器畫面, 編輯好的 App 必須透過連網至 Corona 公司才能進行模擬與發佈.

由於 Corona SDK 只是一個模擬器, 沒有提供 Lua 語言編輯開發工具, 雖然可以使用一般的記事本, 但操作較麻煩. 這本書建議使用 Koneki 這個免費的 Eclipse 專案來開發, Koneki 是以 Eclipse 為平台的 M2M (Machine to Machine) 應用程式開發工具, 內嵌了 Lua 解譯器, 具有 Lua 語法提示, 而且按 Run 執行 App 時會自動啟動 Corona SDK 模擬器, 可以提升專案開發的方便性. 因為Koneki 是以 Eclipse 為核心的, 所以也要先下載安裝 JDK 才行.

# 下載 JDK
# WHAT IS KONEKI?
# 下載 Koneki Lua Development Tool (約 73M)

注意, Koneki 有分 32/64 位元, 必須依據 JDK 是 32/64 位元選擇相同位元的 Koneki, 否則無法啟動 Koneki, 會出現 "fail to load jni shared library jvm.dll" 錯誤. 因為我的 JDK 是 32 位元, 所以 Koneki 也要選擇 32 位元才行.

解壓縮 Koneki 可放在 D:\Koneki 下, 點擊 LuaDevelopmentTools.exe 就會啟動 Koneki 了 :


啟動後 Koneki 會先詢問 Workspace, 因為我們將 Corona SDK 安裝在 D:\Corona 下, 所以把 Workspace 改為 D:\Corona, 所有的專案是放在此目錄下 :


然後從 "File/New/Lua project" 新增一個專案 :


這樣就會產生一個專案了 :



20150905 補充 :

今天在 ACER D260 小筆電安裝 Corona 完開啟時出現下列畫面 :


原來顯示卡必須支援 OpenGL 至少 2.1 版, 否則無法做到精緻繪圖, 我這 D260 可能沒有, 按 Cancel 仍可開啟 Corona. 啟動 Corona 後須先登錄, 但一個免費帳號只能在一台機器登錄, 除非在我的 Inhon 筆電登出, 所以只好用 Yahoo mail 再去申請一個帳號.



2015年7月17日 星期五

關於 PL2303HX 在 win8 無法驅動的問題

為了給 Arduino Pro mini 灌程式, 今年 4 月在露天買了一條蠻好用的 PL2303HX USB-TTL 程式上傳線 (價格便宜 & 板子有封裝), 在 XP 或 Win7 安裝官網所下載的 1.8.0 版驅動程式都可以抓到 com port, 上傳都 OK, 參考 :

# 安裝 PL2303HX USB 轉 TTL 驅動程式
# PL2303HX 下載線 USB轉TTL 長1米 UART Arduino Pro mini 可

但是這條 PL2303HX 線一直無法被家裡的聯想桌電 Win8.1 與我的 Inhon Win8.1 筆電抓到 (錯誤代碼 Code 10 : 無法啟動此裝置), 所以我向賣家詢問是否無法在 Win8.1 系統使用, 其回答如下 :

"可以在win8使用,但要注意、Win8系統自帶的驅動程式均不支援PL2303HX, 必須要關閉Win8的驅動程式自動更新,請自行下載2009年以前的驅動程式才可正常使用哦!"

我也在谷歌搜尋到好幾個解答, 但其實都沒有啥用 :

https://drive.google.com/file/d/0BzdGbZCSZTdsdTh4dTFmUEF1bzQ/view
Prolific PL2303 USB-to-Serial port adapter driver fails to install
win8 PL2303驱动的问题(已经解决掉了),有问题的同学可以参考
PL2303 Prolific USB to TTL Driver for Windows 8.1

最後找到這個外國人的解答, 這才了解為何露天賣家說要找 2009 年以前的驅動程式安裝才行, 原來這條上傳/下載線裡面的晶片可能是仿製的 (原文用 Fake, 假冒的), 所以原廠旺玖科技 Prolific 已經在新版的驅動程式中封殺此類晶片, 參見 :

FAKE PL2303 – HOW TO INSTALL ON WINDOWS 8.1

"A quick investigation gave an unpleasant anwser – PL2303 chips are fake!
In the newest drivers Prolific blocked all fake chips and the driver in Windows 8.1 is also blocking my fake pl2303. But there is a solution – you have to install old drivers – version 3.3.2.105."

我照文中建議方法, 去下載 2009 年以前的驅動程式 :

# IO-Cable_PL-2303_Drivers-Generic_Windows_PL2303_Prolific

解開後執行其中的 PL2303_Prolific_GPS_1013_20090319.exe, 但這只是把驅動程式複製到系統裡, 還必須做更新驅動程式的動作, 才能把黃色驚嘆號去掉, 讓系統抓到 com port :


選下面那個 "瀏覽電腦上的驅動程式軟體" :


還是一樣選下方的 "讓我從電腦上的裝置驅動程式清單中挑選"


挑選剛剛安裝的那個 3.3.2.105 版驅動程式 (2008/10/27) :


再按下一步, 跑完 "正在安裝驅動程式軟體" 後, 即可抓到 com port 了 :


驚嘆號三角形消失, 大功告成.

關於 USB-TTL/UART 轉接線問題, 高手葉難寫過一篇很完整的文章, 詳見 :

Raspberry Pi:透過序列埠登入系統

20150722 補充 :

我量了 TXRX 線輸出為 3.3V (VCC 輸出為 5V), 似乎可用在 ESP8266 (但電源必須用 AMS1117 電源模組輸出的 3.3V 才夠力), 參考 PL2303HX 的 PDF 規格書,

http://www.prolific.com.tw/UserFiles/files/ds_pl2303HXD_v1_4_4.pdf

在 "3.0 Introduction" 中有提到可連接 3.3v 設備 :

" Flexible signal level requirement on the RS232-like serial port side also allows PL-2303HXD to connect directly to any 3.3V~1.8V range devices."

20150622 補充 :

我在露天找到這款可支援 Win10 的 PL2303TA 晶片的下載線, 要 88 元, 我當初買 PL2303HA 的才 34 元! 其實有網友照上面程序在 Win10 安裝 2008 年驅動程式 OK, 我今天也來試試看.

# ►474◄ PL2303TA USB轉TTL/RS232 4Pin 支持WIN7 WIN8 WIN10 $88


2015年7月14日 星期二

Lua 學習筆記 (一) : 基本語法

最近花了一點時間來學 Lua, 作為學習 NodeMCU 的準備. Lua 目前在 TIOBE 排行第 34, 雖然屬於後段班, 但由於核心以 C 語言寫成, 編譯後僅 100KB 左右, 啟動速度快, 執行效率高, 可利用 C/C++ 擴展, 不僅可嵌入到其他程式語言裡, 還能嵌入到硬體晶片中, 非常適合用來處理 C 不擅長的部分 (例如陣列與字串), 在過去早已廣泛被各類線上遊戲採用為腳本語言, 我認為低價的 NodeMCU 平台的出現, 會使 Lua 在物聯網的應用發展中漸漸受到重視, 因為它跟 C/C++ 太麻吉啦!

Lua 語言是巴西里約熱內盧 Pontifical Catholic University 大學的科技軟體開發學院 (Tecgraf) 教授 Roberto Ierusalimschy , Luiz Henrique de Figueiredo, 以及 Waldemar Celes 所設計的. Tecgraf 學院與巴西石油公司有合作開發關係, Tecgraf 協助石油公司開發圖形顯示與地質探勘專案軟體, 先後創造了 DEL 與 SOL 兩種資料驅動語言. Roberto 教授以這兩種語言為基礎, 研發出一個更完整, 具備可嵌入與可攜性的簡易語言. 由於 SOL 在葡萄牙語意思為太陽 (Sun), 所以在朋友建議下將這新語言命名為 Lua, 葡語為月亮 (Moon) 之意. 自 1993 年 Lua 1.0 發布以來, 歷經多次改版, 納入 prototype-based 的物件導向功能與事件驅動機制 (與 Javascript 類似) 等. 1996 年 Roberto 教授在美國 Dr. Dobb's Journal 期刊 (以微電腦軟體為主軸) 發表了一篇標題為 "Lua: an Extensible Embedded Language" 的文章, Lua 才開始踏出巴西走向世界, 許多遊戲軟體如 LucasArts 與 World of Warcraft (魔獸世界) 紛紛改用 Lua 作為 Scripting 語言, 知名手機遊戲開發工具 Corona 與 Moai 也是以 Lua 作為腳本語言, 甚至連 TCP/IP 軟體 Wireshark 與網路入侵檢測軟體 Snort 也內嵌了 Lua, 顯示 Lua 的簡單易學與強大功能正吸引全世界開發者的注意, 詳參 :

A brief history of Lua
The Evolution of Lua (PDF)
Lua as a Configuration And Data Exchange Language (PDF)
# Wiki : Category:Lua-scripted video games
# Wiki : Lua (programming language)

在 Windows 上操作 Lua 請參考 :

Lua 解譯器的用法

Lua 語言特色摘要如下 :
  1. Lua 是動態語言 (Dynamic) :
    亦即它是在執行時期 (Runtime) 才做型別檢查, 所以宣告變數時不需要宣告其資料型別, 而且執行中可任意變換其型別. 其他知名的語言如 Javascript, PHP, Python, Ruby 等都是動態語言. 而 Java 與 C 等靜態語言則是在編譯時期就做型別檢查, 宣告變數時必須同時指定其資料型別, 而且宣告後不能再更換為其他型別, 若賦予之資料與宣告型別不符就會產生編譯錯誤.
    參考 :
    靜態語言 vs. 動態語言的比較
  2. Lua 是弱型別語言 (Weak typing) :
    弱型別語言允許一個變數在相對應的記憶體區域中可以存放不同類型的資料, 而強型別語言則不可以. 弱型別語言的型別推斷功能可以進行較大程度的隱性 (自動) 型別轉換, 反之, 強型別語言的自動型別轉換則較少, 強弱是相對的, 並非絕對. 注意, 動態語言不一定是弱型別語言, 例如動態語言的 Python 與 Ruby 就屬於強型別語言; 而靜態語言的 Java 也有自動型別轉換, 但是屬於強型別語言.
    參考 :
    Wiki 類型系統
    JavaScript 語言核心(4)弱型別的代價 
  3. Lua 擴展能力強 (Extensible) :
    Lua 的核心非常精簡小巧, 語法簡潔優美, 類似簡化的英文, 其強大的功能來自於易擴展性, 主要是透過以 Lua 本身內建或用 C/C++ 編寫的外部函式庫來達成, 也具有 Java, Fortran, Smalltalk, Ada 的 API 介面來擴展函式庫. 
  4. Lua 可嵌入其他語言中 (Embedable) :
    Lua 可以嵌入到 C/C++, Java, C#, Python, Ruby, Perl 等其他語言中, 做為其函式庫使用. 而且 Lua 可以雙向呼叫 (bi-directional), 亦即可由 Lua 呼叫宿主語言函式, 也可以由宿主語言呼叫 Lua 函式, 一般腳本語言通常只專注在呼叫外部函式庫. 
  5. Lua 是跨平台語言 (Portable) :
    Lua 以 ANSI C/C++ 語言編寫而成, 可在多數作業系統上執行, 甚至在嵌入式系統如手機 Android 與 iPhone, 遊戲機 PSP, PS3, 甚至以 WiFi 晶片 ESP8266 為基礎的 NodeMCU 上也可以執行, 可移植性極高.   
Lua 的優勢是執行速度快, 語法簡單學習曲線不陡峭. 以下摘要整理 Lua 程式的基本語法, 主要參考下列資料 :

# Programming in Lua (first edition) (線上電子書)
Learn Lua in X minutes (PDF)
Lua Tutorial (Lua Users)
Lua Tutorial (TutorialPoints)
Lua Tutorial (Youtube)
[Lua] 語法筆記
[Lua] Table使用手冊
看影片學 Lua 程式設計
# Scripting系統概論與Lua簡介
  1. 區塊 (chunk 或 block) :
    Lua 程式的一段陳述 (statement) 稱為 chunk, 它可以是指一條指令, 也可以是一群指令. 例如 :

    a=100
    print(a)

    或者

    a=100 print(a)

    每條指令間不須像 Javascript 或 PHP 那樣用分號結尾, 直接跳行即可, 但用分號結尾也是可以的 (行尾的分號對 Lua 而言是可有可無的, optional), 例如 :

    a=100;
    print(a);

    但如果兩條敘述要寫在同一行就必須用分號隔開 (不是用逗號), 例如 :

    a=100; print(a)

    最常見的區塊是函數 (function end), 迴圈 (for end, while end, repeat end), 判斷 (if end), 以及匿名區塊 (do end), 在這四種區塊內的變數都是自成一個單元, 享有相同的作用域或環境 (scope, context) :

    function function1()
      --do something
    end

    for a=1, 100, 5 do
      --do something
    end

    if a<=10 do
      --do something
    end

    do
      --do something
    end

    注意, 在 Lua 解譯器的交談模式中, 每一行完整的指令就是一個 chunk, 所以這一行定義的區域變數跳到下一行時是新的一個 chunk, 已經超出其作用域 (scope) 而無法存取, 執行的結果將不受上一行區域變數之影響. 此問題可用 do end 區塊解決, 包含在此區塊內的陳述都屬於同一 chunk. 
  2. 程式註解 :
    Lua 使用開頭的兩個 dash (--) 作為單行註解符號 (一直到行尾), 例如 :

    --這是單行註解行

    多行註解則是使用兩個 dash 與雙中括號 --[[ 開頭, 一直到下一個雙中括號為止, 所包含的區域解譯器會略過不予處理 :

    --[[這是
    多行
    註解]]

    例如下列範例 test.lua :

    --[[
    print ("Hello World!")
    ]]
    print ("Hello World!")

    執行此程式只會印出一行 "Hello World!", 因為第一個 print 指令被註解掉了不會執行.
    在程式開發過程中, 為了除錯方便常會使用多行註解來控制某一段程式是否要執行, 測試完畢後又要把 --[[ 與 ]] 分別去掉, 有個取巧的辦法可以解決此麻煩, 就是在結尾中括號前也加上雙 dash :

    --[[
    print ("Hello World!")
    --]]
    print ("Hello World!")

    這樣當要取消註解, 讓原先被註解掉的程式碼恢復執行時, 只要在註解開頭處再加一個 dash 即可 (因為 ---[[ 中前面的兩個 dash 把這行變成單行註解, 迫使結尾的 --] 單飛為單行註解, 多行註解破功) :

    ---[[
    print ("Hello World!")
    --]]
    print ("Hello World!")

    這樣註解頭失去多行註解功能, 而註解尾變成單行註解, 不用刻意去除. 這個程式會印出兩行 "Hello World!".
    但中括號有時令人覺得眼花撩亂, 一律使用 -- 其實會比較整齊與單純. 
  3. 識別字 (Identifier) 與保留字 :
    識別字用來指派變數或函式名稱, Lua 識別字的限制與 Javascript 一樣, 只能使用英文字母, 數字, 以及底線之組合, 但是第一個字元不可以是數字, 所以 2au 不是合法的識別字. 此外雖然可以用底線開頭, 但是因為 Lua 解譯器內部使用以底線開頭的變數, 特別是用底線開頭, 後面是大寫字母組成的識別字, 例如 _VERSION (這是 Lua 特殊用途的保留字), 所以最好不要用底線開頭來命名變數, 以免與系統衝突.

    另外, Lua 有 22 個保留字, 這些都不能拿來當識別字 :

    local nil not
    or and
    if then else elseif
    for end in do while until repeat break
    true false
    function return
    goto

    其中 nil 即 Javascript 或 PHP 的 null 或 NULL, 即無值之意. 被設為 nil 的變數會在記憶體管理下一次掃描時被垃圾回收而消失. 相較於 Javascript 有 29 個保留字, Python 的 33 個, Java 的 50 個, PHP 的 53 個, 而 C# 高達 87 個, Lua 卻只有 22 個, 可見 Lua 有多精簡.

    Lua 是有分大小寫的 (case-sensitive), 所以 and 是保留字不能用, 但 AND, And 卻是合法的識別字.
  4. 全域變數與區域變數 :
    只要不是用 local 宣告的變數都是全域變數, 即使它位於函數或迴圈等區塊中, 例如 :

    a=100

    全域變數一經賦值後就會一直存在記憶體中, 直到被設為 nil 才會被記憶體管理回收. 存取未賦值的全域變數會得到 nil. 全域變數實際上會放在名為 _G 的特殊表格中 (Table, 即關聯式陣列, 是 Lua 唯一的資料結構, 所有的變數, 函式都是以 table 來儲存), 安全性較高.

    區域變數是以 local 宣告的變數, 其作用域 (scope) 僅限於所在之區塊 (block) 內, 例如在函式, 分岐控制, 迴圈或 do end 結構中使用的變數應該宣告用 local 宣告為區域變數. 區塊中的區域變數會掩蓋同名的全域變數 (即不會存取到同名之全域變數), 意即更改區域變數之值不會影響全域變數的值. 當程式區塊執行結束時, 區塊內的區域變數就會被記憶體管理自動回收 (因此不需要刻意在區塊末尾將其設為 nil). 唯一的例外是, 如果全域變數有參考到區域變數, 則此區域變數不會隨著區塊結束而被回收, 例如 :

    a=1
    function myfunc()
      local b=2
      a=b      --全域變數 a 參考到區域變數 b
    end
    myfunc()
    print(b)   --輸出 nil (無法存取到區域變數)
    print(a)   --輸出 2

    由於全域變數 a 在函數內參照了區域變數 b, 使得 b 被全域化, 因此在呼叫函數 myfunc() 後, 原本是區域變數的 b 無法正常地被垃圾回收而留存在記憶體中 (但在上層全域卻看不到), 成為垃圾回收的漏網之魚. 這種參照方式要盡可能避免, 否則可能因 memory leak 造成程式崩潰.

    除非必要不要使用全域變數, 要盡量使用區域變數, 因為它的執行速度比較快, 而且在記憶體運用上也較有效率, 當它到達作用域盡頭時就會失去作用而被記憶體管理自動回收. 因為當 Lua 解譯一個變數時, 如果它前面有 local 標示為區域變數, 則解譯器會在目前的區域中尋找此變數, 找不到就是 nil; 如果沒有 local, 就會往上一層去找, 直到最上層為止, 找不到才是 nil, 因此全域變數要花較多時間尋找, 會影響執行效率, 所以除非是必要的全域變數, 盡量使用區域變數. 例如 :

    local a=1
    local b=2
    if a print(a)      --> 輸出 1
      local a=10      -- then 區塊內的區域變數, 不影響外面的區域變數 a
      print(a)           --> 輸出 10
    end
    print(a)             --> 輸出 1
    print(b)             --> 輸出 2

  5. 多重指派 (multiple assignment) :
    Lua 跟 Python 一樣具有多重指派語法, 可以在一個陳述中同時為多個變數賦值, 各變數以逗號隔開, 例如在交談模式中 :

    > do
    >> local a,b,c=1,2,3
    >> print(a,b,c)
    >> end
    1  2  3

    但如果賦值不足, 則未賦值之變數預設為 nil, 例如 :

    > do
    >> local a,b,c=1,2
    >> print(a,b,c)
    >> end
    1  2  nil

    若賦值超過變數之數目, 多出來的值會被視而不見略過. 多重指派讓資料交換變得很簡潔, 只需要一條指令即可 :

    local a,b=1,2
    a,b=b,a   --交換後 a=2, b=1
  6. 資料型態 (data types) 與運算子 :
    Lua 是動態弱型別語言, 其變數是無型態的 (typeless), 宣告時不需要指定資料型態, 但變數的值當然有型態, 因為解譯器是靠值的資料型態來動態地配置記憶體.
    Lua 有八種資料型態 :

    (1). nil  (無值)
    (2). boolean (布林)
    (3). number (數值)
    (4). string (字串)
    (5). table (表格, 關聯式陣列)
    (6). function (函式)
    (7). thread (執行緒)
    (8). userdata (使用者資料)

    前面六種都是其他語言中常見的型態, 而 thread 與 userdata 則較特殊. 事實上這八種資料都是使用 table 來實作的, 因為 table 是 Lua 唯一的資料結構. 使用者定義資料 userdata 是記憶體中的一個區塊, 用來給 C 函式透過 API 存取資料, Lua 無法建立或操控此資料. 而 thread 是用來指派一個例外的獨立執行緒, 但這與一般作業系統的 thread 不同, Lua 不支援真正的多執行緒 (先佔式記憶體分享, 因為 ANSI C 不提供), 不過 Lua 透過 coroutine 提供非先佔式或非記憶體分享多執行緒. 而 thread 就是 coroutine 與低層 API 的組合.

    Lua 有一個內建函數 type() 可用來檢測變數的資料類型, 例如 :

    print(type(1))          --輸出 number
    print(type("Tony"))  --輸出 string
    t={}         
    print(type(t))           --輸出 nil (因為是個空的表格)
    t={name="tony"}
    print(type(t))           --輸出 table

    以下整理最常用的字串, 數值, 布林值, 與無值 nil.

    (1) nil

    nil 相當於 Javascript 的 null, 表示一個變數無值, 即尚未初始化. 一個變數只宣告而未賦值, 預設就是 nil. 全域變數一經宣告就會存在於記憶體中, 除非我們把它設為 nil 才會被垃圾收集機制刪除.

    (2). boolean

    在 Javascript 中 true 與 1, false 與 0 是同義的, 但在 Lua 卻不同, Lua 的布林值只有 true 與 false 兩種, 1/0 並非 true/false 的別名, 配合 not, and 與 or 運算用在條件控制的邏輯判斷上. 但 Lua 的條件控制並非只能依賴這兩個布林值, boolean 以外的型態都可以用在邏輯判斷, 但除了 false 與 nil 在邏輯上為假外, 其他均為真, 例如 :

    b=0.22
    if (b) then print("true")   --> 印出 true
    else print("false")        
    end

    但是要注意, Lua 的 and 與 or 運算結果有點特別, 採用所謂 shortcut evaluation (捷徑估值法), 其傳回值不一定是 true 或 false, 而是取決於第一個運算元. 如果 and 運算的第一個運算元是 false 或 nil, 就直接傳回第一個運算元 (即 false 或 nil); 否則傳回第二運算元, 例如 :

    print(nil and 5)               --> 印出 nil  (第一個是 nil/false 就傳回 nil/false)
    print(false and "OK")     --> 印出 false  (第一個是 nil/false 就傳回 nil/false)
    print(2.2 and "OK")        --> 印出 OK (第一個不是 nil/false 就傳回第二個)

    其次, 如果 or 運算的第一個運算元是 nil 或 false, 就直接傳回第二個運算元, 否則就傳回第一個運算元, 例如 :

    print(nil or 5)                  --> 印出 5  (第一個是 nil/false 就傳回第二個)
    print(false or "OK")        --> 印出 OK  (第一個是 nil/false 就傳回第二個)
    print(2.2 or "OK")           --> 印出 2.2  (第一個不是 nil/false 就傳回自己)

    運算元最好只使用 true, false/nil 來進行運算, 以免邏輯判斷出現非預期結果.

    與布林值有關的除了邏輯運算外還有關係運算子 :

    > (大於) < (小於) >= (大於等於)  <= (小於等於) == (等於) ~= (不等於)

    與其他語言比較不同的是 Lua 用 ~= 表示不等於 (C/Java/PHP 等使用 !=), 例如 :

    if (nil ~= false) then print("不相等") end   --> 印出 不相等
    if (2.2>0) then print("正數") end                --> 印出 正數

    注意, 資料型態不同的變數不能使用關係運算子加以比較, 特別是比大小運算子 ( >, <, >=, <=) 會出現錯誤訊息. 例如 :

    > if ("OK">0) then print("正數") end
    stdin:1: attempt to compare number with string
    stack traceback:
             stdin:1: in main chunk
             [C]: in ?

    必須是相同資料型態才能進行含有大小的比較, 例如 :

    if ("smart">"rich") then print("smart is better")    --> 印出 smart is better
    else print("rich is better")
    end

    而 == 與 ~= 這兩個與大小無關的運算即使資料型態不同也不會出現錯誤, 例如 :

    if ("knowledge" == 0) then print("idiot")
    else print("expert") end    --輸出 "expert"

    事實上, == 與 ~= 運算會先去看兩個運算元資料型態是否相同, 然後再去比較其內容. 前者 == 會先看資料型態是否相同, 如果不同就直接傳回 false (不用比內容啦!), 型態相同才去比較內容, 相同傳回 true, 不同傳回 false, 例如 :

    if 1==true then  --資料類型不同傳回 false
      print("same")
    else
      print("different")   --輸出 different
    end

    if ("power" == "power") then print("power is power")
    else print("power is not power") end   --輸出 "power is power"

    if ("knowledge" == "power") then print("knowledge is power")
    else print("knowledge is not power") end   --輸出 "knowledge is not power"

    而 ~= 運算只要型態不同, 就直接傳回 true 了; 若型態相同才去比內容, 相同傳回 false, 不同傳回 true, 例如 :

    if ("money" ~= 0) then print("have money")
    else print("have no money") end   --輸出 "have money"

    if ("knowledge" ~= "power") then print("knowledge is not power")
    else print("knowledge is power") end   --輸出 "knowledge is not power"

    對於 table, function 等物件, 變數儲存的是參考 (指向實際的資料儲存位置), == 與 ~= 運算比較的是其參考, 例如 :

    t1={1,2,3}
    t2={1,2,3}
    if t1==t2 then print("same")
    else print("different")  --輸出 different (t1 與 t2 是不同參考)
    end
    t3=t1   --複製參考, t3 與 t1 指向同一個 table
    if t1==t3 then print("same")  --輸出 same
    else print("different")
    end

    上例之 t1 與 t2 雖然內容相同, 但參考不同, 故 t1==t2 運算傳回 false, 而 t3=t1 是複製參考, 兩者指向同一個 table, 故 t1==t3 傳回 true.

    (3). number

    數值方面, 可以使用 10/16 進位整數, 小數, 科學表示法來表示, 但 Lua 並沒有整數型態, Lua 的數值一律使用雙準度浮點數儲存 (IEEE 754). 例如 :

    print(2000)          --> 印出 2000
    print(3.14159)     --> 印出 3.14159
    print(2e3)            --> 印出 2000.0
    print(2E-2)          --> 印出 0.02

    雖然使用浮點數來表示整數, 但在 Lua 不會產生進為誤差 (rounding errors).

    科學表示法的指數用 e 或 E 都可以. 如果要表示 16 進位數, 數值就要以 0x 或 0X 開頭, 例如 :

    print(0xff)          --> 印出 255

    數值的運算子有如下七個 :

    + (加) - (減) * (乘) / (除) % (餘數) ^ (次方) - (單元運算, 負數), 例如 :

    print(1/2)       --> 印出 0.5
    print(5%3)     --> 印出 2
    print(2^10)    --> 印出 1024.0
    print(-2)         --> 印出 -2

    當字串與數字混合運算時, Lua 會進行自動轉型, 將數字字串轉成數字再運算, 例如 :

    print(1+"100")     --輸出 101.0
    print(1+".1")        --輸出 1.1

    (4). string

    Lua 的字串與 Java 一樣是不可變的 (immutable), 對字串的操作事實上是產生另外一個新字串. 字串的用法跟 Javacript 或 PHP 類似, 可用雙引號單引號括起來, 除此之外, 也可以用兩個中括號對 (主要用在跨行的長字串), 例如 :

    a="Hello"
    b='World'
    print(a,b)                          --> 印出 Hello   World
    print([[Hello World!]])    --> 印出 Hello   World!

    如果字串中有引號時, 只要秉持成對 (matching) 與替換 (alternate) 原則就不會弄錯, 例如 :

    print("This is Tony's book.")   --> 印出 This is Tony's book.

    這裡所有格必須用單引號, 因此整個字串要用雙引號括起來. 如果用單引號就會出錯 :

    print('This is Tony's book.')   --> 錯誤! stdin:1: ')' expected near 's'

    如果堅持用單引號, 則所有格必須用倒斜線跳脫 :

    print('This is Tony\'s book.')   --> 印出 This is Tony's book.

    或者乾脆用雙重中括號免得麻煩 :

    print([[This is Tony's book.]])   --> 印出 This is Tony's book.

    常用的跳脫字元如下 :

    \" : 雙引號
    \' : 單引號
    \n : 換行
    \r : 回車
    \\ : 倒斜線

    字串也可以用 ASCII 編碼來表示 (如果覺得這樣很有趣, 又不會太麻煩的話), 例如 ABC 的 ASCII 編碼以十進位表示分別為 65, 66, 67, 所以要印出 "ABC" 可以用倒斜線跳脫 ASCII 碼來表示 :

    print("\65\66\67")     --> 印出 ABC

    也可以用十六進位表示, 但要加一個小寫 x (不能用大寫 X) :

    print("\x41\x42\x43")     --> 印出 ABC

    參考 : Wiki : ASCII

    對於可能會超過一行長字串, 為了編輯的方便需要拆成數行時, Lua 提供兩個方式來輸入長字串, 第一個是用 [[ 與 ]] 符號來包圍一塊長字串區域, 例如 :

    a=[[This is a very
                        very
                        very ...
                                long story.]]
    print(a)

    印出的結果與編輯時的樣子相同, 會保留所有的空格.
    第二個方法是用跳脫字元 \z 來串接長字串, 例如 :

    a="This is a very \z
                       very \z
                       very ... \z
                              long story."
    print(a)    --> 印出 This is a very very very ... long story.

    可見使用 \z 不會保留空格, \z 會直接串接到下一行的非空白字元.

    Lua 取得字串長度是在字串前面加個 "#", 例如 :

    print(#"ABC")          --> 印出 3
    a="Hello World!"
    print(#a)                  --> 印出 12

    也可以使用內建的 string.len() 函式, 例如 :

    print(string.len("Hello World!"))    --> 印出 12

    至於串接字串, 有別於 Javacript 用加號, PHP 用點號, Lua 是用連續兩個點號來串接字串, 例如 :

    print("Hello".." ".."World!")     --> 印出 Hello World!

    由於 Lua 是弱型態語言, 當數值字串進行數值運算時會自動進行型態轉換, 例如 :

    print("12" + 3)            --> 印出 15, 會先將 "12" 轉成 12 再加 3.
    print("4.5e25" * "3")    --> 印出 1.35e+026

    但如果不是數值字串, 就會無法轉成數值而發生錯誤, 例如 :

    > print("1 hundred" + 900)   --> 1 hundred 不是數值
    stdin:1: attempt to perform arithmetic on a string value
    stack traceback:
            stdin:1: in main chunk
            [C]: in ?

    反之, 當數值進行字串運算時, Lua 也會自動將數值先轉成字串再運算, 例如 :

    print(20 .. 15)   --> 印出 2015

    注意, 這裡數值與字串串接運算符 .. 之間必須有一個空格, 否則第一個點會被認為是小數點而產生 malformed number 錯誤.

    以上是數值與字串的隱性型別轉換, 顯性的轉換則是利用 tonumber()tostring() 函式, 例如 :

    if (tonumber("2e2") == 200) then print("match") end     --> 印出 match
    if (tonumber("10.5") == 10.5) then print("match") end    --> 印出 match

    (5). Table (表格)

    Lua 的 table 其實就是關聯式陣列 (associative array), 這是 Lua 唯一的資料結構, 所有的資料型態都是用 table 來實作的, 例如全域變數就是儲存在名為 _G 的特殊表格中, 宣告一個全域變數 a="123" 其實跟 _G["a"]="123" 是一樣的. 在其他語言中常見的陣列 (array), 串列 (list), 紀錄 (record), 佇列 (queue), 或集合 (set) 等, Lua 都用 table 來實現.
    Lua 的 table 是用大括號來宣告的 :

    t={}    --> 宣告一個空的表格

    表格是一種關聯式陣列, 所以可以用數字當索引, 也可以用字串當索引, 事實上, 在 Lua 中除了 nil 外, 任何值都可以當 Table 的索引, 例如 :

    t={}
    t[0]="peter"
    t[2]=23
    t["2"]=45                        -- 這跟 t[2] 無關
    t["gender"]="female"
    print(t[2])     --輸出 23
    print(t[2"])    --輸出 45
    print(t["age"])   --輸出 nil (無此元素不會出現錯誤, 而是認為新元素賦值 nil)

    當然也可以在宣告時同時賦值, 例如 :

    t={[0]="peter", [2]=23, ["gender"]="female"}     -- 注意喲, 索引必須用中括號

    如果索引名稱符合識別字限制 (英數字與底線組合, 不以數字開頭), 則中括號與引號可以省略, 例如 :

    t={name="peter", age=23, gender="female", _class=0}

    所以, 索引 a 與 ["a"] 是同樣的意思, 下列宣告前後都是同一元素, 後者的會蓋掉前者 :

    t={["a"]=123, a=456}
    print(t["a"])    --> 印出 456 (被覆蓋了)     

    Table 的最後一個元素若跟著逗號是允許的, 例如 :

    t={1,2,3,}

    這對於以迴圈自動產生 Table 元素非常方便, 因為不需要花功夫去除最後一個逗號.        

    雖然都是關聯式陣列, 但 Lua 的 table 跟 PHP 的關聯式陣列在索引的使用上是不一樣的, 以數值當索引時, PHP 只能用 0 與正整數當索引, 而 table 的索引則不限於整數, 可以是任何數值, 可用實數, 也可以是布林值, 例如 :

    t={}
    t[2.2]="too small"
    t[2.2e10]="too big"
    t[-199.99]="negative"
    t[true]=true
    t[false]=false

    對於字串索引, Lua 也提供點符號來存取表格, 這跟物件或紀錄 (record) 的用法是一樣的, 例如 :

    t={}
    t.name="peter"                  -- 相當於 t["name"]
    t.age=23                            -- 相當於 t["age"]
    t.gender="female"            -- 相當於 t["gender"]
    t._ID1="S1122334455"    -- 相當於 t["_ID1"]

    注意, 這裡點後面的欄位名稱受識別字命名法規範, 亦即只能用英文字母, 底線與數字之組合, 而且不能用數字開頭, 例如 t.2xy 是不合法的.
    這種點符號最容易讓人誤解之處是, 點後面的欄位名稱是個字串, t.a 意思是 t["a"], 而不是t[a], t.a 的 a 就是字串 "a", 而 t[a] 的 a 是指一個變數 a, 所以 t[a] 的索引決定於 a 變數的值, 例如 :

    t={}
    a="x"
    t[a]=1             -- 即 t["x"]=1
    print(t.a)         --> 印出 nil (因為 t.a 就是 t["a"], 並未定義故為 nil)
    print(t[a])       --> 印出 1 (因為此 a 為變數, t[a] 即 t["x"], 已設為 1)

    如果要用 table 來實作一般的陣列, 而非關聯式陣列, 那就略過索引的指定, 直接把元素的值放在中括號內即可, 例如 :

    t={1, 2, 3}
    print(t[0])         --> 印出 nil
    print(t[1])         --> 印出 1
    print(t[2])         --> 印出 2
    print(t[3])         --> 印出 3

    如果要知道陣列長度 (即有幾個元素), 跟取得字串長度一樣, 使用 # 運算子即可 :

    t={"a", "b", "c", 1, 2, 1.7e-34}
    print(#t)     --> 印出 6

    但要注意的是, 存取元素時, 索引是從 1 開始算的, 而不是像 Javascript 或 PHP 那樣是從 0 開始, 因為在不指定索引的情況下, Lua 的整數索引預設是從 1 開始數的, 這在 Lua 是普遍的法則. 要不, 你就得自行指定索引 (愛從哪開始就從哪開始) :

    t={[0]=1, [1]=2, [2]=3}
    print(t[0])         --> 印出 1
    print(t[1])         --> 印出 2
    print(t[2])         --> 印出 3
    print(t[3])         --> 印出 nil (未定義)

    但這樣就失去懶人的目的了.

    Lua 允許使用負數做為陣列索引, 但是 # 運算子卻只能計算索引為 1 起始的整數索引元素, 例如 :

    t={}
    for i=-5,5 do
      t[i]=i
    end
    print(#t)   --輸出 5

    表格的元素也是可以是另一個表格, 謂之巢狀表格, 而且可以要多深就有多深, 例如 :

    t={name="peter", im={qq="1234567890", skype="aaa"}}
    print(t.im.qq)                  --> 印出 1234567890
    print(t["im"]["skype"])   --> 印出 aaa

    可以用 key 或 index 兩種方式來存取巢狀表格的元素.

    表格的元素也可以由函數的傳回值來產生, 例如 :

    function odd()
      return 2,4,6,8,10   --傳回多值
    end
    t={odd()}     --表格的元素由 odd() 函數產生
    print(table.unpack(t))   --輸出 2      4      6      8      10

    上例中先呼叫自訂的 odd() 函數, 用其傳回值來當元素, 再呼叫 table.unpack() 函數來拆解表格.

    (6) function (函式)

    Lua 的函數跟 table 一樣是個物件, 它其實是用 table 建構的. Lua 提供豐富的內建函數, 也可以利用 function 保留字來自定函式以便將演算邏輯抽象化 (abstract). 內建函數中最常用的是 print(), 用來在螢幕上輸出資料. 上面範例都只用了一個參數, 實際上 print() 可以接受多個參數, 各參數用逗號隔開, 輸出時各參數會以 tab 隔開 (8 個空格), 例如 :

    name="tony"
    print("Name=", name)   --輸出 "Name=    tony"
    print(1,2,3,"abc")    --輸出 "1       2       3     abc"

    Lua 的函式屬於第一級函式 (first-class function), 亦即, 函式可以像數值或字串等一般的值一樣被指派給一個變數儲存在資料結構中, 例如 :

    a=print    --將系統函數 print() 指派給變數 a
    a("ok")    --輸出 ok

    函數也可以當作引數傳遞給另外一個函式, 或者被當成回傳值傳回給呼叫者, 當然也就具有閉包 (closure) 性質了. 除了 Lua 外, 其他具有 first-class function 功能的語言有 Python, PHP, Javascript, 以及 Ruby 等.

    # Wiki : first-class function

    函式的宣告包括 scope(=local, 可有可無), function name, argument(可有可無), body, return value (可有可無), 與 Javascript/PHP 不同的是, Lua 語法用 end 標誌函式終點, 不用大括號 (已被用在 table) :

    scope name(arguments)
        body
        return values
    end


    當傳入比宣告之參數還要多的引數時, 多餘的引數會被丟棄; 反之, 若傳入之引數比參數少, 那些沒有傳入引數之參數值預設為 nil. 例如 :

    function f(x,y)
       print(x,y)
    end

    則 :

    f(1,2,3,4)         --輸出 1   2   
    f(1)                  --輸出 1   nil

    函數即使沒有參數, 呼叫它時也需要小括弧, 例如 func1(), 但有一個例外, 就是當函數只有一個參數而且此參數是字串或表格時, 可以不用小括弧, 例如 :

    print "I love you"         --輸出 I love you
    print {name="Tony"}    --輸出 table: 0075e350

    Lua 函數不能像 PHP 那樣在參數列中賦予參數預設值, 不過可以用 or 運算子來模擬預設值, 例如 :

    function inv(a)
       local a=a or 0   --用 or 模擬預設值=0
       return -a
    end
    print(inv())      --輸出 0
    print(inv(2))    --輸出 -2

    此例中的自訂函數 inv() 會回傳相反數, 當沒有傳入參數時, 區域變數 a 為 nil, 照 or 運算規則, 若第一運算元為 false/nil, 就傳回第二運算元 0, 達到模擬預設值目的.

    Lua 的函數還有一個其他語言所沒有的特性, 就是 Lua 函數可以傳回多個回傳值. 例如內建函數 string.find() 就會傳回兩個整數值, 此函數用來在字串中尋找子字串, 其兩個傳回值分別代表所找到之第一個子字串之開始與結束索引, 例如 :

    str="LuaLua"
    print(string.find(str, "Lua"))     --輸出 1       3
    s, e=string.find(str, "Lua")   --利用多重指派取得兩個傳回值
    print(s, e)   --輸出 1      3

    在自訂函數中傳回多值時, 各值以逗號隔開即可, 呼叫時用多重指派取得各傳回值, 例如 :

    function myfunc() {
      local a, b, c, d
      --do somthing
      return a,b,c,d
    end
    w,x,y,z=myfunc()

    Lua 函數也提供不定長度參數功能 (variadic), 參數列使用 ... 來表示一個不確定長度的串列, 它相當於是一個會傳回多值得函數, 可以用 print(...) 顯示其傳回值, 例如 :

    function sum(...)
      local s=0
      for i,v in ipairs{...} do   --呼叫內建函數 ipairs() 拆解陣列 {...}
         s=s+v
      end
      return s
    end
    print(sum(1,2,3,4,5))     --輸出 15

    Lua 沒有直接支援名稱引數 (named argument), 但是可以用表格來模擬, 例如 :

    function profile(args)
      print(args.name)
      print(args.gender)
      print(args.age)
      print(args.phone)
    end
    profile({name="Tony",gender="male",age=50,phone="0911092288"})

    因參數為表格或字串時, 函數呼叫可以略去小括弧, 故下面這樣也可以 :
    profile{name="Tony",gender="male",age=50,phone="0911092288"}
  7. 運算子的優先順序 :
    在不用小括弧限制之下, Lua 運算子的優先順序如下 :

     順序 運算子
     1 (最低) or
     2 and
     3 < > <= >= ~= ==
     4 ..
     5 + - (減)
     6 * / %
     7 not # -(負)
     8 (最高) ^
  8. 流程控制 :
    (1). 判斷 :
    Lua 的判斷式語法如下 :

     判斷式 語法 範例
     單向
     (單條件)
     if 條件式 then
        敘述
     end
     if score >= 60 then
       print ("及格")
     end
     雙向
     (單條件)
     if 條件式 then
        敘述
     else
        敘述
     end
     if score >= 60 then
       print ("及格")
     else
       print ("不及格")
     end
     巢狀
     (多條件)
     if 條件式 then
        敘述 
     elseif 條件式 then
        敘述
     else
        敘述
     end
     if score >= 90 then
       print ("優等") elseif score >= 80 and score < 90 then
       print ("甲等")
     elseif score >= 70 and score < 80 then

       print ("乙等")
     else
       print ("丙等")
     end

    (2). 迴圈 :
    Lua 只有 for 與 while 兩種迴圈, 沒有 do while 迴圈. 注意 while 迴圈必須控制條件式設定終止條件, 以免成為無窮迴圈. 如果要拜訪表格元素, 可以使用內建函數 pairs() 來取得每一組鍵-值對.

     迴圈 語法 範例
     for 迴圈
     (確定次數)
     for 起始值, 終止值 do
        敘述
     end
     local sum=0
     for i=1,10 do
       sum=sum + i
     end
     for 迴圈
     (遍歷表格)
     for key,value in pairs(表格) do
        敘述
     end
     local t={name="Tony",age=50}
     for key,value in pairs(t) do
       print(key, value)
     end
     while 迴圈 (不確定次數) while 條件式 do
        敘述
        條件運算式
     end
     local sum=0 local i=1
     while i <= 10 do
       sum=sum + i   i=i + 1
     end
     print(sum)

以上 Lua 語法摘要也參考了下列幾本書籍 :
  1. Learn Lua for iOS Game Development (Apress, 2012) 
  2. Learn Corona SDK Game Development (Apress, 2013)
  3. Corona SDK Mobile Game Development, 2nd Edition (Packt, 2015)
其他參考資料 :

# App開發新選擇—Corona SDK
https://coronalabs.com/
http://getmoai.com/
http://www.cocos2d-x.org/
# Creating standalone Lua executables