第6回 自作TELNET・プロポ
2025.04.24
YouTube でも紹介しています。画像をクリックすると再生できます。
今回はTELNET通信による遠隔制御を行います。
最初はTeraTermを使ってロボットカーを制御し、それをTELNETプロポーショナルシステム、略してTELNETプロポに置き換えていきます。
ロボット・カーの組立て
●Arduino UNO用ロボット・カー
今回作成するTELNETプロポのテスト用に購入しました。

ロボット・カーですが、Arduino UNO搭載型のロボット・カーが加工しやすいです。
すでに組み立て済みの中古品を購入したためArduino UNOを含め不要なパーツを取り外し、モータドライバモジュールのみを残しました。

・瞬間ピーク電流は最大3A、定格電流25W
・2個の内蔵Hブリッジ
・2相ステッピングモータまたは4相ステッピングモータ、2相DCモータを駆動可能
・ドライブ電圧:5-35V、ロジック電圧:5V。※ドライブ電圧が12Vを超える場合は、外部5Vロジックを使用
OSOYOO Model-X Motor Driver Module
仕様に関しては下記をご覧ください
ドローン制御 まずはロボットカーでお勉強
●KeyeStudio 328 WiFi Plus
2025年4月8日の記事で紹介したUNOボードに通信用ESP8266を搭載したマイコンボードです。
OSOYOO Model-X Motor Driver Module は、外部5Vロジックなのでこちらの拡張UNOボードを使いましたが、
3.3V駆動のモータードライバーモジュールであれば、ESP8266搭載のWeMos D1や後述のKeyestudio ESP32 PLUS のようなArduino UNO形状のボードでもよいと思います。

ESP8266およびUNO側プログラムのビルド、アップロード方法は下記をご覧ください。
KeyeStudio 328 WiFi Plus

最小構成のロボットカーに、328 WiFi Plus を取付けています。
ソースコードのビルドには、PlatformIOを使用しています。
Arduino開発環境構築 PlatformIO
●ESP8266側プログラム
ESP8266側プログラムでは、TELNETサーバを起動してクライアントからの送信文字を受け取ります。
受け取った文字はそのままUNO側にシリアル出力します。
telnet.ino (抜粋)
void loop()
{
if (telnet.connected()) {
while (telnet.available()) Serial.write(telnet.read());
} else {
telnet.begin(&server);
}
}
WiFiサーバはSTAモードで起動し、ESP8266には固定でIPアドレス 192.168.11.64を割り振っています。
※記事の最後のリンクからソースコードをダウンロードできます。
●UNO側プログラム
ESP8266から受け取った文字に従い、モータードライバーモジュールに動作を指示します。
control.ino (抜粋)
void set_Motorspeed(int SPEED_L,int SPEED_R)
{
analogWrite(PIN_ENB, SPEED_L);
analogWrite(PIN_ENA, SPEED_R);
}
void go_Advance(void) //Forward
{
digitalWrite(PIN_IN1, HIGH); // IN1
digitalWrite(PIN_IN2, LOW); // IN2
digitalWrite(PIN_IN3, HIGH); // IN3
digitalWrite(PIN_IN4, LOW); // IN4
set_Motorspeed(SPEED, SPEED);
}
void loop()
{
if (Serial.available()) {
elapsed_time = millis();
char c = Serial.read();
if (command != c) {
switch(c) {
case 'U': go_Advance(); break;
case 'L': go_Left(); break;
case 'R': go_Right(); break;
case 'D': go_Back(); break;
case 'C': stop_motor(); break;
default:break;
}
command = c;
}
} else {
if (command != 'C') {
if ((millis() - elapsed_time) > 1000) {
stop_motor();
command = 'C';
}
}
}
}
TELNET通信の不意の切断に備えて、ロボットカー側に自動停止機能を付けています。

ロボットカーの電源を入れます。

ESP8266で設定したIPアドレスを指定してTeraTermを立ち上げます。

ロボットカーに接続されると、接続先IPアドレスと電波強度が返されます。
パソコンのキーボードからU(前進)、L(左折)、R(右折)、D(後退)、C(停止)キーを押すとロボットカーが指示に従い動作します。
また、プロポ側からの通信が1秒以上途絶えたときにはモーターを停止させる処理を入れています。
それでは、TeraTeam の操作を、TELNETプロポーショナルシステム、略してTELNETプロポに置き換えていきます。
コントローラの組立て
コントローラ側で必要となる部品です。
●ジョイスティックRKJXV122400R DIP化キット

●アナログ・スティック

amazon ではジョイスティック・キットとしても販売してるので、それらを購入されたほうが割安かもしれません。
●keyestudio UNO Prototype Circuit Breakout Board PCB


プロトタイプ基板にジョイスティック・キットをはんだ付けしています

配線はこんな感じになります。ヘッダーピンを付けてUNOのハットにしています。
●Keyestudio ESP32 PLUS Development Board WROOM-32 module WIFI+Bluetooth Compatible with Arduino
UNO形状のESP32ボードを使用し、ジョイスティックを被せて一体化します。
ESP32のWiFi機能を利用して、ジョイスティックからの指示を送信、
これをロボット・カーに搭載した328 WiFi Plus で受信してサーボ・モータを制御しています。
※画像をクリックすると拡大表示されピン配置を確認できます
Keyestudio ESP32 PLUS Development Board
This is a universal WIFI plus Bluetooth development board based on ESP32, integrated with ESP32-WROOM-32 module and compatible with Arduino.
It has a hall sensor, high-speed SDIO/SPI, UART, I2S as well as I2C. Furthermore, equipped with freeRTOS operating system, which is quite suitable for the Internet of things and smart home.
Specifications
CPU: Tensilica Xtensa LX6 microprocessor 240 MHz
Memory: 448KB ROM / 520KB SRAM
Voltage: 3.3V-5V
Current Output: 1.2A(maximum)
Maximum power Output: 10W
Working temperature: -10℃~50℃
●Arduino UNO R3用エンクロージャ

ESP32 PLUS Development Board を格納しようとすると、外部電源ソケットの位置が合わないため、スチロールカッターなどでケースの一部を切断する必要があります。

UNO型ESP32に被せるジョイスティック・ハットはこんな感じになります
ジョイスティックとESP32の接続は下記の通りです
| JOYSTICK | ----- | ESP32 |
| L-SWITCH | ------- | GPIO32 |
| L-Y | ------- | GPIO34 |
| L-X | ------- | GPIO36 |
| R-SWITCH | ------- | GPIO33 |
| R-Y | ------- | GPIO35 |
| R-X | ------- | GPIO39 |
| GND | ------- | GND |
| V | ------- | 3.3V |
ESP32 Plus にコードを書き込み、動作確認してみます
#define JOYSTICK_LX 34
#define JOYSTICK_LY 33
#define JOYSTICK_LSW 32
#define JOYSTICK_RX 39
#define JOYSTICK_RY 36
#define JOYSTICK_RSW 35
void setup()
{
Serial.begin(115200);
}
void loop()
{
uint16_t Lx, Ly, Rx,Ry;
Lx = analogRead(JOYSTICK_LX);
Ly = analogRead(JOYSTICK_LY);
Rx = analogRead(JOYSTICK_RX);
Ry = analogRead(JOYSTICK_RY);
Serial.printf("Lx:%d Ly:%d Rx:%d Ry:%d\n",Lx,Ly,Rx,Ry);
delay(500);
}
シリアルモニタを起動して、ジョイスティックからの取得値を表示してみます
$ pio device monitor -p /dev/ttyUSB0 -b 115200

取得できる値の範囲は12ビットの整数値0~4095です。
ジョイスティック無操作(中心にある状態)では中央値を取得できるはずですが多少のズレが生じています。
まずは無操作状態での中央値の平均を求めます。
次にスティック操作の変位量から、レバーの方向を算出します
左のジョイスティック、右のジョイスティックの順で動かしてみた結果です。左右同時でも構いません。

ロボット・カー制御には左側のジョイスティックのみを使用します。
L→L(左旋回),R→R(右旋回),U→A(前進),D→B(後退),C→S(停止)としてロボット・カーに指示を与えます。
次にデータ送信するためのTELNETクライアントを組み込みます。
●TELNETクライアント
TELNETクライアントとして参考になるなライブラリを探すのに苦労しました。

ivanalayan15/ESP-Telnet-Client
上記の github から3つのソースコードを用います。
・src > ESPTelnetClient.cpp
・src > ESPTelnetClient.h
・examples > telnetRaspberry > telnetRaspberry.ino
クラスファイルはそのまま使用できます。
変更するのはラズベリーパイ用TELNETクライアントのソースコードです。
ESP8266用なので、インクルードするファイルはESP32用に変更します。
controller.ino (抜粋) ※telnetRaspberry.inoから名称変更
void setup()
{
while(1) {
if (digitalRead(JOYSTICK_LSW) == LOW) break;
delay(100);
}
ジョイスティックはプッシュボタンの機能を持っています。
レバーを押すことで処理を開始するようにしました。
LXcenter = 0; LYcenter = 0; RXcenter = 0; RYcenter = 0;
for (int i=0; i<30; i++) {
LXcenter += analogRead(JOYSTICK_LX);
LYcenter += analogRead(JOYSTICK_LY);
RXcenter += analogRead(JOYSTICK_RX);
RYcenter += analogRead(JOYSTICK_RY);
}
LXcenter /= 30;
LYcenter /= 30;
RXcenter /= 30;
RYcenter /= 30;
ここでは、ジョイスティック無操作状態でのX座標、Y座標の平均値を求めています。
if (!WiFi.config(LOCAL_IP, GATEWAY, SUBNETMASK, PRIMARY_DNS)) while(1);
WiFi.mode(WIFI_STA);
WiFiMulti.addAP(SECRET_SSID, SECRET_PASS);
Serial.print("Waiting for WiFi ");
while (WiFiMulti.run() != WL_CONNECTED) {
Serial.write('.');
delay(500);
}
Serial.printf("\nWiFi connected\n");
IPAddress ip = WiFi.localIP();
Serial.printf("CONTROLLER: %d:%d:%d:%d\n",ip[0],ip[1],ip[2],ip[3]);
Serial.printf("login ");
while (!tc.login(esp8266IP)) {
Serial.write('.');
delay(500);
}
Serial.printf("\n");
}
ログイン時にユーザ名、パスワードは不要なので、接続先のIPアドレスのみを指定しています
char stick(int horizontal, int vertical)
{
char judgeH = 'C', judgeV = 'C';
int diffH = 0, diffV = 0;
if ((horizontal < 0) && (horizontal < (FREE_PLAY * -1))) {
judgeH = 'L'; diffH = (horizontal - FREE_PLAY) * -1;
} else if ((horizontal > 0) && (horizontal > FREE_PLAY)) {
judgeH = 'R'; diffH = (horizontal - FREE_PLAY);
}
if ((vertical < 0) && (vertical < (FREE_PLAY * -1))) {
judgeV = 'D'; diffV = (vertical - FREE_PLAY) * -1;
} else if ((vertical > 0) && (vertical > FREE_PLAY)) {
judgeV = 'U'; diffV = (vertical - FREE_PLAY);
}
if ((diffH > diffV)&&(judgeH!='C')) {
return judgeH;
} else if ((diffH < diffV)&&(judgeV!='C')) {
return judgeV;
} else {
return 'C';
}
}
ジョイスティックのレバー操作判定処理です。中央値から乖離幅が最大の方向を判定しています。
void loop()
{
int Lx, Ly;
char stickLeft;
unsigned char ch;
static int pos = 0;
Lx = analogRead(JOYSTICK_LX) - LXcenter;
Ly = analogRead(JOYSTICK_LY) - LYcenter;
stickLeft = stick(Lx,Ly);
tc.write(stickLeft);
while(tc.available()) {
ch = tc.read();
switch (ch) {
case 0xff:
pos = 2;
break;
default:
if (pos > 0) {
pos--;
} else {
Serial.write(ch);
}
break;
}
}
delay(10);
}
ループ内のwhile() {}はTELNET通信でのネゴシエーション情報をカットしています
コントローラはUSBまたはDCジャック給電で動作しますが、
ラズベリーパイとのUSB接続による電源供給時にはシリアルモニタを利用できます
$ pio device monitor -p /dev/ttyUSB0 -b 115200

ロボットカーの電源を入れます。続いてコントローラのプッシュボタンを押して接続を開始します。
レバーを操作すると、指示に従いタイヤが回ります。

今回は屋内での試験的な操作なので、STAモードで設計していますが、屋外で使用する場合はAPモードに変更してください。
その際には電波が届かなくなることも考慮して、ロボットカー側に自動停止機能を付けてください。
if ((millis() - elapsed_time) > 1000) {
stop_motor();
command = 'C';
}
●I2C JOYSTICK 2 UNIT (STM32G030)
今回のようなラジコンにはジョイスティック1つで済むので下記のジョイスティックでも対応できます

ドキュメント
ジョイスティックを搭載したコントロール用ユニットです。
I2Cインターフェースを採用しており、3軸コントロール信号入力(X軸/Y軸アナログ入力、Z軸キーデジタル入力)に対応しています。
特徴
〇X軸 / Y軸 + Z軸プッシュボタン
〇STM32G030マイコン搭載
〇RGB LEDを搭載
〇I2C制御
〇ふたつのレゴ互換穴
〇開発プラットフォーム:Arduino、UIFlow
仕様
〇MCU:STM32G030F6P6@Cortex-M0+、32 KBフラッシュメモリ、8KB SRAM、64 MHz
〇通信プロトコル:I2C: 0x63
〇X/Y軸オフセット出力:16-bit ADC出力(0-65535)
〇Z軸ボタン出力:0/1
〇RGB LED:1 x WS2812C
〇製品サイズ:40 x 24 x 23.9 mm

m5stack/M5Unit-Joystick2

GroundStudio Carbon D4 (ESP32-PICO-D4)にはQWIICコネクタが付いています。
●ソースコード
自作TELNET・プロポ SOURCE CODE
※TELNETクライアント・ライブラリは本文記載のURLからダウンロードしてください
|
Raspberry Pi(ラズベリー パイ)は、ARMプロセッサを搭載したシングルボードコンピュータ。イギリスのラズベリーパイ財団によって開発されている。
たいていのことは100日あれば、うまくいく。長田英知著
「時間がなくて、なかなか自分のやりたいことができない」
「一念発起して何かを始めても、いつも三日坊主で終わってしまう」
「色んなことを先延ばしにしたまま、時間だけが過ぎていく」
そこで本書では、そんな著者が独自に開発した、
まったく新しい目標達成メソッド「100日デザイン」について、
その知識と技術を、余すところなくご紹介します。
まんがで納得ナポレオン・ヒル 思考は現実化する
OLとして雑務をこなす日々に飽き足らず、科学者だった父が残した薬品を商品化すべく、起業を決意した内山麻由(27)。彼女はセミナーで知り合った謎の女性からサポートを得ながら、彼女と二人三脚でナポレオン・ヒルの成功哲学を実践し、さまざまな問題を乗り越えていく。
ヒル博士の<ゴールデンルール>に従い、仕事に、恋に全力疾走する彼女の、成功への物語。
今日は人生最悪で最高の日 1秒で世界を変えるたったひとつの方法 ひすいこたろう著
偉人の伝記を読むと、最悪な日は、不幸な日ではなく、新しい自分が始まる日であることがわかります。最悪な出来事は、自分の人生が、想像を超えて面白くなる兆しなのです。偉人伝を読むことで、このときの不幸があったおかげで、未来にこういう幸せがくるのかと、人生を俯瞰する視線が立ち上がるのです。
ご飯は私を裏切らない heisoku著
辛い現実から目を背けて食べるご飯は、いつも美味しく幸せを届けてくれる。
29歳、中卒、恋人いない歴イコール年齢。バイト以外の職歴もなく、短期バイトを転々とする日々。ぐるぐると思索に耽るけど、ご飯を食べると幸せになれる。奇才の新鋭・heisokuが贈るリアル労働グルメ物語!
【最新版Gemini 3に対応!】できるGemini (できるシリーズ)
Geminiを「最強の知的生産パートナー」として使いこなすための、実践的なノウハウを凝縮した一冊です。
基本的な操作方法から、具体的なビジネスシーンでの活用、日々の業務を自動化するGoogle Workspaceとの連携、さらには自分だけのオリジナルAIを作成する方法まで余すところなく解説します。
Rustプログラミング完全ガイド 他言語との比較で違いが分かる!
Rustの各手法や考え方を幅広く解説!
500以上のサンプルを掲載。実行結果も確認。
全24章の包括的なチュートリアル。
ポチらせる文章術
販売サイト・ネット広告・メルマガ・ブログ・ホームページ・SNS…
全WEB媒体で効果バツグン!
カリスマコピーライターが教える「見てもらう」「買ってもらう」「共感してもらう」すべてに効くネット文章術
小型で便利な Type-C アダプター USB C オス - USB3.1 オスアダプター
Type-C端子のマイコンボードをこのアダプタを介して直接Raspberry Piに挿すことができます。ケーブルなしで便利なツールです。
Divoom Ditoo Pro ワイヤレススピーカー
15W高音質重低音/青軸キーボード/Bluetooth5.3/ピクセルアート 専用アプリ/USB接続/microSDカード
電源供給USBケーブル スリム 【5本セット】
USB電源ケーブル 5V DC電源供給ケーブル スリム 【5本セット】 電源供給 バッテリー 修理 自作 DIY 電子工作 (100cm)
|