2016年4月19日火曜日

Open Hack Day 2016で作った作品の紹介

Open Hack Day 2016 の展示会

先日、ヤフー株式会社が主催したOpen Hack Day の展示会に出展してきました。Open Hack Day当日に体調を崩してしまったため出場を断念したので、開発する予定だった作品を後日の展示会に向けて制作し、披露してきました。

この展示会は、Open Hack Dayで開発した作品を展示するという内容でした。

自転車に合わせて景色が動く

作った作品はこちら。一緒に出場したメンバが動画にまとめてくれました。


自転車を漕ぐとセンサが回転したことを読み取り、漕いだタイヤの回転速度に応じて映像が進行します。自転車のブレーキを掛けてタイヤが止まると映像も静止します。

複数台のプロジェクタで部屋一面に映像を投影し、部屋に居ながらにして違う場所の景色の中をサイクリングできたら楽しいだろうなという発想です。今回はTheta Sで撮影した映像を素材として使っていますが、コンピュータグラフィックスで作られたファンタジの世界を冒険できたら素敵ですね。
また、スポーツジムなどで自転車を漕いだり、ランニングしたりするマシンがありますが、同じ景色ではなく景色が変わったら運動もより一層捗るのではないかと思います。

展示では、諸事情の関係でプロジェクタの投影ではなくノートPCでの表示となっております。

センシングの仕組み

自転車にホールセンサ(磁気センサ)を取り付け、後輪ホイールの各所にネオジウム磁石を取り付けます。ホールセンサは磁石が近づくと反応します。ネオジウム磁石が近づく度に反応するため、その周期から速度を算出します。シリアル通信でPCに値を送信します。

映像はUnity

Theta Sで撮影した映像をUnityにMovieTextureとしてSphereオブジェクトに割り当てます。SerialPortでセンサから速度を取得し、それに応じてMovieTextureの再生速度を変えています。
Unityによって映像を作成しているため3次元情報を持っています。カメラオブジェクトを複数個設けることで複数台のプロジェクタにそれぞれの角度の映像を投影できます。また、ゲームの箱庭世界を冒険することや、OculusなどのVRデバイスに入力することにもつなげられます。

まとめ

今回は、Open Hack Dayの展示会で自転車を漕ぐと、その速度に合わせて映像が動く作品を展示しました。

2016年3月30日水曜日

UnityとAVRのUSART シリアル通信とReadLineで問題

概要

Unityからシリアルポートの入出力を行います。入出力先はAVRマイコンです。AVRマイコンはUSART機能を使って通信を行います。

これまで

UnityのC#ではなく、通常のWindows .NetFrameworkでシリアル通信を実装してきました。(最新バージョンの.Netでも.Net2.0でも正しく動作しました。)

Unityでシリアル通信

Unity(mono)と.Netの違いはあるとはいえ、同じ実装でシリアル通信できるはずです。
ただし、使用するフレームワークを.Net2.0に指定しなければいけません。
ツールバのEditor→Project Settings→PlayerからApi Compability Levelを.Net2.0にします。
.Net2.0を選択

ReadLineで通信が途絶える問題

基本的には通常のC#の実装と同じです。しかし、次の問題に遭遇し、苦労しました。(おそらくUnityに付属するライブラリに問題があると思われます。)
  • SerialPort#ReadLine() で入力できない。
ReadLine()を実行する場所で止まってしまいます。また、タイムアウトするように設定したら、毎回タイムアウトしてしまいます。

1バイトずつ読みこむように変更

SerialPort#ReadLine()は文字通り、改行コードまでの1行を取得するメソッドです。
AVRマイコン側も
    uint16_t hallCount = 0;
・・・・
    printf("%d\n", hallCount);
とprintf()で改行コードを書き出しているため問題ないはずです。ところが、通信が止まってしまいます。
そこで、諦めて1バイトずつ入出力するようにしました。

  • AVR側は、16bit int型をビットシフトして1バイトずつ2回に分けて送信レジスタに登録する。
  • C#側はSeralPort#ReadByte()メソッドを使って2回に分けて取得する。
C#のコードは前回実装したコードと同じですが、次の変更を行いました。
var high = serialPort.ReadByte();
var low = serialPort.ReadByte();
var val = (high << 8) + low;
また、AVRのコードもこのように1バイトずつ書き込むように変更しました。

これで通信ができるようになりました。

まとめ

Unityでシリアル通信をするとき、SerialPort#ReadLine()では通信が止まってしまうため、ReadByte()で1バイトずつ通信することで問題を回避しました。

2016年3月22日火曜日

基本: AVRのUARTとC#でシリアル通信 (受信割り込み)

概要

今回は、AVRでUSART受信割り込みを使ったプログラムを作成したいと思います。

要件

  • AVRはPCから送信された値を受信し、受信割り込みを発生する。
  • 受信割り込み時に"echo back: <val> \n"という文字列をPCに送信できる。
  • <val>はPCから送信された値で置換する。

準備

ハードウェア

もちろんこれは必須ではなく、AVR168Pもしくはこれと互換性のあるAVRマイコンとFT232RLが実装されており、USBでパソコンと接続できればOKです。
AVRとFT232RLの取り付けの解説は割愛しますが、次のように実装します。
  • AVRのTXDとFT232RLのRXDが接続されている。
  • AVRのRXDとFT232RLのTXDが接続されている。
AVRとFT232RLを使ったUSB-シリアル通信の実験に解説されているとおりです。

ライブラリ

UARTを使った処理をかんたんに実装するために、次のコードを実装しました。初期化と読み書き、割り込み処理といった基本的なレジスタ操作をまとめたものです。

開発

AVR

dev3/usartsample/main.cを作成しました。割り込みなしのコードとほぼ同じですが、割り込み設定をしている箇所が異なります。
/**
* 受信割り込み発生時に実行される関数
* @param data 受信データ
*/
void rxEventListener(uint8_t data) {    
    printf("echo back: %d \n", data);
}

int main(void) {
    // 受信割り込みありでUSARTを初期化(8MHzクロック時, 9600ボーレート)
    USART_init(RX_COMPLETION_INTERRUPT, 51);

    // 受信割り込み発生時に実行する関数を登録
    USART_setRxCompletionInterruptListener(*rxEventListener);

    // printfで使用する関数を登録
    fdevopen(*USART_sendData, NULL);

    // 割り込み全許可
    sei();

    printf("Initialized>>\n");
    while (1) {
    }
}
  • UCSRnBレジスタのRXCIEn(7bit目)を1(true)にして、受信割り込み許可を行っています。(該当コード
  • 割り込みベクタUSART_RX_vectで受信割り込みを駆動できます。(該当コード)
  • 初期化しても、sei()を唱えないと割り込みは発生しません。
これで、PC側からの値に応じて、処理を変えたり、レスポンスする内容を変更したりできますね。

C#

前回同様にSerialSample/Program.csを使用します。

基本: AVRのUARTとC#でシリアル通信

概要

AVRとPC間でシリアル通信する方法を確認しました。AVRでは、UART機能を使用し、C#では.NetFrameworkのSerialPortクラスを使用して実現します。
ここでは、通信の基本であるエコーバックを実装し、通信のやり方を確認します。

準備

ハードウェアの準備

もちろんこれは必須ではなく、AVR168Pもしくはこれと互換性のあるAVRマイコンとFT232RLが実装されており、USBでパソコンと接続できればOKです。

AVRとFT232RLの取り付けの解説は割愛しますが、次のように実装します。
  • AVRのTXDとFT232RLのRXDが接続されている。
  • AVRのRXDとFT232RLのTXDが接続されている。
AVRとFT232RLを使ったUSB-シリアル通信の実験に解説されているとおりです。

ライブラリ

UARTを使った処理をかんたんに実装するために、次のコードを実装しました。初期化と読み書き、割り込み処理といった基本的なレジスタ操作をまとめたものです。

サンプル

単純なエコーバック

  • パソコンから文字をAVRに送信する。
  • AVRは受信した文字のアスキコードをエコーバックする。

AVR

これを実現するために、AVRで実装したコードはdev1/usartsample/main.cです。

int main(void) {
    # USARTを初期化します。割り込みなし,ボーレート9600
    USART_init(NOMAL, 51);

    # printfをするときはUSART_sendData関数を利用するように登録します。
    fdevopen(*USART_sendData, NULL);

    # printfしてみます。
    printf("Enter>>\n");

    # 以下、データを受信して、受信したデータを送信するエコーバックを繰り返します。
    while (1) {
        uint8_t val = USART_recieveData();
        printf("%d\n", val);
    }
}


  • USART_initの2つ目の引数51はボーレート設定値を示します。
    • クロック8MHz動作時で9600のボーレートです。
    • データシートに値の設定方法が解説してありますので、参照してください。
  • fdevopen()でUSART_sendData関数を登録することでprintfを使えるようにしています。

C#

VisualStudioからC#プロジェクトを作成します。今回はコンソールアプリケーションとします。
コンソールアプリケーションの作成(C#)

SerialPortクラスを使用して、Read&Writeを行うプログラムを実装します。( SerialSample/Program.cs )

            if (!serialPort.IsOpen) {
                serialPort.Open();
            }

            while (true) {
                string val = System.Console.ReadLine();               
                serialPort.Write(val.Substring(0, 1));
                var readVal = serialPort.ReadLine();
                System.Console.WriteLine(readVal);
            }

  • AVR側は複数バイトの受信に対応していないため、Substringメソッドで先頭文字だけ抽出しています。
  • SerialPort.Write()で書き込み、SerialPort.ReadLine()で\nまで読み込みます。

実行結果

次のように、入力した文字に対するアスキーコードを返しています。アスキーコード表で確認すると正しくレスポンスされていることがわかります。
実行結果

補足

今回、C#でシリアル通信の実装を確認するためC#で通信を実装しましたが、TeraTermを用いても等価のことを実行できます。

2016年3月13日日曜日

Unity5 ThetaSの画像をSkyboxで動的にアニメーション

ThetaSの映像を動的アニメーションで表示したい


360度カメラThetaSで撮影した映像をUnityに取り込んで表示したいです。

要件

要件は次の通りです。
  1. 1人称視点でカメラの向きに応じた角度の映像を見れる。
  2. プログラムから映像の再生をコントロールできる(再生、停止、x倍速再生など)。
1.の要件だけであれば「360度カメラthetaで撮った写真をunityで使う」のやり方で実現できます(このブログエントリでは、Blenderで円球を作っていますが、通常のSphereでもこだわりを捨てれば問題ないと思います。)。
しかし、1.のやり方では、通常の再生のみで2.の再生をコントロールすることができません。現状、MovieTextureでは動画の再生コントロールには対応していないからです。

方針

  • 動画の各フレームを静止画に変換し、静止画のテクスチャを高速で切り替えることでアニメーションを実現する。
  • Sphereマテリアルではなく、Skyboxにアニメーションを投影する。
現状、MovieTextureによる動画の再生コントロールができないようです。そこで、ThetaSで撮影した360度動画の各フレームを静止画として出力して、高速で切り替えることによって上記の要件を実現します。静止画を割り当てたテスクチャを切り替えはプログラムからコントロールするため再生速度などの変更も可能と言えるでしょう。

また今回は、ThetaSで撮影した素材をSkyboxに割り当てます。他のオブジェクトを設置しやすくなるからです。(夜空のThetaS映像をSkyboxで投影し、UFOなどのオブジェクトが動いていたら素敵です。)

早速 作ってみましょう。

Theta Sの360度動画を静止画群に変換

Adobe PremiereとAdobe Media Encoderで動画の各フレームをJPEG画像に変換しました。
ThetaS動画を出力した静止画群

画像群をUnityに取り込み

作成した360度画像群をUnityに取り込みます。一つのディレクトリにまとめてます。
画像群を取り込み

取り込み後はテクスチャをCubeMapとして設定します。すべての画像を選んで、[Unity4,Unity5]thetaとかで撮った全球画像をSkyboxに指定する方法を適応します。すべての画像がCubeMap Typeとして設定されるまでしばらく時間がかかるかと思います。
取り込んだ全ての画像をCubemapテクスチャにする

Skyboxの作成とMain Cameraへアタッチ

  1. 新規マテリアルを作成し、Shaderを「Skybox/Cubemap」にします。
  2. HierarchyでMain Cameraを選択し、InspectorのAdd Componentボタンを押します。
  3. Rendering→Skyboxを選び、Skyboxコンポーネントを追加します。
  4. Custom Skyboxに1.で作成したSkyboxをドラッグし、設定します。
Skyboxを作成し、Main Cameraに登録

スクリプトの作成

Skyboxの設定はUnityEditor上で設定することが多いと思います。しかし、C#(もしくはJavaScript)のコード上からSkyboxのテクスチャを設定します。再生コントロールをするためです。
次の手続きの実装を行います。
  • 作成したコードはMain Cameraにアタッチする。
  • Startメソッドで、AssetDatabaseを使ってテクスチャを読み込み、リストに追加する。
  • UpdateメソッドでSkyboxのテクスチャを適切に切り替える。
まずは次のコードを書いてみました。Updateでは毎回フレームを切り替えています。テクスチャが繰り返し一定速度で再生されるはずです。(フレームレートは入力元の映像とおなじになるとは限らないです。)


// SkyboxRunner.cs
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;

public class SkyboxRunner : MonoBehaviour {

    Skybox skybox;
    List skyboxTextures = new List();
    int index = 0;

    void Start () {
        // アタッチしたスカイボクスを取得
        skybox = GetComponent();

        // AssetDatabaseからテクスチャをロード
        var guids = AssetDatabase.FindAssets("t:Texture", new string[] { "Assets/SkyboxTex/nightsky1" });
        foreach (string guid in guids) {
            Texture texture = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(guid));
            skyboxTextures.Add(texture);
        }
    }
 
    void Update () {        
        // スカイボックスのテクスチャを切り替える
        skybox.material.SetTexture("_Tex", skyboxTextures[index]);
        index++;
        if (index >= skyboxTextures.Count) {
            index = 0;
        }
    }

}

ここでは、一定速度での繰り返し再生であるため、通常の再生と変わりません。Updateメソッドの内容を変更すれば、フレーム更新を自在に操ることができます。


まとめ

Theta Sで撮影した映像をUnityの3D空間に投影し、再生コントロールもしたかったのですが、MovieTextureなどでは実現できなかったため、各フレームを静止画に書き出してアニメーションすることで実現しました。
(もっといいほうがあればいいのですが、、、)

2016年2月6日土曜日

AVR ATMega168P のマイコンボード組み立ててみた.

Arduino互換のマイコンボードキット

秋月電子で販売されている「ATMEGA168/328用マイコンボード(I/Oボード)」を組み立ててみました.ハンダ付けにについては分かりやすいマニュアルも付属しており,初心者でもかんたんい組み立てることが出来ると思います.



Arduinoとして使うことも出来ますが,恐らく自分はそのままAVRマイコンとして利用すると思います.

ソフトウェアを毎回手頃に書き込んだり,デバッグしたりするのに便利そうだったので購入しました.

注意箇所

組み立て中の注意箇所としては次のことがあるだろうと感じました.
  • プリント基板は背面だけでなく,表面にも実装されています.表側までハンダが流れ込んで固定されていないと,接触不良になる場合があります.

AVRライタの向き

若干迷ったのが,AVRライタISP mkIIを差し込む向きです.このように差し込めばOKです.

USB・シリアル通信モジュールは取り外し可能に

FT232RL USBシリアル変換モジュールは直接ハンダ付けするのではなくソケットを設けて取り外しできるようにしました.比較的価格の高いモジュールの上,他の用途でも使えるため直接半田付けするのはもったいないと感じました.

で,

これで書き込みもデバッグもラクになりました.Arduino同様に素のAVRに対してプロトタイピングできる!


Visual Studio 2015 Update1 と Atmel Studio 7の相性問題

注意

この記事は2016年2月6日現在の内容です.今後不具合が改善され,状況が変わることがあります.

追記:
Atmel Studio build 790(2016年2月リリース)では、この問題は解決されたようです。この問題が発生したら、以下で紹介する方法ではなく、Atmel Studioを最新版にアップグレードすることをおすすめします。

Atmel Studio7がおかしい

Atmel StudioでAVRの開発環境をセットアップしたところ,インストール中に後述するエラーダイアログが表示され,起動後の新規プロジェクト作成画面もテンプレートプロジェクトが表示されなくなっている.
色々調べたところ,Visual Studio 2015 Update1とAtmel Studio7の共有モジュールに相性問題があるようで,一時的な解決方法をAtmel社のサイトで案内していた.
ちなみに,Visual Studio 2015 RTMの場合ではこの現象が(自分の環境では)起こらなかった.

環境

  • OS: Windows 10 64bit
  • 操作:Visual Studio 2015 Update1のインストール後に,Atmel Studio 7をインストール

現象

  • Atmel Studio7のインストール中に次のダイアログが表示された.いずれもYes(はい)をクリックして次に進めた.インストール終了後,起動時もダイアログが表示された.
'ErrorListPackage' package did not load correctly
'ServiceProviderImplemntations' package did not load correctly




  • 新規プロジェクトの作成ダイアログでテンプレートが表示されない.

解決策

次のAtmel社のサイトの案内通りに操作したら直った.


よかったです.
今後,根本的な解決を来します.