工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

任意のDCモーターを360°連続回転カスタムサーボに変換するステップバイステップガイド

概要

このチュートリアルでは、任意のDCモーターをスタンドアローンのカスタムサーボモーターに変換する方法を学びます。通常のサーボが180°または270°の可動範囲に限定されるのに対し、このカスタムサーボは無制限の360°連続回転が可能で、さらに回転範囲を任意の値に調整できます。センターポイント(中立位置)も同時に調整可能です。

感度(応答速度)調整機能も搭載。入力モードは3種類:

シリアルモニターからの値入力とRC送信機による手動操作を同時に行うことも可能。サーボは常に現在位置を把握し、シリアルモニターで確認できます。

さらに連続回転モードでは、無限回転しながら位置を追跡可能。シャフトを任意の角度(無限回転数含む)へ移動指令できます。

これら全てを実現するのが、12ビットエンコーダー「AS5600磁気ロータリーポジションセンサー」とDCモーター駆動用PID制御です。

独自マイコンと必要回路を全て搭載したカスタムサーボモーターコントローラーボードを設計。ボードを出力シャフト中心に配置(シャフトに特定マグネット装着)、定格3.5Aまでの任意サイズDCモーターを接続、12V電源供給するだけで、上記全機能を持つスタンドアロンサーボモーターが完成します。

サーボモーターの動作原理、クローズドループ制御、PID制御、カスタムPCB/ギアボックス設計、コード解説まで全工程を解説します。

サーボモーターの動作原理

一般的なRCサーボを分解すると:小型DCモーター、コントローラーボード、ポテンショメーター、3線接続(電源2線+信号1線)、減速/増トルク用ギアが内蔵されています。ポテンショメーターが出力シャフトに連結され位置センサーとして機能。コントローラーは入力信号(目標位置)とポテンショメーターのフィードバック(実位置)を比較し、エラーを処理してモーターを目標位置まで駆動。これがクローズドループ制御システムです。

カスタムサーボモーターの作り方

より大型のDCモーターで同じクローズドループシステムを実装するには、出力シャフトに何らかの形で位置センサーを取り付け、マイクロコントローラーでDCモーターを駆動すればよいです。

位置センサーとして最もシンプルなのはRCサーボと同じポテンショメーターですが、回転範囲が270°に限定されるためサーボの可動範囲も制限されます。マルチターンポテンショメーターならより広い範囲/分解能が得られますが、やはり回転数に限界があります。

無制限の回転範囲が必要ならエンコーダーを使用します。エンコーダーはシャフトの角度位置を無限回転で追跡できる電気機械デバイス。インクリメンタル/アブソリュート、光学/磁気/容量式など様々なタイプがあり、それぞれ長所短所があります。

AS5600エンコーダー - 磁気ロータリーポジションセンサー

磁気エンコーダーであるAS5600を採用。極めてコンパクトで実装容易、高精度/高分解能。内蔵ホール効果センサーが磁場方向の変化を検知。出力シャフトにマグネットを取り付け、チップから0.5-3mmの距離に配置するだけ。シャフト/マグネットが回転するとホール効果センサーが磁場変化を捉え、内蔵12ビットA/Dコンバーターで4096位置/回転(360°)を出力。角度変化0.0878°まで検出可能。低コストで入手しやすく、カスタムサーボに最適です。

他に必要なのはマイクロコントローラーとDCモータードライバー。DRV8871(ピーク3.5A対応)とATmega328(表面実装版、DIP版よりコンパクト)を選定。スタンドアローン動作可能な最小限のカスタムPCBに全て収めることを目標としました。

カスタムサーボモーター回路図

部品表

注: アフィリエイトリンクを含みます。

ATmega328と推奨最小構成(16MHz発振子、コンデンサー、抵抗)。AMS1117で12V→5V降圧。AS5600推奨回路(コンデンサー2個、I2C用プルアップ抵抗2個)。DRV8871は電流制限抵抗1個とデカップリングコンデンサー2個。2つのトリマーポテンショメーターをアナログ入力に接続(回転範囲調整用、感度調整用)。センターポイント設定用タクトスイッチ、2way DIPスイッチで動作モード選択。入力用ピンヘッダー(アナログ電圧入力またはRC受信機からのデジタルPWM入力、5V、GND)。プログラミング用SPI/シリアルポートピンヘッダー。

回路ワークフロー

  1. 入力(目標角度位置)を2ピンで受信:アナログ電圧(ポテンショメーター)またはデジタルPWM(RC受信機)
  2. マイコン内部で入力とAS5600検出実位置を比較(I2C通信)
  3. エラー計算し、PID制御でDRV8871へPWM信号出力、DCモーターを目標位置まで駆動
  4. 全回路12V駆動、AMS1117がマイコン等5V部品へ給電

PCB設計

回路図に基づき可能な限り小型化、40×40mmに収めました。エンコーダーを裏面中央に配置し、出力シャフト中心と容易にアラインメント可能。他部品は表面実装でエンコーダー/シャフトと干渉しないよう配置。

PCBWayで発注:ガーバーファイルアップロード、プロパティ選択、適正価格。4層基板(中間層GND、コスト若干増)。デフォルトから色ホワイト、表面処理イマージョンゴールド(無料なら受け入れ)のみ変更。ガーバーファイルはPCBWayプロジェクト共有からダウンロード・直接発注可能。

数日で到着。品質良好、設計通り、イマージョンゴールド仕上げ。SMD部品ハンダ付け:インジケーターLED、コンデンサー、抵抗から開始。初SMDハンダ付けでかなり苦戦。最も困難だったのはATmega328(ピンが微小で密集)。AS5600裏面実装、スルーホール部品(DIPスイッチ、ポテンショメーター、ターミナルブロック、ピンヘッダー)は容易。最終的な外観はまずまずです。

カスタムサーボ3Dモデル

Onshapeでギアボックス設計。DCモーターに依存する設計で、コントローラーボードと組み合わせて任意サイズのDCモーターが使用可能。ここでは37mm径、内蔵ギアボックス出力50RPMのDCモーターを使用。50RPMはサーボとして良好だが、より高トルクを得るため3倍減速ギアボックスを追加。ヘリンボーンギア採用(効率的、3Dプリント容易)。DCモーターと目標出力速度に応じて自由にギアボックス設計可能。

コントローラーボードをギアボックス背面に配置、出力シャフト中心に完璧にアラインメント。DCモーターシャフトを直接出力として使う場合は1:1ギアセットでシャフト位置を正しく追跡。ベルト駆動も選択可能。無限の設計自由度があります。

3DモデルとSTLファイルダウンロード

Onshapeでブラウザ閲覧・探索可能(無料アカウントで利用可)。3Dモデル、STLファイルは以下からダウンロード:STEPファイル、STLファイル(3Dプリント用)。

カスタムサーボ組み立て

3DプリントパーツとM3ボルト/スレッドインサート、ベアリングで組み立て。

  1. DCモーターをベースプレートにM3×8mmボルトで固定。
  2. 2つのギア設置:小ギアをモーターシャフトへ、大ギアをサーボ出力とする。出力シャフトは2分割構成:片側にギア接続用、反対側にサーボ出力側への取り付け用スレッドインサート。小ギアにもスレッドインサートでグリブネジ固定用。
  3. ヘリンボーンギアは同時にスライド挿入しないと噛み合わない(順次挿入不可)。グリブネジで小ギアをモーターシャフト固定。12V印加でギアセット動作確認。
  4. サイドパネル、出力シャフト用ボールベアリング、トップカバーでギアボックス完成。バックプレートにM3スレッドインサート、M3×20mmボルトで全体固定。再テストOK。出力シャフト背面回転部にAS5600追跡用マグネット挿入。
  5. コントローラーボードをM2ボルト/ナットでギアボックス固定。AS5600とマグネットが完璧にアラインメント。
  6. 重要:マグネットの着磁方向。軸方向着磁か径方向着磁かにより、AS5600 ICに対して垂直または平行に配置する必要あり。最初は方向が合わず、マグネット向きを変更して対応。
  7. DCモーター線をハンダ付け、ターミナルブロックでコントローラー接続。電源線もターミナルブロック経由で5.5mm DCコネクター接続。完成。

コントローラープログラミング

ATmega328pにブートローダー書き込み必須(ブートローダーなしではコードを理解不能)。

ブートローダー書き込み

  1. Arduinoボード(ここではArduino Nano)を用意。
  2. SPI通信でArduinoとコントローラーボードのSPIピン接続。
  3. Arduino IDEで「ArduinoISP」スケッチ例を開きNanoへ書き込み。Nanoがブートローダー書き込み機能を持つ。
  4. ツールメニュー→書き込み装置「Arduino as ISP」選択→「ブートローダーを書き込み」クリック。
  5. 書き込み中NanoのLEDが激しく点滅し、成功すれば完了。

コード書き込み

USB-UARTインターフェースモジュールでコード書き込み。コントローラーボードに専用ピンあり。AS5600ライブラリとPIDライブラリをArduino IDEライブラリマネージャーからインストール後、書き込み実行。

完成。ポテンショメーター接続でテスト。※アナログ入力はコントローラーボードの「S」ピンへ(設計時に「A」ピンと誤配線)。DIPスイッチでアナログ入力モード選択、電源投入でポテンショメーターによる位置制御動作確認。DCモーターからサーボモーターへの変換成功。

ソースコード

/* Custom-built Servo Motor - Arduino Code by Dejan, www.HowToMechatronics.com
Libraries: AS5600 encoder: https://github.com/RobTillaart/AS5600
PID controller: https://github.com/br3ttb/Arduino-PID-Library/blob/master/PID_v1.h */
#include "AS5600.h"
#include "Wire.h"
#include 
AS5600 as5600; // use default Wire
double Pk1 = 2; // 到達速度
double Ik1 = 0;
double Dk1 = 0.025;
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 = "";
int centerAngle = 2047; // 180度
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);
  pinMode(centerSet, INPUT_PULLUP);
  pinMode(inputSwitch, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  myPID.SetMode(AUTOMATIC);
  myPID.SetOutputLimits(-255, 255);
  myPID.SetSampleTime(20);
}

void loop() {
  encoderValue = as5600.readAngle(); // エンコーダー値読み取り - 現在位置
  // 連続回転モード
  if (digitalRead(modeSwitch) == 0) {
    // シリアルモニターから目標角度入力
    while (Serial.available() > 0) {
      int inChar = Serial.read();
      if (isDigit(inChar)) {
        inString += (char)inChar;
      }
      if (inChar == '\n') {
        Setpoint = inString.toInt(); // セットポイント = 目標角度
        inString = "";
      }
    }
    if (digitalRead(inputSwitch) == 0) {
      // ポテンショメーター入力
      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) {
      // RC受信機入力
      inputValue = pulseIn(ch1, HIGH, 30000);
      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++;
    }
    // エンコーダーRAW値を角度値に変換、象限判定で回転数追跡
    angle = encoderValue * 0.087890625;
    if (angle >= 0 && angle <= 90) quadrantNumber = 1;
    if (angle >= 90 && angle <= 180) quadrantNumber = 2;
    if (angle >= 180 && angle <= 270) quadrantNumber = 3;
    if (angle >= 270 && angle <= 360) quadrantNumber = 4;
    if (quadrantNumber != previousQuadrantNumber) {
      if (quadrantNumber == 1 && previousQuadrantNumber == 4) numberOfTurns++;
      if (quadrantNumber == 4 && previousQuadrantNumber == 1) numberOfTurns--;
      previousQuadrantNumber = quadrantNumber;
    }
    if (totalAngle >= 0) totalAngle = (numberOfTurns * 360) + angle;
    else totalAngle = (numberOfTurns * 360) + angle;
    Input = totalAngle; // PID入力値
  }
  // 制限付き回転モード
  else if (digitalRead(modeSwitch) == 1) {
    rangeAdjustment = analogRead(A1);
    leftLimit = 0 + 30 + rangeAdjustment;
    rightLimit = 4097 - 30 - rangeAdjustment;
    if (digitalRead(inputSwitch) == 0) {
      // アナログ入力 - ポテンショメーター
      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) {
      // デジタル入力 - RC送信機
      inputValue = pulseIn(ch1, HIGH, 30000);
      Setpoint = map(inputValue, 1000, 2000, -255, 255);
    }
    // センターアngle設定
    if (digitalRead(centerSet) == LOW) {
      centerAngle = encoderValue;
      angleDifference = 2047 - encoderValue;
      delay(1000);
    }
    // 実測値をセンターポイント基準でオフセット調整
    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;
    }
    Input = map(angleValue, leftLimit, rightLimit, -255, 255); // PID入力値
  }
  // 感度調整
  Pk1 = analogRead(A2) * 0.002;
  myPID.SetTunings(Pk1, Ik1, Dk1);
  myPID.Compute(); // PID演算
  // 右回転
  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);
  }
  // 左回転
  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);
  }
  // 停止
  else if (Output > -1 && Output < 1) {
    pwmValue = 0;
    digitalWrite(motor_IN1, LOW);
    digitalWrite(motor_IN2, LOW);
  }
}

コード概要

ループ冒頭でエンコーダー値読み取り。連続回転モード(modeSwitch=LOW)ではシリアルモニターからの数値入力をセットポイントとして受け付け。入力モードがポテンショメーターならアナログ値読み取り、値の大小でセットポイントを微調整。RC受信機ならパルス幅読み取りで同様に微調整。RAWエンコーダー値を角度変換し、象限判定で回転数(numberOfTurns)をカウント。totalAngleをPIDのInputとする。

制限付き回転モード(modeSwitch=HIGH)では、トリマーポテンショメーター(A1)で回転範囲調整(leftLimit/rightLimit)。アナログ入力ならポテンショメーター値を-255〜255にマッピングしてセットポイントに。RC入力ならパルス幅を同様にマッピング。タクトスイッチ(centerSet)長押しで現在位置を新センターポイントとして記録(angleDifference計算)。実測エンコーダー値をangleDifferenceでオフセット補正し、補正値をleftLimit/rightLimit範囲で-255〜255へマッピングしてPID入力とする。トリマーポテンショメーター(A2)でPゲイン調整、PID演算実行、出力値でPWM駆動(デッドバンド補正付き)。

PIDゲイン初期値:P=2, I=0, D=0.025。コードは最適化の余地あり。SMDハンダ付けの難しさ、PCB配線ミスなどトラブルシューティング覚悟で挑戦を。初回で動かず、PCB再発注・数回試行で動作達成。

この記事セクションはまだ構築中です。後で再度チェックしてください…。

製造プロセス

  1. マイクロホン製造の全工程:ウェハー製造からパッケージングまで
  2. コンベアシステム完全ガイド:仕組み、種類、導入メリット
  3. CNC加工 vs 3Dプリント:違いを徹底比較
  4. 黒板:中世の角板から現代のホーローへ
  5. 現代ブラジャーの完全な進化と生産
  6. OscPocketO - コンパクトなArduinoシンセサイザー&ドラムマシン
  7. 電子インク:仕組み、歴史、未来応用
  8. Microsoft Teams用カスタムミュートボタン:リモート会議を快適に
  9. START:PS2キーボード、LCD、Ethernet、リモートシェル搭載のスタンドアロンArduinoターミナル
  10. フライスと旋削の統合:マルチタスキングマシンで効率向上
  11. Arduinoオーディオ周波数検出器 – 高感度サウンドモジュールで最大音量ピークの周波数を測定