ぷろろろぐ

制御系学生の雑記

年末までにReact+Reduxで何か作る その1

はじめに

今年で3年目となる完全勝利20xxですが,今回はReact+Reduxの勉強も兼ねてちゃんと作っていこうと思う.ついでに作業メモとして記事も残す.

ちなみに完全勝利とは…?という方のために一応説明すると,僕が2015年の年末に10分くらいで作った糞サイト.ガンダムUCの楽曲"UNICORN"(多分完全勝利の曲と言ったほうが伝わると思う.ググって)の盛り上がるところでちょうど年を越すというだけのもの.身内でSkype年越ししながらみんなで開いて遊んだ.絶対近いうちに曲使ってるアレで怒られが発生しそうなのでなんとかしたい………

完全勝利2016

完全勝利2017

実は知り合いのアレでフロントのインターンをやらせてもらったのだけど,大学が忙しくてあまり開発に携われていないというのと,ガッツリフロントをやったことがないので自分の理解が足りていないなぁという場面が多々あって,それの勉強も兼ねて自分でひとつサービスを作ってみようと思ったという話.

作業記録なのでだらだら書いていきます.用語とかもなるべく説明していこうと思う.なので長くなると思う…理解不足気味なので間違ったところがあったら指摘してください…!

やりたいこと

  • とりあえず「React+ReduxでSPA」
  • ホスティングはFirebase.赤字兄貴チャット機能とか付けられるといいですね
  • Twitter連携とかできるともっと良いのだが…

そもそもReactって何

ここを読むのが早い.

qiita.com

 上の記事の最初に書いてあるとおり,画面に表示するUIパーツ(コンポーネント)を作るためのライブラリ.ボタンとかなんだとか.最終的にそれらを配置していってページを作るみたいな流れになる.

とりあえずWebページ作って軽くDOM操作したいって時はjQuery使うのが速いけど,いちいち要素指定して中身いじって…っていうのを大規模アプリケーションでやると早いうちに死ぬのは目に見えている.

Reactは,親から渡されるpropsと自分の内部状態を示すstateによって自動で内容を書き換えてくれる.便利ですね.

超単純に言うと,TLに流れるツイートのコンポーネントを考えたとき,そのコンポーネントはpropsとしてユーザIDとかユーザ名とかツイート内容とかを受け取る.まずコンポーネントの見た目とかを定義しておいて,ユーザIDの部分に{this.props.userid}みたいに入れておく.その後,画面上に生成するときについでにツイートに関するpropsを渡すと書き換えを勝手にやってくれるぞい.という話.

propsとstateの話はこことかわかりやすいかもしれない.

qiita.com

Reduxって何

わからん.俺達は雰囲気でReduxをやっている.

これは半分冗談ですが残りの半分は本気で,理解しているとは言い難い.

mae.chab.in

ほん,ReduxはFluxを発展させたようなやつなんやな.Fluxってなんや.

qiita.com

よくわからないけど,急激なフロントエンドの進化によってどんどん構造が複雑化していき,フロントでやる内容がとても多くなった.色々デザインパターンはあるけどつらくなってきた… そこでFacebookがFluxというデザインパターンを提唱した.

saneyukis.hatenablog.com

とはいっても別に完全に新しい概念ではなく,従来からあるMVCのイイカンジに落ち着くけど名前がついてないデザインパターンに名前をつけて定義しただけ.らしい.名前がついていることは大切ですね.シンゴジラでも似たようなこと言ってます.

Fluxは以下の図のような一方通行のデータフローを持つ.

f:id:protocol1964:20171119143606p:plain

図の出典: https://github.com/facebook/flux

mae.chab.in

まず,アプリケーションが持つ状態(state)はStoreに格納されている.ViewはStoreを見ているのでStoreが更新されるとスッ…とViewが更新される.コンポーネント毎に状態持ってると管理つらくて死ぬからどっかにまとめたろ,といった感じでしょうか.

ただ,Viewが直接Storeをいじることはなく,更新内容を格納したActionを発行し,そいつを受け取ったDispatcherがStoreをいじる.

もうちょっと詳しく書くと,Viewで何かしらかの操作(onClickとか)が発生したとき,ActionCreatorがそれに合わせてActionを発行する.操作が何であれ,Dispatcherが読める形にするのがActionCreatorのお仕事.そうして発行されたActionはStoreの管理人Dispatcherに渡され,DispatcherはStoreを更新する.最後に,更新されたStoreの情報を元にViewが再構成され…という流れ(合ってる…?)

なるほど.自分で書いててわかってきたぞ.やっぱ記事にするのは大切だね.

 

で,ようやくReduxの話.Reduxとは… これを読んだほうが早い.

qiita.com

まずFluxではStoreを複数持つことを許していたけれど,Reduxは1つのStoreにアプリケーションの全てのstateを格納する.ReduxのStoreは1つだけ.

Viewでの操作からActionCreatorがActionを発行するとこまではFluxと同様.ただ,Actionの送り先はDispatcherではなくReducerという名前になっている.Reducerは現在のStoreの状態と受け取ったActionから,新しいStoreを生成する部分.らしい.よくわからんけど.Storeを更新するという意味ではDispatcherと似たような動きではある.

これは実際にちゃんと書いたこと無いので曖昧なんだけど,DispatcherはActionをStoreに投げる仲介者であるのに対し,ReducerはActionで受け取った情報をもとにStoreを新しく生成するもの.という違い?合ってるかな.

簡単に書くとこのような感じの説明になると思う.ReactでReduxを使う時はReactのstateをReduxで管理するためにreact-reduxを使ったり色々あるらしいが,そこらへんは追々.

 

長くなってしまったのでとりあえずここで区切って,次から実際に作り始めようと思う.というか既に作り始めているのでさっさと書いてしまおう.

DQ11をやって思ったこと【ネタバレ有】

普段全くテレビを見ない(というかテレビがない)のでDQ11の存在を発売3日前くらいに知り,DL版を予約して発売日からちょいちょいプレイしています.

一応表ENDは終わり,今裏ENDに向けて進めているところですが,ちょっと思うところがあったので書きます.

 

以下ネタバレ有り

 

 

 

 

 

 

 

表ENDまではよかったんですよ.世界崩壊~表ENDの間に各PTキャラは精神的に大きく成長します.カミュの妹を助け出すくだりとか,ベロニカの死とか,色々あるじゃん.最後の砦のくだりとかメッチャ興奮しましたよ.世界崩壊~表ENDまでの間で,世界観やキャラクターの肉付けされていく量がすごい大きかったと思うんですよね.

そこでラスボスを倒して世界には平和が訪れるわけです.ここまでの評価なら文句なしの★5です.ベロニカ居ないけど…

で,ベロニカが死んでしまったということで,どうせベロニカ復活に関するイベントでもあるのかなと思っていたのですが,まさかね,時間遡行でそれが実現されるとは思っていませんでしたね.

時間遡行は使いようによっては物凄く強いツールとなります(シュタゲとかそうですね)が,物凄く扱いが難しいツールです.

表ENDが終わると,ちょっとしたイベントの後に世界崩壊直前まで時間遡行してしまいます.これはベロニカが死ぬ直前なので,数十時間ぶりにベロニカを見た時はちょっと涙出そうになりました.

でも,前述したとおり,世界崩壊~表ENDの間でのキャラクターの肉付けが大きかったんですよ.それらが全て”無かったこと”にされてしまうわけです.

例えばホメロス.どちらにせよ魔物側の人間ですが,命の大樹のイベント戦で主人公にあっさり倒されてしまいます.時間遡行前ではホメロスが何故魔物側についたのか知るイベントがありましたが,時間遡行後の世界の流れとしてみると主人公以外の人間はこれを知る術がないわけです.グレイグ可哀想…

カミュの妹も主人公の勇者パワーでわりとあっさりと救出されます.時間遡行前の同イベント時のカミュすごいよかったのに…なんというか拍子抜け.レベルや能力は時間遡行前と一緒だけど,あのイベントが有ると無いとではなんかキャラが別人なんだよな…

…まだプレイ途中なので全部把握していませんが,時間遡行によって”無かったこと”にされてしまう部分があまりにも大きすぎると感じました.僕はむしろ世界崩壊~表ENDまでが本編と思ってる人間なので,とても残念です.

ローシュのくだりやニズゼルファのくだりなど,色々なストーリー展開があって時間遡行を用いたのかと思いますが,時間遡行使わない手はなかったのかなぁ…

あ,でも時間遡行後の世界で拝めるベロニカ(おとなのすがた)とか女賢者セニカちゃんは色々と良かった.

あとNier:automataをプレイしたばかりだったので,ニズゼルファが完全に機械生命体にしか見えない.

こんなところかなぁ.まだLv55なのであと15近く上げるのは流石に厳しい.コツコツやっていきます.

Macintosh SE/30を魔改造した話

こんにちは.はじめてクレカを作ったら2日で給料分の買い物をしてしまい既に八方塞がりの私です.

先日,私の大学のとある研究室からMacintosh SE/30が廃棄品としてやってきました.

f:id:protocol1964:20170417234403j:plain

部室にやってきた瞬間に部員による解体作業の憂き目にあってしまい(一応起動しないことは確認しました),現物の画像は残っておりませんが,解体中の写真がこちらです.

 ロジックボードは先輩が,電源回路は後輩が取り出し,残るは筐体.これを何か活用できないだろうか…そう考えました.

 

「…モニタ一体型PCを組めばいいのでは?」

 

Macintosh SE/30の筐体はそのまま,内部にPCパーツを組み込んで魔改造することに.

さて,SE/30の表示部はブラウン管ですから,それなりに筐体の容積は確保されているとはいえ,やはりPCを組み込むには若干小さめ.

f:id:protocol1964:20170417235517j:plain

ゲーミングPCから引っ張り出してきた750Wの電源装置とCPU,メモリ,SSDはコスト削減の為に維持したい…とし,手元にある部品から行き当たりばったりに組み込んでいきます.

SSDは下部スペースに.ここの有効活用はこれしかない.

f:id:protocol1964:20170417235712j:plain

電源は背面の穴に合わせて設置…したのですが,やはりファンが外装に隠れて吸気できないとまずいので,最終的には内側にファンがくるようにしてあります.結束バンド有能すぎる…(固定の手法として正しいとは言っていない)

f:id:protocol1964:20170418000049j:plain

今回の改造の目安のひとつに,ケース加工は一切行わない,というものがあります.やはりMacintoshの筐体に穴は開けたくないですからね〜〜〜〜()

というか,エアフローがクソすぎるのでケースに穴開けようと思ってたら,先輩方に「ケース加工は甘え」と言われてしまったので,最初からある穴で頑張ることにしました.

次にマザボその他を組み込んでいきます.今回は手持ちのi7 3770を流用したかったので,LGA1155でMicro-ATXなボードを探した結果,ASUSのB75M-PLUSが丁度よく売っていたので採用しました.とはいえ筐体にはMicro-ATXでも入らなかったので,Micro-ATXより一回り小さいボードを探した結果,これしかなかったという感じです(Flex-ATXというらしい?公式サイトではMicro-ATXと呼んでいるけど).

グラボはZOTACのGTX1050Ti.値段的には玄人志向が最安値だったのですが,筐体の横幅を考えると少しでも小型のほうが良かったので採用.結果としてこの判断は正解でした.

f:id:protocol1964:20170418000758j:plain

筐体に組み込みます.グラボは重力などによって垂れ下がらないように無理やり固定.魔改造感が出てきました…

f:id:protocol1964:20170418001039j:plain

ちなみに言い忘れていましたが,今回作ろうとしているのはモニタ一体型の「ゲーミングPC」です.小型のレトロな筐体で最新のゲームが動いている様子はロマンありますよね…(なお発熱

さて,最低限必要な部品は揃ったので,液晶とコントローラ基板が届くまでの間にOSのインストールと設定を済ませておきます.

f:id:protocol1964:20170418001857j:plain

ジョブズに呪い殺されるのを覚悟でインストールしています.

Mac「シテ……コ…ロシテ…」

 

さて,あとは液晶を搭載すれば一体型PCと呼べるものになります.このMacのディスプレイは9インチです.9インチ前後の液晶で入手が容易なもの…といえば,一つしかありませんね.

iPadRetinaディスプレイです.

Retinaは解像度2048*1536.申し分ないレベルです.Amazonで4000円くらいで売られていました.また,Retina用のコントローラ基板も売られており,AbuseMarKにて販売されています.

abusemark.com

コントローラは比較的すぐ届いたのですが,液晶は中国からの発送だったので,少々時間がかかりました.届き次第,早速搭載します.

f:id:protocol1964:20170418002829j:plain

デェェェン

メチャクチャ綺麗で驚きました.UIの倍率を1倍にしていると文字が小さすぎてつらいものがあります.あと画面枠に対して大きい(9.7インチ)ので,四辺が見えなくなってしまいます.ここはグラボのドライバでなんとかなるのかな?調べていないけど.

f:id:protocol1964:20170418003351j:plain

うおぉ

まだ試してないけどこの画面でEliteとかNFSとかやりたいですね…

 

画面を取り付けてテンションが上がっていましたが,現実的な問題がいくつか残っています.マザボインターフェイス部がちょうど筐体の壁面で隠れてしまうので,あそこらへんのポートは全て使用できません.何かしらかの手段を用いて少なくともUSB,オーディオ端子を筐体の穴から出さないと色々と厳しいPCとなってしまいます.

あとうまくいったと思った液晶ですが,バックライトにそれなりに電力を食われるらしく,端子によっては電力不足.また筐体の背面のせいでマザボのUSBが使えなくなってしまうので,何かしらかの方法を用いて電源装置から5Vを引っ張らないといけません.これについてはペリフェラル端子を適当に分解すればいけるかな〜と考えています.

とりあえず,取り急ぎ筐体に納めてみました.

f:id:protocol1964:20170418004201j:plain

チョロっと出てる電源スイッチもしっかり作らねば…まだまだやることは多いです.

完成したら講義に持参するなどのガイジ行為に手を染めるかちょっと悩んでいますが,とりあえず完成度を高めていこうと思います.

放射温度計MLX90614をmbedで使った話 と I2Cの解説のようなメモ

こんにちは.春休みに入った瞬間に生活リズムの位相がπ/2ほど遅れました.直していきたいです.

最近,友人にとあるロボットの大会に誘われたので,機体の設計を友人に任せ,電装系(かっこいい響きですね)を色々と作ったりしています.

というわけで,このロボットに使用するつもりの放射温度計MLX90614をmbedで使った話です.ちなみに使用するマイコンはみんな大好きLPC1114です.

もともとは,秋月で売っている焦電センサ D203Bを用いて,自分で放射温度計を作成するつもりだったのですが,色々と厳しい感じになったので,少々高いですが市販されている放射温度計モジュールを使用することにしました.

赤外線温度センサ MLX90614 - MLX90614BAA - ネット販売

こちらのセンサですが,I2C(厳密にはSMBus)インターフェイスで通信を行える大変便利な物となっております.ただ,日本語の情報があまり存在しないんですよね.センサを動かすにあたって,こちらの記事を参考にさせていただきました.

温度センサMLX90614を使ってみる : Hoge-Puge-Foo
情報が少ない放射温度計センサMLX90614を使ってみた
Sensor de temperatura infrarrojo Melexis | Espacio de Victor Pasilla

まず,データシートも英語だしよく分からんからとりあえずi2c.read()で読むゾ とやっても読めなかったりします.そりゃそうだ.

というわけでデータシートを見ると,通信のタイミングは次のようになっております.

f:id:protocol1964:20170220221818p:plain

まず,スタートコンディションを発行し,続いて7bitのスレーブアドレス(このセンサのアドレスは0x5aです),書き込みを示すWr(0)を送信します.ちゃんと接続されていればスレーブからアクノリッジ(ACK)が送られてくるので,続いて8bitのコマンドを送信します.再びACKがスレーブから帰ってくるので,リピートスタートコンディション(Sr)を発行します.再び7bitのスレーブアドレスと,今度は読み取りを示すRd(1)を送信し,ACKが返ってくると,スレーブから3バイトのデータが送られてきます.3バイト目を受信し,ACKを返してからストップコンディションを発行して,一連の通信は終了します.

…と,図に書いてあることをつらつらと文章に起こしましたが,ここで用語の解説を挟みます.自分も最近勉強したばかりなので間違えていたら教えてください…


まずスタートコンディションとは,マスタが「今から俺がマスタになって通信するゾ」といった感じで,バスに接続されているスレーブ全体に対して送信するメッセージです.実際の信号では,SCLが上がっている時にSDAを下げることを示します.

オシロスコープで見るとこんな感じ.上がSCL,下がSDAです.
f:id:protocol1964:20170220223754j:plain

最初,SCLが上がっている時にSDAが下がり,SCLが動き出してデータのやり取りをしているのが分かりますね.


次にアクノリッジ
簡単に言うと,受信側がしっかりとデータを受信できているか,その確認のために発行されます.
上の図で言うと,一瞬だけピョコッと出ている信号に相当します.送信側は受信側のACKを受信してから次の1バイトを送信するので,ACKが帰ってこないと通信が進みません.


続いてリピートスタートコンディション.
I2Cの通信は,前述のスタートコンディションから始まり,スレーブアドレスとR/W情報の送信,データのやり取りの後,ストップコンディションという,スタートコンディションとは反対にSCLが上がっている時にSDAを上げることで,「通信終了ォ!」とマスタが宣言し,終了します.
この一連のやりとりの中で,最初にスレーブアドレスと同時にR/W情報も送信しているので,一連の過程において送信者,受信者の立場は固定されています.ここで,通信中に立場を変えたい場合(最初に読みたいアドレスを送り,帰ってくる情報を見たい等)があります.
この時は,ストップコンディションを発行せずに,再びスタートコンディションを発行し,R/Wビットを変更することで実現できます.この時に発行するスタートコンディションの事を,リピートスタートコンディションと呼びます.

赤枠の部分,SCLが上がっているタイミングでSDAが下がり,スタートコンディションが発行されていますね.

f:id:protocol1964:20170220231727j:plain


I2Cよく知らんけどとりあえず使ってるという人でも,これで前述の通信タイミングの説明を理解できるかと思います.

さて,まずは実際に動いたソースがこちら

#include "mbed.h"

Serial pc(dp16, dp15);
I2C i2c(dp5, dp27);

int main() {
    i2c.frequency(20000);
    while(1){
        char recieve[3];
        i2c.start();
        if(i2c.write(0xb4)){
            if(i2c.write(0x07)){
                i2c.read(0xb5, recieve, 3);
            }
        }
        i2c.stop();
        int h = recieve[1] << 8;
        int l = recieve[0];
        int tmp = h+l;
        float temp = (((float)tmp * 2.0) - 27315.0)/100.0;
        printf("temp:%f\n\r", temp);
        wait(0.5);
    }
}

ifの中でwriteを実行していますが,多分ちょっと違うと思うのであまり気にしないでください.実行順序の参考程度に.

まず,I2Cのクロック周波数について,データシートにはこう書いてあります.

f:id:protocol1964:20170220231138p:plain

100kHz〜10kHzで使ってね!とのことですが,10kHzだと通信がうまく行きませんでした.適当に設定しましょう.

あとは指示されたタイミング通りに関数を叩くだけです.


まずスタートコンディションを発行するために,i2c.start()を実行.

次にスレーブアドレス0x5aと,書き込みを示す0を送信するため,i2c.write(0xb4)を実行します.0xb4とは,要はこういうことです.

f:id:protocol1964:20170220233546p:plain

次に,アドレス0x07を送信します.詳細はデータシート8.3.4項まで.


ここで,i2c.write()の連続送信を使って0xb4と0x07を送ればええやん!と言われる気がします.
i2c.write()の連続送信を用いると,スタートコンディションとストップコンディションが自動発行され,送信するだけならこの関数1つ叩けば終わります.ただ,送信後にリセットスタートコンディションを発行したいので,ストップコンディションが自動発行されるのはマズイ.

i2c.write()の4つ目の引数をtrueにすれば,連続送信後にストップコンディションが自動発行されずに済むハズなのですが,オシロで見てみると何故かストップコンディションが発行されている…ので,このような形になりました.もしかしたら,ここらで悩んでいた時に設定していたSCLの周波数が遅すぎて不具合があったのかもしれません.


さて,アドレス,データの送信まで終わったので,再びスタートコンディションを発行して,今度は読み取りです.
3バイトが連続で送られてくるので,i2c.read()の連続受信を使用します.アドレスは上の図と同様に,Readの1を当てて0xb5です.
i2c.read()の連続受信ではスタートコンディションが自動発行されるので,i2c.start()は省略しています.

3バイト受信し,最後にi2c.stop()でストップコンディションを発行して終了です.記事書きながら思ったのですが,i2c.read()の連続受信はストップコンディションを自動発行するはずなので,i2c.stop()はやらなくても良い気がします.

最後に,受信したデータを計算することで摂氏温度へ変換します.


…と,このような感じで動かせました.

センサの特性上,物体から離れるほど検知する温度は低くなっていき,対象物の材料によって放射率も変わってくるので,そこらへんは要調整ですね.

大会まで1ヶ月ちょい.この調子で大丈夫なんだろうか…


[追記]
ググったらmbedライブラリが出てきた.なんで調べなかったんだろう… mbed恐るべし
MLX90614 I2C Infrared Thermometer | mbed

unity-socket-ioでアドレスを変えたい

unityでsocket.ioを使うには以下のアセットを使っています.

github.com

使い方は調べれば出てくるので割愛します.

で,prefabをとりあえずsceneにぶちこむとこうなりますね.

f:id:protocol1964:20170204101607p:plain

基本的にはこの SocketIOComponent の url を任意の値にして実行するのですが,実行毎にアドレスが変わるとか,定まってないときのメモ.

GameObject.Findとかでオブジェクトを取得して,SocketIOComponentのurlを直接変えればいいじゃんと思ったんですが,これ初期値をずっと引っ張るっぽいですね.

ということで,prefabのurlをスクリプトから変えてあげて,そいつをInstantiate.

url間違えたー!とかいう場合は,一旦Destroyしてあげて,prefabのurl直してもう一回生成.

完全勝利2017

あけましておめでとうございます.

2016年は本当にあっという間にすぎてしまい,なにもできずに終わってしまった1年間でした.今年はものづくり,開発,勉強を怠らず,積極的に知識を磨いていきたいと思います.

意識高い挨拶はここまでとして,2016年末にこんなものを作りました.

https://protocol1964.github.io/perfect-victory-2017/

github.com

ガンダムUCの「UNICORN」で新年を迎えるためのサイトです.完全勝利2016に引き続き,今回で2度目となります.

簡素な作りなので特にこれといった技術的な話はありませんが,身内だけで済ませようと思っていたものが意外と他の界隈に飛び火してしまい,若干怖かったです.

完全勝利2016では何故か私だけ完全勝利できずに悲しい思いをしましたが,今年は無事成功したので,実りのある1年となりそうです.

ちなみに,完全勝利2018ではサイト内チャット(赤字兄貴)の実装や,途中参加を可能にしたりと,色々とやりたいことが浮かんできたので,また12月頃に新しく作ろうと思います.今回同様githubで公開するつもりなので,何かあったら気軽にプルリク送ってください.

スペクトラムアナライザの筐体を作り直した

こんにちは.

過去の記事でスペアナを作りましたが,あまりにも筐体がお粗末だったので作り直しました.回路はそのままです.

参考記事

sut.hatenablog.com

筐体の完成品はこちら

 

結構製品っぽくできたんじゃないでしょうか.個人的には結構気に入っています.

裏面

 

筐体の素材はカナセライトのアクリル板です.今回は2mm厚.AutoCADで図面を書いて,CNCフライスで切削しました.CNCほんとすごい…

裏面の部品がこちら

 

基板を突っ込んだ姿

 

相変わらずLEDアレイの接触不良に悩まされています.叩けば治るんですがね…

CNCフライスを使って得た知見として,アクリサンデーは切削には向きません.エンドミルとの摩擦でだんだん溶けてきて,最終的には凄いことになります.エンドミル2本くらい葬りました.

とりあえずこのスペアナはここで完成として,改良版は左右チャネルを分割しようかなと検討中.周波数帯の分割も増やしたいので,ユニバーサル基板だと色々無理がありそう.なので配線を高密度で設計して発注しようかなと.エッチングも無理がありますからね…

とりあえず,春休みの機会に作れればいいなぁ