2014年8月12日

Arduino 第二課 - 跑馬燈

繼自學第一課: LED switch 用開關控制 LED (或者其他元件)後, 接著進入較複雜的(程式)控制: 跑馬燈。

材料
LED x3 (以上)
Resistor 330Ω x3 (搭配LED數量)

製作
< 參考「Arduino互動設 計入門2」- p4-19 ~ p4-21 >
紅色線: 高電位/電源輸出
黑色線: 低電位/電源回流

分兩種接法: 左圖為源流(source current) 與 右圖潛流(sink current)


電路圖如下:

程式如下:
const byte LEDs[] = {4 ,7, 10};
const byte LEDs_SIZE = sizeof(LEDs);

const byte INIT_VALUE = LOW; // LOW/HIGH when using source-/sink-current circuit
byte count = 0;

void setup() {
  for (byte i=0; i< LEDs_SIZE; i++) {
    pinMode(LEDs[i], OUTPUT);
  }
}

void loop() {
  for (byte i=0; i< LEDs_SIZE; i++) {
    digitalWrite(LEDs[i], INIT_VALUE);
  }
  
  count = count % 3;
  digitalWrite(LEDs[count], ! INIT_VALUE);
  count++;
  
  delay(200);
}

上述, 使用了廻圈(loop)與陣列(array)的寫法; 源流接法時, 將
const byte INIT_VALUE = LOW;

潛流接法時, 將
const byte INIT_VALUE = HIGH;

另外, 可使用 DDRx (Data Direction Register)來控制 pin 的輸出入, 並使用 shift 的程式技巧來達成:

<以DDRD/PortD為例>

// for sink-current circuit
const byte INIT_VALUE = 0b00001000;
const byte LED_SHIFT = 2;
byte count = 0;

void setup() {
  DDRD = 0b10101000; // OFF for pull-down circuit
}

void loop() {
  count = count % 3;

  if (count == 0) {
    PORTD = INIT_VALUE;
  } else {
    PORTD <<= LED_SHIFT;
  }

  count++;
  delay(200);
}

上述為潛流接法的寫作, 源流的寫法得花點時間想想。

ps.
上述二例寫法與「Arduino互動設 計入門2」- p4-28, p4-31有點不同

2014年8月10日

Arduino 第一課 - LED switch

去天瓏買書時, 老闆慫恿我買 Arduino 的書來看, [年紀這麼大了, 學還來得及嗎?] 我這樣子問, 他說:[玩玩嘛!]. 於是真得玩了起來.

會有這樣子的想法, 是多年前 Make: 正夯(現在已發行《Make》雜誌國際中文版), 印象所及是曾看一篇網頁說明了用紅外線指示筆+光碟機做出了一個雷射筆(槍), 不久後新聞報導了大陸的網購網站竟然開始賣這樣子危險的東西; 另外, 還有 GPS 尋寶遊戲的導航製作. 試想, 我自己是否依樣畫葫蘆呢?!

而 Arduino 對我所學非專科的人來說, 多半只是看看而已; 直到一年多前開始察覺已經出現很多網站刊出很多有趣的東西之後, 我才順著天瓏老闆的話, 試著玩玩, 看是否如同以前的中推會同事一般, 做出個藍芽搖控玩具呢?!

但自學的第一課是什麼呢? 買材料! 而買材料的第一步是找一間電子材料行隨意逛逛. 看了玲瑯滿目各式規格看不懂的電子料件, 足足花了三個小時才買到了一些要學習的基本材料; 當然, 這樣子的結果是有先做功課的; 不然, 第一時間, 大概會因為眼花潦亂, 嚇到後打退堂鼓的.

即然身為 software developer 是沒在怕的, 先自我催眠: 只不過是組裝電路後把程式寫入即可. 於是乎產出了第一個電路及程式: LED switch

材料
Switch x 1 (微動開關)
LED x1
Resistor 330Ω (for LED)
Resistor 10KΩ (for Switch)

製作
< 參考「Arduino互動設 計入門2」- p4-8, p4-12, p4-14 >
紅色線: 高電位/電源
黑色線: 低電位/接地
白色線: 輸出 or 輸入
要注意上拉(pull-up)電阻與下拉(pull-down)電阻的選用與接法不同:


圖左為下拉電阻接法, 右圖為上拉電阻接法; 電路圖如下:

程式如下:
const byte SWITCH = 10;
const byte LED = 16;

//boolean lastState;

void setup() {

//  lastState = LOW;
  
  pinMode(SWITCH, INPUT);
  pinMode(LED, OUTPUT);
  pinMode(LED_2, OUTPUT);
  
  digitalWrite(LED_2, LOW);
}

void loop() {
    boolean click = false;
    boolean currentState = digitalRead(SWITCH); // pull-down circuit, use NOT when using pull-up circuit

    if (currentState != lastState) {
      delay(20);
      currentState = digitalRead(SWITCH); // pull-down circuit, use NOT when using pull-up circuit
      
      if (currentState != lastState) {
        click = true;
        lastState = currentState;
      }
    }
    
    if (click) {
      digitalWrite(LED, currentState );
    }
}

程式以下拉電阻接法寫的, 若為上拉電阻接法, 只要將其中
    ... = digitalRead(SWITCH);

改為
    ... = digitalRead(! SWITCH);

即可.

done!

ps.
「Arduino互動設 計入門2」- p4-16 的程式寫法會嚇到初學者的

2014年4月19日

Upgrade subversion 第二彈

自從 upgrade 至 Mavericks 後, 大多不太敢將開發工具也一起 upgrade, 必竟編譯環境並非像這些軟件更新的這麼快。

以個人的工作平台為例:
Mavericks  +  GGTS v3.5.0(Eclipse v3.8.2)  +  Xcode v5.1  +  JDK 1.7.0_51

對於更新 JavaHL native lib 以整合 subversion eclipse plug-in v1.7.x,過去雖有經驗,但仍無法使用 Homebrew 順利安裝,發生的問題有二:
  1. 安裝 subversion v1.7.10 時, 無法取得 serf
  2. 安裝 subversion17 (v1.7.14) 時, 無法載入 zlib
不免要花上一些時間來解決。而這狀況有點像是綜合了前兩篇所提到的問題:
但,索性有過這樣子的經驗後,找到了解決的方法:
  1. 解開 subversion17 安裝時留下來的壓縮檔
  2. 手動進行編譯
  3. 產生 java.library.path 路徑內的 lib 連結
做法如下:
cd /tmp
cp /Library/Caches/Homebrew/subversion17-1.7.14.tar.bz2 .
open subversion17-1.7.14.tar.bz2
cd /tmp/subversion-1.7.14
確認 java --version 為 1.7.0
make clean
./configure --prefix=/usr/local/Cellar/subversion17/1.7.14 --with-apr=/usr/bin --with-zlib=/usr/local --with-sqlite=/usr/local/opt/sqlite --with-serf=/usr/local/opt/serf --disable-mod-activation --disable-nls --without-apache-libexecdir --without-berkeley-db --enable-javahl --without-jikes
修改 Makefile:
...
JAVAC_FLAGS = -target 1.7 -source 1.7
...
再進行安裝:
make install-javahl
make install
cd /Library/Java/Extensions
sudo ln -sf /usr/local/Cellar/subversion17/1.7.14/lib/libsvnjavahl-1.dylib
sudo ln -sf /usr/local/Cellar/subversion17/1.7.14/lib/libsvnjavahl-1.jnilib
打開 GGTS, 設定 [Team]/[SVN]/[SVN interface]:

that's it.

2014年4月7日

IPO

IT 領域中, input --> process --> output 是基本結構

社會層面上, "法(條)" 是 "法治化" 的結果;
就邏輯上而言, 法治化是 process , 法(條)是 output

那 input 是什麼呢?!

若從 IT 技術上來看, Garbage in 就會 garbage out

換句話說, 對於目前政經問題(服貿協議法治化/太陽花學運), 我們更該注意 input 到法治化過程中的內涵

2014年1月23日

BeanUtilsBean 的小小應用 2

在利用 BeanUtilsBean 的一點小技巧來解決部份 property 不做 copyProperties() 的需要之後。
如果處理 BigDecimal 的 property 賦值, 而其值為 null 時, 會出現...
Exception in thread "main" org.apache.commons.beanutils.ConversionException: No value specified
at org.apache.commons.beanutils.converters.BigDecimalConverter.convert(BigDecimalConverter.java:...)
...


解決問題前, 先從 BeanUtils 取得 BeanUtilsBean.getInstance() 來處理 copyProperties() 的 source 中看到:

    private static final ContextClassLoaderLocal beansByClassLoader = new ContextClassLoaderLocal() {

        protected Object initialValue() {
            return new BeanUtilsBean();
        }
    };

實際是使用了預設的 BeanUtilsBean() constructor:

    public BeanUtilsBean() {
        this(new ConvertUtilsBean(), new PropertyUtilsBean());
    }

    public BeanUtilsBean(ConvertUtilsBean convertUtilsBean, PropertyUtilsBean propertyUtilsBean) {
        this.log = LogFactory.getLog(BeanUtils.class);
        this.convertUtilsBean = convertUtilsBean;
        this.propertyUtilsBean = propertyUtilsBean;
    }
明顯的看到它使用了預設的 ConvertUtilsBean() constructor, 並在 deregister() method 中建構各類型的 converter 以便爾後的 properties 賦值處理:

    public ConvertUtilsBean() {
        this.converters.setFast(false);
        deregister();
        this.converters.setFast(true);
    }
    ...
    public void deregister() {
        ...
        register(BigDecimal.class, new BigDecimalConverter());
        ...
    }
    ...
但, 當中 BigDecimalConverter() constructor 是不預設賦值的:
    public BigDecimalConverter() {
        this.defaultValue = null;
        this.useDefault = false;
    }
另一 constructor 則是:
    public BigDecimalConverter(Object defaultValue) {
        this.defaultValue = defaultValue;
        this.useDefault = true;
    }
也就是說, 可以使用另一組 BigDecimalConverter() constructor 來避免上述的 exception 發生:
    BeanUtilsBean defaultNullValueBeanUtils = new BeanUtilsBean(new ConvertUtilsBean() {

        @Override
        public void deregister() {
            super.deregister();
            // 這裡還是預設了 null 為其值
            register(new org.apache.commons.beanutils.converters.BigDecimalConverter(null), BigDecimal.class);
            ...
        }
    }, new PropertyUtilsBean());
    ...
    defaultNullValueBeanUtils.copyProperties(dest, orig);
    ...
done!