Arduinoだけで和音を鳴らす方法

f:id:inajob:20200103112556p:plain

はじめに

私はRakuChordというArduinoを基にした電子楽器を作っています。

RakuChordはArduinoたった1つでキーの押下の読み取り、ディスプレイの制御、音の生成を制御しています。

inajob.github.io

この記事では、RakuChordでどのように和音を生成しているか?ということを解説していきます。

 

実はこのRakuChord。初期バージョンは10年前くらいで、和音のロジックもそのころから少しずつ改良を加えてきています。

しかし、どこにもドキュメントを残さずにここまで来たため、自分でもなぜこのソースコードで和音が鳴っているのかよくわからなくなることがありまして・・・自分の備忘録的な意味も込めてこの記事を書く事にしました。

Arduinoで「単音」 

【永久保証付き】Arduino Uno

【永久保証付き】Arduino Uno

  • メディア: Personal Computers
 

Arduinoで「単音」を出すのはとても簡単です。最も簡単なのは無限ループを作り、そこでdigitalWriteであるピンの出力を上げたり下げたりする方法です。そのピンにスピーカをつなげることで、単音を再生することができます。

適切に待ち時間を入れることで、これだけで単音を鳴らすことができます。

例えば440Hz(ラの音)を鳴らす時は 1/440秒の半分の待ち時間を入れてdigitalWriteでHIGH/LOWを繰り返せばよいのです。

f:id:inajob:20200104181608p:plain

void setup() {
  pinMode(9, OUTPUT);
}

bool flip = false;
void loop() {
  flip = !flip;
  digitalWrite(9, flip);
  delayMicroseconds(2272/2); // 1/440 = 0.0022727... = 2272uS
}

この方法では、音を鳴らしている間はほかの処理を行うことができません。

しかしArduinoの関数であるtoneを使うとこの問題も解決します。toneは周波数を指定すると即座に処理が終わり、次の命令を実行することができますが、音は鳴り続ける。という動作をします。

void setup() {
  pinMode(9, OUTPUT);
  tone(9,440);
}

void loop() {
// ここで処理中も音は鳴り続けている }

https://www.arduino.cc/reference/jp/language/functions/advanced-io/tone/

例えばゲーム機などを作る際、簡単なBGMであればtoneで十分です。

Arduinoで「和音」

Arduinoで「和音」というのは「単音」の時ほど簡単ではありません。

和音を鳴らすためにはいくつかの方法が考えられます。

1. 複数のピンを使う

和音の数だけピンを使い、オペアンプなどで合成したのちにスピーカーとつなげることで和音を鳴らすことができます。この方法は「単音」を複数並べるという点で単純でわかりやすいですが、ピンをたくさん使うことや、音の合成のためにオペアンプなどの部品が必要なことがデメリットです。

2. ソフトウェアで合成する

今回紹介するのはこちらの方法です。この方法では1つのピンの出力で和音を演奏する方法です。ソフトウェアの処理が複雑になりますが、単純な回路で和音を再生することができます。(音量が小さくて良いなら、それこそArduinoに直接スピーカをつなげるだけでもOKです)

2.1 既存のライブラリ

ソフトウェアで和音を合成するためには、これから紹介する「1から処理を書く」方法とは別に、既存のライブラリを利用することもできます。


2.1.1 Mozzi

MozziはArduinoで利用できるシンセサイザーライブラリとして非常に有名なものです。下記ページで大量のサンプルを聞くことができます。

おそらく音関係でやりたいことの大半は、このライブラリを使うことで実現できます。

このライブラリは音を扱う様々な処理の詰め合わせセットのようなものです。そのため単に「和音を鳴らしたい」という場合でもそこそこのプログラミングが必要となります。単純に和音を鳴らしたい場合はこの後紹介する別のライブラリのほうが簡単に実現できると思います。

一方、単純な和音ではなく、「音作り」にこだわりたい人にとってはMozziの豊富な音関係の関数群は非常に強い武器となるでしょう。

sensorium.github.io

2.1.2 PWMDAC_Synth

PWMDAC_Synthはまさに「Arduinoで和音を鳴らす」ことに特化したライブラリです。6重和音を扱うことができ、さらにエンベロープも設定できます。 

https://ja.osdn.net/users/kamide/pf/PWMDAC_Synth/wiki/FrontPage

2.1.3 VRA8-Pシリーズ

VRA8-Pで利用できる3音を扱えるシンセサイザーのライブラリです。ArduinoのCPUをフルに使うことで、ほかのライブラリを圧倒する高音質を実現しています。

ただし、この音源はArduinoのメモリ・CPUをかなり占有してしまうため、何かのロジックと組み合わせる場合は注意が必要です。場合によってはArduinoを2つ並べるなどして、片方は制御、片方はVRA8-Pを用いた音源、というような使い方のほうが良いかもしれません。

github.com

2.2 自分で和音を鳴らす処理を書く

既存のライブラリでは「痒い所」に手が届かない場合や、メモリ・CPU使用量を細かく調整したい場合、和音の合成処理自体に興味があるような場合は、自分で和音を鳴らす処理を書く事のがおすすめです。

ということで、以降RakuChordの音源での和音の処理について解説していきます。

RakuChordの音源のソースコード

RakuChordのファームウェアオープンソースで公開しています。

音源周りの処理は https://github.com/inajob/rakuchord/blob/cc088ecfc711f7f432e1a3cc55a3f5a8bb0b9c37/firmware/src/MultiTunes.cpp にまとめています。

ここからは、このソースコードを眺めながらArduinoで和音を鳴らす方法を紹介します。

soundSetup

 この関数が音を鳴らすための準備をするものです。起動時に1度だけ呼び出すことを想定しています。

内部では和音合成に必要なタイマーのセットアップを行っています。

RakuChordで使うのはArduinoのピンのうちDigitalの9番ピンです。まずは9番ピンをOUTPUTに設定しています。

 

次にタイマーの設定を行います。このタイマーは9番ピンのPWMの制御と、和音の波形の計算のタイミング制御のために利用しています。

Arduinoが使用しているマイコンATMega328には複数のタイマーが存在しますが、ここではTimer1を使用します。

Timer1の設定のためにはTCCR1AとTCCR1Bという2つのレジスタを用います。このレジスタの特定のビットを上げたり、下げたりすることでTimer1の挙動を設定します。

ここでは下記のような設定をしています。

  • WGM13~10 = 0001
    • 8bit位相基準PWM
  • COM1A1~0 = 10
    • カウントアップ比較一致でLOW、カウントダウン比較一致でHIGH
  • CS12~10 = 001
    • 分周なし

 ちょっとこれだけでは何を言っているかわかりませんね・・もう少し解説します。

分周比

 Timer1はTCNT1の値を適当な間隔でインクリメントしたりデクリメントしたりする仕組みです。具体的にどのようにTCNT1を動かすのかは後ほど説明しますが、その間隔について指定するときに用いるのが分周比です。

ATMega328が動作している周波数に対しての比率でこの間隔を指定します。

今回は「分周なし」の指定なので、Arduinoに搭載されている水晶発振子である16MHzの間隔でTCNT1を動かすことになります。

8bit位相基準PWM と 比較一致

WGM13~10によりTCNT1をどのように動作させるかを指定しています。

今回は8bit位相基準PWMという指定です。このモードではTCNT1は0から1ずつカウントアップしていき0xff(8bitの上限)までカウントアップしたら次は1ずつカウントダウンしていきます。そして0まで下がったらあとは繰り返しです。

オーバーフロー割込みは0xffに達したタイミングで実行されます。

つまり図にするとこのような感じです。

f:id:inajob:20200103105132p:plain

 

COM1A1~0,はTCNT1の動作と連動してデジタル9番ピンにどのような信号を出力するかを設定しています。今回は「カウントアップ比較一致でLOW、カウントダウン比較一致でHIGH」を指定しています。

比較に用いる値はOCR1Aレジスタの値です。

つまり図にするとこのような感じです。

f:id:inajob:20200103105625p:plain

このようにタイマーと連動してデジタル9番ピンを制御することで、非常に高速にピンをHIGH/LOWに切り替えることができます。またOCR1Aの値を変更することで、ON/OFF時間の比率を変更することができます。

これがPWM(Pulse Width Modulation)というテクニックです。このように短い間隔でHIGH/LOWを切り替えることで、HIGH(5V)とLOW(0V)という2種類の値しか出力できないデジタル回路においてアナログっぽい値を作ることができます。(厳密にはアナログとは違いますが・・)

 このPWMを使うことで、単なる矩形波よりも複雑な様々な波形を生成することができます。もちろん「和音」も「波形」であらわすことができるため、そのような信号をPWM作ることで和音を鳴らすことができます。

タイマー割込みの設定

最後にこれらのタイマーを有効にするためにTIMASK1にTOIE1のビットを設定します。これでTCNT1が上限に達したときに割込みが発生します。 

TIMER1_OVF_vect

今回利用するTimer1のオーバーフロー割込みはこの名前で呼び出されます。

ここまでの話を総合すると16MHzでTCNT1が0 → 0xFF → 0と繰り返し変化していきます。 これを1周期とするとこの1周期にかかる時間は

f:id:inajob:20200103110223p:plain

となります。

ソースコード上ここでTCNT2に値を代入しているが、これは何の意味もなさそう・・・)

基本的にはこの割込みルーチンの中でdn[x]にd[x]を足していきます。xは0~4の5通りあり、これがオシレータを表しています。つまり独立した5つの音を制御しているということです。

最終的にはこのdn[x]から波形テーブルを引いて、5つあるそれぞれの結果をすべて足し合わせてOCR1Aレジスタの値として設定しています。

dn,dと音程

dn[x]とd[x]はunsigned intです。つまり16ビットの値です。

先ほど見たように割込みルーチンの中でdn[x]にd[x]をどんどん足していきます。

このd[x]はRakuChordの鍵盤の押下により「音程に対応した値」が代入されています。

「音程に対応した値」というのはhttps://github.com/inajob/rakuchord/blob/cc088ecfc711f7f432e1a3cc55a3f5a8bb0b9c37/firmware/src/tones.hに定義しています。

このソースコードによると「音程に対応した値」というのは周波数そのものとなっています。(NOTE_A4が440、NOTE_A5が880となっていることからも、これが良く知っている周波数と同じであることがわかります。)

一方、d[n]の値は割込みルーチンの中で、上位6ビットを使ってテーブルを引いています。

波形テーブルは64サンプルで1波形を表しています。dn[x]は16ビットですが、その上位6ビット(0~63)を取り出すことでこのサンプルを読みだしています。

d[x]の値を変数としてdn[x]が何回の割込みで1周するかを計算します。

f:id:inajob:20200103110252p:plain

割込みの発生間隔は上で求めたので、これを掛け合わせることで波形1周期にかかる時間が計算できます。

f:id:inajob:20200103110338p:plain
式を変形します

f:id:inajob:20200103110357p:plain

波形1周期にかかる周波数を求めます(↑の逆数)

f:id:inajob:20200103110420p:plain

これによりd[n]の値は周波数をだいたい2で割ったものとなります。

つまり実際にはd[n]の値の表す周波数より1オクターブ低く、かつ少し誤差のある音が鳴っていることがわかります。

オーディオアンプ

どの方法をとったとしても、Arduinoのピンから出てくる信号のレベルは低いものです。イアホンや小さなスピーカであれば何とか音が鳴りますが、大きな音を鳴らしたい場合は、Arduinoとは別にオーディオアンプが必要です。

RakuChordではLM386というICを利用してこれを実現しています。

調べるとLM386を採用したオーディオアンプのモジュールも販売されているため、回路を作るのが面倒な人は、これらを使うのが良いでしょう。

まとめ

Arduinoで和音を生成する方法を紹介しました。

この方法は私が様々なライブラリや、タイマーの仕様を読んで試行錯誤して作成したもので、この方法が唯一の方法ではありませんが、Arduinoで1から和音を生成したい人にとっては試行錯誤の足掛かりとなるのでは、と考えています。

(もっと良い方法や、間違いなどがあれば教えてください。→https://twitter.com/ina_ani) 

 

Arduinoでちょっとリッチな音が鳴るようなガジェットを作りたい人の助けになれば幸いです。

 

2019年まとめ

f:id:inajob:20191226114018p:plain
ピックアップニュース

今年はいくつかのトピックに分けて個人的なニュースを紹介します。バズった1年、通販の1年、表面実装の1年、継続の1年、健康の1年、出版の1年と、様々な点で楽しく充実した2019年でした。

バズった1年

今年はとにかくバズりました。特に家事スプレッドシートの件はねとらぼでも記事にしていただいたり、その結果Yahoo!ニュースに載ったりと、普段できない体験ができました。

 

家事スプレッドシートがバズる

パンツのゴムを通すやつがバズる

アドベントカレンダーの記事「Kubernetesの中にLinuxデスクトップ環境を作る」がややバズる

qiita.com

通販の1年

昨年はイベントで販売したRakuChordですが、今年は通販に挑戦しました。3月と9月に販売しましたがいずれも即完売ということで幸先の良いスタートとなりました。

初めての通販ということで、多くの知見を得ることができました。

inajob.hatenablog.jp

inajob.hatenablog.jp

note.com

inajob.hatenablog.jp

表面実装の1年

昨年まではスルーホール部品のみを使った電子工作をしていましたが、今年は表面実装に挑戦しました。4月に単4電池1本で動くArduino基板を作り、その後は電子ゲーム機HACHIBARを3回、設計を変えつつ基板発注しました。もう少しで表面実装作品の販売ができそう?というところまで経験を積むことができました。

inajob.hatenablog.jp

www.shumi-tech.online

継続の1年

昨年に引き続きKubeWeekly読書メモをほぼ毎週更新することができました。(これは業務だったりもしますが・・)加えて今年は海外の電子工作事例を紹介するブログを開設し、こちらはほぼ平日毎日更新することができました。

ここ最近の自分の関心である「Kubernetes」「電子工作」についてインターネット上で一定の発信力を示せたのでは?と考えています。

qiita.com

inajob.netlify.com

健康の1年

ここ数年続けている「朝のラジオ体操」、「ダンスダンスレボリューション」を実施し、「ダンスダンスレボリューション」については途中で「Wii Fit」に切り替え、さらなる健康を獲得しました。(週末30minジョギングはなかなか継続できません・・)

inajob.hatenablog.jp

出版の1年

これは今年というよりは去年頑張ったのですが、私が共同執筆として名を連ねる本が2冊発売されました。書籍の執筆という非常に面白い経験を得ることができました。(興味がある人は買ってくださいね!)

みんなのDocker/Kubernetes

みんなのDocker/Kubernetes

 

ステータス

  • 引っ越してから3年目
  • 会社に入ってから10年目(来年で11年目)
  • 結婚してから3年ちょっと

今年学んだスキル

  • 電子工作キットの通販
  • 表面実装基板の作成、発注

月別振り返り

1月

2月

3月

4月

5月

6月

7月

8月

9月

10月

  • HACHIBAR 試作3回目

  • inline-editor改良

    inajob.github.io

  • スピーカーボックスを自作

  • 同人ハードウェアミートアップ参加
  • RakuChord爆音化改造

11月

12月

参考

 

Nu:Tekt NTS-1 digital kitでサウンドプログラミング入門 #KORG #NTS1

Nu:Tekt NTS-1 digital kit

Korgが発売している1ボイスのハードウェアシンセサイザーです。

組み立て式のキットとして販売され、1ボイスのオシレータ、それにつながるフィルタとエンベロープ、さらにモジュレーション、ディレイ、リバーブといったエフェクトをかけることができます。

 外部からのオーディオ入力もサポートしており、外部音源に対するエフェクタとしても利用することができます。さらに、テンポシンクのための入出力、MIDI入力、USB(MIDI)とインターフェースも豊富です。

極めつけはカスタムのオシレータ、モジュレーションが作成・利用できるという機能まであります。

RakuChordなどで音を生成するプログラムをちょっと書いたことがある私にとっては、「プロ」の作ったシンセサイザーのハードウェアからソフトウェアまでを触ることができるこの製品は非常に魅力的でした。

組み立て

f:id:inajob:20191128231310p:plain

まずは組み立てです。といってもはんだ付けなどは必要ありません。

まずは基板兼ケースとなっているパネルを折り曲げて分離します。(辺に折り曲げてしまうと取り返しがつかないのでここが一番緊張しました。)

f:id:inajob:20191128231345p:plain

それからそれらをねじで止めて、鍵盤となるリボン抵抗をコネクタで接続し完成です。

USBコネクタに電源をつなげると起動し、鍵盤をタッチすることで音が鳴ることが確認できました。

f:id:inajob:20191128231413p:plain

音を出して遊ぶ

鍵盤を押すと、当然それに対応した音が鳴ります。しかしこのリボン抵抗は細かい操作ができず、音出しのテストくらいしか使用に耐えません。USB/MIDI接続を使いMIDIホストと接続することで、この問題は解消できそうです(まだ試していない)

しかしアルペジエータの機能を使うことで、それっぽいメロディをNTS-1だけでも演奏することができます。

プリセットのオシレータを使い、フィルタ、エンベロープをぐりぐり動かすだけでもかなり面白いです。

エフェクタとして遊ぶ

オーディオ入力端子に自作電子楽器のRakuChordをつなげて、エフェクタとして利用してみました。

モジュレーションのコーラスエフェクトやリバーブは音に深みが出て非常に面白いです。

ディレイはテンポと同期する機能がないため、うまく速度を調整するといい感じに動きますが、合わせるのが非常に難しいです。ぜひテンポと同期できるディレイを実装してほしいと思いました。

オシレータを自作して遊ぶ

プログラマとして見逃せないのがカスタムオシレータの自作です。調べるとNTS-1で利用できるSDKが公開されており、これを使うことでC/C++でオシレータやモジュレータが作れるようです。

github.com

しかし、このSDK、ドキュメントが非常に少なく、また海外・国内ともにあまりチュートリアルのようなものがありません。これは、結構苦労しそうです・・

↓に用意されているスクリプトを使うことでLinux,Windows,macOSそれぞれの環境でNTS-1で利用されているSTM32用のgccをセットアップすることができます。

logue-sdk/tools/gcc at master · korginc/logue-sdk · GitHub

しかし、これらをちゃんとセットアップするのは依存関係も含めて結構手間です。

ということで、まずはこのlogue-sdkの環境をまるっと閉じ込めたコンテナイメージを作成しました。

GitHub - inajob/logue-sdk-docker

このコンテナイメージを使うことで、Dockerをインストールするだけでlogue-sdkの開発を始めることができます。

さて、セットアップは簡単にできるようになったので、いよいよプログラミングです。

オシレータの作成例があるので、これを参考にします↓

logue-sdk/platform/nutekt-digital/demos/waves at master · korginc/logue-sdk · GitHub

このプログラムはよくできていてwaves.hppというファイルにC++のオブジェクトとして、オシレータが実装されており、waves.cppでlogue-sdkから呼び出されるフックの関数を実装しています。

よくできているのですが、SDKの利用方法を学ぶ際にはもう少し簡単な例が欲しいところです。

そこで、とりあえず簡単に「ラ」を鳴らすだけのオシレータを実装してみることにしました。

 

変更したファイルはこれだけ

  • waves.cpp, waves.hpp:これは削除
  • simple.cpp:新しく作成。後ほど説明
  • manifest.json:オシレータの名前やパラメータの設定
  • project.mk:書き換えてsimple.cppを指すように変更

実際にはsimple.cppを作るところ以外はほとんど機械的な変更だけです。

>> code
#include "userosc.h"

uint16_t param1; // オシレータのパラメータ記録用
uint32_t tot; // オシレータの位相の記録用

// このオシレータが起動したときに呼ばれる?
void OSC_INIT(uint32_t platform, uint32_t api)
{
  param1 = 0;
  tot = 0;
}
// オシレータが次の波形を計算するために呼ばれる?
// ynのアドレスからframes分までのメモリに波形を書き込む
// paramsに押された鍵盤の音階や周波数が入っている
void OSC_CYCLE(const user_osc_param_t * const params,
               int32_t *yn,
               const uint32_t frames)
{

  q31_t * __restrict y = (q31_t *)yn;
  // 終了メモリアドレス
  const q31_t * y_e = y + frames;

  // メモリへの書き込みループ
  for (; y != y_e; ) {
    // サンプリングレートは48KHzのようなので、以下の式で440Hzの矩形波が作れる
    // 別途param1を設定することで周波数を変更できるようにしてみる(本当は鍵盤で指定された周波数にすべき)
    float sig = (tot/(48000 / (440 + param1))%2 == 0)?0:1;
   // floatからq31に型変換しメモリに書き込む 
    *(y++) = f32_to_q31(sig);
    tot ++; // 位相を進める(オーバーフローするときに波形が乱れるのであまりよくないような気がする)
  }
}

void OSC_NOTEON(const user_osc_param_t * const params)
{
  // note onの時に呼ばれる
}

void OSC_NOTEOFF(const user_osc_param_t * const params)
{
  // note offの時に呼ばれる
}

// オシレータのパラメータが変更されたときに呼ばれる
void OSC_PARAM(uint16_t index, uint16_t value)
{
  switch (index) { // どのパラメータが変更されたかが入っている
  case k_user_osc_param_id1: //今回はこの変更のみで処理する
    {
      param1 = value; // 0..15 // OSC_CYCLEで使うので変数に入れておく
    }
    break;
  default:
    break;
  }
}
 
<<

 

これが今回の”「ラ」が鳴るだけオシレータ”です。

よく見るととても簡単です。要はOSC_CYCLEでどんどんメモリに次の波形を書き込んでいけばよいわけです。

ビルドは先ほど紹介したlogue-sdk-dockerを使えば簡単にできます。ビルドができると拡張子ntkdigunitのファイルができるので、Librarianという専用ツールでNTS-1に書き込みます。

これでOSCに新しいオシレータが追加されます。

ついでに、このプログラムを改造して押された音階に対応する音が鳴るようにしてみます。

>> code

void OSC_CYCLE(const user_osc_param_t * const params,
               int32_t *yn,
               const uint32_t frames)
{
  q31_t * __restrict y = (q31_t *)yn;
  const q31_t * y_e = y + frames;

  // メモリへの書き込みループ
  for (; y != y_e; ) {
    // osc_w0f_for_note(音階番号, 音階からのずれ周波数?) でオシレータの変分を返す
    // これらは引数のparams->pitchに入っている
    // 参考: https://github.com/korginc/logue-sdk/blob/master/platform/nutekt-digital/inc/userosc.h#L56
    // > high byte: note number, low byte: mod (0-255)

    float w = osc_w0f_for_note((params->pitch)>>8, params->pitch & 0xFF);
    // nowに今の位相が記録されている、これをフレームごとにずらしていく
    now += w;
    // プリセットのウェーブテーブルのnowの位相の値を取り出す
    float sig = osc_wave_scanf(wavesB[param1], now);
    // floatをq32に変更しメモリに書き込む
    *(y++) = f32_to_q31(sig);
  }
}

<<

こんな感じです。osc_w0f_for_noteとかosc_wave_scanfとか、wavesBとかはほかのソースコードを見ながらで書いています。この辺もう少しドキュメントが欲しいところです。(そもそもプリセットのwaves[A-D][0-15]にはどんな波形が入っているか書いてあるドキュメントが見当たらない・・)

 

と、こんな具合でC言語と勘があれば自分でオシレータを作ることができることがわかりました。

 

(ここまでのソースコードhttps://github.com/inajob/simple-oscで公開しています。)

追記: 日本語のドキュメントが公開されました! https://korginc.github.io/logue-sdk/ja/

感想

このガジェットはDTMをたしなむ人はもちろんですが、サウンドプログラミングを学びたい人」にとっても非常に便利なものであると感じました。

音をソースコードで記述する「サウンドプログラミング」ですが、リアルタイムに鳴らそうとすると、たくさんのタスクが並列に処理されるOSの上では案外書きにくいものです。

そこで役に立つのがマイコン上でのサウンドプログラミングです。これまではArduinoやmbedでも似たようなことができましたが、これらはオーディオに特化していないため、パソコンからのMIDI信号受信や、外部音源の取り込み、ディレイを扱うための大きなメモリなど、かなりの周辺機器を自作しないとまともなオーディオプログラミング環境になりません。これにはかなり高度な電子工作、マイコンプログラミングの知識が必要です。

しかしこのNTS-1はこれらの面倒な部分をすべて受け持ってくれて「サウンドプログラミング」の「おいしいところ」だけを扱うことができます。

 

といった感じで、本当にこれはサウンドプログラミング界のArduinoというべき開発環境であると感じました。

また、単純にハードウェアMIDI音源、オーディオエフェクタとしても非常に使いやすいし、品質も良いためプログラミングとは無縁のDTMユーザにもおすすめできます。(まぁ私はDTMユーザではないのでこの部分の評価はほかの人の記事を見ていただくほうが良いです)

 

私は自作電子楽器RakuChordの後段のエフェクタとして、また自作電子楽器の音源の研究という2つの目的でこれからもこのNTS-1を活用していきたいと考えています。

 

記事の中にも書いた通りプログラミング周りはドキュメントなどが少なく、これからの盛り上がりが非常に大事であると考えています。

ぜひぜひ、NTS-1を買った人は得られた知見を公開してもらえると助かります!

 

またTwitterで情報を記載する際にはハッシュタグ#NTS1を使うことをお勧めします(製品名であるNTS-1はハイフンが含まれておりハッシュタグにできないため。)

 

私も自分が発見したことをブログや下記Scrapboxのページにまとめていこうと思うので、NTS-1ユーザの方は見てみてください。

scrapbox.io

 

Amazonで買えます↓ 

 

1年継続!自宅ダンスダンスレボリューションからの1000円追加でWii Fitへの挑戦

1年間継続できました!

去年の11月ごろに購入したWiiダンスダンスレボリューションですが、ここまでの約1年間、なんだかんだと継続することができました!

inajob.hatenablog.jp

(といっても「毎日欠かさず」、とまではいきませんでしたが、「ほぼ毎日」といった感じですが・・)

 

普段からあまり運動をしない私ですが、ダンスダンスレボリューションのおかげでまぁ少しは運動習慣をつけることができたのかなと思います。

 

実施方法は「毎朝3曲踊る」というものです。

f:id:inajob:20191104093700p:plain

上図が典型的な平日の脈拍です。朝8時ごろにガッと上昇しているところがありますが、ここがダンスレボリューションです。その後通勤のためにしばらく高い状態が続き、続いてお昼、そして夕方の帰宅時に上昇しています。

 

(ちなみに上記グラフはFitbit Versaが記録したものです。こうやって運動習慣が可視化されるのは結構面白いのでおススメです。)

Fitbit Versa スマートウォッチ Black L/Sサイズ  [日本正規品] FB505GMBK-CJK

Fitbit Versa スマートウォッチ Black L/Sサイズ [日本正規品] FB505GMBK-CJK

 

遊んだソフト

もともと去年購入時は

こちらのダンスダンスレボリューションフルフルパーティーで遊んでいました。

最近になって、別のソフトも遊んでみようかなと思い

Dance Dance Revolution with MARIO (マットコントローラ同梱)

Dance Dance Revolution with MARIO (マットコントローラ同梱)

 

 こちらのゲームキューブ版のDance Dance Revolution with MARIO(以下 マリオDDR)も購入しました。(中古ですごく安かったので・・)

良く知らなかったのですがWiiではゲームキューブのソフトも遊ぶことができるためソフトとメモリーカードを購入するだけで、遊ぶことができました。

(できればメモリーカードWiiのものが使えると良かったのですが・・)

 

Wii版のダンスレボリューションマットで遊べるかどうかは心配だったのですが、全く問題なく動作しました。

f:id:inajob:20191104095629p:plain

こちらのマリオDDRはマリオにまつわる楽曲や、クラッシック曲をベースにした音楽によるダンスレボリューションです。前述のフルフルパーティーに比べると比較的難易度は易しく、ちょっと物足りない感じがしましたが、よく知っている曲でダンスダンスレボリューションを遊べるという点では楽しかったです。

トラブルはあった?

Wiiやマットが中古ということで、いろいろ 心配事があったのですが、問題が起きたのはこれです。

これはWiiの映像出力をHDMIに変換してくれる非常に役に立つアダプタなのですが、頻繁に抜き差しをしていたこともあり、これのオーディオジャックが内部でもげてしまいました。

f:id:inajob:20191104095304p:plain

幸いにも電子工作の心得があったため、難なくはんだ付けしなおして事なきを得ました。 

Wii本体やマットに関しては1年間遊び続けていますが、特に問題は起きていません。さすが任天堂です。

ダンスは上達した?

ダンスダンスレボリューションが良いのは「自分が進化する」というところです。

購入時は全く歯が立たなかった曲も何度もこなすうちにだんだん踊ることができてくるという体験が楽しく、ここまで継続することができました。

特にダンスレボリューションは1つの曲でも複数の難易度が用意されているため、次から次へとハードルが用意されている感じで、継続していても楽しかったです。

 

フルフルパーティーで「Difficult」の曲は大体A以上は記録できるようになりました「Expert」はなかなか難しく曲によってまちまち・・というところです。

もともと「Basic」の曲が楽しい!くらいのところからスタートしたのでかなりの上達です。

フルフルパーティに関しては難易度がちょうど僕に合っているらしく、まだ楽しめそうです。一方マリオDDRについては、一番難しいモードでも比較的簡単にAがとれてしまい、ちょっと簡単すぎかな、という感じでした。

効果のほどは・・?

こういう健康施策はいまいちわかりやすい効果が出ないものですし、ダンスダンスレボリューション以外の要因も絡んでくるので、効果が出たといっても一概にこれが良かった!ということも難しそうです。なので以下は参考までに・・

足の裏の感覚が変わった

これはダンスレボリューションを始めて1週間ほどで実感があったのですが、歩いているときの足の裏の感覚が少し変わった気がします。今やもうそれが普通になって特に何も感じませんが、何か足の使い方が変わったのかもしれません。

風邪が減った

ここ2-3年本当によく風邪をひきました。まぁそういうこともあって運動習慣をつけようと頑張っていたわけですが、、

今年は例年に比べて風邪をひく回数が減ったように思います。

風邪をが長引くことが減った

上記に加えて体調不良の期間が短くなったように感じます。

朝シャキッとするようになった

ダンスダンスレボリューションは朝行っていたのですが、花粉症のシーズンなどは花粉によるだるさや鼻水が少し楽になるように感じました。

まぁ調べてみると朝に急に運動をすることは健康上あまりよくない、というような話もあるようですが、僕の場合は特に悪いことは今のところ起きていません。

他にも行っている運動習慣

ダンスダンスレボリューションのほかに、毎朝のラジオ体操週末の30minジョギング(これは結構サボりがちですが、、)などを行っています。これら2つはダンスレボリューションより以前から行っていたものなので、上記の気づいた変化はダンスレボリューションによるところが大きいのでは?と考えています。(とはいえ、運動習慣が遅延して影響を及ぼすこともあると思うのでなんともわかりません)

体重は変化なし

僕は体系で言えば「やせすぎ」なので、ダイエット効果は全く期待していませんでしたが、この程度の運動では特に体重が大きく増減することはありませんでした。

ネクストチャレンジ!

そろそろダンスダンスレボリューションはやりつくした感があるので、次は・・・・

Wiiフィット プラス (バランスWiiボードセット) (シロ)

Wiiフィット プラス (バランスWiiボードセット) (シロ)

 

 Wii Fitに挑戦します!(これまた中古ですごく安かったので!)

中古だと1000円くらいでバランスボードと一緒に購入できました!どうせ買うならWii Fit Plusがおすすめです。

f:id:inajob:20191104100527p:plain

購入して数日ですが、早くも背中の筋が痛いです。

1年後、さらに健康になれているといいなぁ。

 

 

Androidを変愚蛮怒専用機にする

これは?

以前Raspberry Pi Zeroを使った携帯型の変愚蛮怒専用機を作成しました。

inajob.hatenablog.jp

しかし、よく考えてみると、ここまで頑張って作ることなく変愚蛮怒を遊ぶ方法がありそうです・・・ そうです スマートフォン を利用するのです。

といっても、遊びたいゲームのiPhone/Android版が存在しないときはどうすればよいでしょうか?

ちょっと調べるとAndroidDebian Linuxを動作させる方法があるようです。

これを利用してAndroid変愚蛮怒を遊ぶ方法を考えてみました。 

f:id:inajob:20191010221624p:plain

AndroidLinux 「GNU Root」

まずはRoot権限なしでAndroid上でLinuxユーザランドを動かす方法を探します。

play.google.com

これを使いました。

注意としては、GNU Rootはもうメンテナンスされていません。そのため新しいAndroid端末ではインストールできません。

代わりにUserLAndというソフトが使えそうです。(ただし僕は古いAndroid端末しかもっていなかったのでGNURootしか使えませんでした。)

play.google.com

 

おそらくこれから紹介する方法はUserLAndでも動作するのでは?と思いますが、確証はないです。

 

GNURootはもう古いアプリなので説明は手身近に・・

 (ここからGNURoot特有の記載です)

Rootfsとして DeibanのWheezyを選択し「Create New Rootfs」をタップ。

するとGNURoot Wheezyというソフトをインストールする画面になるので、そのままインストールします。

その後再びGNURootを起動し「Launch Rootfs」をタップすることでコンソールが起動します。

Root権限が必要な場合は「Launch as Fake Root」にチェックを入れて「Launch Rootfs」をタップするとRoot権限のコンソールが起動します。

必要に応じて2つのコンソールを使い分ける必要があります。 

Debian Wheezyはすでにパッケージリポジトリがarchiveのものしか存在しないのでまずは/etc/apt/source.listを下記のように編集する必要があります。(本当はアップグレードしたいのですが、GNURootがすでにメンテされていないので・・)

dev http://archive.debian.org/debian/ wheezy main contrib non-free
dev-src http://archive.debian.org/debian/ wheezy main contrib non-free

 編集したらapt-get updateしておきます。

さて、ここまででAndroid上にDebianユーザランドを用意することができました。 

 (ここまでがGNURoot特有の記載です)

変愚蛮怒のビルド

変愚蛮怒Linux版はソースコードで提供されています。そのためビルドする必要があるので、必要なライブラリをインストールします。(後で使うのでmake, unzip, curlも入れておきます) 

# apt-get install libncurses5-dev make unzip curl

依存関係でgccやらいろいろ入ります。

 

ここからは一般ユーザで操作します。

変愚蛮怒をダウンロードしてビルドします。

$ cd /home
$ curl -L https://ja.osdn.net/projects/hengband/downloads/10331/hengband-1.6.2.tar.gz/ > hengband-1.6.2.tar.gz
$ tar xzf hengband-1.6.2.tar.gz
$ cd hengband-1.6.2
$ ./configure --without-x
(時間がかかります)
$ make
(すごく時間がかかります)

これで./src/hengbandにバイナリが生成されます。

ここで、./src/hengbandを実行すると、確かに起動するのですが、全体的に文字化けてしまいます。(SHIFT+Qなどで終了できます。)

これは変愚蛮怒EUC-JPにしか対応していないからです。加えてAndroidのTerminalはUTF-8の日本語は表示できますがEUC-JPには対応していません。

 

ここで、役に立つのがcocotです。

cocotのビルド

vmi.jp

cocotは、端末とプロセスの間に割り込んで文字コード変換を行うツールです。これはまさに今欲しい機能です。EUC-JPで動作する変愚蛮怒の出力を受け取り、端末にはUTF-8を返すことで、文字化けを解消できそうです。

こちらもAndroid用のバイナリは存在していないので、自分でビルドします。

$ cd /home
$ curl -L https://github.com/vmi/cocot/archive/master.zip >cocot.zip
$ unzip cocot.zip
$ cd cocot-master
$ ./configure
$ make

特に問題なくcocotもビルドできました。

あとはcocotを通して変愚蛮怒を起動すればよいだけなのですが、なぜか一般ユーザで実行すると「Error: openpty()」などと表示されて実行できないので、rootの端末で作業が必要でした。

 さて、ドキドキしながら起動します。

# cd /home
# cd hengband-1.6.2
# ../cocot-master/cocot -t UTF-8 -p EUC-JP -- src/hengband

 日本語も表示された!

ということでこれでAndroidでも簡単に変愚蛮怒で遊べるようになりました。

ただ、この方法をもってしても、まれに表示の一部が文字化けする起きるようです。まぁゲームの進行に支障がないレベルのものなので、この点は妥協するとしましょう・・

別解: Xで変愚蛮怒を使う

前回Raspberry Piで試したときはX11環境をセットアップしました。Androidでもこの方法で変愚蛮怒を利用することができますが、Androidの容量を非常にたくさん消費するので、あまりお勧めしません。

しかし、もし上記の方法でうまくいかない場合はX環境での実行を試してみるのもよいでしょう。

(といいつつ、詳しい方法はここでは書きません だいたい前回記事のRaspberry Piと同じ方法になると思います。)

f:id:inajob:20191012174818p:plain

おまけ: 3Dプリンタでケースを作る

前回の変愚蛮怒専用機と同様、3Dプリンタでケースを作りました。

f:id:inajob:20191012174138p:plain

f:id:inajob:20191012174201p:plain

スマートフォンの中にバッテリーもディスプレイもCPUも内蔵されているため、非常に簡単な作りで、しかもコンパクトに設計できました。

ちなみにここで使ったキーボードはこちら↓

 まぁ作ってみたのですが、、 意外と使いづらい。キーボードと本体は分離してたほうが遊びやすいですね・・また今後改良していきたいと思います。

まとめ

ということで、物理キーボード付きの変愚蛮怒専用Androidが完成しました。

これで、気軽にどこでも変愚蛮怒が楽しめます!

Oracle Cloud Always Freeで作る 0円Kubernetesクラスタ

これは何?

Oracle社が発表したAlways FreeサービスでKubernetesクラスタを作成する方法を紹介します。

f:id:inajob:20191006162003p:plain

Oracle Cloud Free Tier | Oracle 日本

Oracle Cloud Free Tierはクレジットカードの登録さえすれば、無料でいくつかのリソースを利用することができます。

特に今回利用するFree Tierは

  • 2つのVM(1/8 CPU, 1GB Memory)
  • 10TB/monthの外部通信

です。

 

以前こういう記事を書きました。

inajob.hatenablog.jp

この記事でははVultrというVPSサービスを使い$10でKubernetesクラスタを作る方法を紹介したのですが、そのとき利用したVPSのスペックは 1CPU,1GB Memory のVM2台でした。

 

CPUこそ劣るものの、これでできるならOracle CloudののFreeTierでもKubernetesクラスタが作れるのでは?と考え挑戦してみました。

注意

この手順を使って作るクラスタはインターネットからアクセスできる状態になります。この手順通り実施したとしても様々な攻撃のリスクが存在しています。この手順を実行し起きたいかなる問題も筆者は責任を負えませんので、個人の責任で作業を行ってください。

また、これらの手順を実行した結果によってOracle Cloudへの課金が生じる可能性があります、こちらに関しても筆者は責任を負いません

FreeTierへの登録

ここは割愛します。クレジットカードの登録などが必要です。

また、ここで登録したリージョンが「ホームリージョン」となり、Free Tierで利用できるのはそのリージョンだけになるようです(お金を払えばそれとは関係なくどのリージョンでも利用できます。)

ここFreeTierが発表されてしばらくはJapanリージョンではVMが払い出せない状況にありましたが、ここ数日で払い出せるように回復しているように見えます。

 

追記:この記事を書いている2019/10/06現在、再び払い出せなくなりました。(この症状の時 VM作成時に Out of host capacity というエラーが出ます。)

VMの作成

f:id:inajob:20191006131954p:plain

インスタンス命名は何でもいいです、イメージソースはここではUbuntuの18.0.4にします。また、パブリックIPを割り当てるために「シェイプ、ネットワーク、ストレージオプションの表示」をクリックします。

f:id:inajob:20191006132111p:plain

そして”Assign in public IP address”を選択します。

さらにSSHキーを適切に設定して「作成」をクリックします。

VMが作成できると「パブリックIPアドレスが表示されます。このIPにsshすることで、作成したVMにログインできます。

 

同じ要領でWorkerのVMも作成しておきます。

このようにして作ったVM2台はちょうどAlways Free Tierの要件を満たしており、無料で利用することができます。

これから作るKubernetesクラスタ

f:id:inajob:20191006161646p:plain

master, workerのVMを作り、その2台でKubernetesクラスタを構築します。ingress-controllerをデプロイし、インターネットからそこを経由してクラスタ内のWebアプリケーションにアクセスできるようにします。(0円で)

Kubernetes Nodeの構築

次にKubernetesのNodeとして必要なパッケージのインストールです。これをざざっと実行することで

  • 最新のDockerパッケージのインストール
  • 最新のKubernetesパッケージのインストール
  • Kubernetesとしては非推奨ですが)Swapの有効化とKubeletの設定

が行えます。

apt-get update && apt-get install -y apt-transport-https ca-certificates curl software-properties-common
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

apt-get update
apt-get install -y docker-ce
apt-get install -y kubelet kubeadm kubectl

dd if=/dev/zero of=/swapfile count=2048 bs=1M
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo "/swapfile   none    swap    sw    0   0" >> /etc/fstab

sed -i 's/\/usr\/bin\/kubelet/\/usr\/bin\/kubelet --fail-swap-on=false --system-reserved=memory=100Mi /' /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

systemctl daemon-reload
systemctl restart kubelet

ネットワークの設定(Oracle Cloud)

Kubernetesクラスタを構築する前にネットワークの設定をする必要があります。

必要なポートの設定はInstalling kubeadm - Kubernetesが参考になります。

要するにMasterはWorkerからの6443、MasterからすべてのNodeへの10250が疎通できれば良さそうです。

またこれから利用するオーバーレイネットワークのWeaveNetで利用する6783ポートも開ける必要があります。

 

「仮想クラウドネットワーク」から(おそらくmasterという名前(初めに作ったVMと同じ名前になる?)目的のネットワークを選択し、さらにその中にあるサブネットを選択します(おそらく1つしかないです)。さらに、その中のセキュリティリストを選択し、下記のように設定します。

 

上のほうのルールはもとからあるものです。

f:id:inajob:20191006133749p:plain

ネットワークの設定(iptables

Oracle Cloudの設定とは別に各ホストのiptablesも設定する必要があります。

master

iptablesの設定は既存の設定に依存します。ここまでセットアップしたVMでは例えば下記のようになっているはずです。

# iptables -L INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination
1    ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
2    ACCEPT     icmp --  anywhere             anywhere
3    ACCEPT     all  --  anywhere             anywhere
4    ACCEPT     udp  --  anywhere             anywhere             udp spt:ntp
5    ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:ssh
6   REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

 行番号6のルールより前に通信を許可しないと、通信が捨てられてしまいます。

5行目のような(ここではSSHを許可している)ルールを追加していく必要があります。

iptables -I INPUT 6 -p tcp -m state --state NEW -m tcp --dport 6443 -j ACCEPT
iptables -I INPUT 6 -p tcp -m state --state NEW -m tcp --dport 6783 -j ACCEPT
iptables -I INPUT 6 -p tcp -m state --state NEW -m tcp --dport 10250 -j ACCEPT

 こんな感じで設定します。

Masterの構築

# kubeadm init --ignore-preflight-errors=swap

swapが有効だとうまくセットアップできないので、あえて無視するように設定します。

コマンドがうまく実行できるとkubeadm joinのスニペットが表示されます。

Workerの構築

# kubeadm join <前手順で生成されるものをコピペ> --ignore-preflight-errors=swap

 Workerでは基本的にはスニペットを実行するだけですが、ここでもswapを無視して進めるようにします。

kubectlでのアクセス

kubeconfigをコピーしてきます。(セキュリティ上はあまりよくないですが・・)

# cp /etc/kubernetes/admin.conf /home/ubuntu/
# chmod 644 admin.conf

 以降は一般ユーザで作業できます

 

$ export KUBECONFIG=/home/ubuntu/admin.conf
$ kubectl get nodes

 node一覧が表示されれば成功です。

ネットワークアドオンのデプロイ

 Pod間の通信を可能にするためにネットワークアドオンであるWeave Netをデプロイします。

$ kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"

 

Ingress Controllerのデプロイ

Webサービスを公開するためにIngress Controllerをデプロイします。

ここでは GitHub - zlabjp/nghttpx-ingress-lb: nghttpx ingress controller for Kubernetes を使うことにします。

 

まず該当するingressリソースがない場合に表示する404画面用のPodをデプロイします。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: default-http-backend
  namespace: kube-system
spec:
  selector:
    matchLabels:
      k8s-app: default-http-backend
  replicas: 1
  template:
    metadata:
      labels:
        k8s-app: default-http-backend
    spec:
      terminationGracePeriodSeconds: 60
      containers:
      - name: default-http-backend
        # Any image is permissible as long as:
        # 1. It serves a 404 page at /
        # 2. It serves 200 on a /healthz endpoint
        image: k8s.gcr.io/defaultbackend-amd64:1.5
        livenessProbe:
          httpGet:
            path: /healthz
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 30
          timeoutSeconds: 5
        ports:
        - containerPort: 8080
        resources:
          limits:
            cpu: 10m
            memory: 20Mi
          requests:
            cpu: 10m
            memory: 20Mi

 

apiVersion: v1
kind: Service
metadata:
  name: default-http-backend
  namespace: kube-system
  labels:
    k8s-app: default-http-backend
spec:
  selector:
    k8s-app: default-http-backend
  ports:
  - name: 8080-8080
    port: 8080
    targetPort: 8080
    protocol: TCP

次にingress-controllerが利用するServiceAccountとその権限を設定します。

apiVersion: v1
kind: ServiceAccount
metadata:
  name: nghttpx-ingress-serviceaccount
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: nghttpx-ingress-clusterrole
rules:
  - apiGroups:
      - ""
    resources:
      - configmaps
      - endpoints
      - nodes
      - pods
      - secrets
    verbs:
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - nodes
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      - services
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - "networking.k8s.io"
    resources:
      - ingresses
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - ""
    resources:
        - events
    verbs:
        - create
        - patch
  - apiGroups:
      - "networking.k8s.io"
    resources:
      - ingresses/status
    verbs:
      - update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: nghttpx-ingress-role
  namespace: kube-system
rules:
  - apiGroups:
      - ""
    resources:
      - configmaps
      - pods
      - secrets
      - namespaces
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      - configmaps
    resourceNames:
      # Defaults to "<election-id>-<ingress-class>"
      # Here: "<ingress-controller-leader>-<nginx>"
      # This has to be adapted if you change either parameter
      # when launching the nginx-ingress-controller.
      - "ingress-controller-leader-nginx"
    verbs:
      - get
      - update
  - apiGroups:
      - ""
    resources:
      - configmaps
    verbs:
      - create
  - apiGroups:
      - ""
    resources:
      - endpoints
    verbs:
      - get
      - create
      - update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: nghttpx-ingress-role-nisa-binding
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: nghttpx-ingress-role
subjects:
  - kind: ServiceAccount
    name: nghttpx-ingress-serviceaccount
    namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: nghttpx-ingress-clusterrole-nisa-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: nghttpx-ingress-clusterrole
subjects:
  - kind: ServiceAccount
    name: nghttpx-ingress-serviceaccount
    namespace: kube-system

 最後にingress-controllerをデプロイします。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nghttpx-ingress-controller
  namespace: kube-system
  labels:
    k8s-app: nghttpx-ingress-lb
spec:
  selector:
    matchLabels:
      k8s-app: nghttpx-ingress-lb
  template:
    metadata:
      labels:
        k8s-app: nghttpx-ingress-lb
        name: nghttpx-ingress-lb
    spec:
      serviceAccountName: nghttpx-ingress-serviceaccount
      terminationGracePeriodSeconds: 60
      hostNetwork: true
      containers:
      - image: zlabjp/nghttpx-ingress-controller:latest
        name: nghttpx-ingress-lb
        imagePullPolicy: Always
        livenessProbe:
          httpGet:
            path: /healthz
            # when changing this port, also specify it using --healthz-port in nghttpx-ingress-controller args.
            port: 11249
            scheme: HTTP
          initialDelaySeconds: 30
          timeoutSeconds: 5
        # use downward API
        env:
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: POD_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
        ports:
        - containerPort: 80
          hostPort: 80
        - containerPort: 443
          hostPort: 443
        args:
        - /nghttpx-ingress-controller
        - --default-backend-service=$(POD_NAMESPACE)/default-http-backend
        - --healthz-port=11249
        - --logtostderr

 これで、このクラスタWebサービスをデプロイする準備が整いました。

追加のネットワーク設定

インターネットからの80番アクセスを許可するために追加でネットワークの設定が必要です。

 

f:id:inajob:20191006141934p:plain一番下にある80番ポートについてのルールを追加しました。

 

また、workerのiptablesも合わせて追加の設定が必要です。


iptables -I INPUT 6 -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT

 (INPUT 6の”6”はルールを見て適切な行番号を指定する必要があります。)

 

ここで、手元のPCからworkerのパブリックIPにアクセスをしてみると

f:id:inajob:20191006142222p:plain

このようにそっけない404ページが表示されるはずです。これはKubernetesクラスタ内のPodが返したものです。

Webアプリケーションのデプロイ

最後に、nginxをクラスタ上にデプロイして動作確認をしてみます。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: test-service
spec:
  ports:
    - port: 80
  selector:
    app: nginx
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: test-ingress
spec:
  rules:
  - http:
      paths:
      - backend:
          serviceName: test-service
          servicePort: 80

 これをデプロイしたのちに、先ほどと同様にworkerのパブリックIPにアクセスすると

f:id:inajob:20191006142525p:plain

おめでとう!無事Kubernetesクラスタ上のアプリケーションにインターネットからアクセスできるようになりました。

まとめ

Oracle CloudのAlways Free Tierを使って、Master1台、Worker1台のKubernetesクラスタを作ることができました。

貧弱な構成ですが、無料の範囲内でインターネットからアクセスできるKubernetesクラスタを作れるのは面白いおもちゃになりそうと感じました。

また、Oracle Cloudは初めて使いましたが、普段使っているVPSと遜色なく利用することができ、特段詰まることもありませんでした。

 

2回目のRakuChord(らくこーど)通販、完売しました

このブログでもたまに触れている、僕の制作している電子楽器「RakuChord(らくこーど)」ですが、以前3月に通販してから、かれこれ半年たちました。そして満を持して9/4から第2回の通販を開始していました。

f:id:inajob:20190907174249p:plain

毎日ちょろちょろと売れていき本日9/7に完売しました

 

RakuChordがどんな楽器か?というのは下記の動画が参考になると思います。

さらに詳しい説明は公式ページ(RakuChord(らくこーど) - 楽にそれっぽい演奏ができる電子楽器)を見ていただくとして、本日のブログでは前回からの差分や、今後の展開について紹介しようと思います。

ここまでの歩み

実は開発はかなり昔から行っており2010年の記事があります。

このころはユニバーサル基板に100均のまな板をエンクロージャにしています。

その後、様々な形を検討しています。これは小型化したバージョン。

そしてこちらは長いバージョン

月日は流れ・・

基板を発注できるようになりました。

そして3Dプリンタでケースを作れるようになったことで夢の「キット化」が実現したわけです。

で、2019年3月に初めての通販を実施。

で、今回記念すべき2回目の通販を行ったという流れです。

前回からの差分

バージョン表記

今回からバージョンを数字で表記するようにしました。今回がv1.3ということにしました。今後も変更を加えていくたびにこのバージョンで区別できるようにするつもりです。

互換性

今回販売したものは2019/3に販売したものと構造はほぼ同じで、ソフトウェアについても互換性があります。ということで2019/3バージョンをお持ちの方は最新版のファームウェアに更新することで、RakuChord v1.3を体験することができます。(ソースコードはこちら https://github.com/inajob/rakuchord

前回のハードウェアバグ修正

以前販売時にこのブログでも紹介した(https://inajob.hatenablog.jp/entry/rakuchord-e-commerce)ハードウェアの問題点を修正しています。具体的にはOLEDから発生するノイズを低減するための電解コンデンサを追加しました。

また、前回アドホックに追加したプルアップ用の抵抗も、ちゃんと部品としてフットプリントを用意しました。

アンプの音量増加

LM386周りの回路を見直して、音量が少し大きくなるように回路を改良しました。

組み立てやすさのための修正

前回はスイッチとダイオードが非常に近くにあったため、はんだ付けが難しいところがありました。今回少しマージンを大きめにとったので、前回よりは作りやすくなったと思います。

前回(D19が近すぎる)→f:id:inajob:20190907173641p:plain

今回(程よくマージンがあります)→f:id:inajob:20190907173656p:plain

スイッチのフットプリント変更

メインスイッチのフットプリントを変更し、オムロンの12mmx12mmのスイッチなどが利用できるようになりました。実際はキットに同梱しているスイッチがマウントできれば、まぁそれで十分なのですが、手元ではいろいろなスイッチで試して遊んでいます。

基板の色

バージョンごとに色は変えていきたいなと思い、今回は黄色にしました。思ったより暗い色で、個人的には前回の白のほうが好みです。まぁケースに隠れてしまうのでいいのですが・・

LM386を二個入れた

前回なぜか検品したにもかかわらず、LM386というICが動かない症例が複数あったため、とりあえずキットにはLM386を2つ入れてあります。全く根本対策になっていませんが、ひとまずこれで様子を見ます。

f:id:inajob:20190907190449p:plain

今後の予定

今回も完売ということですが、そろそろ需要があるのか心配になってきました・・、しかし少なくとも次もアップデートしたいことがあるので、引き続き販売を予定しています。

 

「買いたい!」という方は 下記から「入荷お知らせメールを受け取る」をクリックしておいてほしいです。

自作電子楽器 RakuChord(らくこーど) v1.3 - inajobの作品販売 - BOOTH

 この設定は販売者は見ることができるため、今後のRakuChord開発の励みになります。

また「応援したい!」という方は「スキ!」を押していただけると、こちらも開発の励みになります。

追加予定の機能

ここに書いているのはあくまで「案」であり、次のバージョンにすべてが搭載されるわけではないことをご承知おきください。

  • ケースの外からもアクセスしやすい拡張端子(OPシリーズとのSyncや、MIDI出力、外部音源ICの接続、アナログコントローラの追加、などを想定)
  • SMD部品の利用と半完成キット化
  • より扱いやすい筐体

などなど、が今のところ考えている改良です。(SMD化は次のバージョンでは難しいか?・・)

他にもほしい機能があればぜひぜひコメントやTwitterhttps://twitter.com/ina_ani)で教えてください。

 おまけ

こんかいも部品を頑張って数えました。キットはこれがつらい・・

f:id:inajob:20190907190609p:plain