2016年6月29日 星期三

好書 : Make 12 : 開發板選擇指南

這本書是我從河堤分館借的, 這其實是一本雜誌 (Make 第 12 期), 內容包括很多創客作品與點子, 只是這期主題為各式開發板的介紹, 我買過 1~6 期, 後來看到圖書館有進就沒再買了 :

# Make:Technology on Your Time國際中文版12


以下是我的閱讀心得與摘要 :

對於入門創客而言, 怎樣選擇開發板可能是第一個要傷腦筋的問題. 這本 Make :12 期就介紹了各式各樣的開發板 (p48 : Special : Board field guide), 從最受歡迎的微控器 (Microcontroller) Arduino 到單板電腦 (Single-board computer) Raspberry Pi, 以及與此兩大開源硬體類似的 pcDuino 與 BeagleBone 系列等等, 真的是目不暇給. 它也提到了在 Arduino 出現之前的 Z80 (令我懷念的 CPU) 與 PIC 微控器, 但卻獨漏了曾稱霸單晶片數十年的 8051 系列.

而 Maker 熱潮中的明星 Arduino 之所以成功, 主要是因為 Arduino IDE 將複雜難懂的細節包裝成容易使用的介面, 其真正的優勢不在硬體, 而是軟體, 引領了硬體專案開發方式的跟風. 其中德儀 (TI) 推出以 MSP430 晶片為主控的 LaunchPad, 價格為 25 美元, 比正廠 UNO 的 30 美元便宜, 加上新版開發平台 Energia 可將 Arduino 的 sketch 直接匯入使用, 似乎擺明就是要搶 Arduino 的市場. LaunchPad 在露天有賣 :

# LaunchPad TI MSP430 第二代Rev. 1.5 (8051/AVR/Arduino以外的選擇) $400
# MCUapps™含稅美國 TI 原廠 MSP-EXP430G2 MSP430G2 第二代 LaunchPad 開發板套件 $430
# 【秋葉原電腦周邊-旗艦店】㊣ TI原裝正版 MSP430開發板MSP-EXP430G2 LaunchPad $450
{TI 開發板}MSP432P401R LaunchPad開發套件-可用Energia MT編程開發,支援 RTOS $499# MCUapps™含稅原裝 MSP430F5529 MSP-EXP430F5529LP USB LaunchPad 開發板 $580

另一款以 ARM Cortex 為基礎的 Netduino, 微控器是 32 位元的 STM32Fx, 此開發板採用 .Net Micro 為作業系統, 可直接使用 Visual C# 開發, 此為其名稱中 Net 的由來, 並非內建網路晶片. 此開發板價格較貴, 在露天可找到 :

# 《iCshop3》Netduino Mini【sparkfun】 $1690

老實說我跟微軟的開發技術一直都不對盤, 討厭 Visual Studio 與 .Net, 唯獨對 JScript 的 ASP 有好感.

還有一款是 Parallax 出的 Propeller 系列, 其特點是採用 8 核心控制器, 也就是能夠同時跑 8 個程序 (相當於有八個 Arduino 的 loop 在跑), 可用來執行需要平行處理效能的應用. 這款開發板露天也有賣 :

# 【Arduino飆機器人暢貨中心】Propeller 開發測試板 歐美進口 Parallax $1100
 
創客界另外一塊明星板是以 Linux 為作業系統的 Raspberry Pi (Arduino 沒有作業系統), 它原本是為教育用途而設計的板子 (希望孩子們能以最低代價學習程式語言), 但因為價格低廉功能強大成為創客最愛的開發板.

其他以 Linux 為基礎的較受歡迎開發板有 TI 的 BeagleBone 與 pcDuino, 性能都比舊的 Raspberry Pi 優秀, 但樹苺派也推出了 Pi 3. 新版的 BeagleBone Black 將作業系統從 SD 卡搬到內建記憶體, 使得 SD 卡可挪做資料儲存使用, 其性能較樹苺派高, 相對地價格也較高,  :

# 《德源科技》現貨 2015版本 BeagleBone Green 綠色 狗骨頭(送電子書) $1278
# MCUapps™含稅原廠代理 BeagleBone Green 雙 Grove 介面開發板 $1350
# 《德源科技》●大特價 美國版 最新版 BeagleBone Black - Rev C (送電子書) $2200
#  (微控制器科技) 2016新品 美國原裝 BeagleBone Black Rev C (送初學者電子書) AM335x $2250

pcDuino 採用全志的 CPU A20, 價格比 Pi 3 稍貴些 :

# 《德源科技》Pcduino 1GHz ARM A10處理器 1GB DRAM 2GB Flash 性能超樹莓派 Raspberry Pi Rev. 2 $1600
# 最新上市 pcDuino NANO 高性能 A20 1GHz ARM Cortex-A7 小巧型的單板電腦 / Ubuntu / Andriod / Linux 1080p $1600
# pcDuino3 Nano 雙核A20 開發板 ARM Cortex-A7超樹莓派2/cubieboard $1700

其實雜誌沒提到的還有兩款很受歡迎的 Linux 開發板 : Banana 與 Cubiboard, 都比樹苺派稍貴些, 效能應該都比樹苺派好, 但使用者社群陣容卻無法與樹莓派相比擬. 我覺得只要看出版商有沒有幫這些板子出書, 就知道誰比較有份量了. 我相信這方面 Arduino 跟 Raspberry Pi 絕對有不可撼動的地位. Arduino 雖然沒有作業系統, 但其支援的感測器種類最多, 硬體控制能力也強, 所以適合做為簡單或低階的控制工作; 而樹苺派因為有 Linux 加持, 所以適合做為需要連網的高階工作, 例如做為網路伺服器等.

P62 "The board room" 這篇介紹了九種新的開發板, 其中我感興趣的有 TinyDuinoSpark Core 這兩款, 它們都非常小巧, TinyDuino 價格為 19.95 元美金, 硬體規格與 UNO 相當, 而 Spark Core 則是 ARM Cortex M3 架構, 內建 Wifi 而且與 Arduino 相容, 價格卻是比較便宜的 19 美金, 光是內建 Wifi 就很誘人了.  還有一款是內建 BLE 藍芽的 BLEduino 也很不錯, 使用 Atmega32u 做 MPU.

P70 介紹利用 Arduino 與磁簧開關製作冰箱開門感應器, 並利用 xively 物聯網服務將冰箱門開關的情形饋送到伺服器上, 以便觀察使用的頻繁度. 還可以利用 Zapier 這項服務來驅動網路應用程式自動執行工作, 參考 :

# xively.com/dev/tutorials/zapier

這個有空要來好好研究怎麼用.

P106 介紹使用 EAGLE 軟體來設計一個自己的準 Arduino 板, 而 P112 則是介紹使用 DesignSpark 這套軟體來設計 PCB. 這原本很吸引我, 但是現在我不太想花太多時間在做這種低階的創作上面, 只要用洞洞板做個堪用的雛形就可以了.

最駭人的是 P116 所介紹的 "Nuclear Fusor", 利用高壓電源與真空玻璃管, 製作 Farnsworth-Hirsch 迷你熱融合反應爐, 不過此項實驗需要將 100V 電壓升高到 10KV, 而且玻璃瓶中出現的藍紫光可能含有伽瑪射線, 具有相當危險性, 所以不是那麼容易做的.

總之, 這本書具有非常高的可看性.


三本語音相關的好書

前陣子為了整理 Praat 的簡報資料, 把書櫃中的語言學書籍翻出來複習, 越看越有味, 就跟總圖借了王小川這本語音訊號處理來看, 但發覺整本書都是談理論的, 數學式一大堆讓人頭腦發昏, 實在不對味. 在拿去還之前紀錄一下手邊這三本技術性較強的語音相關書籍.

# 全華-王小川-語音訊號處理 (修訂二版)

三民書局

這本書著重在理論方面, 屬於大學理工科教科書, 需要工程數學方面的基礎才看得懂. 對於如何從理論化為實作則未著墨, 數學不強的人可以拿來翻翻就好. 此書比較吸引我的是關於 LPC 與倒頻譜模型的說明以及最後一章關於中文語音處理的介紹.

# 松崗-楊鎮光-Visual Basic 與語音辨識 (讓電腦聽話)




此書是作者將其碩士論文整理後出版, 大概是市面上唯一一本談語音辨識實作的中文書, 可惜已經絕版, 只能向圖書館借閱. 我在 2004 年逛書店時看到此書如獲珍寶, 立即購下準備按圖索驥玩一遍, 因為那時剛拿到碩士, 對語言學懷有非常炙烈的熱情, 希望能在語音辨識方面有所斬獲, 但是卻因為投入公司網站開發, 陸續在 ASP, Javascript, PHP, jQuery 等前後端技術上打滾, 就逐漸把語言學給忘了, 這本書也就束之高閣矣.

# 香港城市大學-王士元, 彭剛-語言, 語音與技術


這本書是我所有語言學書籍中最喜愛的一本, 乃中研院王士元院士與其門生彭剛所合寫的集理論與技術於一冊之佳作. 前半部由王院士總結語音學相關理論, 從語音的產生, 感知, 到其聲學特徵, 都做了非常精要的介紹. 後半部由彭剛所撰寫的技術篇是吸引我買這本書的最大誘因, 內容包括隱藏式馬可夫模型與向量機這兩個在語音辨識實作上普遍採用的技術之理論基礎, 以及語音合成的方法, 最後一章還特別介紹了開源的語音分析軟體 Praat, 這大概是第一本談 Praat 的語言學書籍吧.


2016年6月28日 星期二

2016 年第 25 周記事

過去的一周重要事項如下 :

週二 6/21 中午免試入學志願序填寫結束, 二哥當日下午去學校領取紙本輸出回來給我簽名蓋章後, 次日交回, 同時繳 230 元與免試入學報名表. 預計下周 7/5 發布錄取通知書, 7/7 向錄取學校報到.

週六公司福利會舉辦奇美博物館參觀, 含中餐晚餐交通費等每人 1700 元 (有點貴), 員工酌收約 400 元, 上個月問爸想不想去, 他說沒去過看看也好, 當時推算二哥學校畢業典禮也過了, 所以就報名三人參加, 菁菁則是要月考了, 而且剛開館時正好小六導師有辦戶外教學去過, 姊姊雖然沒去過, 但也要期末考, 所以有機會再去囉.

我去過奇美兩次了, 感覺還好, 就是參觀牆壁上的畫作與標本而已, 對藝術有興趣的人可能比較會想去吧! 我只是想帶爸出去走走看看, 吃吃喝喝而已, 哪裡都好啦. 而且二哥國中後兩年都在補習拚會考, 現在放暑假在家挺無聊, 與其打電動不如出去玩. 這次我們是早上先到嘉義檜意生活村參觀, 天氣熱到不行, 毒辣的太陽逼得我們盡量找樹陰躲. 中午 11 點在嘉義吃完午餐再往南到奇美博物館參觀. 傍晚到附近的十鼓文化園區吃過晚餐, 大略逛一下就回高雄了.

周末因三隻小狐狸都要補習, 所以只有我回鄉下 (週六從奇美回來已八點半, 就直接載爸回鄉下了), 覺得蠻孤單的. 週日早上去市集前, 拿了鋤頭將菜園那些目無法紀的雜草一一剪除, 鋤出大約六坪空地, 感覺非常舒暢. 只要曬一個上午的太陽, 保證全成乾草一堆, 下周再將暫時沒用的地鋪上黑塑膠布, 以免一下雨又長出來.

除完草還有時間, 就把去年買來多時的小沉水馬達拿出來, 接上 12V 鉛酸電池, 測試看看其揚水高度, 發現至少有 1.5 公尺高, 而且水壓強勁. 我買這個主要是想用太陽能板儲存電能於鉛酸電池, 再用來抽水灌溉之用. 但是我的閒暇時間太過零碎, 只能一有空就做一點, 積少成多總能做出一些成果來.


購買太陽眼鏡

之前公司同事團購時以 $290 買的太陽眼鏡非常好用, 有附一個硬殼保護盒, 但是卻在四月下旬 (4/18~4/22) 帶爸去黑部立山旅遊時, 掉在立山纜車站附近的小商店, 當時是趁纜車還沒來想去買張日本郵票, 排在後面的一個歐巴桑要我幫她看商品說明, 我就把戴著的太陽眼鏡摘下來放在桌上, 結果結帳完就忘了我的太陽眼鏡! 哇咧, 還沒正式用到就遺失了, 殘念!

近日烈陽如炙, 中午出去吃飯或騎車上下班時眼睛被強光照得受不了, 想說再買個太陽眼鏡來戴. 今天上露天找到這家才賣 $119 超商取貨免運費的賣家 :

# 原廠四抗鏡片!保證抗衝擊!1.0安全強化鏡片+抗藍光+抗UV400+抗反射!近視族必備!包覆偏光太陽眼鏡TW-SUPER $119

同事也託我幫他買一個, 先買一個試試看, 好用再買也不遲.

2016-07-06 補充 :

上周五收到貨品了, 我覺得品質還不錯, 而且可以放進掉在日本那隻的硬殼盒子內.

2016年6月27日 星期一

從 HTTP 網頁伺服器獲取時間訊息的方法

Arduino 除了可以利用 UDP 協定從 NTP 伺服器取得時戳外, 也可以透過網頁服務 (TCP 協定) 來取得時間訊息. 我在下面這篇論壇文章中除了獲取 UDP 的相關 資料外, 也從 Mark Brawell 所發表的回應中得知他建立了幾個跟時間有關的網頁服務, 參考 :

Topic: Arduino ESP8266 and NTP (Read 13317 times)
http://www.foxhollow.ca/nodemgr/?info

只要對這些網址發出 HTTP 要求, 就能取得包括日期, 時間, 星期等訊息, 常用的連結如下 :

http://www.foxhollow.ca/nodemgr/?date (日期 2016-Jun-20)
# http://www.foxhollow.ca/nodemgr/?time (12小時制時間 08:44:08pm)
http://www.foxhollow.ca/nodemgr/?time24 (24小時制時間 20:44:41)
http://www.foxhollow.ca/nodemgr/?Day (星期 Mon)
http://www.foxhollow.ca/nodemgr/?Year (年 2016)
http://www.foxhollow.ca/nodemgr/?month (月 06)
http://www.foxhollow.ca/nodemgr/?day (日 20)
http://www.foxhollow.ca/nodemgr/?Hour (24小時制時)

注意, 由於 Mark Brawell 的伺服器位於加拿大東部 (魁北克省), 因此回傳的時間訊息為美東時間, 換算成台北時間必須加 12 小時, 日期則需加 1 天. 星期幾比較簡單, 取得英文簡寫後用陣列轉換即可. 但時間與日期部分在跨年或跨月時就比較麻煩, 因為不只要換算時, 連日, 月, 年都要同步換算. 不如直接取得自 1970/1/1 以來的 Unix 時戳 (GMT 時間), 再加上 28800 秒 (即 8 小時) 後得到台北時間的時戳來換算比較簡單 :

http://www.foxhollow.ca/nodemgr/?unixtime (Unix 時戳)

下面就使用上週製作好的 Arduino Nano + ESP8266 物聯網模組來測試一下以 TCP 協定從 Mark Bradwell 的網頁伺服器擷取時間. 關於使用 TCP/IP 抓取網頁的方法, 參考 :

# 用 ESP8266 的 TCP/IP 連線抓取網頁

關於從 NTP 伺服器取得時間的方法, 參考 :

# 以 Arduino + ESP8266 物聯網模組重作 NTP 實驗 (三) 

本次實驗的程式如下 :

#include <SoftwareSerial.h> 
#define DEBUG true

//system use please do not edit 
SoftwareSerial esp8266(7,8); //(RX,TX) 
const int SW_PIN=4; //Pin to switch configuration or working mode
const int MAX_PAGE_NAME_LEN=48;  //buffer size
char buffer[MAX_PAGE_NAME_LEN + 1]; //store page_name/ssid/pwd
int mode; //store current mode(LOW=configuration, HIGH=working)
//-----application codes listed bellow-----

void setup() {
  //system use please do not edit
  Serial.begin(9600);
  esp8266.begin(9600);
  sendData("AT+RST\r\n",2000,DEBUG); // reset ESP8266 
  pinMode(SW_PIN, INPUT);
  mode=digitalRead(SW_PIN);
  sendData("AT+GMR\r\n",1000,DEBUG); 
  if (mode==LOW) { //setup mode : for wifi configuration
    sendData("AT+CWMODE=3\r\n",1000,DEBUG); //configure as access point
    sendData("AT+CIPMUX=1\r\n",1000,DEBUG); //enable multiple connections
    sendData("AT+CIPSERVER=1,80\r\n",2000,DEBUG); //turn on server 80 port         
    }
  else {  //working mode : for running application
    sendData("AT+CWMODE=1\r\n",1000,DEBUG); //configure as a station
    delay(3000); //wait for wifi connection to get local ip
    }
  sendData("AT+CIFSR\r\n",1000,DEBUG); //get ip address
  //-----application codes listed bellow-----
  }
void loop() {
  if (mode==LOW) {setupWifi();} 
  else { //-----application codes listed bellow-----
    Serial.println("Sending HTTP request to www.foxhollow.ca web server ...");
    Serial.println(getCST());
    }
  }

String getCST() {
  sendData("AT+CIPSTART=\"TCP\",\"www.foxhollow.ca\",80\r\n",1000,DEBUG);
  sendData("AT+CIPSEND=24\r\n",1000,DEBUG); //24 bytes include \r\n
  String res=sendData("GET /nodemgr/?unixtime\r\n",3000,DEBUG);
  res.replace("\r\n",""); //remove all line terminator for getting time stamp
  //retrieve time stamp (between ":" and "OK")
  //+IPD,10:1467029520
  //OK
  String t=res.substring(res.indexOf(":") + 1,res.lastIndexOf("OK"));
  //Serial.println(t);
  char buf[10]; //buffer to store unixtime string (for strtol)
  //copy char in string to char array
  for (byte i=0; i<t.length(); i++) {buf[i]=t.charAt(i);}
  char *eptr; //end pointer used in strtol()
  unsigned long epoch=strtol(buf, &eptr, 10); //convert string to long
  Serial.println("GMT time stamp=" + epoch);
  unsigned long c=epoch + 28800; //convert to CST time stamp (GMT+8hr)
  //Convert CST (Taipei time) time stamp to hour:minute:second
  String cst=""; 
  byte hour=(c % 86400L) / 3600; //hour (86400 secs per day)
  if (hour < 10) {cst += "0";} //prefix with "0" if single digit
  cst.concat(hour); 
  cst.concat(":");
  byte  min=(c % 3600) / 60;   //minute (3600 secs per minute)
  if (min < 10) {cst.concat("0");} //prefix with "0" if single digit
  cst.concat(min); 
  cst.concat(":");
  byte sec=c % 60; //second
  if (sec < 10) {cst.concat("0");} //prefix with "0" if single digit
  cst.concat(sec); 
  res=sendData("AT+CIPCLOSE\r\n",5000,DEBUG); //close session 
  if (res.indexOf("OK") != -1) {return cst;}
  else {return "00:00:00";}  
  }

void setupWifi() {
  if (esp8266.available()) { // check if the esp is sending a message   
    if (esp8266.find("+IPD,")) {
      delay(1000);
      //esp8266 link response : +IPD,0,498:GET / HTTP/1.1
      //retrieve connection ID from response (0~4, after "+IPD,") 
      int connectionId=esp8266.read()-48;  //from ASCII to number
      //subtract 48 because read() returns ASCII decimal value
      //and in ASCII, "0" (the first decimal number) starts at 48
      if (esp8266.find("GET /")) { //retrieve page name (router)
        memset(buffer, 0, sizeof(buffer));  //clear buffer (all set to 0)
        if (esp8266.readBytesUntil('/', buffer, sizeof(buffer))) {
          if (strcmp(buffer, "update") == 0) { //update wifi
            //"?ssid=aaa&pwd=bbb HTTP/1.1"             
            esp8266.find("?ssid="); //skip ssid token
            memset(buffer, 0, sizeof(buffer));  //clear buffer (all set to 0)
            esp8266.readBytesUntil('&', buffer, sizeof(buffer)); //retrieve ssid
            String ssid=buffer;
            esp8266.find("pwd="); //skip pwd token
            memset(buffer, 0, sizeof(buffer));  //clear buffer (all set to 0)
            esp8266.readBytesUntil(' ', buffer, sizeof(buffer)); //retrieve pwd
            String pwd=buffer;
            //configure as a station
            String res=sendData("AT+CWJAP=\"" + ssid + "\",\"" + pwd + "\"\r\n",6000,DEBUG);
                      
            //show setup result
            String webpage="<html>Wifi setup ";
            if (res.indexOf("OK") != -1) {webpage += "OK!</html>";}
            else {webpage += "Failed!</html>";}
            String cipSend="AT+CIPSEND=";
            cipSend += connectionId;
            cipSend += ",";
            cipSend +=webpage.length();
            cipSend +="\r\n";
            sendData(cipSend,1000,DEBUG);
            sendData(webpage,2000,DEBUG);
            
            String closeCommand = "AT+CIPCLOSE=";
            closeCommand+=connectionId; // append connection id
            closeCommand+="\r\n";   
            sendData(closeCommand,3000,DEBUG);                 
            }
          else { //show setup page
            String webpage="<html><form method=get action='/update/'>SSID ";
            webpage += "<input name=ssid type=text><br>";
            String cipSend = "AT+CIPSEND=";
            cipSend += connectionId;
            cipSend += ",";
            cipSend +=webpage.length();
            cipSend +="\r\n";
            sendData(cipSend,1000,DEBUG);
            sendData(webpage,2000,DEBUG);

            webpage="PWD <input name=pwd type=text> ";
            cipSend = "AT+CIPSEND=";
            cipSend += connectionId;
            cipSend += ",";
            cipSend +=webpage.length();
            cipSend +="\r\n";
            sendData(cipSend,1000,DEBUG);
            sendData(webpage,2000,DEBUG);

            webpage="<input type=submit value=Connect></form></html>";
            cipSend = "AT+CIPSEND=";
            cipSend += connectionId;
            cipSend += ",";
            cipSend +=webpage.length();
            cipSend +="\r\n";
            sendData(cipSend,1000,DEBUG);
            sendData(webpage,2000,DEBUG);

            String closeCommand = "AT+CIPCLOSE=";
            closeCommand+=connectionId; // append connection id
            closeCommand+="\r\n";   
            sendData(closeCommand,3000,DEBUG);
            }
          }
        }
      }
    } 
  }

String sendData(String command, const int timeout, boolean debug) {
  String response="";
  esp8266.print(command); // send the read character to the esp8266
  long int time=millis();
  while ((time+timeout) > millis()) {
    while(esp8266.available()) {
      // The esp has data so display its output to the serial window 
      char c=esp8266.read(); // read the next character.
      response += c;
      }  
    }
  if (debug) {Serial.print(response);}
  return response;
  }

在此程式中, 首先我們對 ESP8266 下達如下 AT 指令以建立一條 TCP 連線 :

AT+CIPSTART="TCP", "www.foxhollow.ca", 80

然後再用下列 AT 指令告訴 ESP8266, 我們要傳送的資料長度含尾端跳行共 24 bytes :

AT+CIPSEND=24

接著傳送 HTTP 內容, 也就是 GET 方法與要存取之資源路徑 :

GET /nodemgr/?unixtime

內容只有 22 個字元, 但要加上尾巴的 \r\n 兩個跳行字元, 所以上面 CIPSEND 要設為 24. 然後利用字串的 substring() 函數擷取 Unix 時戳數據, 先將回應訊息中的跳行全數去除後, 抓取 ":" 與 "OK" 中間的字串即得. 再用迴圈將時戳字串複製到字元陣列中, 以便利用 strtol() 函數將字元陣列轉換成 long 型態整數, 這樣才能進一步換算成時間. 

最後必須用下列指令釋放 TCP/IP 連線 :

AT+CIPCLOSE

上面程式編譯後記憶體耗用情形如下 :

草稿碼使用了 12,080 bytes (39%) 的程式存儲空間。最大值為 30,720 bytes。
全域變數使用了 924 bytes (45%) 的動態記憶體,剩餘 1,124 bytes 供局部變數。最大值為 2,048 bytes 。

可見比之前用 NTP 要節省 (分別是 43% 與 58%), 全域變數省最多.

下面是序列埠監控視窗擷取的輸出訊息 :

AT+RST


OK
bB�鑭b禔S��"兀L�侒��餾�
[System Ready, Vendor:www.ai-thinker.com]
AT+GMR

0018000902

OK
AT+CWMODE=1

no change
AT+CIFSR

192.168.2.103

OK
Sending HTTP request to www.foxhollow.ca web server ...
AT+CIPSTART="TCP","www.foxhollow.ca",80


OK
Linked
AT+CIPSEND=24

> GET /nodemgr/?unixtime

SEND OK

+IPD,10:1467029879
OK

AT+CIPCLOSE


OK
Unlink
20:17:59
Sending HTTP request to www.foxhollow.ca web server ...
AT+CIPSTART="TCP","www.foxhollow.ca",80


OK
Linked
AT+CIPSEND=24

> GET /nodemgr/?unixtime

SEND OK

+IPD,10:1467029889
OK
� �
AT+CIPCLOSE


OK
Unlink
20:18:09
Sending HTTP request to www.foxhollow.ca web server ...
AT+CIPSTART="TCP","www.foxhollow.ca",80


OK
Linked
AT+CIPSEND=24

> GET /nodemgr/?unixtime

SEND OK

+IPD,10:1467029899
OK
? U
n
`
nan
AT+CIPCLOSE


OK
Unlink
20:18:19

除了使用古老的 NTP 協定外, 看起來用 TCP 協定抓時間比較簡單, 只要做字串處理即可.

參考資料 :

# C Language: strtoll function
# C library function - strcpy()
# Convert string to long long C?
How to convert Unix TimeStamp into day:month:date:year format in C?
# C library function - strftime()
# [Arduino] Timestamp function
# Converting UNIX timestamp to seconds, minutes, hours, days, weeks, month, years, decades ago
# Arduino Time library

2016-06-28 補充 :

長時間觀察結果, 發現此種做法效果不佳, 該伺服器似乎不太能穩定回應要求, 還是用 NTP 為宜.


2016年6月23日 星期四

向 allen_6833 採購電子零件模組一批

因需要補充蜂鳴器與升壓模組等, 向 allen_6833 採購電子零件模組一批. 結果順便買了 NodeMCU 模組等一大堆, 我是逛百貨公司不如逛電子材料店的那種 :

商品名稱
數量
金額
1
90
1
56
4
20
1
180
3
126
1
64
3
57
2
76
1
45
1
35
4
60
1
24
1
32
10
30
6
30
10
40
1
15
1
210

商品總金額: 1190元 + 運費: 60 元 =應付總金額: 1250 元

有需要再買 :

# ►250◄DHT11溫濕度模組 DHT11感測器模組 Arduino 電子積木DHT11模組 送杜邦線 $50*1=50
►113◄ULN2003 五線四相 步進電機 驅動模塊 驅動板 步進馬達驅動模組 $25*1=25
►558◄1A鋰電池專用充電板 充電模塊 TP4056鋰電池充電器 高精度 移動電源 Micro USB $11*3=33
# ►289◄ SIM800L GPRS 轉接板 GSM 模組 micro SIM卡最小 附天線 $300

# i2c OLED Module example

2016-07-08 補充 :

這個在露天買得到的 3cm*7cm 洞洞板跟我在禾樺買的不同之處如下 :


上面是露天買的, 有 10*24=240 洞, 而下面是禾樺的, 只有 9*24=216 洞, 即露天的多了一排, 且正反面都有印 ABCD../123.. 的座標, 禾樺的僅焊錫面才有座標.


2016年6月22日 星期三

可愛的風速風向計

今天在露天 buyic 賣場看到這款可愛的風速風向計, 美則美矣, 可惜要價 $3900 :

氣象站套件(含電路板) 風速計 風向儀 雨量器 APRS $3900

我在想, 要自製風速計不難, 只要用小馬達產生的電壓來類比即可, 但校正才是大問題. 至於風向計就更難了, 據下面這篇描述, 要使用角位移感測器才行, 其原理為利用滑動可變電阻值的變化來產生電位差 :

基于Arduino,制作自己的自动化气象站

要自製感測器? 這可不是憨人想的哈尼甘單哪!


2016年6月21日 星期二

2016 年第 24 周記事

本周菁菁與姊姊跟我一起回鄉下. 昨天天氣非常炎熱, 本來上市集想買西瓜, 但騎機車沒法載. 下午三貼去國中母校對面吃冰, 講到要吃冰, 她們兩個就眼睛一亮.

過去這一周我都在瘋我的 Arduino + ESP8266 物聯網模組, 做了三片 4.5cm*4.5cm 的, 另外周末又做了一片 3cm*7cm 的, 總共四片, 並花了一些時間撰寫製作紀錄, 以便往後參考之用.

晚到的梅雨到上周二停了, 又恢復酷熱難耐的天氣, 我看還是下雨得好, 但不要連續下大雨就好. 最近沒時間弄菜園, 梅雨過後草就恣意滋長, 簡直是目無王法, 本周回去應該有空好好整治一番了.

小舅媽週日中午赴美旅遊, 我幫她買的 T-Mobile 預付卡在抵美後順利啟用, 還好, 我原本擔心還要設 APN 之類的就麻煩了.


二哥 105 國中會考志願序選填

今天是國中會考選填志願序截止日, 選填系統在此 :

http://kh105.kh.edu.tw/signup.php

二哥成績 4A1B, 區間在 2301~2400 之間 :


昨晚跟二哥一起檢查了試填時的順序, 同時把新莊高中與中山附中 (國光) 的互調, 國光換到第三順位, 因為從凹仔底坐捷運四站可達, 而新莊則要坐公車或騎腳踏車. 學校發的學校排序表如下 :


二哥的志願序大致按照這個來選填 :


雖然高師大附中似乎有點距離, 但因為不像姊姊會考第一屆那時跳一個志願序會扣分 (那簡直就是在零和賽局中進行豪賭), 現在一個群組內不扣分, 所以就試試看囉. 希望最大的可能是第二順位的鳳中.

2016-07-06 補充 :

7/5 公布結果, 二哥上網查詢後打電話給我, 如所預料錄取鳳中. 這樣就要搭校車上學了, 每學期大約 7000 元車資.