ラジコンサーボを動かそう２

# はじめに

 **まだ執筆途中です**

ここでは，前回に引き続き <font color=red>**ラジコンサーボ**</font> を動かす実験をします。

目次へ戻るには [ここ](https://qiita.com/hsgucci/items/085680123f758c8c3eb4#%E5%AE%9F%E9%A8%93%E6%89%8B%E9%A0%86) をクリック

※本ページは実験のテキストです。

# サーボテスターを作ろう

前回はラジコンサーボが勝手に動いただけでした．
今回は可変抵抗を回すとラジコンサーボが動くようにします．

つまり「サーボテスター装置」を自作するのと同じことになります．

これまでの **8．アナログ入力の解説** と **9．アナログ出力の解説** ， **10. ラジコンサーボを動かそう** を機能的にまとめたプログラムになります．

# 配線

まずは物理的な配線をします．

下の図を参考にしてブレッドボードで配線してください．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/408ab295-1549-0182-da8d-9a8c5adeedfb.png)

この図で問題になるのは，5VやGNDの接続方法です．
GNDの端子は２個あるのでサーボと可変抵抗にそれぞれ配線することができます．
しかし，5Vの端子は１つしかないので，Arduinoからサーボと可変抵抗に直接配線することはできません．
こんなときには，ブレッドボードの端にある電源用の列に5VとGNDを繋いでおけば，様々なICに電力を供給できます．

具体的には，以下の写真のように配線しました．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/96aa3084-72f6-e6be-22f3-1ee520d7ae4b.png)

# サンプルスケッチを読み込む

サーボテスターと同様なサンプルプログラムも標準で準備されています．

メニューバーから，[ ファイル ]-[ スケッチ例 ]-[ Servo ]-[ Knob ]を開きます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256470/2278d57d-8dfc-e5da-a17d-ff54937980f5.png)

Knobは「ノブ」です．
ドアノブという言い方でよく使いますが，「握り」「取手」「つまみ」などの意味です．

したがって，可変抵抗のツマミを回すプログラム，ということになります．

# コンパイル，プログラムの書き込み，実行

それでは，これまでと同様に、コンパイルし，マイコンへの書き込みを行ってください。

書き込みが完了すると，プログラムが実行されて，最初にラジコンサーボがどこかの角度へ動きます．
その後，可変抵抗のツマミを回すと，ラジコンサーボも連動して動きます．

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">[スケッチ例]-[Servo]-[Knob]の実行結果。 <a href="https://t.co/Gfmc5O5lm1">pic.twitter.com/Gfmc5O5lm1</a></p>&mdash; hsgucci404 (@hsgucci404) <a href="https://twitter.com/hsgucci404/status/1649058518731988992?ref_src=twsrc%5Etfw">April 20, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ツマミを回していないのに，ラジコンサーボがグラグラ揺れるように動く(ハンチング)している場合は，可変抵抗まわりの配線がどこか不安定なのかもしれません．
足がちゃんと刺さっていない，ケーブルの断線，5Vが来てない，などを疑ってみましょう．


# スケッチの解説

```cpp:Knob.ino
#include <Servo.h>

Servo myservo;  // Servoクラスの実体(インスタンス)をmyservoとして作成

int potpin = A0;  // 可変抵抗を接続するピン番号
int val;    // アナログ入力で取得した値を格納する変数

// 初期化関数
void setup() {
  myservo.attach(9);  // myservoクラスに9番ピンを接続する
}

// ループ関数
void loop() {
  val = analogRead(potpin);            // 可変抵抗の値を読み込む (取れる値は0～1023)
  val = map(val, 0, 1023, 0, 180);     // 0～1023の値を0～180の範囲に変換
  myservo.write(val);                  // write関数で出力
  delay(15);                           // 15ミリ秒のウェイトを入れる
}
```

前回と異なる部分だけ解説していきます．

```cpp:グローバル変数の宣言
int potpin = A0;  // 可変抵抗を接続するピン番号
int val;    // アナログ入力で取得した値を格納する変数
```

`analogRead`関数を使う際に必要な変数です．
使用するアナログピンはA0です．
計測した値は変数`val`に格納されます．

```cpp:ループ関数
// ループ関数
void loop() {
  val = analogRead(potpin);            // 可変抵抗の値を読み込む (取れる値は0～1023)
  val = map(val, 0, 1023, 0, 180);     // 0～1023の値を0～180の範囲に変換
  myservo.write(val);                  // write関数で出力
  delay(15);                           // 15ミリ秒のウェイトを入れる
}
```

まず最初にA0ピンの電圧を`analogRead`で読み取ります．
変数`val`には0～1023の範囲のいずれかの値が入ることは， **8．アナログ入力の解説** で学習しました．

次に，valの値を変換します．`myserv.write`関数に入力できる数値は0～180なので，0～1023では大き過ぎます．
 **9．アナログ出力の解説** で学習した`map`関数を使って，入力された値の上限/下限で正規化し、出力用の上限/下限の範囲に変換しています．
解説：[map解説](http://www.musashinodenpa.com/arduino/ref/index.php?f=0&pos=2743)

# 補足

`myservo.write`の関数は，0～180の値を指定します．
さながら0度から180度のような感覚で使えるので初心者には簡単です．

しかし， **実際にはサーボの種類によって可動角度が異なる** ので，角度っぽい数値の指定というのは望ましくありません．
±30度のサーボであれば，servo.write(0)で-30度になりますし，
±135度のサーボであれば，servo.write(180)で+135度になるのです．
ラジコンのヨットに使うロープを巻き取るためのサーボなんか6回転(2160度)とか回るのに，0～180で指定しなければ行けないので，逆に計算が複雑です．

何度も言いますが，
 **<font color=red>servo.write(110)と書いても，ニュートラル(90度)から正確に+20度回るわけじゃない</font>** 
ということを気をつけてください．

0～180という数値のせいで，初心者は「え？どんな製品でもwriteに入力した角度になるんでしょ？」と誤解するのです．

これを説明するのが本当に大変です．
どうしてこんな変な関数を作ったのか，小一時間問い詰めたいくらいですよ(-_-;;;)

---
実はServoクラスには， **10．ラジコンサーボを動かそう１** で解説したようにマイクロ秒を指定して使う関数もあります．
それが`writeMicroseconds`関数です．

解説：[servo.writeMicroseconds関数](http://www.musashinodenpa.com/arduino/ref/index.php?f=1&pos=748)

1500が中間値で±700程度増減させるというサーボ信号(PPM信号)の仕組みをきちんと理解していれば，
こちらの関数を使う方がおかしな誤解をせずに済みます．

# まとめ

アナログ入力の関数と，ラジコンサーボの関数を組み合わせて，サーボテスターを製作しました．
「LEDが光る/消える」「シリアルモニタに文字が出る」といったプログラムよりも，
ラジコンサーボのように物理的な動きが生じるプログラムのほうが楽しめたかと思います．

興味のある人は，応用として以下のようなプログラムもチャレンジしてみてください．

- `writeMicroseconds`関数を使ったプログラム
- 1つの可変抵抗で，2個以上のサーボを同時にテストできるプログラム
- 2個のサーボが互い違いにミラー(反対方向)で動くプログラム
- 可変抵抗を複数個使って，複数のサーボをそれぞれ別個に動かすプログラム

これらができるようになると，3Dプリンタでラジコンサーボロボットを作って動かすことも簡単になります．

[目次](https://qiita.com/hsgucci/items/085680123f758c8c3eb4) へ戻りましょう．