はじめに
Spresenseメインボード1枚を搭載した小型でシンプルなロボットの作り方について紹介します。
小型のロボットを作りたいという気持ちが湧き上がり、回転サーボモータを使えば実現できるのではないかと思い、開発を始めました。
当初、コントローラによる操作を考えましたが、最終的にはロボットの自律化が必要だと感じ、カメラを取り付けることにしました。
なお、部品は全て市販品としたかったのですが、良いアイデアが思いつかず、3Dプリント品が存在します。
また、こだわりで、アドオン基板を設計製作しています。
部品表
名 称 | 購入先 | 型 番 | 価格 | 使用数量 |
---|---|---|---|---|
メインボード | 秋月電子通商 | CXD5602PWBMAIN1 | 6050円/1個 | 1個 |
カメラボード | 秋月電子通商 | CXD5602PWBCAM2W | 3850円/1個 | 1個 |
回転サーボモータ | 秋月電子通商 | FS90R | 500円/1個 | 2個 |
丸ピンソケット(40P) | 秋月電子通商 | 6604S-40 | 150円/1個 | 1個 |
ピンヘッダ (40P) | 秋月電子通商 | PH-1x40SG | 35円/1個 | 1個 |
単4電池ボックス | 秋月電子通商 | BH-411-4A | 40円/1個 | 2個 |
リチウムイオン電池 | アマゾン | 10440 3.7V 320mAh | 3058円/ 4本 | 2本 |
外径26mmギア | アマゾン | Othmro 50102A | 1433円/ 50個 | 2個 |
ねじ M2×4㎜ | アマゾン | Uxcell 六角ソケットキャップ | 860円/ 50本 | 2本 |
ねじ M2×50㎜ | アマゾン | uxcell SUS304 | 2190円/ 60本 | 2本 |
ワッシャM2 | アマゾン | TBDBNR SUS304 | 529円/100個 | 4個 |
ナット M2 | アマゾン | uxcell 炭素鋼 | 689円/100個 | 2個 |
ねじ M2×6㎜ | アマゾン | B30-0206 | 677円/ 39本 | 10本 |
★3Dプリント品 | なし(自作) | なし(自作) 4種類 | 自作PriceLess! | - |
★アドオン基板 | 基板メーカ | なし(自作) 1種類 | 約30円/1個 | 1枚 |
※購入先は、あくまで参考としてください。また、価格は変動があります。
- 上記★印 2点の部品は、データを次の場所で公開しています。
https://drive.google.com/drive/folders/1Z4-JthyYZUP1su3JkKWqWyHkxQpko9QY?usp=sharing - ★アドオン基板の代替手段は、末尾に記載しています。代替の場合は、丸ピンソケット(40P)は不要です。
使用工具
・マイクロプラスドライバ(ベッセル +00×75 9900)
・ボールポイントドライバ(アネックス 対辺1.5mm×100 No.6700)
・ピンバイス[ドリルφ1.8mmとφ2.0mm]
・その他: ニッパー、ハンダごて、ヤスリ等の一般工具
準備作業
-
【推奨事項】 ねじM2×50mm 1本 ねじ山削除
ねじ山が回転サーボモータの配線の被覆を損傷させるため、ねじの中央部をヤスリで削る。
(収縮チューブを被せることも考えましたが、根本原因のねじ山削除にしました)
-
【挑戦 推奨事項】 回転サーボモータの配線短縮
回転サーボモータの配線を短くすることをお勧めします。
挑戦する場合は、方法について記事の最後に記載していますので、ご確認ください。
組立作業
-
はんだ付けをする。
アドオン基板 と ピンソケット(13ピン×2)・ピンヘッダ(3ピン×2)
アドオン基板 と 電池ボックス
リード線が長すぎるため約6割の長さで切断し被覆を剥いた後、はんだ付けする。
また、断線対策として並列配線も取り付ける。
〇電池ボックスからの配線が断線した場合、片方の電池だけが消費されてしまうため電池ボックス同士も配線で接続することにしました。
-
ねじ締付M2×50mm (ワッシャとナット使用) :回転サーボモータ、ベース部分の組立
後端部品(呼び名 しっぽ)が、ロボットの中央にくるように調整する。
-
ねじ締付 M2×6mm:電池ボックス、カメラボード、メインボードの取付け
メインボードにカメラボードを差し込む。
各種部品をねじM2×6mmを締めて固定する。
-
アドオン基板の挿入、回転サーボモータのコネクタ接続
コネクタの向きと接続先に注意してください。
・向き:写真(配線の色)を見て正しい向きで接続してください。
・接続先:右側の回転サーボモータは奥側に、左側の回転サーボモータは手前側に接続してください。
プログラム内容
プログラムの内容を次に示します。
#include <Servo.h>
#include <Camera.h>
Servo servoLeft;
Servo servoRight;
const int PIN_LEFT = 15;
const int PIN_RIGHT = 14;
// サーボの設定値
const int CENTER = 90; // 停止位置
const int MIN_SPEED = 10; // 初期速度
const int MAX_SPEED = 100; // 最大速度
const int SPEED_STEP = 10; // 速度の増加量
int currentSpeed = MIN_SPEED; // 現在の速度
// カメラ設定
const int IMG_WIDTH = 160;
const int IMG_HEIGHT = 120;
// LED検出の閾値
const int BLUE_THRESHOLD = 10; //青色
const int BRIGHTNESS_THRESHOLD = 50; //明るさ
const int MIN_PIXELS = 5; //最小ピクセル
void setup() {
theCamera.begin();
theCamera.setStillPictureImageFormat(
IMG_WIDTH,
IMG_HEIGHT,
CAM_IMAGE_PIX_FMT_RGB565);
servoLeft.attach(PIN_LEFT, 500, 2400);
servoRight.attach(PIN_RIGHT, 500, 2400);
stop();
delay(1000);
}
void loop() {
CamImage img = theCamera.takePicture();
if (img.isAvailable()) {
int ledX = findBlueLED(img);
if (ledX >= 0) { // LED検出時
int center = IMG_WIDTH / 2;
int margin = IMG_WIDTH / 6;
if (abs(ledX - center) < margin) {
// 中央にある場合は前進速度アップ
if (currentSpeed < MAX_SPEED) {
currentSpeed = min(currentSpeed + SPEED_STEP, MAX_SPEED);
}
forward();
} else if (ledX < center) {
turnLeft();
} else {
turnRight();
}
} else {
// LED未検出時は停止して速度リセット
currentSpeed = MIN_SPEED;
stop();
}
}
delay(100);
}
int findBlueLED(CamImage &img) {
uint16_t *buf = (uint16_t *)img.getImgBuff();
int bluePixels = 0;
int sumX = 0;
// 画像全体スキャン
for (int y = 0; y < (IMG_HEIGHT); y++) {
for (int x = 0; x < (IMG_WIDTH); x++) {
uint16_t pixel = buf[y * IMG_WIDTH + x];
int blue = pixel & 0x001F;
int red = (pixel & 0xF800) >> 11;
int green = (pixel & 0x07E0) >> 5;
// 明るさを計算
int brightness = (red + (green >> 1) + blue);
// 明るさのチェック と 青色判定
if (brightness > BRIGHTNESS_THRESHOLD && // 明るさのチェック
blue > BLUE_THRESHOLD && // 青色の基準値
blue > red * 1.5 && // 青色が赤の1.5倍
blue > (green>>1) * 1.5) { // 青色が緑の1.5倍
bluePixels++;
sumX += x;
}
}
}
return (bluePixels >= MIN_PIXELS) ? (sumX / bluePixels) : -1;
}
void forward() {
servoLeft.write(CENTER + currentSpeed);
servoRight.write(CENTER - currentSpeed);
}
void turnLeft() {
servoLeft.write(CENTER - MIN_SPEED);
servoRight.write(CENTER - MIN_SPEED);
}
void turnRight() {
servoLeft.write(CENTER + MIN_SPEED);
servoRight.write(CENTER + MIN_SPEED);
}
void stop() {
servoLeft.write(CENTER);
servoRight.write(CENTER);
}
<プログラムの説明>
カメラを搭載したロボットが青色LEDを追跡して自動的に追従する機能を実装したものです。
【主な特徴】
- カメラによる青色LED検出
- 160×120ピクセルの解像度で画像を取得
- 明るさと色相の条件を組み合わせて青色LED検出
- 誤検出を防ぐため、最小ピクセル数のチェックを実装
- スムーズな走行制御
- LEDが正面にある場合は徐々に速度を上げて追従
- 左右にある場合は適切な方向に旋回
- LED見失い時は安全に停止
- 走行性能の最適化
- 初期速度10、最大速度100で設定
- 中央にLEDがある場合、10ずつ段階的に加速
- 旋回時は最小速度で慎重に方向転換
【動作の流れ】
- カメラで画像を取得(100ミリ秒間隔)
- 画像内の各ピクセルで青色LEDの判定
- 明るさが50以上
- 青色成分が10以上
- 青色が赤や緑の1.5倍以上
- LED位置に応じた移動制御
- 中央(画面幅の1/6以内):前進&加速
- 左側:左旋回
- 右側:右旋回
- 未検出:停止
ロボットの操作方法
-
青色LED追跡
カメラの前に青色LEDを点灯させると、ロボットが青色LEDを追いかけます。
〇残念ながら、ロボットを誘う感じで、青色LED点灯場所を動かす必要があります。
プログラムの改良を試みたのですが、改善には至りませんでした。
改善し続けると記事の投稿ができなくなるため、今回はここで一旦終了としました。
プログラムに詳しい方、ぜひ改良をお願いしたいです(^^♪。
その他(補足等)
-
ロボットのサイズについて
縦・横サイズは、クレジットカードの範囲内にほぼ収まりました。
ディスイズ クレジットカードサイズ!
特定の年代以上の方には分かると思います。
興味のある方は、「CMビデオカメラ、パスポートサイズ」で検索してみてください。
-
3Dプリント品のドリル通しについて
3Dプリンタによっては、不要な作業かもしれません。
私が所有する3Dプリンタは、熱溶解積層方式であり、ドリル通しが必要でした。
ただ、電池ケース穴のドリル通しは必要です。穴の大きさがφ1.6mmのままでは ねじを締めることができませんでした。ドリルでφ1.8mmにする必要があります。
ちなみに、代替手段として、ドリルの代わりに、工具「ボールポイントドライバ」を通す方法があります。M2ねじを締めることができるようになります。 -
ピンソケットについて
サードパーティー製 拡張ボードを取り付けできるように選定しましたが、ピンソケット(メス)の形状は丸く、拡張ボードのピン(オス)は四角で、残念ながら差し込むことができませんでした。
当初、「シングルピンソケット (低メス) 1×20 (20P) 型番 2212S-20SG-36」の使用を試みました。こちらは拡張基板が差し込みできます。
しかし、基板の厚み分、ピンの突出し長さが短くなります。また、Spresenseのメインボードのピンソケットに対して、ピンが細いようで、すぐに抜けてしまいました。
-
アドオン基板の代替について
代替手段として、「SPRESENSE アドオン用ユニバーサル基板 SSCI-039024」を使用する方法があります。
基板上の配線(渡り)は手間がかかるかもしれませんが、ぜひ挑戦してみてください。
〇このロボットを作ってみたい方のために、委託販売などで入手可能にすることが望ましいと考えていますが、現段階ではその手段が確立されていません。
ただし、基板を入手したいという要望があれば、対応を検討したいと思います。 -
【挑戦 推奨事項】 回転サーボモータの配線短縮
配線の3分の1の位置で切断し、ねじをゆるめて分解する。
配線の被覆を剥き、はんだ付けで取り付けて、再組立をしてねじを締める。
最後に
今後は、プログラムの改良・発展に取り組みたいと思います。
また、サードパーティー製の拡張ボードが差し込めるようにしたいと考えています。
このロボットは、作りたいという気持ちから製作しましたが、学習用ロボットとして使用して頂けないかなと思っています。
約1万5000円で作ることができるので、教育用途としての可能性は十分にあると感じています。
-
kjsugi77
さんが
2025/01/24
に
編集
をしました。
(メッセージ: 初版)
-
kjsugi77
さんが
2025/01/24
に
編集
をしました。
(メッセージ: 誤記修正(見出しレベルを###→##))
-
kjsugi77
さんが
2025/01/29
に
編集
をしました。
(メッセージ: 各種変更 [ 見出し修正など ])
-
kjsugi77
さんが
2025/01/31
に
編集
をしました。
(メッセージ: 各種変更[ 画像差し替え、微修正 ])
ログインしてコメントを投稿する