====== 6-1 サーボモータ(PWM・ライブラリ) ====== ===== モータについての基礎知識 ===== ==== モータの種類 ==== 回転運動をする電子部品といえば「モータ」です。モータにはいくつかの種類があります。 == DCモータ == {{:gimmickkouza:electronic_basic:6:6-1.png?400|}} 直流電流をかけるとひたすら回転するモータです。 ラジコンカーやミニ四駆などに使われています。 DCモータには2つの端子があり、一方に電源の+側、もう一方に-側を繋ぐと回転します。 接続を逆にすると逆回転する他、電圧が高くなるほど回転が速くなる性質があります。 DCモータは位置制御ができない、高い電圧・電流が必要など、初心者が扱うにはちょっとコツがいります。 特にR4からは各GPIOピンに8mAまでの電流しか流せなくなったので、DCモータを使う場合はモータードライバやトランジスタ、MOSFETなどを使う必要があります。 2024年6月現在、"Arduino DCモータ" で検索すると出てくる作例は殆どがR3を使ったものです。R4では同じように扱えない点にご注意ください。 /* R4からはGPIOピンで8mAしか流せなくなったのでモータードライバやトランジスタ、MOSFETなどを使う必要があります。 位置制御ができない、高い電圧・電流が必要など、初心者が扱うにはちょっとコツがいります。 Arduino DCモータ で調べると大体落ちてるのはR3のサンプルなので、ご注意を。 */ == ステッピングモータ == {{:gimmickkouza:electronic_basic:6:6-2.png?400|}} 左:電子工作キットの小型ステッピングモータ 右:3Dプリンタから外したステッピングモータ    電気信号を入力することで、角度や回転数を指定して高精度に回転させられるモータです。 特に低速時のトルク(ねじろうとする力)が非常に高く、静止状態でもトルクを維持できる特長があります。 身近(?)なものではFDM式3Dプリンタなどに使われています。 電子工作用途ではサーボモータの方が種類が多く、一般的に使われている印象があります。 最低4本ピンがあり、どこにどれを差したらいいか分かりづらく、電圧も足りない。扱うにはモータードライバが必須。そして重い。 ……といった具合で、初心者が扱うにはかなりくせがあるモータです。 よほど精度が必要でもない限り、使わなくてもいいと思います。 (ちなみに精度が高くても分解能が低い製品もあります) /* 実際に扱う際は初心者にはかなりくせがある…(最低4本ピンがあり、どこにどれを差したらいいか分からない。電圧も足りない。モータードライバ必須。そして重い。なので使わないほうがいいと思います…とか書いてもいいかもです。 よほど精度が必要でもない限り…ちなみに精度は高くても分解能が低いやつもある。*/ == サーボモータ == {{:gimmickkouza:electronic_basic:6:6-3.png?400|}} 電気信号で制御できるモータです。 回転「角度」が制御できるタイプと、回転「速度」が制御できるタイプがあります(製品により決まっています) 360度連続回転可能な製品以外は、完全に回転し続けることはできません。 トルクが高いものほど動作電圧が高くなります。 電子工作では、ロボットやアニマトロニクスの制作などでよく使われています。 本項ではこちらのモータを使用します。 サーボモータはDCモータ、ステッピングモータと比べて扱いやすいモータです。 サーボモータはモータードライバが中に内蔵されていて、実際の中身はDCモーターだったりします。 こちらの記事がわかりやすいのですが、普段サーボモータと呼んでいるものはラジコンサーボという部類のモータです。 https://qiita.com/hsgucci/items/1ae0dbeb0438db8a23fa また、サーボモータの中にも、PWM形式とシリアル制御形式の2種類があります。 電子工作で一般的に使われているのは、PWM形式のラジコンサーボです。 /* 追加です。 回転「角度」が制御できるタイプと、回転「速度」が制御できるタイプがあることを書いとくと親切そうです サーボモータはモータードライバが中に内蔵されていて、実際の中身はDCモータだったりします これがわかりやすいのですが、普段サーボモータと呼んでいるものはラジコンサーボという部類です。 https://qiita.com/hsgucci/items/1ae0dbeb0438db8a23fa また、サーボモータの中にも、PWM形式と、シリアル制御形式の2種類があって、普段使うのは、PWM形式のラジコンサーボとなります。 上記に比べてサーボモータは扱いやすいからこれ使いますよってのがあったほうがいいです。 */   /*回転「角度」が制御できるタイプと、回転「速度」が制御できるタイプがあることを書いとくと親切そうです*/ ==== SG90サーボモータについて ==== {{:gimmickkouza:electronic_basic:6:6-4.png?400|}} 本項で使用する「SG90」は電子工作では定番のサーボモータです。 小さい分パワーはそれなりですが、入手しやすく5Vのマイコンで扱いやすいサーボです。 ---- 初めて使う電子パーツは、まずデータシートで仕様を確認しましょう。 SG90は秋月電子通商の販売ページにデータシートがありますので、こちらで仕様を確認します。 (下記に販売ページのリンクを掲載しておきますので、リンク先にあるデータシートのPDFをご確認ください)  マイクロサーボSG-90の販売ページ(秋月電子通商):  https://akizukidenshi.com/catalog/g/g108761/ 2024年6月現在、こちらのページに掲載されているデータシートには「Operating voltage: 3.3 V (~6V)」の記載があります。 なので最小動作電圧は3.3V、最大6Vまでの電圧をかけられるようです。 また「Servo can rotate approximately180degrees(90 in each direction)」の記載があります。 このサーボは左右90度ずつ、計180度の回転が可能とわかります。 /*データシート直リンクよりは秋月の購入ページに飛んでデータシートを案内したほうがいいかもです。 理由は2つあって、購入ページからデータシートに飛んでもらう流れを身に着けてもらうこと、**秋月の購入ページのデータシートのリンクが更新され、古いリンクのデータシートに飛べなくなる場合があることがあるためです**(こっちが厄介、表立って説明する必要はないんですが。)ちなみに秋月のデータシートが公式の最新じゃないこともある…南無三・・・ */    ===== 6-1-1_Servo_PWM ===== ==== 配線図 ==== {{:gimmickkouza:electronic_basic:6:6-1-1.png?600|}}    ===使う部品リスト=== ^ 部品 ^ 個数 ^ | SG90 | 1個 | SG90から出ているワイヤには、メス型のコネクタがついているかと思います。 両端がオスピンになっているワイヤを挿し込むことで、Arduinoと接続することができます。 3本出ているワイヤのうち、橙色はD11へ、赤色は5Vへ、茶色はGNDへ繋いでください。    完全に余談ですけどSG90のワイヤの配色、P型・D型色覚の人には見にくいのではないかと思うんですがどうなんでしょうね。 ちなみに正規品のSG90であれば3本の線のうち真ん中が必ず5Vになるようです。 とはいえロット違いや将来的に変更が生じる可能性がないとも言えないので、参考程度に… {{:gimmickkouza:electronic_basic:6:img_6513.jpg?200|}} SG90のワイヤ。 P型・D型色覚でない自分でもパッと見わかりにくいんじゃ(byるためすた) 真ん中が5Vになるので絶対にショートしないところはポイント高い(byまつはちさん) /*面倒じゃなければ写真が欲しいかもです。ワイヤの配色ひどいですよね…真ん中が5Vになるので絶対にショートしないところはポイント高い*/    ==== PWMの仕組み ==== 実際に動かす前に、サーボモータを動かすのに必要な仕組み、「PWM」について説明します。 先程の第5章では「デジタル入力」「デジタル出力」「アナログ入力」の3つを説明しました。 この時「アナログ出力」はないの?と思った方もいらっしゃると思います。 Arduinoには電圧を自在に調整して出す「アナログ出力」の機能はありません。 その代わりとして、**PWM(パルス変調(Pulse Width Modulation))という出力方式を利用して、「疑似的なアナログ出力」**を可能にしています。 (厳密に言うとR4シリーズにはアナログ出力の機能があります(後述)が、他のシリーズのArduinoでは使えない機能なので、PWMの使い方も履修しておいた方がいいかと思います)    === PWMの基本1:analogWriteの場合=== サーボモータの説明をする前に、よりベーシックな"analogWriteを使ったPWM"についての説明をします。    Arduinoが出力できる電圧は0Vか5Vのどちらかです(いわゆるデジタル出力です) analogWriteのPWMでは、この**0Vと5Vの電圧を高速で切り替えて出すことによって、"0Vと5Vの中間の電圧"を疑似的に作り出し**ます。 **"中間の電圧"の値は、0Vと5Vを出力する長さの割合**によって決まります。 {{:gimmickkouza:electronic_basic:6:6-1-pwm6.png?500|}} /*{{:gimmickkouza:electronic_basic:6:6-5.png?400|}}*/ 上の図はanalogWriteのPWMのモデル図です。 PWM周期の中でHIGH(5V)とLOW(0V)を3:2の割合の長さで出すことによって、3Vの出力を疑似的に作り出しています。 HIGHとLOWの割合によって出力される電圧は変わります。 以上がPWMの基本です。 PWMを利用することで、電圧の変化によって動作が変化する部品を操作することができます。 例えばLEDの明るさを変化させたり、DCモータの回転速度を変えたりすることができます。 本項ではanalogWriteのサンプルコードもご用意しておりますので、後ほどご覧ください。 /*ちなみにanalogWriteのOWM周波数は490Hzです。(約2ms)5番ピンと6番ピンで出すときだけ980Hz(約1ms)サーボモータのPWMよりずっとはやい周期で制御してます。*/ === PWMの基本2:サーボモータの場合 === さて、サーボモータもPWMによって制御可能な部品ですが、こちらはanalogWriteとは若干の違いがあります。 説明の為に、先程のSG90のデータシートの図を掲載します。 {{:gimmickkouza:electronic_basic:6:6-6.png?600|}} こちらはデータシート2枚目の図に、講師が説明を書き加えたものです。 図の中央には少し盛り上がってから下がり、右端で再度隆起しているグラフがあります。 まず一番下の薄青緑で塗られた「20ms(50Hz) PWM Period」はSG90サーボモータのPWM信号の周期を表します。 色付けされた1周期分の幅が20ms(=20ミリ秒)です。 この20ミリ秒の周期の中で、何ミリ秒の間HIGHにするかでサーボの動きを指定することができます。 この"何ミリ秒の間HIGHにするか"を「パルス幅」と呼び、その「パルス幅」にあたる部分が、グラフ最初の盛り上がり部分、薄赤色に色付けした「0.5~2.4ms DutyCycle」です。 0.5msは最小動作のパルス幅、2.4msは最大動作のパルス幅を示します。 つまり、20msのPWMの周期うち、HIGHにする時間を0.5msにすると最小角度の0度、2.4msにすると最大角度の180度になるように、内部のギアが動く仕様になっています。 ちなみに90度にしたい場合は、0.5msと2.4msの中間の1.45msの間HIGHにすればOKです。 /*これみんな躓くので、上の図のPWM(analogWriteとかで出力されるのはこっち)が周期のすべてを使ってDuty比を決めてるのに対し、異なり、特定の周期の一部の範囲だけのDuty比を使っているのがサーボモータなど、具体的な説明はばっちりなのでこれに加えて抽象度高い説明があったほうがいいかもしれない・・・こないだTaiYOさんにも説明したんですがめっちゃ大変だった‥‥*/ === analogWriteのPWMとサーボモータのPWMって結局何がどう違うの? === ==analogWriteはPWM周期全体がデューティーサイクル== 最初の図をもう一度出します。 {{:gimmickkouza:electronic_basic:6:6-1-pwm1.png?500|}} analogWriteでのPWMは、PWM周期の全体がデューティーサイクルとなります。 どういうことか、可視化してみましょう。 {{:gimmickkouza:electronic_basic:6:6-1-pwm3.png?500|}} PWM周期のうちのHIGHにする幅の割合によって出力電圧が決まります。 先程は3Vを出力電圧としましたが、HIGHの幅が狭ければもっと低い電圧が出力されます。 {{:gimmickkouza:electronic_basic:6:6-1-pwm4.png?500|}} PWM周期の全ての幅=デューティーサイクルの幅なので、PWM周期のすべて100%をHIGHにすることだってあります。 {{:gimmickkouza:electronic_basic:6:6-1-pwm7.png?500|}} /*ちなみにanalogWriteのOWM周波数は490Hzです。(約2ms)5番ピンと6番ピンで出すときだけ980Hz(約1ms)サーボモータのPWMよりずっとはやい周期で制御してます。 Duty100%を使うこともありますよ!6-1-3_analogWrite.inoでint DUTY = 255;にしてるのがまさにそれ */ ==サーボはPWM周期のほんの部分がデューティーサイクル== analogWriteの図に対応するサーボモータのPWMの図も召喚してみましょう。 {{:gimmickkouza:electronic_basic:6:6-1-pwm2.png?500|}} サーボモータのPWMでは、PWM周期のうちごく一部分の範囲だけがデューティーサイクルとなっています。 PWM周期のうちデューティーサイクル外の部分については、出力を操作することはありません。 デューティーサイクルの最小値~最大値の中で幅を指定することによって、サーボモータの動作が変わります。    ==そもそも両者は速度感からして違うんじゃな== SG90サーボのPWM周期は50Hz、つまり20msでした。 つまりこんな感じ。 {{:gimmickkouza:electronic_basic:6:6-1-pwm8.png?500|}}    それに対して、analogWriteのPWM周期は490Hz、約2msです。 (ちなみに5番ピンと6番ピンで出すときだけは980Hz(約1ms)です) つまり、analogWriteのPWMはサーボモータのPWMよりずっとはやい周期で制御しています。 先程のサーボの図にanalogWriteを足して速度感の違いを可視化してみると、こんな感じです。 {{:gimmickkouza:electronic_basic:6:6-1-pwm9.png?500|}}    ==== サンプルコード解説 ==== サンプルコード6-1-1_Servo_PWM.inoを開いてください。 /* int servo_PIN = 11; pinMode(Servo_PIN, OUTPUT);で大文字小文字がまじってコンパイルエラーになります。 delay(20); //20ms待機する これ、正しくは delayMicroseconds(10000-pulse_WIDTH); delayMicroseconds(10000); じゃないですかね。20ms周期ならその分引かないと正確にならない気がします… delayMicroseconds(20000-pulse_WIDTH);としないのは、delayMicrosecondsは16383usまでしか動作しないためです https://kimudiary.com/arduino/arduino%E3%81%A7%E3%82%B5%E3%83%BC%E3%83%9C%E3%83%A2%E3%83%BC%E3%82%BF%E3%82%92%E5%8B%95%E3%81%8B%E3%81%99/ 私は試してみたときこのコンパイルエラーに引っかかりました。 This library only supports boards with an AVR, SAM, SAMD, NRF52 or STM32F4 processor. サーボライブラリが古かったみたいで、新しくIDEインストールしてれば起きないのかもしれませんが… https://python-beginner.blog/arduinounor4-sg90-error/ */ int servo_PIN = 11; //サーボのPWM通信線はD11に接続 int pulse_WIDTH = 1450; // 任意のパルス幅を入れる。サンプルでは1.45ms(=90度) void setup() { pinMode(servo_PIN, OUTPUT); //D11をデジタル出力に設定する } void loop() { digitalWrite(servo_PIN, HIGH); //D11をHIGHにする delayMicroseconds(pulse_WIDTH);//pulse_WIDTHで設定したミリ秒待機する digitalWrite(servo_PIN, LOW); //D11をLOWにする delayMicroseconds(10000-pulse_WIDTH); //まず10msからパルス幅を引いた時間分delayする delayMicroseconds(10000); //残りの10msぶんdelayする(delayMicrosecondsは16383usまでしか動作しないため) } サンプルコード6-1-1では、ベタにパルス幅を指定する方法でサーボを動かします。 仕組みとしては、デジタル出力とdelayを組み合わせて任意のパルス幅を作り出します。 今回初登場のdelayMicrosecondsは、delayと同じ"任意の時間分待機する"関数です。 両者の違いは時間の単位のみです。 delayが"ミリ秒"で時間を指定するのに対し、 delayMicrosecondsは更に短い単位の"マイクロ秒"で待機時間を指定することができます。 ===このスケッチを実行しようとするとコンパイルエラーが出てしまう人のための情報=== ArduinoIDEにインストールされているServoライブラリが古い場合、R4でServoライブラリを使用しようとするとエラーが出る場合があります。 (逆に言うと、本講座資料の実践の為に新しくArduinoIDEをインストールした人ではこのエラーは恐らく出ないかと思います)    「警告:ライブラリServoはアーキテクチャavr, megaavr, sam, samd, nrf52, stm32f4, mbed, mbed_nano, mbed_portenta, mbed_rp2040に対応したものであり、アーキテクチャrenesas_unoで動作するこのボードとは互換性がないかもしれません。」 もしくは 「This library only supports boards with an AVR, SAM, SAMD, NRF52 or STM32F4 processor.」    Arduinoに6-1-1を書き込もうとしてこれらのエラーが出た場合は、下記の手順でServoライブラリをアップデートしてください。 ==手順1:ライブラリマネージャを開く== {{:gimmickkouza:electronic_basic:6:6-11.png?400|}} ライブラリマネージャを開きます。 ArduinoIDEの左側に並んでいるアイコンのうち、上から三つめがライブラリマネージャです。 ==手順2:ライブラリを探す== {{:gimmickkouza:electronic_basic:6:6-12.png?400|}} アイコンをクリックするとライブラリマネージャが出現します。 今回はServo用のライブラリを探したいので、検索欄に「Servo」と打ち込みます。 (この画像は6-2の使い回しなので、別の文字列が入っていますがお気になさらず…) 打ち込むと検索ワードに該当するライブラリがズラーっと下に現れます。 ==手順3:公式のライブラリを見つけてインストールする== {{:gimmickkouza:electronic_basic:6:6-1-1_servo_pwm_arduino_ide_2.2.1_2024_06_18_22_00_42.png?400|}} 今回はArduino公式がリリースしているライブラリをインストールします。 検索結果の中から、__**ライブラリ名が「Servo」開発者が「by Michael Margolis, Arduino」のものをインストール**__してください。 (だいたい検索結果の最上位に出てくるかと思います) ライブラリのバージョンは最新版で大丈夫です。    参考リンク:https://python-beginner.blog/arduinounor4-sg90-error/    ===そんなわけでコード解説に戻ります=== == 1行目 == int servo_PIN = 11; //サーボのPWM通信線はD11に接続 PWMを使って任意の電圧を出力したい場合は「~」の付いたデジタル出力端子を使います。 が!、今回は普通のデジタル出力にdelayを組み合わせてパルス幅を作り出すので、「~」がついていないソケットでも大丈夫です。 (~の付いている11にしたのは後の都合のためです…) == 2行目 == int pulse_WIDTH = 1450; // 任意のパルス幅を入れる。サンプルでは1.45ms(=90度) パルス幅をマイクロ秒で指定します。90度に動かすには1.45ミリ秒のパルス幅が必要なので、 マイクロ秒換算した1450の数値を入れています。 180度まで回したい時は2.4ミリ秒=2400マイクロ秒、の数値を、原点の0度に戻したい時は0.5ミリ秒=500マイクロ秒の数値を入れます。 それ以外の角度は…パルス幅を計算して求めてください… また、map関数を使う方法もあります! [[gimmickkouza:electronic_basic:8:2_pca9685|]] で出てきますので、よければこちらもご覧ください。 /* 高度なやり方だと、map関数で変換もできると思います。(要確認) http://www.musashinodenpa.com/arduino/ref/index.php?f=0&pos=2743 */ == 5行目 == pinMode(servo_PIN, OUTPUT); //D11をデジタル出力に設定する D11を出力モードにします。何の変哲もないデジタル出力の設定です。 == 9行目 == digitalWrite(servo_PIN, HIGH); //D11をHIGHにする パルス幅を作り出すため、まずはD11をHIGHにします。 == 10行目 == delayMicroseconds(pulse_WIDTH);//pulse_WIDTHで設定したミリ秒待機する delayMicrosecondsによってpulse_WIDTHに入れた数値のマイクロ秒分待機します。 == 11行目 == digitalWrite(servo_PIN, LOW); //D11をLOWにする パルス幅の時間分HIGHにしたので、D11をLOWにします。 == 12・13行目 == delayMicroseconds(10000-pulse_WIDTH); //まず10msからパルス幅を引いた時間分delayする delayMicroseconds(10000); //残りの10msぶんdelayする(delayMicrosecondsは16383usまでしか動作しないため) 11行目を終えてすぐloop文の先頭に戻ると、PWMの1周期が終わらないうちにHIGHが再度出力されてしまいます。 なので、PWMの1周期を終えるまで、ここで待機します。 待機する時間は20ms(SG90のPWM1周期)からパルス幅(本コードでは変数pulse_WIDTHの数値)を引いた残りの時間です。 そんなわけで delayMicroseconds(20000 - pulse_WIDTH); …と言いたいところですが、ここで一つプチ落とし穴です。 __delayMicrosecondsで扱える最大の時間は16383us__です。 なので、delayMicrosecondsの引数に20000usを突っ込むことはできません。 ここは少し面倒ですが、2回に分けてdelayMicrosecondsをかける必要があります。 1回目のdelayMicrosecondsは10msからpulse_WIDTHの数値を引いた時間分待機させます。 続く2回目のdelayMicrosecondsで、残りの10msぶん待機させます。 この2行の記述により、本来記述したかった delayMicroseconds(20000 - pulse_WIDTH); と同じ効果を実現できます。       ===== 6-1-2_Servo_library ===== {{youtube>PuH5LhkhHpY?large}}    サーボモータはパルス幅を指定して動かすだけでなく、「ライブラリ」を使うことでもっと簡単に、直感的に動作させることができます。    センサやディスプレイ、モジュールなどは、第5章までに扱ってきたLEDの球やタクトスイッチなどと比べると、非常に複雑な電子部品です。 その機能を使うためには、本来であれば難解で膨大な命令を記述しなければなりません。 そういった**複雑な電子部品をなるべく簡単に扱えるように作られたコードの集合体を、「ライブラリ」と呼びます。** ArduinoIDEのインストール時に、基礎的な「ライブラリ」はデフォルトでインストールされています。今回使うServoライブラリもその一つです。    それ以外の「ライブラリ」は、電子部品のメーカーが提供していることが多いです。 また有志のすごい人が自作しているライブラリもあります。 そのため、有名な電子部品や人気な電子部品は、リリース元の異なる複数のライブラリがある場合があります(LEDテープなんかがそうですね) **あるライブラリのルールは、そのライブラリを使っているプログラムの中でしか使えないので、注意が必要です。**    ==== 配線図 ==== {{:gimmickkouza:electronic_basic:6:6-1-1.png?600|}}    回路は直前の6-1-1で作ったものをそのまま流用できます。 何もいじらなくてOKです! ===使う部品リスト=== ^ 部品 ^ 個数 ^ | SG90 | 1個 | ==== サンプルコード解説 ==== サンプルコード6-1-2_Servo_library.inoを開いてください。 #include //サーボモータ制御用の標準ライブラリをインクルードします int servo_PIN = 11; //サーボのPWM通信線はD11に接続 Servo myservo; //スケッチ内で使うサーボのインスタンス名を宣言 void setup() { myservo.attach(servo_PIN,500,2400); //サーボのピンをD11で指定/パルス幅の最小/同左最大 } void loop() { myservo.write(0); //サーボを0度にする delay(500); myservo.write(45); //サーボを45度にする delay(500); myservo.write(90); //サーボを90度にする delay(500); myservo.write(135); //サーボを135度にする delay(500); myservo.write(180); //サーボを180度にする delay(500); } == 1行目 == #include //サーボモータ制御用の標準ライブラリをインクルードします 早速「ライブラリ」の登場です。今回使うのは「Servo」ライブラリです。 Servoライブラリは、ArduinoIDEに最初からインストールされているライブラリです。 ライブラリをスケッチの中で使いたい場合は、ライブラリのインクルードが必要です。 「スケッチ」→「ライブラリをインクルード」→「Servo」を押すと、宣言部に  #include  の一文が入ります。 これによりServoライブラリを読み込んで、このスケッチの中で使用できるようにします。 (本サンプルコードでは既にインクルードされているため、この処理は不要です) == 3行目 == int servo_PIN = 11; //サーボのPWM通信線はD11に接続 デジタル出力とdelayを使ってパルス幅を指定した6-1-1では、やってることは実質デジタル出力でしたので、どのデジタル出力ソケットを使ってもOKでした。 今回はPWM出力が可能なデジタルソケット、つまり**「~」がついている「D3/D5/D6/D9/D10/D11」のどれかのソケットを使う必要があります。** == 5行目 == Servo myservo; //スケッチ内で使うサーボのインスタンス名を宣言 スケッチ内で使うサーボのインスタンス名を作成します。 この先サーボの設定や動作の制御をするときは、このインスタンス名を指定して命令を書きます。 インスタンスの命名も、変数の命名と同じような要領でやるのが望ましいです。つまり、「英語を使った説明的な名前」です。 ざっくり言うと「どんなライブラリで何を動かすのか」という観点で命名するのがよいでしょう。 今回はサーボモータを動かすのでmyservoにしました。 == 8行目 == myservo.attach(servo_PIN,500,2400); //サーボのピンをD11で指定/パルス幅の最小/同左最大 先ほど作成したインスタンス名「myservo」を使って、サーボの設定をします! 今回引数で指定するのは、 (サーボを繋いだソケット番号 , 最小のパルス幅 , 最大のパルス幅) です。 このうち後ろ二つのパルス幅については省略可能です。今回は律儀に「,500,2400」を入れます。 一番先頭のサーボを繋いだソケット番号は必須となります。今回は変数servo_PINの中身「11」が代入されます。 == 12行目 == myservo.write(0); //サーボを0度にする サーボの角度を0度にします。命令はたったのmyservo.write(0); だけです。 引数には動かしたい「角度」の数値を入れます。今回は0度なので(0)となります。 角度を指定する → [その角度分動かすのに必要なPWM信号を生成して送信する] → サーボが動く という動作のうち、[ ]の部分をライブラリが勝手にやってくれるイメージです。 なので、「69度」や「154度」のようなめんどくさい角度も計算不要で一撃で動かせます。**楽ですね。** == 13行目 == delay(500); delayで待機します。 == 14~21行目 == myservo.write(45); //サーボを45度にする delay(500); myservo.write(90); //サーボを90度にする delay(500); myservo.write(135); //サーボを135度にする delay(500); myservo.write(180); //サーボを180度にする delay(500); 12・13行目のセットが数回繰り返されます。違いは角度です。 0度→45度→90度→135度→180度 と、delayを挟みながら段階的にサーボが動き、180度まで達するとloop文の先頭に戻りまた0度から動作を繰り返します。    ---- サーボをArduinoにたくさん繋げて動かしたいぜ!!!!と思ったそこのアナタ! サーボをたくさん繋げる方法は第8章、 [[gimmickkouza:electronic_basic:8:2_pca9685|]] で出てくるのでそっちも見てくれよな!!!!! **間違ってもArduinoに沢山のサーボを直接繋げたらダメだぞ!!!!!!!**    Arduinoにはアナログ出力機能がないため、疑似的アナログ出力のPWMを使う必要がある …と丸く収めようとしたかったのですが、なんとR4シリーズにはアナログ出力機能が追加されていたため、このコーナーを書く羽目になってしまいました。トホホ。    R4シリーズには、DAC(デジタルアナログコンバータ。アナログ入力で出てきた、アナログ信号をデジタル信号に変換するADCの逆バージョンみたいなやつ)が搭載されており、A0ソケットでのみで扱うことができるようです。 本資料ではDACの扱い方の詳細は割愛しますが、興味のある方は下記リンクを参考に、チャレンジしてみるといいと思います。    Arduino UNO R4 Minima Digital-to-Analog Converter (DAC)(Arduino公式): https://docs.arduino.cc/tutorials/uno-r4-minima/dac/    またDACについてはこちらのページでまつはちさんが補足してくれています:[[gimmickkouza:electronic_basic:7:3-r3-r4|]]       ===== 6-1-3_analogWrite ===== 6-1-3と6-1-4はLEDを使ったanalogWriteのサンプルコードとなっております。 サーボモータの使い方ではありませんが、せっかくPWMについて学習したのですから、ぜひこちらも実践してみてください! そんなわけで、PWMを使った疑似的なアナログ入力で、LEDの明るさを調節してみましょう! analogWriteのPWMについてもう一度おさらいしておきたい方は、本ページを上の方~~~までスクロールしてください。 講師はとても親切なのでインターナルリンクも貼っておきますよ。**親切なので。** [[gimmickkouza:electronic_basic:6:1_servo_pwm#PWMの仕組み|]] /*サーボモータのページなのにanalogWriteでの制御が登場するのが気になるので一言ほしいです https://curiouser.sakura.ne.jp/lutamesta/doku.php/gimmickkouza/electronic_basic/6/1_servo_pwm#pwmno%E5%9F%BA%E6%9C%AC こことの関連性も書きたい */    ==== 配線図 ==== {{:gimmickkouza:electronic_basic:6:6-1-3.png?600|}}    今回使う関数はanalogWriteですが、あくまで__"PWMを使い疑似的にアナログ出力をする"ものなので、アナログソケットではなくPWM対応の「~」がついたデジタルソケットを使います。__ またいつものことですが、LEDの抵抗はお使いになるLEDの仕様に合わせたものを計算してお選びください。 ===使う部品リスト=== ^ 部品 ^ 個数 ^ | 砲弾型LED球 | 1個 | | 抵抗器\\ (抵抗値は使うLEDのデータシートをもとに各自計算してください) | 1個 |    ==== サンプルコード解説 ==== サンプルコード6-1-3_analogWrite.inoを開いてください。 /*使う部品の表が欲しい LEDの何なのか書いたほうがわかりやすい ledPinとか */ int LED_PIN = 10; //LEDはD10に挿す int DUTY = 255;//デューティサイクルを設定(0~255) void setup() { pinMode(LED_PIN,OUTPUT);//(PWMの場合pinModeは実は省略可能) } void loop() { analogWrite(LED_PIN,DUTY);//D10にDUTYの値を出力 } == 2行目 == int DUTY = 255;//デューティサイクルを設定(0~255) PWMのデューティサイクル(=HIGHを出力する時間)を0~255の数値で設定します。 数値が大きいほどLEDは明るく、小さいほど暗く光ります。 == 5行目 == pinMode(LED_PIN,OUTPUT);//(PWMの場合pinModeは実は省略可能) PWMは出力しかしないので、実はpinModeの記述は省略することができます。 もちろん書いても問題ありません。今回は律儀に書いてみました。 == 9行目 == analogWrite(LED_PIN,DUTY);//D10にDUTYの値を出力 PWM出力をするときに使うanalogWrite関数です。 引数の一番目には出力するピン番号を(今回は変数LEDの中身「10」)、二番目には出力するアナログ値(今回ならDUTYの中身「255」)を書いておきます。 変数DUTYが255の状態でLEDは最も強く光ります。 DUTYの値を減らして書き込むと、明るさが弱くなっているのがわかるかと思います(ぜひ試してみてください)       ===== 6-1-4_analogWrite_firefly ===== analogWriteを使うことで、LEDの明るさをスイッチで切り替えたり、CdSセルで取得した明るさに連動させて可変させる…なんてこともできるようになります。 またコードでDUTYの変化を細かく制御することで、発光パターンを作り出すこともできます。 サンプルコード6-1-4では、"蛍のようにゆっくりと明滅する"発光パターンを作成しています。    ==== 配線図 ==== {{:gimmickkouza:electronic_basic:6:6-1-3.png?600|}}    配線は6-1-3と同じ、そのままの状態でOKです。 ===使う部品リスト=== ^ 部品 ^ 個数 ^ | 砲弾型LED球 | 1個 | | 抵抗器\\ (抵抗値は使うLEDのデータシートをもとに各自計算してください) | 1個 |    ==== サンプルコード解説 ==== サンプルコード6-1-4_analogWrite_firefly.inoを開いてください。 /* LEDの何なのか書いたほうがわかりやすい SPEEDはdelay(SPEED)とするのはdelayは遅延させる意味のためちょっと違和感あるので、duarationとかにした方がいいと思います。 あと単位書いたほうがいいと思います。[ms]とか。 int ledPin = 10; //LEDはD10に挿す int duaration = 5;//[ms]delayの待ち時間です。明滅する速度に関係します。 */ int LED_PIN = 10; //LEDはD10に挿す int duaration = 5;//[ms]delayの待ち時間です。明滅する速度に関係します。 void setup() {//(今回pinModeは省略しちゃいま~す) } void loop() { for(int i = 0; i < 255; i++){//iに+1をし続け0から255になるまでの間ループ analogWrite(LED_PIN,i);//D10にiの値を出力 delay(duaration);//次の出力までduaration分待機する } delay(500);//完全に明るくなったら少し停止するといい感じに見える for(int i = 255; i > 0; i--){//iから-1をし続け255から0になるまでの間ループ analogWrite(LED_PIN,i);//D10にiの値を出力 delay(duaration);//次の出力までduaration分待機する } delay(500);//完全に暗くなったら少し停止するといい感じに見える } == 2行目 == int duaration = 5;//[ms]delayの待ち時間です。明滅する速度に関係します。 このスケッチでは、LEDに送るアナログ値を1段階ずつ増減させ点灯することで、連続的に明るさが変化するように見せます。 この"1段階ずつ増減"の合間にdelay(duaration);を挟むことにより、明滅の速度を調整します。 (duarationを増やすと、よりゆっくり明滅するようになります) == 8行目 == for(int i = 0; i < 255; i++){//iに+1をし続け0から255になるまでの間ループ 8~11行目と13~16行目に2つのfor文があります。8~11の方はLEDを徐々に明るくする for文で、13~16の方はLEDを徐々に暗くするfor文です。 引数の中身を見ていきます。第一引数(1番目の引数って意味だよ)では初期値0の変数iを設定 します。第二引数で、"このiが255より小さい間このfor文をループする"条件を指定し、 第三引数では"このfor文を1回ループするごとにiに+1をする"ことを指定します。 == 9行目 == analogWrite(LED_PIN,i);//D10にiの値を出力 analogWrite関数で、LED_PINにアナログ値を出力します。 出力する値の指定には、for文を回すために作られた変数iを使い回し、その数値を出力します。 == 10行目 == delay(duaration);//次の出力までSPEED分待機する 変数duarationに設定した数値分待機します。 == 12行目 == delay(500);//完全に明るくなったら少し停止するといい感じに見える 一つ目のfor文を抜けた時点で、LEDの明るさは最大値になっています。 明るさが最大の時にその状態を少し継続させるとちょっといい感じに見える(個人の感想)ので、delay(500);で待機します。 17行目のdelay(500);も同じ目的(LEDが完全に暗くなった時に、いい感じに見せる為に待機させている)です。 この2行は完全に個人の好みなので、増減削除はご自由に。