電車でGO!コントローラでSoracom Airの通信速度を変える


# はじめに

アマゾンデータサービスジャパンの瀧澤です。今回は、AWSとは直接は関係のない話ですが、とても興味深いSoracom Airについて触れたいと思います。

[Soracom Air](https://soracom.jp/services/air/)は、IoT 向けのデータ通信 SIM "Air SIM" を提供するサービスですが、特徴の一つに、「データ通信速度をAPIを使い自由に制御可能」というのがあります。通信速度は、このブログを執筆時点で、32kbps、128kbps、512kbps、2Mbpsから選ぶことができ、私が思うにこれは、画期的だなと思っています。IoTデバイスからのデータ量が少ない時は、低速かつ低料金な設定を行うことができ、多くのデータを転送するときには、高速な通信帯域にすることができ、従量課金で請求されます。これをAPIやGUIで制御できるのはとても面白い仕組みだと思います。
さて、この仕組みをシンプルに体感するため、この記事では、「電車でGO!」のコントローラで、通信速度を変えてみたいと思います。
**コントローラをMAXにすると、Soracom Airの通信速度もMAX**になるというわけです。

![aファイル_000.jpg](https://qiita-image-store.s3.amazonaws.com/0/61619/4865cf43-46fa-526f-4868-6d41841d527b.jpeg)


# 用意したもの

- Raspberry piまたはホストとして動作するPC（今回はMacBookを使いました）
- 電車でGO!のコントローラ（N64版）
- Arduino Uno R2
- [Arduino モーターシールド](http://akizukidenshi.com/catalog/g/gM-06684/) （電車でGO!のコントローラでNゲージを走らせないのであれば不要です。）
- Nゲージのジオラマ （電車でGO!のコントローラでNゲージを走らせないのであれば不要です。）


# 仕組み・実現したこと

電車でGO!のコントローラは、「切」から「5」までの6段階のスイッチになっています。この「切」をSoracom Airの「s1.minimum」に割り当て、「1」を「s1.slow」に、「2」を「s1.standard」、「3」以上を「s1.fast」に割り当てて、コントローラレバーを操作すると、Soracom Airの通信速度を変えられるようにしてみたいと思います。
ついでに、コントローラレバーにあわせて、Nゲージのレールに0V-12Vの電圧を加えるために、Arduinoにモーターシールドを加えてみたいと思います。モーターシールドは、arduinoのPWM出力（0-5V）を0-12Vに昇圧し、外部電源で2Aの電力を供給できます。arduinoのPWM出力用のPINに、0を設定すると0Vとなり、255を設定すると5Vが出力されますので、モーターシールドを経由すると、Nゲージを動かすのに必要な0-12Vとなり、Nゲージの列車の速度を変えることができます。

（自分の趣味ではなく、子供にせがまれてて）Nゲージジオラマを作っているのですが、Nゲージの速度の制御とSoracom Airの通信速度の変更をセットにしてみたいと思います。列車の速度と通信速度は関係ないんじゃ？との意見もあると思いますが、実世界では、列車の速度が上がれば、その列車が生成する情報量は増えると思いますので、ジオラマを元に実世界のシミュレーションということで考えてみたいと思います。
なお、ジオラマは作ったことなかったのですが、子供にせがまれて、約1年ぐらい前より、ダラダラと作っているので、その道のプロの方からの指摘は甘んじて受けます。

![ファイル_009.jpeg](https://qiita-image-store.s3.amazonaws.com/0/61619/ba95b4bd-fa4f-0577-991b-1c87b7a25c63.jpeg)

## 電車でGO!コントローラの分解

![aファイル_000(3).jpg](https://qiita-image-store.s3.amazonaws.com/0/61619/64f95432-c513-bbe8-ace7-37196dccaa48.jpeg)![aファイル_000(2).jpg](https://qiita-image-store.s3.amazonaws.com/0/61619/441128cd-0d84-229b-0813-9a96f1f47a1d.jpeg)
まず、コントローラを分解してみました。コントローラ部には、HC148というチップが使われていました。[データシート](http://www.ti.com/lit/ds/symlink/sn74hc148.pdf)によれば、8つのPINそれぞれのHigh/Lowを検出し、3つのPINにHighになったPINの情報を2進数で出力するもののようです。コントローラーが1の位置の場合は、3つのPINでは、001と出力され、5の位置の場合は、101になります。この出力をarduinoのdegital入力PINに接続します。コントローラー分解してチップ確認しデータシート見てラッキー！と思いました。昔のデバイスは、ファーム書き換え可能なチップではなく、シンプルなプログラムモジュールのようなチップであり、簡単に動作を理解することができます。

## arduino + モーターシールドなどの配線

![aファイル_002.jpg](https://qiita-image-store.s3.amazonaws.com/0/61619/62eb79b9-6645-a6cc-50d6-ff14a5453042.jpeg)

arduinoとモーターシールドの接続は、まあ、乗っけるだけです。arduinoは、こういったシールドが充実しているのが魅力ですね。0-12Vで制御可能な出力をNゲージの線路と接続することで、Nゲージの速度を変えられます。そして、電車でGO!コントローラからの配線もarduinoのデジタル入出力PINに接続します。なお、Soracom Airだけを制御するなら、モーターシールドはいりません。
そして、USB経由でホストコンピュータに接続します。ホストコンピュータからはシリアル入出力が可能なので、今回は、MacBookを使いましたがraspberry piを使ったほうが、それっぽい気がします。ホストコンピュータからは、WiFi経由で、モバイルルータに挿入したSoraCom Air SIMで通信を行います。


## コーディング

コーディングはシンプルです。arduino側は、コントローラから読み取った3bitを読みとり、モーターシールドの制御と、0-5の数字にしたデータをシリアルに出力します。
ホストコンピュータ側は、USBシリアル経由できたデータを読み取り、変化があった時だけ、Soracom AirのAPIで速度を変更します。Soracom Airは、RubyのSDKがあるので、今回はこれを使いました。とても簡単です！。
SDKの使用方法、サンプルは、[https://dev.soracom.io/jp/tools/](https://dev.soracom.io/jp/tools/)にあります。

### arduino側

```lang:trainctr.ino
//Arduino PWM Speed Control：
int E1 = 5;  
int M1 = 4; 
int E2 = 6;                      
int M2 = 7;

// Arduino HC148 reciever pin:
int pushButton1 = 11;
int pushButton2 = 12;
int pushButton3 = 13;

int speedvalue = 0;
int dirvalue = HIGH;

int speedvalue2 = 0;
int dirvalue2 = HIGH;
 
void setup() 
{ 
    pinMode(M1, OUTPUT);   
    pinMode(M2, OUTPUT);
    pinMode(pushButton1, INPUT);
    pinMode(pushButton2, INPUT);
    pinMode(pushButton3, INPUT);
    Serial.begin(9600);   
} 
 
void loop() 
{ 
    int speedcommand;
    int controller_speed;

    int buttonState1 = digitalRead(pushButton1);
    int buttonState2 = digitalRead(pushButton2);
    int buttonState3 = digitalRead(pushButton3);
    
    controller_speed = buttonState1 * 4 + buttonState2 * 2 + buttonState3 - 1;
    speedvalue2 = controller_speed * 255 / 5;

    Serial.println(controller_speed);

    digitalWrite(M1, dirvalue);    // Direction         
    analogWrite(E1, speedvalue2);   // PWM Speed Control

    digitalWrite(M2, dirvalue2);    // Direction         
    analogWrite(E2, speedvalue2);   // PWM Speed Control
  
    delay(50);
}
```

### ホスト側

```lang:soracontroller.rb
require 'soracom'
require 'serialport'
require 'pp'

soraspeed = ["s1.minimum", "s1.slow", "s1.standard", "s1.fast"]
oldcommand = 0
commandcount = 0
value= 0

client = Soracom::Client.new(email: 'メールアドレス', password: 'パスワード')

sp = SerialPort.new('/dev/cu.usbmodem1411', 9600, 8, 1, 0) # 9600bps, 8bit, stopbit 1, parity none

loop do
  commandcode = sp.gets
  puts commandcode
  if !(oldcommand == commandcode) then
      sims = client.list_subscribers
      imsis = sims.map { |sim| sim['imsi'] }
      value = commandcode.to_i
      puts soraspeed[value]      
      client.update_subscriber_speed_class(imsis, soraspeed[value])
      oldcommand = commandcode
  end
end
```

# まとめ

**SoracomでGO!コントローラーが完成しました。**
とても簡単に、電車でGO!コントローラでSoracom Airの通信速度を変更することができました。そして、それにあわせて、Nゲージの列車の速度も変わります。なんか、実デバイスでSoracom Airの通信速度が変わり、Nゲージの速度も変わると、ちょっと感動します。触って、目に見えて、裏側の通信速度も変わっているのは、心地よい感覚でした。

応用としては、AWS IoTや、Kinesisを使い、arduino側からのデータをAmazon Web Servicesに送信し、データの可視化や分析をしてみても面白いかもしれません。今回は、ジオラマの中の世界ですが、実世界のコントローラ的な装置から、自由に通信速度を変えたくなるシーンはいろいろある気がしています。
はじめて、Soracom AirのSDKを使ってみましたが、体感することで、その可能性をより実感することができ、アイデアもいろいろとわきました。ぜひ、皆さんも楽しんでみてください。


# 免責

ハードウェアの分解や解析を行うことを勧める記事ではありません。自己の責任で解釈をお願いします。
また、こちらは個人の意見で、所属する企業や団体は関係ありません。