Arduinoで安くてオトクに簡単無線通信(315MHz編)

# こんな方にオススメなお話

無線通信したいけど、
XBee(*1)さんは¥2,500くらいして安くなったにせよ大量につかうと割高だし、
ESP-WROOM-02さん(*2)は¥1,000以下で安いけどWifiでネットワーク組むほどは...
とよくばりなアナタに。

消費電力おさえめで、ネットワーク組むほど賢いのは不要、
ついでにいうと送信だけとかでもokですよ！って方には恐らくベストな選択肢、
315MHzさんのお話です。

※ あとは通信速度もとめてたり、通信距離求めている場合は微妙かも。

# ひつようなもの

![](https://docid81hrs3j1.cloudfront.net/contents/large/789_201602_102.jpg)
Arduino UNO x 2
https://www.switch-science.com/catalog/789/

![](http://www.aitendo.com/data/aitendo/_/70726f647563742f32303132303332395f3836363631382e676966003235300000660066.jpg)
送信モジュール(315MHz) [RF315-TX5-R]
http://www.aitendo.com/product/4138

| VCC | 1.8 - 3.6V |
|:-----------------|------------------:|:------------------:|
| 動作電流 | 10mA |
| 外形寸法 | 11.0 x 16.0 x 5.0mm |

![](http://www.aitendo.com/data/aitendo/_/70726f647563742f633734313231343365362e676966003235300000660066.jpg)
受信モジュール（315MHz） [RF315-RXB12]
http://www.aitendo.com/product/2607

| VCC | 3.3 - 5.0V |
|:-----------------|------------------:|:------------------:|
| 動作電流 | 2.5 - 2.7mA | 
| 出力 | 300 - 500m | 
| 外形寸法 | 30.0 x 8.5 x 5.0mm |
| バンド幅 | 200KHz |


# 配線

## 送信側

![15725349_10210964879495655_2123920786_o.jpg](https://qiita-image-store.s3.amazonaws.com/0/2915/29ce1883-00da-818e-e157-7f4c932dd72e.jpeg)

| Arduino UNO | 送信モジュール側(RF315-TX5-R) |
|:-----------------|------------------:|:------------------:|
| 3.3V | VCC |
| D12 | DATA |
| GND | GND |

&nbsp;

## 受信側

![15540128_10210964879255649_1344473852_o.jpg](https://qiita-image-store.s3.amazonaws.com/0/2915/f286eba3-4dfb-69a7-a2f2-2b9415018c82.jpeg)

| Arduino UNO | 受信モジュール（RF315-RXB12) |
|:-----------------|------------------:|:------------------:|
| 3.3V | VCC |
| D11 | DATA |
| GND | GND |


# ソース

送受信は、お手軽無線用モジュール VirtualWire をつかいます。
https://www.pjrc.com/teensy/td_libs_VirtualWire.html

## 送信側
```c:send.ino
/**
 * 315MHz通信モジュール 送信側プログラム
 * 使用デバイス: RF315-TX5-R
 * /
#include <VirtualWire.h>

#define SEND_PIN 12 // D12

void setup() {
  vw_set_tx_pin(SEND_PIN);
  vw_setup(2000);
}

void loop() { 
  int numData = 25;
  char datas[numData];
  for (int i=0;i<numData;i++) {
    datas[i] = i;
  }
  vw_send((uint8_t *)datas, numData);
  vw_wait_tx();
}
```

送信データが少ない場合(2byteずつ送るとか)、
vw_setupの2000msを6~7000msくらいまで上げると、
送信速度があがるようです。

上の例のように複数バイト送る場合は、2000くらいが安定です。
データ量、主観的評価なので誤差はあると思いますが、
一度に送る送信量は25くらいがmaxで、30とか送ると届かなくなったりした気がします。


## 受信側
```c:recv.ino
/**
 * 315MHz通信モジュール 受信側プログラム
 * 使用デバイス: RF315-RXB12
 * /
#include <VirtualWire.h>

#define RECV_PIN 11

void setup() {
  delay(1000);
  Serial.begin(9600);
  Serial.println("receiver setup");

  vw_set_rx_pin(RECV_PIN);
  vw_setup(2000);
  vw_rx_start();
}

void loop() {
  uint8_t buf[VW_MAX_MESSAGE_LEN];
  uint8_t buflen = VW_MAX_MESSAGE_LEN;
  if (vw_get_message(buf, &buflen)) {
    Serial.print("Got: ");
    for (int i = 0; i < buflen; i++) {
      Serial.print(buf[i], DEC);
      Serial.print(' ');
    }
    Serial.println();
  }
}
```

# おまけ

文字列の送信をしたい方向けのサンプル落ちてたので、ぺたり。
http://www.buildcircuit.com/how-to-use-rf-module-with-arduino/

めでたしめでたし。

[^1] ... https://www.switch-science.com/catalog/996/
[^2] ... https://www.switch-science.com/catalog/2346/


# おまけ その2(ちょっっとだけ省電力化)

VDDを送信するときだけ流すようにすることで、
ちょっとだけ省電力化(ってほど変わらなかった気もしますが…)。

ちなみにテストは下記のArduino Pro mini 3.3V 16MHzつかいました。
http://www.tinyosshop.com/index.php?route=product/product&product_id=275

| 通常時(アイドル時) | 送信時 |
|:-----------------|------------------:|:------------------:|
| 約10mA | 約17mA |

ソースは下記になります。

```c:send2.ino
/**
 * 315MHzのモジュール簡易送信プログラム
 * VDDに3.3V常時接続ではなく、SEND_EN_PINとVDDつないで通常時はlowにして省電力にするバージョン
 */
#include <VirtualWire.h>

#define MY_ID 90
#define SEND_PIN 2 // DATA <-> D12
#define SEND_EN_PIN 3 // VDD <-> D3

#define PACKET_ID 0
#define PACKET_TYPE 1
#define PACKET_DATA 2

#define SEND_INTERVAL 10000

unsigned long sendTimer;

void setup() {
  pinMode(SEND_EN_PIN, OUTPUT);
  digitalWrite(SEND_EN_PIN, LOW);

  vw_set_tx_pin(SEND_PIN);
  //vw_set_ptt_inverted(true);
  vw_setup(2000); // Bits per sec
}
 
void loop() {
  if (millis() - sendTimer > SEND_INTERVAL) {
    digitalWrite(SEND_EN_PIN, HIGH);
    delay(50); // wait for wakeup

    for (int j=0;j<10;j++) {
      int numCount = 25; // 25くらいがmax、30とかにすると落ちる
      char counts[numCount];
      counts[PACKET_ID] = MY_ID;
      counts[PACKET_TYPE] = j * 10;
      for (int i=PACKET_DATA;i<numCount;i++) {
        counts[i] = i;
      }
      vw_send((uint8_t *)counts, numCount);
      vw_wait_tx(); // Wait until the whole message is gone
    }
  
    digitalWrite(SEND_EN_PIN, LOW);

    sendTimer = millis();
  }
}
```



以下、コメントでご指摘いただいたので追記します(2017.08.01)。
製品自体には問題はありませんが、ちょっとアンテナを工夫するだけで軽く微弱の範囲を超えてくるものです。
電波障害を起した場合、使用者が法的責任を問われる可能性がありますので、ご注意ください。