あらゆる DC モーターをカスタム 360° サーボに変える – ステップバイステップガイド
このチュートリアルでは、DC モーターを多くの機能を備えたスタンドアロンのカスタム サーボ モーターに変える方法を学びます。動作が 180 度または 270 度に制限されている通常のサーボとは異なり、このサーボには 360 度の無制限の範囲があり、それに加えて、必要な値に回転範囲を調整する機能もあります。
これはかなり便利だと思いますし、それに加えてサーボの中心点を調整することもできます。したがって、中心点と回転範囲の両方を同時に調整できます。
次のビデオを見るか、以下のチュートリアルを読むことができます。
もう 1 つの特徴は、感度やサーボが入力にどれだけ早く応答するかを調整できることです。入力について言えば、3 つの異なる入力モードがあります。
アナログ電圧入力またはポテンショメータを使用してサーボを制御できます。RC 送信機でサーボを制御したり、PC またはラップトップのシリアル モニタに角度値を入力してシリアル ポート経由でサーボを制御したりできます。
シリアルモニターから値を入力してサーボを制御し、RC送信機を使用して手動でサーボを動かすことも同時に行うことができます。サーボモーターは常に現在位置を認識しており、シリアルモニターで確認できます。
このサーボモーターの機能リストの一番上にあるのは、連続回転モードです。それは正しい。この連続回転モードでもサーボモーターの位置を制御し、追跡することができます。サーボモーターのシャフトを無限の回転数で任意の位置に設定できます。
これらすべては、このサーボ モーターが採用する 12 ビット エンコーダー、AS5600 磁気回転位置センサー、および DC モーターを駆動するために実装された PID 制御のおかげで可能になります。
私は、任意の DC モーターをスタンドアロン サーボ モーターに簡単に変えるための独自のマイクロコントローラーとその他すべてを含む、このカスタム サーボ モーター コントローラー ボードを作成しました。
ボードを出力シャフトの中心に配置し (シャフト上の特定の磁石を含む)、最大 3.5A 定格電流の任意のサイズの DC モーターを接続し、システム全体に 12V で電力を供給するだけで、これらすべての機能を備えた通常の DC モーターからサーボ モーターが得られます。
ここでは、このカスタム ビルド サーボ モーターを作成するプロセス全体を説明しますので、自分でサーボ モーターを作成することもできます。サーボ モーター、閉ループ コントローラー、PID コントローラーの動作原理、そのカスタム PCB とギアボックスの設計方法、およびその背後にあるコードについて説明します。
サーボモーターの動作原理
サーボ モーターの動作原理を説明するために、一般的な RC サーボ モーターを分解して、内部に何が入っているのかを見てみましょう。
小型の DC モーター、コントローラー ボード、ポテンショメータ、および 3 線接続 (電源用の 2 本と入力信号用の 1 本) があることがわかります。また、DC モーターの速度を落としたり、トルクを高めたりするためのギアもいくつかあります。
これは、ほとんどの RC またはホビー サーボ モーターの一般的なセットアップです。ポテンショメータは DC モーターの出力シャフトに取り付けられており、位置センサーとして機能し、サーボ モーター シャフトの現在の位置をコントローラーに伝えます。コントローラー ボードは、入力信号 (目的の位置) とポテンショメータからのフィードバックとして取得した実際の位置に基づいて DC モーターを制御します。これは閉ループ制御システムを表します。
入力信号、つまり目的の位置は、位置フィードバック センサーから取得したモーターの実際の位置と比較されます。発生した差はエラーと呼ばれ、コントローラーで処理され、モーターが目的の位置に到達するまで移動するように命令されます。
カスタム サーボ モーターの作成方法
したがって、これらの一般的な RC サーボが使用するものより大きな DC モーターを備えた独自のサーボ モーターを構築したい場合は、同じ閉ループ制御システムを実装できます。
何らかの方法で出力シャフトに取り付けられた位置センサーと、DC モーターを駆動するためのマイクロコントローラーが必要です。
さて、位置センサーについてですが、最も簡単な解決策は、RC サーボで見たような単純なポテンショメーターを使用することです。ただし、これらのタイプのポテンショメータの問題は、回転範囲が 270 度しかなく、サーボ モータの回転範囲が直接制限されてしまうことです。複数の回転が可能で、より優れた範囲と分解能を提供できる他のタイプのポテンショメータもありますが、それでも回転には限界があります。
サーボ モーターの回転範囲を無制限にする必要がある場合は、エンコーダーを使用する必要があります。エンコーダは、無制限に回転してシャフトの角度位置を追跡できる電気機械デバイスです。エンコーダには、インクリメンタルやアブソリュート、あるいはセンシング技術に応じて光学式、磁気式、静電容量式など、さまざまなタイプがあります。もちろん、それぞれに独自の長所と短所があります。
AS5600 エンコーダ – 磁気回転位置センサー
磁気エンコーダ、つまり AS5600 磁気回転位置センサーを使用することにしました。エンコーダは非常にコンパクトで実装が簡単で、高精度または分解能が得られるからです。このマイクロチップがどれほど小さいかを見てください。
磁場の方向の変化を検出できるホール効果センサーが内蔵されています。したがって、モーターの出力シャフトに磁石を取り付け、マイクロチップの近くに 0.5 ~ 3 mm の距離で配置するだけです。
モーターのシャフトと磁石が回転すると、ホール効果センサーが磁場の方向の変化を捕捉します。内蔵 12 ビット A/D コンバータの助けを借りて、AS5600 センサーは 1 回転または 360 度の回転ごとに 4096 の位置を出力できます。
つまり、0.0878 度という小さな角度位置の変化を検出できるということです。これは非常に印象的であり、非常に手頃な価格で簡単に入手できるため、カスタム構築のサーボ モーターとしては最適です。
わかりました。それでは他に何が必要ですか。マイクロコントローラーと DC モーター用のドライバーです。私は、最大 3.5 アンペアの電流を処理できる DRV8871 DC モーター ドライバーと Atmega328 マイクロコントローラーを選択しました。
DIP バージョンよりもはるかにコンパクトなため、表面実装バージョンを選択しました。私の目標は、サーボがスタンドアロン デバイスとして動作できるように、すべてを含めることができるできるだけ小さいカスタム PCB を作成することでした。
カスタム サーボ モーター回路図
このカスタム構築サーボ モーターの完全な回路図は次のとおりです。
このプロジェクトに必要なコンポーネントは、以下のリンクから入手できます。
- AS5600 磁気エンコーダ ………………..Amazon / AliExpress
- DRV8871 DC モータードライバー……………….……。 Amazon / AliExpress
- Atmega328p-AU ………………………………。 Amazon / AliExpress
- 16Mhz 水晶発振器 ……………………..Amazon / AliExpress
- AMS1117 5V 電圧レギュレータ ……..……。 Amazon / AliExpress
- 3386P 角型ポテンショメータ ………………。 Amazon / AliExpress
- コンデンサ 0805 キット………………………….…。 Amazon / AliExpress
- 12V DC モーター – ~ 50RPM ………….……。 アマゾン / アリエクスプレス
開示:これらはアフィリエイト リンクです。 Amazon アソシエイトとして、 私は対象商品を購入することで収入を得ています。
したがって、Atmega328 マイクロコントローラと、16Mhz 発振器、いくつかのコンデンサ、抵抗を含む推奨される最低限の回路が用意されています。
マイクロコントローラーと 5V を必要とするその他のコンポーネントに電力を供給するために、AMS1117 電圧レギュレーターを使用しています。これにより、12V の電源入力が 5V に降下されます。
ここでは、IC2 通信用に 2 つのコンデンサと 2 つのプルアップ抵抗を含む推奨回路を備えた AS5600 位置センサーを示します。
DRV8871 DC モーター ドライバーに必要なのは、電流を制限するための抵抗 1 つとデカップリング コンデンサ 2 つだけです。次に、マイクロコントローラーのアナログ入力に接続された 2 つのポテンショメーターがあり、1 つは回転範囲の調整用、もう 1 つはサーボの感度の調整用です。プッシュボタンはサーボの中心点を設定するために使用され、双方向ディップスイッチはサーボの動作モードを選択するために使用されます。サーボの入力には、アナログ電圧入力または RC レシーバーからのデジタル PWM 入力のいずれか、および 5V およびグランド ピン用のピン ヘッダーがあります。 SPI プロトコルとシリアル ポートを介してマイクロコントローラーをプログラミングするためのピン ヘッダーもあります。
この回路とそのワークフローの概要を次に示します。入力または希望の角度位置は、これら 2 つのピンを介して受信され、ポテンショメータからのアナログ電圧または RC 受信機からのデジタル PWM 信号のいずれかになります。入力はマイクロコントローラーに入力され、そこでエンコーダーまたは AS5600 位置センサーによって検出された実際の角度位置と比較されます。このセンサーは、IC2 プロトコルを通じてマイクロコントローラーと通信します。
次に、マイクロコントローラーが計算を行って誤差を計算し、それに基づいて PWM 信号を DRV8871 ドライバーに送信し、DC モーターが目的の位置に到達するまで駆動します。
回路全体は 12V で駆動され、AS1117 電圧レギュレータはマイクロコントローラーとその他のコンポーネントに 5V を適切に供給します。
PCB 設計
回路図によると、PCB をできるだけ小さく設計しようとした結果、40x40mm になりました。
エンコーダは、簡単に取り付けてサーボの出力シャフトと位置合わせできるように、PCB の底面の正確な中心点に配置しました。
他のすべてのコンポーネントは、エンコーダーや出力シャフトと干渉しないように反対側に配置されています。
PCBWay に PCB を注文しました。ここでは、ガーバー ファイルをアップロードし、PCB のプロパティを選択して、手頃な価格で注文するだけです。
PCBを4層になるように設計し、真ん中の層はGND用であるため、価格が少し高くなります。 PCB の色を白に選択したことを除いて、デフォルトのプロパティは何も変更しませんでした。また、追加料金なしで、該当する場合は表面仕上げをイマージョン ゴールドに変更することを受け入れることにチェックを入れます。
PCBWay プロジェクト共有コミュニティからガーバーを見つけてダウンロードでき、そこから PCB を直接注文することもできます。
それにもかかわらず、数日後に PCB が到着しました。 PCB の品質は素晴らしく、すべてが設計と同じで、浸漬金表面仕上げで入手できました。
さて、コンポーネントのはんだ付けに進むことができます。このインジケーター LED、コンデンサー、抵抗器などの小さなコンポーネントから始めました。
実はこの小さなSMDコンポーネントをはんだ付けするのは初めてで、本当に本当に苦手でした。
ピンが非常に小さく、互いに非常に近いため、Atmega328 マイクロコントローラーのはんだ付けが最も困難でしたが、なんとかやり遂げることができました。
AS5600 エンコーダ マイクロチップは、ディップ スイッチ、ポテンショメータ、端子台、ピン ヘッダーなどのより大きなスルーホール コンポーネントだけでなく、PCB の裏側にも簡単にはんだ付けできました。
とにかく、これがコントローラー ボードの最終的な外観です。結局のところ、まともなものになったと思います。
次に、DC モーターとこのコントローラー ボードに適したギアボックスを作成します。
カスタム サーボ 3D モデル
Onshape を使用して、このカスタム サーボ モーターのギアボックスを設計しました。もちろん、ギアボックスの設計は DC モーターに依存します。先ほど述べたように、作成したばかりのコントローラー ボードと組み合わせて、あらゆるサイズの DC モーターを使用できます。
ここでは、直径 37 mm の DC モーターと、50 RPM を出力する内蔵ギアボックスを使用しています。 50RPM はサーボ モーターにとって適切な速度ですが、より良いトルクを得るためにそれより少し低くしたかったため、3 倍減速のギアボックスを作成しました。この目的のために、3D プリンターで効率的かつ簡単に作成できるヘリンボーン歯車を使用しました。
もちろん、ここでは、使用する DC モーターと取得したい出力速度に応じて、このギアボックスの設計を自由に行うことができます。
コントローラー ボードをこのギアボックスの裏側に配置し、出力シャフトの中心に完全に位置合わせしました。
DC モーター シャフトを出力として直接使用したい場合は、1:1 ギアセットを使用するだけで、シャフトの位置を正確に追跡できます。あるいは、そのような場合にはベルトシステムを使用することもできます。先ほども言いましたが、ギアボックスの製造には無限の可能性があります。
3D モデルと STL ファイルをダウンロード
Onshape を使用すると、このカスタム構築サーボ モーターの 3D モデルを Web ブラウザ上で直接表示して探索できます。 (そのためには Onshape アカウントが必要です。自宅で使用するために無料のアカウントを作成できます)
もちろん、パーツの 3D プリントに必要な STL ファイルだけでなく、3D モデルもここからダウンロードします。
STEP ファイル:
3D プリント用の STL ファイル:
カスタムサーボの組み立て
ここにこのビルド用の 3D プリント部品があり、サーボ モーターの組み立てを開始できます。
これらに加えて、M3 ボルトとネジ付きインサート、およびベアリングも必要です。
まず、長さ 8 mm の M3 ボルトを使用して DC モーターをベース プレートに固定しました。
次に、2 つのギアを所定の位置に取り付けます。小さいギアは DC モーター シャフトに直接接続され、大きいギアはサーボの出力になります。ただし、 の出力軸は 2 つの部分で構成されています。
この出力軸部分の両側にネジ山付きインサートを取り付けました。片側はギアを接続するため、もう一方はサーボの出力に何かを取り付けるためです。
また、DC モーター シャフトに固定するために使用する小さなギアにネジ付きインサートを取り付けました。これで、取り外したギアを所定の位置にスライドさせます。これらはヘリンボーン ギアなので、両方を同時に所定の位置にスライドさせなければなりません。そうしないと、1 つずつ挿入するとペアリングできません。
イモネジを使用して、小さなギアを DC モーターのシャフトに固定しました。 DC モーターに 12V を印加して、ギアセットが適切に動作するかどうかを確認しました。
サイド パネル、出力シャフトのボール ベアリング、トップ カバーを挿入することで、ギアボックスの組み立てが完了します。
バックプレートに M3 ネジ付きインサートを取り付けたので、長さ 20 mm の M3 ボルトでアセンブリ全体を固定できます。ギアボックスを再度テストしましたが、うまく機能しました。出力シャフトが裏側でどのように回転するかがわかります。ここで、AS5600 エンコーダーが追跡する磁石を挿入する必要があります。
M2 ボルトとナットを使用して、コントローラー ボードをギアボックスに固定します。 AS5600 位置センサーは磁石と完全に位置合わせされているため、出力シャフトが回転すると磁場の変化が適切に測定されます。
ここで、永久磁石の磁化方向が非常に重要であることに注意してください。軸方向に磁化されているか直径方向に磁化されているかに応じて、磁石を AS5600 IC に対して垂直または平行に配置する必要があります。
AS5600 エンコーダーが測定できるように適切な磁化がなかったため、磁石の方向を変更することになりました。
次に、DCモーターに2本のワイヤーをはんだ付けし、モーターとコントローラーを端子台で接続しました。電源に関しては、電源端子台に2本の線を接続し、反対側には12V電源を接続するためのDC電源コネクタがあります。 以上で、カスタムビルドのサーボ モーターが完成しました。
コントローラのプログラミング
あとはこのサーボに命を吹き込むか、コントローラーをプログラムするだけです。そのためには、まずブートローダーを ATmega328p マイクロコントローラーに書き込む必要があります。ブートローダーがなければ、マイクロコントローラーは言語や送信されるコードを理解できません。
ブートローダーの書き込み
ブートローダーを ATmega328p に書き込むには、Arduino ボードが必要です。私の場合は Arduino Nano ボードを使用します。
SPI 通信を使用するので、Arduino ボードとコントローラー ボード上の適切な SPI ピンを接続する必要があります。
ここで、Arduino IDE を使用して、ArduinoISP サンプル スケッチを開いて、Arduino Nano ボードにアップロードする必要があります。このコードにより、Arduino Nano はブートローダーを ATmega328 マイクロコントローラーに書き込むことができるようになりました。
次に、プログラマーとして、[ツール] メニューから ISP として Arduino を選択し、[ブートローダーの書き込み] をクリックする必要があります。
ブートローダーの書き込み中に、Arduino NANO ライトが何度も点滅することに気づくはずです。これにより、ブートローダーの書き込みが成功します。
コードのアップロード
それが完了したら、USB to UART インターフェース モジュールを使用して、コードをプログラミングしたり、コントローラー ボードにアップロードしたりできるようになります。
この回路図のように、コントローラーボードには専用のピンがあり、簡単に接続できます。
これで、私が作成したこのカスタム構築サーボのコードを開いて、コントローラーにアップロードできます。ただし、その前に、まず AS5600 センサーと PID コントロールのライブラリをインストールする必要があります。これは、Arduino IDE ライブラリ マネージャーから簡単に行うことができます。アップロード ボタンを押すと、USB to UART インターフェイス モジュールを介してコードが ATmega328 コントローラに書き込まれます。
以上で、カスタムビルドのサーボモーターが完成しました。これで、ポテンショメータを接続してテストできるようになりました。アナログ入力は「A」ピンではなく、コントローラー ボードの「S」ピンに接続されることに注意してください。
PCB を設計するときに、これら 2 つのピンを ATmega328 に誤って接続してしまいました。次に、DIP スイッチを介してアナログ入力モードを選択し、サーボに電力を供給します。
これで、ポテンショメータからのアナログ入力を利用してサーボ モーターの位置を制御できるようになりました。 DC モーターをサーボ モーターに変換することに成功しました。
ソースコード
次に、このカスタム構築サーボ モーターのコードを見てみましょう。
/*
* Custom-built Servo Motor - Arduino Code
* by Dejan, www.HowToMechatronics.com
*
* Libraries:
* AS5600 encoder: https://github.com/RobTillaart/AS5600
* PID conroller: https://github.com/br3ttb/Arduino-PID-Library/blob/master/PID_v1.h
*/
#include "AS5600.h"
#include "Wire.h"
#include <PID_v1.h>
AS5600 as5600; // use default Wire
double Pk1 = 2; //speed it gets there
double Ik1 = 0;
double Dk1 = 0.025;
//Define Variables we'll be connecting to
double Setpoint, Input, Output;
PID myPID(&Input, &Output, &Setpoint, Pk1, Ik1, Dk1, DIRECT);
#define motor_IN1 5
#define motor_IN2 6
#define ch1 2
#define centerSet 7
#define inputSwitch 3
#define modeSwitch 4
int ch1Value;
int encoderValue, inputValue, pwmValue;
String inString = ""; // string to hold input
int centerAngle = 2047; // 180 degrees
int angleDifference = 0;
int angleValue = 0;
int leftLimit = 30;
int rightLimit = 4067;
int rangeAdjustment = 0;
float sensitivityAdjustment = 0;
float angle = 0;
int quadrantNumber = 2;
int previousQuadrantNumber = 3;
int numberOfTurns = 0;
float totalAngle = 0;
int error = 0;
char incomingByte = 0;
int intInput = 0;
void setup() {
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("AS5600_LIB_VERSION: ");
Serial.println(AS5600_LIB_VERSION);
Wire.begin();
pinMode(motor_IN1, OUTPUT);
pinMode(motor_IN2, OUTPUT);
// Activate the Arduino internal pull-up resistors
pinMode(centerSet, INPUT_PULLUP);
pinMode(inputSwitch, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
myPID.SetMode(AUTOMATIC); // PID Setup
myPID.SetOutputLimits(-255, 255);
myPID.SetSampleTime(20);
}
void loop() {
// Read encoder value - current position
encoderValue = as5600.readAngle();
// Continuous rotation mode
if (digitalRead(modeSwitch) == 0) {
// Enter desired angle for the servo to go to through the serial monitor
while (Serial.available() > 0) {
int inChar = Serial.read();
if (isDigit(inChar)) {
// convert the incoming byte to a char and add it to the string:
inString += (char)inChar;
}
// if you get a newline, print the string, then the string's value:
if (inChar == '\n') {
Setpoint = inString.toInt(); // Setpoint - desired angle
// clear the string for new input:
inString = "";
}
}
if (digitalRead(inputSwitch) == 0) { // Potentiometer as input
inputValue = analogRead(A0);
if (inputValue < 400) {
Setpoint = Setpoint - 0.3;
}
if (inputValue < 300) {
Setpoint = Setpoint - 0.3;
}
if (inputValue < 200) {
Setpoint = Setpoint - 0.3;
}
if (inputValue > 600) {
Setpoint = Setpoint + 0.3;
}
if (inputValue > 700) {
Setpoint = Setpoint + 0.3;
}
if (inputValue > 800) {
Setpoint = Setpoint + 0.3;
}
}
else if (digitalRead(inputSwitch) == 1) {
inputValue = pulseIn(ch1, HIGH, 30000); // RC receiver as input
if (inputValue < 1450) {
Setpoint--;
}
if (inputValue < 1350) {
Setpoint--;
}
if (inputValue < 1250) {
Setpoint--;
}
if (inputValue < 1150) {
Setpoint--;
}
if (inputValue > 1550) {
Setpoint++;
}
if (inputValue > 1650) {
Setpoint++;
}
if (inputValue > 1750) {
Setpoint++;
}
if (inputValue > 1850) {
Setpoint++;
}
}
// Convert encoder RAW values into angle value
angle = encoderValue * 0.087890625;
// Quadrant 1
if (angle >= 0 && angle <= 90) {
quadrantNumber = 1;
}
// Quadrant 2
if (angle >= 90 && angle <= 180) {
quadrantNumber = 2;
}
// Quadrant 3
if (angle >= 180 && angle <= 270) {
quadrantNumber = 3;
}
// Quadrant 4
if (angle >= 270 && angle <= 360) {
quadrantNumber = 4;
}
if (quadrantNumber != previousQuadrantNumber) {
// Transition from 4th to 1st quadrant
if (quadrantNumber == 1 && previousQuadrantNumber == 4) {
numberOfTurns++;
}
// Transition from 1st to 4th quadrant
if (quadrantNumber == 4 && previousQuadrantNumber == 1) {
numberOfTurns--;
}
previousQuadrantNumber = quadrantNumber;
}
if (totalAngle >= 0) {
totalAngle = (numberOfTurns * 360) + angle;
}
else {
totalAngle = (numberOfTurns * 360) + angle;
}
// Establish Input value for PID
Input = totalAngle;
}
// Limited Rotation Mode
else if (digitalRead(modeSwitch) == 1) {
rangeAdjustment = analogRead(A1);
leftLimit = 0 + 30 + rangeAdjustment;
rightLimit = 4097 - 30 - rangeAdjustment;
if (digitalRead(inputSwitch) == 0) { // Analog input - Potentiometer
// Get value from potentiometer
inputValue = analogRead(A0);
if (inputValue < 15) {
inputValue = 15;
}
if (inputValue > 1008) {
inputValue = 1008;
}
Setpoint = map(inputValue, 15, 1008, -255, 255);
}
else if (digitalRead(inputSwitch) == 1) { // Digital input - RC transmitter
inputValue = pulseIn(ch1, HIGH, 30000); // Read RC receiver as input
Setpoint = map(inputValue, 1000, 2000, -255, 255);
}
// Set center angle
if (digitalRead(centerSet) == LOW) {
centerAngle = encoderValue;
angleDifference = 2047 - encoderValue;
delay(1000);
}
// Adjust angle value according to the center point (angleDifference)
if (centerAngle < 2047) {
angleValue = encoderValue + angleDifference;
if (encoderValue < 4097 && encoderValue > (4096 - angleDifference)) {
angleValue = encoderValue - 4097 + angleDifference;
}
}
if (centerAngle > 2047) {
angleValue = encoderValue + angleDifference;
if (encoderValue >= 0 && encoderValue < abs(angleDifference)) {
angleValue = encoderValue + 4097 + angleDifference;
}
}
else if (centerAngle == 2047) {
angleValue = encoderValue;
}
// Establish Input value for PID
Input = map(angleValue , leftLimit, rightLimit, -255, 255);
}
// Adjusting sensitivity
Pk1 = analogRead(A2) * 0.002;
myPID.SetTunings(Pk1, Ik1, Dk1);
// Run PID process to get Output value
myPID.Compute();
// Move right
if (Output > 1 ) {
pwmValue = Output;
if (pwmValue < 30 && pwmValue > 5) {
pwmValue = pwmValue + 30;
}
if (pwmValue <= 5) {
pwmValue = 0;
}
digitalWrite(motor_IN1, LOW);
analogWrite(motor_IN2, pwmValue);
}
// Move left
else if (Output < 1 ) {
pwmValue = abs(Output);
if (pwmValue < 30 && pwmValue > 5) {
pwmValue = pwmValue + 30;
}
if (pwmValue <= 5) {
pwmValue = 0;
}
analogWrite(motor_IN1, pwmValue);
digitalWrite(motor_IN2, LOW);
}
// Do not move
else if (Output > -1 && Output < 1) {
pwmValue = 0;
digitalWrite(motor_IN1, LOW);
digitalWrite(motor_IN2, LOW);
}
//Serial.print(Setpoint);
//Serial.print("\t");
//Serial.println(totalAngle);
}Code language: PHP (php) コードの概要
したがって、エンコーダー値またはシャフトの現在位置を読み取ることでループを開始します。
// Read encoder value - current position
encoderValue = as5600.readAngle();Code language: JavaScript (javascript) 次に、連続回転モードの場合は、シリアル モニターから値を受け取り、それらを PID コントローラーの設定値または希望の角度として使用します。
// Enter desired angle for the servo to go to through the serial monitor
while (Serial.available() > 0) {
int inChar = Serial.read();
if (isDigit(inChar)) {
// convert the incoming byte to a char and add it to the string:
inString += (char)inChar;
}
// if you get a newline, print the string, then the string's value:
if (inChar == '\n') {
Setpoint = inString.toInt(); // Setpoint - desired angle
// clear the string for new input:
inString = "";
}
}Code language: JavaScript (javascript) 入力モードがポテンショメータに設定されている場合、そのアナログ入力を読み取り、どれだけ回すかに応じて設定値を修正します。
if (digitalRead(inputSwitch) == 0) { // Potentiometer as input
inputValue = analogRead(A0);
if (inputValue < 400) {
Setpoint = Setpoint - 0.3;
}
if (inputValue < 300) {
Setpoint = Setpoint - 0.3;
}
if (inputValue < 200) {
Setpoint = Setpoint - 0.3;
}
if (inputValue > 600) {
Setpoint = Setpoint + 0.3;
}
if (inputValue > 700) {
Setpoint = Setpoint + 0.3;
}
if (inputValue > 800) {
Setpoint = Setpoint + 0.3;
}
}Code language: JavaScript (javascript) 入力が RC 受信機の場合、同じ設定値補正を行います。
ここでは、RAW エンコーダ値を角度値に変換し、これらの if ステートメントを使用して、シャフトの現在の位置がどの象限にあるかを追跡します。
// Convert encoder RAW values into angle value
angle = encoderValue * 0.087890625;
// Quadrant 1
if (angle >= 0 && angle <= 90) {
quadrantNumber = 1;
}
// Quadrant 2
if (angle >= 90 && angle <= 180) {
quadrantNumber = 2;
}
// Quadrant 3
if (angle >= 180 && angle <= 270) {
quadrantNumber = 3;
}
// Quadrant 4
if (angle >= 270 && angle <= 360) {
quadrantNumber = 4;
}Code language: HTML, XML (xml) この情報により、シャフトがどのように回転するか、いつ完全に回転するかを追跡できます。合計角度は、PID コントローラーの入力値です。
if (quadrantNumber != previousQuadrantNumber) {
// Transition from 4th to 1st quadrant
if (quadrantNumber == 1 && previousQuadrantNumber == 4) {
numberOfTurns++;
}
// Transition from 1st to 4th quadrant
if (quadrantNumber == 4 && previousQuadrantNumber == 1) {
numberOfTurns--;
}
previousQuadrantNumber = quadrantNumber;
}
if (totalAngle >= 0) {
totalAngle = (numberOfTurns * 360) + angle;
}
else {
totalAngle = (numberOfTurns * 360) + angle;
}
// Establish Input value for PID
Input = totalAngle;Code language: JavaScript (javascript) 一方、回転制限モードの場合は、まず回転範囲の調整に使用されるポテンショメータの値を読み取り、それに応じて左右の回転制限を調整します。
rangeAdjustment = analogRead(A1);
leftLimit = 0 + 30 + rangeAdjustment;
rightLimit = 4097 - 30 - rangeAdjustment; 入力モードがポテンショメータの場合、その値を PID コントローラの設定値として使用します。
if (digitalRead(inputSwitch) == 0) { // Analog input - Potentiometer
// Get value from potentiometer
inputValue = analogRead(A0);
if (inputValue < 15) {
inputValue = 15;
}
if (inputValue > 1008) {
inputValue = 1008;
}
Setpoint = map(inputValue, 15, 1008, -255, 255);
}Code language: HTML, XML (xml) 入力モードが RC レシーバーの場合、レシーバーから受信 PWM 値を読み取り、その値をセットポイントとして使用します。
else if (digitalRead(inputSwitch) == 1) { // Digital input - RC transmitter
inputValue = pulseIn(ch1, HIGH, 30000); // Read RC receiver as input
Setpoint = map(inputValue, 1000, 2000, -255, 255);
}Code language: JavaScript (javascript) 別の中心点を設定するには、プッシュ ボタンが押されたかどうかを確認し、その位置を新しい中心点としてキャプチャします。
// Set center angle
if (digitalRead(centerSet) == LOW) {
centerAngle = encoderValue;
angleDifference = 2047 - encoderValue;
delay(1000);
}Code language: JavaScript (javascript) それによると、エンコーダからの実際の読み取り値を調整し、新しい中心点と古い中心点の間の角度の差によってそれらをオフセットする必要があります。その値を PID コントローラーの入力値として使用します。
if (centerAngle > 2047) {
angleValue = encoderValue + angleDifference;
if (encoderValue >= 0 && encoderValue < abs(angleDifference)) {
angleValue = encoderValue + 4097 + angleDifference;
}
}
else if (centerAngle == 2047) {
angleValue = encoderValue;
}
// Establish Input value for PID
Input = map(angleValue , leftLimit, rightLimit, -255, 255);Code language: HTML, XML (xml) 他のポテンショメータからのアナログ入力を使用して、PID コントローラの比例ゲインを調整し、最後に PID プロセスを実行して出力値を取得します。
// Adjusting sensitivity
Pk1 = analogRead(A2) * 0.002;
myPID.SetTunings(Pk1, Ik1, Dk1);
// Run PID process to get Output value
myPID.Compute();Code language: JavaScript (javascript) その出力値は、PID コントローラーからの出力値に応じて、またはエンコーダーが読み取る望ましい位置と実際の位置との間の誤差に応じて、PWM 信号で DC モーターを左または右、または静止位置で駆動するために使用されます。
// Move right
if (Output > 1 ) {
pwmValue = Output;
if (pwmValue < 30 && pwmValue > 5) {
pwmValue = pwmValue + 30;
}
if (pwmValue <= 5) {
pwmValue = 0;
}
digitalWrite(motor_IN1, LOW);
analogWrite(motor_IN2, pwmValue);
}Code language: HTML, XML (xml) このビデオはこれで終わりです。コードは十分に最適化されておらず、改善の余地があることに注意してください。
また、このプロジェクトを再作成しようとする場合は、トラブルシューティングの準備をしておく必要があります。特に小さな SMD コンポーネントをはんだ付けする場合には、問題が発生する可能性がたくさんあります。
このサーボは最初から動作しませんでした。最初は PCB の接続が間違っていたため、新しいアップデートを適用して PCB を再度注文しましたが、動作するまでさらに数回試す必要がありました。
記事のこのセクションはまだ作成中です。しばらくしてから確認してください…
製造プロセス