シゲゾーンでSG90を15個ほど買ってきたので、動作確認をしたい。

ほんとは、360度版がほしかったのだけど、3Fは臨時休業だったのだ。1Fに在庫置いててくれて助かる。荷物があって15個数えるのが面倒だったので、店内の在庫から出してもらったw
とりあえず、指定の動作角度内で往復動作できたらいいかな。
ATOMとかだと、5Vが安定しないので電源は別に確保して、GNDは共通化しないといけないそうな。めんどくさいな。でも、実はそのままでも動くんじゃね?
「ATOM Lite の Groveポート(G26)は 3.3V ロジックです。SG90 は通常5V駆動が望ましいため、別途電源供給が必要な場合があります。」
SG90だと、0-180度なんだけど、個体によってはそこまでの角度で動かないものもあって、プラスチックのギアをガリガリやってしまうこともある。なので10-170くらいのパラメータで設定するのが普通かな。今回はそれも無視する。
SG90の制御パルスは500μs~2500μsで、中立位置は1500μsになる。ガリガリ防止には、750-2250くらいがよさげ。
Arduino向けのServo.hは動かないので、ESP32Servo.hを使う。ライブラリマネージャからインストールする。

とりあえず、動作可能範囲は全部動かして180度でリピートするようにしてみる。
#include <M5Atom.h>
#include <ESP32Servo.h>
#define SERVO_PIN 26
Servo myServo;
int pmin = 500;
int pmax = 2500;
int p = 1500;
int pd = 10;
void setup() {
M5.begin();
// SG90用にパルス幅を調整(デフォルトでも動くことが多い)
// 50HzのPWM(標準的なサーボ)
myServo.setPeriodHertz(50);
// パルス幅500us〜2250us(角度に応じた範囲)
myServo.attach(SERVO_PIN, pmin, pmax);
// 初期位置を中央に
myServo.write(90);
delay(1000);
}
void loop() {
myServo.write(p);
Serial.printf("p = %d\n", p);
p += pd;
if (p > pmax) {
p = pmax;
pd = -pd;
} else if (pmin > p) {
p = pmin;
pd = -pd;
}
delay(10);
}
あと、なんか途中で通電すると、チッチッチッチッと言うばかりで、ぜんぜん動かないこともある。なんでだろ? PCにつないでいるときに起きる。ACアダプタでは起きない。なんかシリアルとかの信号もれているのかも。やっぱ、電源分離とかは必須かねぇ...
サーボの取り替え時に初期化ができない。LEDで状態がわかるようにする。スケッチを変更する。
#include <M5Atom.h>
#include <ESP32Servo.h>
#define SERVO_PIN 26
Servo myServo;
const int pmin = 500;
const int pmax = 2500;
const int pcenter = 1500;
int p = pcenter;
int pd = 10;
// サーボの状態を定義する列挙型
enum ServoState {
SERVO_STOPPED, // 停止中(中央位置)
SERVO_MOVING, // 動作中(左右に往復)
SERVO_RETURNING_TO_CENTER // 中央位置へ復帰中
};
ServoState currentServoState = SERVO_STOPPED; // サーボの現在の状態
// ボタンの状態管理用変数
bool prevButtonPhysicalState = false; // 前回のループでのボタンの物理的な状態 (true: 押されている, false: 離されている)
unsigned long lastButtonProcessedTime = 0; // 最後にボタンイベントを処理した時刻
const unsigned long buttonDebounceInterval = 200; // ボタンのデバウンス時間(ミリ秒)。必要に応じて調整してください。
// サーボ中央復帰用のタイマー変数
unsigned long servoReturnStartTime = 0;
const unsigned long servoReturnDuration = 750; // サーボが中央に戻るのを待つ時間(ミリ秒)。サーボの速度に合わせて調整。
void setup() {
M5.begin(true, false, true); // LED/Serial/I2Cを有効化
Serial.begin(115200); // シリアル通信を開始(デバッグ用)
myServo.setPeriodHertz(50);
myServo.attach(SERVO_PIN, pmin, pmax);
myServo.write(pcenter); // 初期位置に設定
M5.dis.drawpix(0, 0x00ff00); // 初期は停止中(緑点灯)
delay(1000); // 初期化待ち
Serial.println("セットアップ完了。サーボは中央で停止中。");
}
void loop() {
M5.update(); // M5Atomの状態を更新(ボタンの状態も含む)
// 現在のボタンの物理的な状態を読み取る
bool currentButtonPhysicalState = M5.Btn.isPressed();
// ボタンの立ち上がりエッジ(押された瞬間)を検出する
// かつ、前回のボタン処理から十分な時間が経過していることを確認(ソフトウェアデバウンス)
if (currentButtonPhysicalState && !prevButtonPhysicalState && (millis() - lastButtonProcessedTime > buttonDebounceInterval)) {
lastButtonProcessedTime = millis(); // ボタンイベントを処理した時刻を更新
Serial.println("ボタンが押されました!");
// サーボの現在の状態に基づいて、次の状態へ遷移
if (currentServoState == SERVO_MOVING) {
// 動作中にボタンが押された場合:中央復帰状態へ
Serial.println(" サーボは動作中でした。中央に戻します。");
currentServoState = SERVO_RETURNING_TO_CENTER;
p = pcenter; // 目標位置を中央に設定
myServo.write(p); // サーボを中央に移動するコマンドを発行
servoReturnStartTime = millis(); // 中央復帰タイマーを開始
M5.dis.drawpix(0, 0x00ff00); // 緑点灯(停止中/復帰中を示す)
} else if (currentServoState == SERVO_STOPPED) {
// 停止中にボタンが押された場合:動作状態へ
Serial.println(" サーボは停止中でした。動作を再開します。");
currentServoState = SERVO_MOVING;
M5.dis.drawpix(0, 0x000000); // LED消灯(動作中を示す)
}
// SERVO_RETURNING_TO_CENTER 状態中にボタンが押されても、ここでは何もしない
// これにより、中央復帰中にボタンが連打されてもすぐに動作を再開しない
}
prevButtonPhysicalState = currentButtonPhysicalState; // 次のループのために現在のボタン状態を保存
// サーボの状態に応じた処理
switch (currentServoState) {
case SERVO_MOVING:
// サーボを現在のp値に移動
myServo.write(p);
p += pd; // p値を増減
// 範囲チェックと方向反転
if (p > pmax) {
p = pmax;
pd = -pd;
} else if (p < pmin) {
p = pmin;
pd = -pd;
}
delay(10); // サーボの移動速度を調整するための遅延
break;
case SERVO_RETURNING_TO_CENTER:
// サーボを中央位置に固定し、指定時間待つ
myServo.write(pcenter); // 中央位置に留まるように繰り返しコマンドを送る
if (millis() - servoReturnStartTime >= servoReturnDuration) {
// 指定時間が経過したら、停止状態へ移行
currentServoState = SERVO_STOPPED;
Serial.println(" サーボ中央復帰完了。停止状態へ移行。");
}
break;
case SERVO_STOPPED:
// サーボを中央位置に固定
myServo.write(pcenter); // 中央位置に留まるように繰り返しコマンドを送る
break;
}
}
とりあえず目的の動作にはなった。電源は別で動作させる必要がありそう。
オリジナル投稿:
SG90の動作確認ツールを作る|kinneko|pixivFANBOX
https://kinneko.fanbox.cc/posts/10039428



