2014年12月29日 星期一

Javascript: 直接使用 HTML 的 Option 值

最近幫一位前輩修改他的網頁,當中用到 SELECT 元件;希望在點擊後會把值傳送到 Javascript 那邊。之前用慣了 this.selectedIndex,今次卻因為設計的緣故不能用 Index 值,需要改為 this.options[this.selectedIndex].value。
<select class="menu" onchange="onClickMenu(this.options[this.selectedIndex].value);">
 <option value="#ancla0" selected="selected">我们的故事</option>
 <option value="#ancla1" class="second_item">课程</option>
 <option value="#ancla2" class="second_item">活动</option>
 <option value="#ancla3" class="second_item">日记</option>
 <option value="#ancla4" class="second_item">联系</option>
</select>

2014年12月25日 星期四

縮時拍攝失敗


聖誕假期到韓國滑雪,順道希望拍攝縮時影片,所以趕製縮時拍攝裝置。腳架帶了、小米電池帶了、縮時拍攝裝置也都帶了。似乎萬無一失,可是卻偏偏拍攝不成。問題出在可惡的小米電池。

當晚在酒店房間,架好腳架、裝好縮時拍攝裝置、接上小米電池,也利用藍牙透過 iPad 設定好拍攝的數值。豈料,小米電池在供電一會後自動停止。電量是滿滿的,充 iPhone 也沒有問題。之前試過 WeChat 送的電池運作量好,估不到買的小米電池卻有這樣的問題。在沒有帶後備電池的情況下,唯有放棄。改為拍攝星星,不過渡假村也實在太光了,雖然影到星星,但光害在相片中也挺高。

2014年12月19日 星期五

趕製《縮時拍攝裝置》・五


代碼雖然完成,但從 iPad 發過去的訊號都變成亂碼,這是 baud rate 不正確所致。記得曾聽聞過 BLE mini 在某個版本之後,靜悄悄地把 baud rate 改了。於是我從最大的 115200 逐個逐個嘗試,到 9600 還是亂碼。向 Peter 老師請教後,估計有兩個情況有可能導致問題發生。一是 BLE mini 壞了,二是韌體問題。我發現還有第三個可能性,是沒有設定端口的方向。不過後來證實了是不用設定方向。檢查韌體,發現版本是 2013 年的,舊了點。下個最新版本並安裝好後,所有部份回愎正常。


還有點時間,繼續設計外觀。造了一個相機接口,可是要很花力氣才能連接。唯有暫時頂檔。

2014年12月18日 星期四

趕製《縮時拍攝裝置》・四


把最後的 BLE mini 也焊接好後,零件部份已經完工。接著是外殼及軟件部份。而軟件部份又分為 Arduino 端及 iOS 端。iOS 端目前可以用《AMIGO Controller》來頂上。外殼內部空間加大了,底板沒有卡著。加高了筒的尺寸,耳機接口有足夠空間。同時也留了放置電線的地方。接著搞 Arduino 部份。

在紙上考慮好需要的指令,定義出相關的參數,以最簡單的方式編寫 Arduino 程式。雖然 delay 指令會佔領著時間,無法做出分工工作,但時間緊迫,暫時使用。以下是目前為止的代碼:
//========================================================================
//  AMIGO Timelapse for Arduino
//------------------------------------------------------------------------
//  Created by Pacess on 2014-12-17
//  Copyright (c) 2014 Hotaru Productions Company.  All rights reserved.
//========================================================================

//------------------------------------------------------------------------
//  0    1         2         3         4         5         6         7
//  5678901234567890123456789012345678901234567890123456789012345678901234

#include <SoftwareSerial.h>

//------------------------------------------------------------------------
//  Command list
//------------------------------------------------------------------------
//   ! means end of command
//
//   Input:  Capital letters for Bluetooth to Arduino
//     O!     = Shutter open
//     C!     = Shutter close
//     F!     = Focus
//     O0000! = Set shutter open duration
//     C0000! = Set shutter close duration
//     R!     = Reset frame counter
//     I!     = Get current information and settings
//     G!     = Go according to the settings
//
//   Output:  Small letters for Arduino to Bluetooth
//     f0000o0000c0000! = Frames taken, Shutter open duration, Shutter close duration
//------------------------------------------------------------------------

//  Defines
const int PORT_LED = 13;

const int PORT_BLUETOOTH_RX = 10;
const int PORT_BLUETOOTH_TX = 11;

const int PORT_SHUTTER = 4;
const int PORT_FOCUS = 3;

const int ONE_SECOND = 1000;

const unsigned int BAUDRATE_ARDUINO = 57600;
const unsigned int BAUDRATE_BLUETOOTH = 57600;

//------------------------------------------------------------------------
//  Global variables
SoftwareSerial bluetoothSerial(PORT_BLUETOOTH_RX, PORT_BLUETOOTH_TX);

int ledValue = HIGH;

//  1 = One second
unsigned int shutterOpenDuration = 1;
unsigned int shutterCloseDuration = 59;
unsigned int framesTaken = 0;

//========================================================================
void setup()  {
   pinMode(PORT_LED, OUTPUT);
   pinMode(PORT_FOCUS, OUTPUT);
   pinMode(PORT_SHUTTER, OUTPUT);

   //  Make sure pin is low
   digitalWrite(PORT_FOCUS, LOW);
   digitalWrite(PORT_SHUTTER, LOW);
   delay(ONE_SECOND/4);

   //------------------------------------------------------------------------
   //  Open onboard serial communication
   Serial.begin(BAUDRATE_ARDUINO);

   //  Wait for serial port to connect.  Needed for Leonardo only
   while (!Serial);
    Serial.println("AMIGO Timelapse is ready!");

   //  Set my data rate for SoftwareSerial port
   bluetoothSerial.begin(BAUDRATE_BLUETOOTH);
   bluetoothSerial.println("AMIGO Timelapse connected.");
}

//------------------------------------------------------------------------
//  Toggle LED light
void toggleLED()  {
   if (ledValue == HIGH)  {ledValue = LOW;}
   else  {ledValue = HIGH;}
   digitalWrite(PORT_LED, ledValue);
}

//------------------------------------------------------------------------
char readSerialByte()  {
   char data = 0;
   while (1)  {
      if (bluetoothSerial.available())  {data = bluetoothSerial.read();  break;}
      else if (Serial.available())  {data = Serial.read();  break;}
   }

   Serial.write(data);
   return data;
}

//------------------------------------------------------------------------
void openShutter()  {
   toggleLED();
   digitalWrite(PORT_SHUTTER, HIGH);
}

//------------------------------------------------------------------------
void closeShutter()  {
   toggleLED();
   digitalWrite(PORT_SHUTTER, LOW);
}

//------------------------------------------------------------------------
void focusNow()  {
   toggleLED();
   digitalWrite(PORT_SHUTTER, HIGH);  delay(ONE_SECOND);
   digitalWrite(PORT_SHUTTER, LOW);
}

//------------------------------------------------------------------------
void loop()  {

   //  Read byte from serial ports
   char dataByte = readSerialByte();

   //------------------------------------------------------------------------
   //  Process command
   switch (dataByte)  {

      default:  {
         //Serial.print("# ");  Serial.println(dataByte, DEC);
      }  break;

      //------------------------------------------------------------------------
      case 'O':  {
         dataByte = readSerialByte();
         if (dataByte == '!')  {

            //  This is an immediate action (O!)
            openShutter();
            Serial.println("OK");
            break;
         }

         //  This should be setting (O0000!)
         unsigned int value = 0;
         do  {

            value = (value<<8)|dataByte;

            //  Read the rest bytes
            dataByte = readSerialByte()-'0';

         }  while (dataByte != '!');
         shutterOpenDuration = value;

         Serial.print(shutterOpenDuration, DEC);  Serial.println(" OK");
      }  break;

      //------------------------------------------------------------------------
      case 'C':  {
         dataByte = readSerialByte();
         if (dataByte == '!')  {

            //  This is an immediate action (C!)
            closeShutter();
            Serial.println("OK");
            break;
         }

         //  This should be setting (C0000!)
         unsigned int value = 0;
         do  {

            value = (value<<8)|dataByte;

            //  Read the rest bytes
            dataByte = readSerialByte()-'0';

         }  while (dataByte != '!');
         shutterCloseDuration = value;

         Serial.print(shutterCloseDuration, DEC);  Serial.println(" OK");
      }  break;

      //------------------------------------------------------------------------
      case 'F':  {
         dataByte = readSerialByte();
         if (dataByte != '!')  {break;}

         focusNow();
         Serial.println("OK");
      }  break;

      //------------------------------------------------------------------------
      case 'R':  {
         dataByte = readSerialByte();
         if (dataByte != '!')  {break;}

         framesTaken = 0;
         Serial.println("OK");
      }  break;

      //------------------------------------------------------------------------
      case 'I':  {
         dataByte = readSerialByte();
         if (dataByte != '!')  {break;}

         bluetoothSerial.print("f");
         bluetoothSerial.print(framesTaken, DEC);
         bluetoothSerial.print("o");
         bluetoothSerial.print(shutterOpenDuration, DEC);
         bluetoothSerial.print("c");
         bluetoothSerial.print(shutterCloseDuration, DEC);
         bluetoothSerial.println();

         Serial.print("f");
         Serial.print(framesTaken, DEC);
         Serial.print("o");
         Serial.print(shutterOpenDuration, DEC);
         Serial.print("c");
         Serial.println(shutterCloseDuration, DEC);
      }  break;

      //------------------------------------------------------------------------
      case 'G':  {
         dataByte = readSerialByte();
         if (dataByte != '!')  {break;}

         bluetoothSerial.print("Start ");
         bluetoothSerial.print(shutterOpenDuration, DEC);
         bluetoothSerial.print(" vs ");
         bluetoothSerial.print(shutterCloseDuration, DEC);
         bluetoothSerial.println();

         Serial.print("Start O");
         Serial.print(shutterOpenDuration, DEC);
         Serial.print(" vs C");
         Serial.print(shutterCloseDuration, DEC);
         Serial.println();

         framesTaken = 0;
         while (1)  {

            Serial.print("Open #");
            Serial.println(framesTaken, DEC);

            openShutter();
            delay(shutterOpenDuration*1000);

            Serial.print("Close #");
            Serial.println(framesTaken, DEC);

            closeShutter();
            delay(shutterCloseDuration*1000);

            framesTaken++;

            if (bluetoothSerial.available())  {break;}
            else if (Serial.available())  {break;}
         }
         Serial.println("OK");
      }  break;
   }
}

2014年12月17日 星期三

趕製《縮時拍攝裝置》・三


零件位置大概有個預算了,接著是外殻的鍊成。在《Inventor》畫了一個圓筒設計,蓋也畫了,同時也打印了。筒蓋接合得非常好。不過,有太多空間浪費了。於是畫了一個新的方型筒。打印出來後,發現左右那 0.5mm 的工差位是不夠,底板還是卡著,使出大一點力氣才能把底板推進筒中,而且耳機接口的空間也不足。有待改善。由於時間緊迫,還是把底板的零件焊接一起。明天還要重寫 Arduino 程式。

2014年12月16日 星期二

趕製《縮時拍攝裝置》・二


一年前打算趕製《縮時拍攝裝置》,最後都趕不上,項目一直閣置沒有理會。一年後的今天,在快要出發韓國時,又再燃起決心。外觀及軟件重新製作,只有三天時間,今回趕得切嗎?

上年外觀設計出來的實物,體積過大,放在相機上方顯得累贅,需要精簡空間。於是先從底板入手,把零件放得密一些,把 Arduino 及 BLE mini 置得貼一些,省下空間。找到了一個最迫而又對稱的設計。我喜歡對稱的美。

2014年12月12日 星期五

在 Mac 安裝 ffmpeg

公司快將推出一款包含很多影片資訊的流動應用程式。有大量的影片需要處理,例如:縮細解像度、檔案格式轉換、加入字幕、放置水印、影片剪接、製作預覽版本...等。為了能更有效處理這些事情,我選用了 ffmpeg 來幫忙。要在 Mac 機上安裝 ffmpeg 不難。首先到 http://ffmpegmac.net/ 下載最新版本,解壓並把檔案拷貝到 /usr/sbin/ 內。這樣便能在 Terminal 下執行 ffmpeg。

2014年12月11日 星期四

AMIGO Arm 設計・五


一覺醒來,物料沒有卡著,打印工作順利完成。看來手動把物料理順後,打印才變得安心。第一次印 30 度斜板,雖然有點方格紋理冒起,效果還是能夠接受。在沒有打印支架的情況下,仍然能保持型狀已經不錯。在放入 Futaba S3003 時,才發現設計時遺漏了置入時的空間及考慮,變得根本無法放入馬達 (T_T)。手術成功,但病人死了。今次又吸收了一點設計經驗。下次努力!

2014年12月10日 星期三

AMIGO Arm 設計・四


今日嘗試設計底座,盡量不以板金方式思考,因而得出這個設計。目前在打印中。單單一層圓盤就得花上 25 分鐘時間。看來打印完整個模型要七個小時。一覺起來便打印完成,如果唔卡料的話...。

2014年12月9日 星期二

AMIGO Arm 設計・三


邊設計邊製作的《AMIGO Arm》現在長成這個樣子了。有點像 Cute 版機械人。頂方還要接上手腕及蟹蚶手。不過,稍為嫌長度不久。組合完成後拿不到遠一點的東西。還有馬達數量應該可以再減少。再想想...。

2014年12月8日 星期一

創富媒體 13:女孩商機


文章刊登於「創富媒體

很多時都聽到一句說話「女人錢很容易賺」。我是相信的。同時,我亦很想開發出一套女性向的遊戲,賺這些女人錢。然而,靈感這樣東西不是想便一定會有;所以到目前還是空想。不過,最近我卻發現到一套遊戲,體現了這個想法。

大女剛踏入八歲,受到同學的感召,迷上了《星光少女 Pretty Rhythm》的《星光寶石 Prism Stone》。根據網上資料顯示,《星光少女》是日本玩具廠商 Takara Tomy、Syn Sophia 與南韓孫悟空玩具公司聯合製作的女性向跨媒體製作專案。於 2010 年 7 月 15 日推出。當中包含動畫、漫畫、大型遊戲機及手提遊戲項目。遊戲是以唱歌跳舞為主的節拍類玩法。遊戲是免費的。而《星光寶石 Prism Stone》則是放在大型遊戲機上使用的道具;最少一顆,最多五顆才能進行遊戲。跟網絡遊戲的設計一樣,每粒寶石擁有不同的服飾、舞蹈及能力。有些寶石是稀有的。寶石分為不同的包裝,最便宜的是一包兩顆;六粒裝、十粒裝的也有;甚至一套完整五粒的套裝也有。從包裝外看不出是甚麼寶石,抽到甚麼就看運數了。一顆平均 HK$15 的寶石,稀有版本可以炒賣到 HK$90 一顆。難怪有女孩告訴我曾用一顆寶石換來五顆。

一個用來放置寶石的膠盒,沒有寶石的,索價 HK$298。有了這個盒是很方便,值不值得真是見仁見智。然而,我面前的女孩身上已經帶著三個。每個都放滿寶石。更說家中還有部分沒有帶來。有這個財力之餘,也十分願意花錢。

這個生意還有一個特別之處,就是遊戲機的地點不多,全香港只有 49 台,賣寶石的地方不代表一定會有遊戲機出現。變相買了也有機會用不到。我曾試過帶女兒到有遊戲機的地方,可是一天兩節,每節只有兩小時的時段已過,沒有得玩。這應該是老闆想出來的鬼主意。因為她跟我說:「現時買包十粒裝的話,我可以立即開機給你,每個女兒可玩一局」。也曾試過到達店舖,但遊戲機壞了。老闆還叫我買點寶石而被我大罵。甚至按照店舖清單去過一個地點,那文具店已結業多時。得物無所用。

最終在父母家附近找到一家長開遊戲機的文具店,可是人龍有十人以上。每個女孩手上都有很多寶石,最少都有二三十粒。遇上裝備利害,身手靈活的女孩,一局遊戲花上五分鐘並不出奇。十個人便要等上五十分鐘,但還是大排長龍。女孩告訴我,現時已經少了人玩,高峰時人龍是目前的兩倍。可見這個遊戲的吸引之處。

2014年12月6日 星期六

BeyondZ 誠聘人才


Project Manager

Responsibilities
  • Work closely with project team to develop mobile applications
  • Brainstorm, develop and contribute to BeyondZ projects
  • Documentation, testing and quality assurance of the developed apps
     
    Requirements
  • Experience in Project Management
  • Experience in leading a programmer team
  • Experience interfacing Apps to server-side APIs
  • Experience building UI and Core App infrastructure
  • Experience with HTTP, XML, JSON, and Web Services via REST
  • Experience with multiple mobile platforms (iOS, Android, Blackberry, Windows mobile) is a strong plus
  • BS degree in Computer Science or equivalent
  • One or more Apps available for download
  • Know any programming language is plus
  • API and/or SDK development is a big plus
     
     
    Marketing Executive

    Responsibilities
  • Planning, advertising, distribution, sponsorship and research of BeyondZ mobile apps
  • Account services / management of clients' projects
  • Follow up the full set of project process and documentations
  • Feedback on consumers' comments
  • Exhibition / Roadshow Management
     
    Requirements
  • Work with passion
  • Creative and positive thinking
  • Degree holder or tertiary education
  • Strong interest in mobile industry
  • Spoken language : English, Cantonese and Potunghua
     
     
    Senior Mobile Apps Developer

    Responsibilities
  • Work closely with project team to develop mobile applications
  • Brainstorm, develop and contribute to BeyondZ projects
  • Documentation, testing and quality assurance of the developed apps
     
    Requirements
  • Solid Java programming
  • Experience interfacing Apps to server-side APIs
  • Experience building UI and Core App infrastructure
  • Experience with HTTP, XML, JSON, and Web Services via REST
  • Experience with other mobile platforms (iOS, Blackberry, Windows mobile) is a plus
  • BS degree in Computer Science or equivalent
  • 3-5 years of Android application development experiences
  • One or more Apps available for download
  • API and/or SDK development is a big plus
  • Candidates with less experience will be considered as Junior Mobile Apps developer
     
     
    Graphics Designer

    Responsibilities
  • Prepare mobile apps graphics for programmers
  • User interface design
  • Website design
  • Facebook apps graphics design
  • Other promotion materials design
     
    Requirements
  • Willing to learn
  • Good art and color senses
  • Passionate about drawings
  • Self motivated and able to work independently
  • A team player with good interpersonal and communication skills
  • Willing to work under pressure and work overtime to meet tight project schedule
  • Hands on experiences in iOS / Android / Facebook application is a strong plus
  • 3D modelling technique is a strong plus
  • 2014年12月5日 星期五

    ArrayZ 推料馬達問題


    AMIGO Arm 的中間部份設計好了,本想打印出來;可是 ArrayZ 再次出現問題。在列印的過程出,膠料沒有被推出。原因是推料的馬達無故地抽搐。亦即是推了少少又回抽少少。所以沒有物料能順利推出。經過一番檢查之後,發現是推料馬達的訊號線跟底板接觸不良。修理過後,目前運作良好。不過,在沒有搬動過的情況下,接線也會發生接觸不良的話,加上物料線又會出現打戟現象,打印起來還真是提心吊膽。看來 ArrayZ 要面向大眾用戶群時,還要有待改進。要是想簡簡單單使用的話,還是選 Makerbot 好一點。

    2014年12月4日 星期四

    AMIGO Arm 設計・二


    繼續 AMIGO Arm 的開發。今天打印的是底部關節。原本預留了 1mm 工差,但打印出來後卻容不下圓碟,唯有把工差加大至 2mm。重新打印。今次成功了。


    考慮了打印時地心吸力引發的問題,在設計時已經沒有加入枝節類的物件;同時要讓碟盤平坦,打印時要反過來打印。圓角的斜度也不能太高,否則將會打印失敗。

    2014年12月3日 星期三

    AMIGO Arm 設計


    ArrayZ 修復完畢。Windows 7 重灌了。Inventor 也裝好了。可以繼續開發工作。繼續以回收箱內的零件設計《AMIGO Arm》。對於整隻手臂沒甚麼頭緒,唯有邊畫邊改邊試。但還是有點想法,部件不要太過板金,需要多一點立體感。不過,原來這樣的設計不易,尤其是立體打印機能打印到出來的話,需要考慮的事情更多、限制更大。


    繪畫了部件,利用立體打印機打印。需時 4 小時,隔晚打印。早上起來,物料再次卡住,導致打印完成,但部件沒完成。雖然如此,還是可以利用部件試試尺寸及位置是否適當。0.5 豪米的出血位十分好用。部件跟伺服馬達配合得相當完美。沒有修改的必要。只要進料順利,便能成功打印兩個部件,組成下臂。