2014/08/25

[電子工作]Sparkを買った。

,
 「Spark Core」と言われる、Wi-Fiモジュール(CC3000)+ARM Cortex-M3マイコン(STM32F103)の載ったモジュールを買いました。特にIoTを意識しての購入ではないのですが、公式ではIoTに使えることを前面に押し出した、新しいモジュールです。

購入して、送られてくるまで

Sparkの購入方法ですが、公式サイトの"BUY SPARK CORE"ボタンから注文することが出来ます。お値段は以下のような感じ。

Subtotal: $39.00
Taxes: $0.00
Shipping: $6.78
Total: $45.78
 
 支払いはPayPalです。注文時のメールに依ると、"Your order will be charged when it is ready to ship, typically less than 1 week after you have placed it. If your payment is declined for any reason, you will be notified via the email connected with your order, and will have an opportunity to update your payment information via our ecommerce site (Celery) or PayPal"だそう。

09/01

前回の注文では、PayPalの事前承認支払いの設定を間違えたらしく、支払い出来なかったみたいです。なので、注文し直しました。

 今回の注文では、送料が$11.04に値上がりしていました。一体どうしてと思ったのですが、注文確定時のメールも前回のから少し違っていたので、この間に何か変更があったんでしょう…。発送方法の選択肢から"Standard"が消え、"USPS"か"DHL Express"の二択となっていたのも変更点です。

 調べてみたところ、下のような記事が出てきました。多分これですね。
New Shipping Options! - Spark http://community.spark.io/t/new-shipping-options/6597

09/06

「発送したよ(Your order has been shipped!)」とメールが来ました。一緒にUSPSのトラッキングナンバーも送られてきたので、荷物がどこにあるか分かります。と思ってみたんですけど、最初は反映まで暫く時間が掛かるみたいですね…

09/15

Sparkが届きました。USPSで9/6に受付され、日本についたのは9/15でした。大体以下のような感じ。

9/6 Gilroy
9/6 San Jose
9/9-10 Los Angeles
9/12 ISC Los Angels(International Service Center)
9/13 Japan
9/14 Customs Clearance(通関手続き)
9/14 Arrival at Post Office
9/15 Delivered

開封の儀

こんな箱が、プチプチが内挿された封筒に入ってやってきました。
"SPARK CORE"と印字された表面。この写真は被写界深度が狭いせいで、遠くの印字がぼやけてて、見てて酔ってしまいそうなので撮り直したい。
裏面。FCCとCE認証のロゴが入っています。
中身を開けた所。やっぱり大きくdocumentのURLが書いてありますね、LPCXpressoやmbedに似ている気がします。
黒いウレタンのようなものを退かすと、ブレッドボードが出てきました。
箱の中身を全部出したところです。Sparkのロゴ入りUSBケーブルは結構お洒落ですね。あと、ステッカーまで付いてきた。
USBで給電した所です。最初は青色のLEDが点滅しました。技適マークがあるのが分かる。
ブレッドボードまで付いてたのはびっくりですが、それ以外は標準的ですね。最近このような、スタイリッシュで複雑に組み合わさった箱が多いですね。Apple製品とか、Anker製品とか。

Hello, worldまで

さて、届いたらとりあえず動かしてみたくなるのが人情です。ここでは、公式サイトの"Get started"に従って、Spark Coreを動かしてみます。

 まず、Spark Coreを使用するためには、以下の手順を踏む必要があります。

  • spark.ioのアカウントを作成する。
  • CoreをWi-Fi親機に接続する。
  • Coreを、spark.ioのcloudに登録する。
  • Coreに名前をつける。
公式サイトでは、これらはスマートフォンの専用アプリから設定することを推薦していますが、よく読むと以下の3種類の設定方法があることが分かります。

  • スマートフォンの専用アプリから設定する(一番楽)。
  • Spark Coreのドライバをインストールし、仮想シリアルポートを通じて、WiFiの設定を行う。次に、コアを登録する。
  • Node.jsのcommand prompt(Spark的にはSpark command lineという)から、"spark-cli"を利用して全ての設定を行う(参照)。
※接続に困ったら、"Connect"のページも見る。
 私は最初、スマートフォンの専用アプリ(Androidなら"Spark Core"というアプリ)で設定しようとしました。これが一番公式サイトでスクリーンショットありますし。しかし、Wi-Fiに接続するところで、幾らやっても「コアが見つかりません」となってしまうので、諦めました。 

 因みに、Wi-Fiで接続する時に入力すべきパスワードは、多分Wi-Fi親機に接続するためのものです(自分のSparkアカウントのものではない)。

 仮想シリアルポートを介した設定では、公式サイトの通りにWi-Fiの接続先を設定しました。が、コアをIDEで登録する時に、"CORES"には自分のコアが出るものの、接続が確認できない状態になってしまいました。

 結局、3番めの方法を行ったら、必要な項目の入力以外は全て自動で行ってくれたので、これが一番楽かなあといった感じです。
Node.js command promptからSpark Coreの設定をした時のスクリーンショット。まずはWi-Fiに接続する設定をした。
Node.js command promptからSpark Coreの設定をした時のスクリーンショット。自動的にclaimingが行われている。

 登録出来ると、LEDがシアン色でゆっくりと点滅するようになります。また、IDEで、左下の[Cores]を選択すると、下図の様にCoreが接続されているか見ることが出来ます。

Coreが接続されると、コアの名前の右側に、シアン色の○が出る。そこにマウスを乗せると、このような吹き出し(Tooltip)が出てくる。
 Hello, world自体は、"Blink an LED"プロジェクトをfork(複製)し、Verify(○にチェックのボタン)→Flash(左の雷マーク)で大丈夫です。しばらくするとSpark Coreの色がめまぐるしく変わり始めて、ちょっと待つとUSBコネクタ脇の青色チップLEDが点滅し始めました。

まとめ

以上が、Spark Coreを購入してから動作させるまでの記録です(メモなので、ページの内容が不親切だとは思います…)。接続に少し苦戦したのと、まだよくIDEの使い方を理解していませんが、無線でプログラムを書き換えたり通信するという真新しさを楽しんでいます。

Read more →

[電子工作]Sparkの技適について

,
 論より証拠、実際に買ってみたら、CC3000モジュールに技適マークが印刷されていました。
Spark Coreの写真。CC3000モジュールに技適マークが書かれていることが分かる。
上の写真で説明は事足りてしまったんですが、届く前は以下のような内容のある記事となっていました。

まえがき

「IoT(Internet of Things)」という単語が今年のトレンドのようになって、ニュースなどでも目にすることが多くなってきました。そんなIoTに欠かせないのが無線モジュールです。"Things"にいちいちLANケーブルを繋ぐのは、あまりいいことではないですからね(床がスパゲッティになっちゃう)。
日本におけるテクノロジのハイプ・サイクルを示した図[1]。「モノのインターネット」は黎明期にあることが分かります。

Sparkとは

無線モジュールの中で、私はSparkというものが気になっています。STM32F103が裏側に乗っていて、DIPパッケージなのでブレッドボードに挿しやすい。そしてなんといってもホームページが新しくて綺麗で(パララックスサイト、ミニマルでフラットなデザイン、全画面の画像とか…)、Web IDEも充実してそうです。
 しかし、これを日本で使う時には、「技適」という問題が出てきます。

技適とは

技適とは、「この機械なら、日本で電波出していいよー」という証明のようなもので、これを受けないと、その機械から電波を出すことが日本では違法になってしまいます。なので、使う無線モジュールが技適を通っているかというのは、些細なことに思われますが結構重要な問題なんです。もちろんSparkに関しても、日本で使うなら「技適(技術基準適合証明)に通っているか」という問題があります。
 ややこしいのは、「技適」は日本だけでの証明であることです。アメリカではFCCという規格になりますし、欧州ならばCEです。なので、海外製品だと「日本だけのために、お金を出して技適を通す」なんてことはしない場合も多いです(Simフリー端末などにありがち)。

 それで、調べたところ、技適を受けてるみたいです。
 Sparkの無線通信部には、Texas InstrumentsのCC3000MODというモジュールが載っています。で、こいつはTIが技適を通したみたいです。CC3000MODで画像検索すると、表面に技適マークの付いたものと付いていないものが出てきますが、技適受けたのが平成25年4月のようなので、その前後でパッケージが変わったのでしょうか。
 なので、Sparkは日本でも使えますね、やったー。

参考

[1] "ガートナー | プレス・リリース | 「日本におけるテクノロジのハイプ・サイクル:2013年」を発表"、http://www.gartner.co.jp/press/html/pr20131015-01.html、2014/08/25閲覧
これってハイプ・サイクルって言うんですね。専門用語覚えられないので、「トレンドのキーワードがどこらへんにあるのか示してる、3次曲線を平行移動したみたいなやつ」って言ってました…。

Spark | Open source IoT toolkit
Spark公式サイト。デザインがとても綺麗。日本の組み込み系もそろそろこれを見習って新しくしてほしい。

CC3000 Product Certification - Texas Instruments Wiki
TI公式なので、ここが一番詳しいです。

総務省 電波利用ホームページ | 技術基準適合証明等を受けた機器の検索
CC3000MODが技適受けてることは、総務省公式も書いてます。

Can I use SparkCore in Japan? - Spark
Sparkの掲示板にあった、技適に関するTopic。
Read more →

2014/08/22

[登山]karrimorのtrim 18を買った

,
 登山でのピストン行程で使うためのサブザックとして、karrimorのtrim 18を買った。一部ではこれをアタックバックと言うらしいので、この単語で調べたほうがいいかもしれない。

どうして要るの

貧乏大学生が登山をする場合、大抵テント泊になる。また、一度行ったらなるべく山を取って帰るので、縦走が多くなる。こうして、テントの装備や何日もの食糧の分だけ荷物も増え、重くなっていく。そのため、容量の大きなザックを背負うことになる。
 問題はピストン行程(A地点から、B地点まで行ってAに戻る。A→B→Aみたいな。)のときで、この時はテントなどの荷物は要らないので置いていき、サブザックに必要なもの(水筒や非常食、薬、雨具など)だけ積めて行くこととなる。
 今までは、登山が趣味だった祖父のザックを使っていた。しかし、ちょっと小さいのと、上と下で、荷物を入れるスペースが分かれている(2気室のザック)のが不便だった。なので、新しいのが欲しくなった。というわけ。

サブザックに求めたもの

大体以下のスペックのを探した。

  • 容量は20L前後
  • 身体に固定できる(できれば腰ベルト)
  • 軽い

以下理由。
 ザックを選ぶ主要因は、まず第一に容量だと思う。入れる荷物は、思い出せる限りでは下のリストに載せたくらい。

  • 水(2L、Platypus)
  • 行動食(タッパーに入れてる。容量不明だけど結構大きい。)
  • 医薬品類(なかなかかさばる)
  • 地図
  • 雨具・防寒具
  • 貴重品(財布、iPod、etc)
実際に店でザックを見た限りだと、15Lくらいでは小さすぎて無理そうだと感じた。せめて18、余裕があれば20かなあといった感じ。

 次に、ザックの作りについて。今回は、買った数日後に剱岳に行く予定だった(剱沢⇔剱岳山頂が数時間のピストン)。また、南アルプスの茶臼小屋⇔光岳のピストンをする予定がある。どちらも長丁場だし、岩場もあるから、ザックをちゃんと身体に固定したいと思っていた。なので、腰の固定ベルトがあるものを選んだ。
 各社が出しているザックの内、サブザックとして売られているものは作りが簡素である。軽量なのを謳って、折りたためる位だから、肩紐も貧弱だし。

 軽いっていうのは、まあ軽さは正義だと思っているから…。

候補

あまり色んなお店を見て回る時間がなかった。私は、都内で比較的広いと聞いていた、新宿の石井山専(ビックロ8F)に行って見た。

サブザック系統では


普通のザックでは

  • trim 18(karrimor)
  • スケッチ15(GREGORY)
  • OSRAYの何か
 サブザックはダメで、迷ったけど、軽いからtrim 18でいいかといった感じ。正直、固定紐がないのは妥協して、軽いサブザックにでもすればよかったと思った。
 それと、トレイルラン用のやつも15L程度で、割といいんじゃないかと思ったけど、ハイドレチューブがゴテゴテしているのもなんかなあ、といった感じ。

使った感想

 剱は雨でポシャった。のでまだ使ってない。


Read more →

2014/08/11

[プログラミング]Pythonでのデータ処理と、numpy.log2(4096)≠12.0になった話

,

概要

・Pythonで、xlsxを用いてExcelファイルを読み込んだ。
・numpyを用いてFFT、pylabで結果を表示した。
・np.log2()の精度?に疑問が生じた。

ExcelファイルからFFTする

データ処理にPythonを使おうとしています。今は、4096個の電圧データをFFT(高速フーリエ変換、Fast Fourier Transform)しようとしています。Pythonには、numpy、scipy、pylabといった強力なライブラリが揃っているので、あまり自分で実装しなくとも、簡単にFFTなど演算が出来ます。楽でいいですね。

 今回は、"testdata.xlsx"というExcelファイルにデータが収まっています。このファイルのSheet1、1列目の1~4096行目に、小数でデータが入っています。この時、これらを取り出して、numpyでFFTを行い、pylabで表示するだけなら以下のスクリプトで出来ます。
# -*- coding: utf-8 -*-

__author__ = 'fenrir_'

import xlrd
import numpy as np
import math
from pylab import *


def rad_to_deg(rad):
    return rad / np.pi * 180


if __name__ == "__main__":
    # Excelからデータを読み出す。Sheet1の一番左の行。
    filename = r"C:\Users\******\testdata.xlsx"
    book = xlrd.open_workbook(filename)
    sheet_1 = book.sheet_by_index(0)

    # PythonのListから、numpy.ndarrayに変換
    col_array_in_numpy = np.array(sheet_1.col_values(0))
 
    # 以後、FFTの処理
    start = 0
    N = 4096    # データ点数
    fs = 2000000

    # Hanning窓を掛ける
    hanning_window = np.hanning(N)
    windowed_data = hanning_window * col_array_in_numpy
    fft_result = np.fft.fft((windowed_data[start:start + N]))

    freq_list = np.fft.fftfreq(N, 1.0 / fs)

    # 振幅・位相のスペクトルを求める。
    amplitude_spectrum = [np.sqrt(c.real ** 2 + c.imag ** 2) for c in fft_result]
    phase_spectrum = [rad_to_deg(np.arctan2(int(c.imag), int(c.real))) for c in fft_result]

    # 元データの波形を表示する
    subplot(311)
    plot(range(start, start + N), col_array_in_numpy[start:start + N])
    axis([start, start + N, np.min(col_array_in_numpy), np.max(col_array_in_numpy)])
    xlabel("time [sample]")
    ylabel("amplitude")

    # 振幅スペクトルを表示する
    subplot(312)
    plot(freq_list, amplitude_spectrum, marker='o', linestyle='-')
    axis([0, fs / 2, np.min(amplitude_spectrum), np.max(amplitude_spectrum)])
    yscale("log")  # 縦軸は対数軸にする
    xlabel("frequency [Hz]")
    ylabel("amplitude spectrum")

    # 位相スペクトルを表示する
    subplot(313)
    plot(freq_list, phase_spectrum, marker='o', linestyle='-')
    axis([0, fs / 2, -180, 180])
    xlabel("frequency [Hz]")
    ylabel("phase spectrum")

    show()
結果、以下のようなグラフが生成されます。(振幅スペクトルは、まだ最大値を基準としたdB表示にはしていません)。 
窓関数なしの場合の、入力データ(上段)と、そのFFT結果
Hanning窓を適用させた場合の、入力データ(上段)と、そのFFT結果
わあ、めっちゃ便利ですね。

一部データを抜き出す処理を加える

さて、今回はデータ数Nは4096でしたが、これが異なる点数の時を考えます。この際、考慮すべきことが1つあります。それは、FFTに使うデータの個数です。というのも、FFTではNは2の累乗である(N = 2^n)ことが望ましいです。なので、N≠2^nであった場合、FFTに用いるデータ数は2^nとなるように、一部を抜き出さねばなりません。例えば、データ数N = kである場合、kよりも小さく、一番大きな2の累乗の数だけ、データを抜き出したくなります。
 実際には、log(2, k)以下の一番大きな整数Nを求めれば、log(2, k) > Nよりk > 2^Nとなります。よく対数の練習問題にあるやつですね。なので、このNを求める処理を加えます。
 Pythonで関数として実装すると、以下のようになりました。
def floor_2_pow(value):
  # 2**N < log2(value) < 2**N+1となるような整数を返す。つまり、valueに一番近い2**N
    log_2_value = np.log2(value)
    exponentiation = np.floor(log_2_value)
    # print "value : %10.24f exponentiation : %10.24f" % (log_2_value, exponentiation)
    return 2 ** exponentiation

 さて、これを書いて実行していたのですが、value = 4096の時、2^11 = 2048が返ってきてしまいました。デバッグして各変数を見てみると、log_2_valueは12.0(float64)ですが、exponentiationが11.0になっていました。floor(n)は、n以下の最大の整数を求める関数ですから、11.0ではなく12.0が入っているはずです。実際に、
    exponentiation = np.floor(np.float64(12.0))
とすれば、exponentiationは12.0になります。なので、問題はnp.floor()以前、np.log2()にありそうです。

 ここで、浮動小数点では丸め誤差などの誤差がよく問題になることを思い出しました。なので、np.log2(4096)の返り値の表示精度を上げてみました(コメントアウトされているprint文の、コメントを外した)。その結果は以下のようになりました。
log_2_value : 11.999999999999998223643161 exponentiation : 11.000000000000000000000000
 これを見ると、np.log2(4096)が実は12.0ではなく、11.999999…を返していたようです。デバッガのWatch窓は小数第一位までしか表示しないので、私が12.0だと勝手に勘違いしていたみたいです。問題はここにあったようです。

検証

さて、本当にnp.log2()が悪いんでしょうか。よく分からなかったので、幾つかの値でnp,log2()をチェックしてみました。以下のスクリプト(verification_log2.py)を用いました。
# -*- coding: utf-8 -*-
__author__ = 'fenrir_'

import math
import numpy as np

if __name__ == "__main__":
    # np.log2()が返す値を検証する。
    for num in range(1, 20):
        val = 2 ** num
        print "np.log2(%d)      : %10.24f  math.log(%d, 2.0)   : %10.24f" % (val, np.log2(val), val, math.log(val, 2.0))

    # np.log10()が返す値を検証する
    for num in range(0, 20):
        print "np.log10(%d)       : %10.24f" % (num, np.log10(10 ** num))
その結果、以下のような結果が得られました。
np.log2(2)      : 1.000000000000000000000000  math.log(2, 2.0)   : 1.000000000000000000000000
np.log2(4)      : 2.000000000000000000000000  math.log(4, 2.0)   : 2.000000000000000000000000
np.log2(8)      : 2.999999999999999555910790  math.log(8, 2.0)   : 3.000000000000000000000000
np.log2(16)      : 4.000000000000000000000000  math.log(16, 2.0)   : 4.000000000000000000000000
np.log2(32)      : 5.000000000000000000000000  math.log(32, 2.0)   : 5.000000000000000000000000
np.log2(64)      : 5.999999999999999111821580  math.log(64, 2.0)   : 6.000000000000000000000000
np.log2(128)      : 6.999999999999999111821580  math.log(128, 2.0)   : 7.000000000000000000000000
np.log2(256)      : 8.000000000000000000000000  math.log(256, 2.0)   : 8.000000000000000000000000
np.log2(512)      : 9.000000000000000000000000  math.log(512, 2.0)   : 9.000000000000000000000000
np.log2(1024)      : 10.000000000000000000000000  math.log(1024, 2.0)   : 10.000000000000000000000000
np.log2(2048)      : 11.000000000000000000000000  math.log(2048, 2.0)   : 11.000000000000000000000000
np.log2(4096)      : 11.999999999999998223643161  math.log(4096, 2.0)   : 12.000000000000000000000000
np.log2(8192)      : 12.999999999999998223643161  math.log(8192, 2.0)   : 13.000000000000000000000000
np.log2(16384)      : 13.999999999999998223643161  math.log(16384, 2.0)   : 14.000000000000000000000000
np.log2(32768)      : 15.000000000000000000000000  math.log(32768, 2.0)   : 15.000000000000000000000000
np.log2(65536)      : 16.000000000000000000000000  math.log(65536, 2.0)   : 16.000000000000000000000000
np.log2(131072)      : 17.000000000000000000000000  math.log(131072, 2.0)   : 17.000000000000000000000000
np.log2(262144)      : 18.000000000000000000000000  math.log(262144, 2.0)   : 18.000000000000000000000000
np.log2(524288)      : 19.000000000000000000000000  math.log(524288, 2.0)   : 19.000000000000000000000000

 うーん、np.log2()はところどころ期待した結果が得られてないようです。math.log()の方は、ちゃんと出てますね。ちなみに、np.log10()ではこのようなことは起きないようです。

 これについては、Stack Overflowでも話題になったみたいです。確かに、浮動小数点の精度は有限ですね。
Python NumPy log2 vs MATLAB - Stack Overflow http://stackoverflow.com/questions/17702065/python-numpy-log2-vs-matlab

対策

この誤差は、np.log2()の求解アルゴリズムに依るものなのでしょうか。丸め誤差でしょうか。今のところ、この原因はよく分からないです(私が無知なので、調べてもない)。とにかく、このままではnp.log2(2^n)≠nとなることがあるようなので、value = 2^nの時はnp.log2()を使わないようにしました。処理としては、「valueが2で割り切れるならば、valueを返す」です。最終的に、コードは以下のようになりました。
def is_dividable_by_2(value):
    while True:
        if value % 2 != 0:
            return False
        elif value == 2:
            return True
        else:
            value /= 2


def floor_2_pow(value):
    # 2**N < log2(value) < 2**N+1となるような整数を返す。つまり、valueに一番近い2**N
    if is_dividable_by_2(value):
        return value
    else:
        log_2_value = np.log2(value)
        exponentiation = np.floor(log_2_value)
        # print "value : %10.24f exponentiation : %10.24f" % (log_2_value, exponentiation)
        return 2 ** exponentiation

参考サイト

・高速フーリエ変換(FFT) - 人工知能に関する断創録 http://aidiary.hatenablog.com/entry/20110618/1308367728
 numpyでのFFTの仕方が載っています。このサイトは、Pythonでの機械学習やデータ処理など、色々有用な例が豊富にあって、とても勉強になります。

・numpy.floor — NumPy v1.8 Manual http://docs.scipy.org/doc/numpy/reference/generated/numpy.floor.html
 numpy.floor()のReferenceページです。numpy.floor(2.0)は2.0だって、例に書いてありますね。5回くらい「えっ本当だよね?」って見返してしまいました…。

・ライブラリ:unittest - Life with Python http://www.lifewithpython.com/2014/03/unittest.html
 Pythonでのテストの書き方が掲載されています。ちなみに、main.pyにある関数をtest.pyで使いたい場合は、from main import *と書けばいいみたいです。

・Creating Tests http://www.jetbrains.com/pycharm/webhelp/creating-tests.html
 私が使っているIDE「PyCharm」のHelpです。テストの作り方が載っています。Ctrl + Shift + Tを押すだけです。楽でいいですね…。

・高速フーリエ変換 - Wikipedia http://ja.wikipedia.org/wiki/%E9%AB%98%E9%80%9F%E3%83%95%E3%83%BC%E3%83%AA%E3%82%A8%E5%A4%89%E6%8F%9B 
 結局のところ、FFTのデータ数Nは、2の累乗「でなければいけない」のか、「であれば一番早い(他の値でもよし)」なのか、どっちなのか。こういう厳密なところを全然おさえられていないので、頭の悪さ、無知といったものが露呈してしまいますね…。
Read more →