第5回 自作シリアル・プロポ
2025.02.22
YouTube でも紹介しています。画像をクリックすると再生できます。
今回は、シリアル接続のプロポを作ってみました。
このプロポをESP32に繋いで、ESP32のWiFi機能を用いてドローンを制御します。
用意するものを下記に示します。
●ジョイスティックRKJXV122400R DIP化キット



●ATTINY85-20PU

・電源電圧:2.7~5.5V
・コア:tinyAVR
・コアサイズ:8bit
・クロック:20MHz
・プログラムメモリ:8kB
・EEPROM:512B
・RAM:512B
・GPIO:6pin
・ADC:4Ch
・I2C:1Ch
・SPI:1Ch
・タイマ:2Ch
・オシレータ:内蔵
この他に16穴ユニバーサル基板、各種ピンヘッダ、シリアル接続用4Pコードなどが必要です。
ATTiny85には解像度10ビットのアナログ端子としてA0~A3の4個が用意されています。
また、シリアル接続用に2つの端子、VCCとGNDで合わせて8つの端子すべてを使います。
●配線
| JOYSTICK | - | ATTiny85 | - | ESP32-S2(テスト用) |
| LEFT | |
| GND | - | GND | | |
| V+ | - | VCC | | |
| Y | - | A1 | | |
| X | - | A3 | | |
| RIGHT | |
| GND | - | GND | - | GND |
| V+ | - | VCC | - | 3V3 |
| Y | - | A2 | | |
| X | - | A0 | | |
| | PB0 | - | RX |
| | PB1 | - | TX |

横にしたブレッドボードに対してジョイスティックDIP化キットを時計回りに90℃回転させて取り付けています。
●開発環境
ソースコードのビルドには、PlatformIOを使用しています。
Arduino開発環境構築 PlatformIO
【参考記事】
TM1637 & ATtiny85
ボード情報を確認します
$ pio boards "ATTiny85"
Platform: atmelavr
=========================================================================
ID MCU Frequency Flash RAM Name
-------------- -------- --------- ------ ---- -------------------------
gemma ATTINY85 8MHz 8KB 512B Adafruit Gemma
trinket3 ATTINY85 8MHz 8KB 512B Adafruit Trinket 3V/8MHz
trinket5 ATTINY85 16MHz 8KB 512B Adafruit Trinket 5V/16MHz
digispark-tiny ATTINY85 16MHz 5.87KB 512B Digispark USB
attiny85 ATTINY85 8MHz 8KB 512B Generic ATtiny85
ATTiny85のピン情報を確認します
~/.platformio/packages/framework-arduino-avr-attiny/variants/tinyX5/pins_arduino.h
#define SS 3
#define MOSI 1
#define MISO 0
#define SCK 2
static const uint8_t SDA = 0;
static const uint8_t SCL = 2;
static const uint8_t A0 = 0x80 | 0;
static const uint8_t A1 = 0x80 | 1;
static const uint8_t A2 = 0x80 | 2;
static const uint8_t A3 = 0x80 | 3;
#define PIN_B0 ( 0)
#define PIN_B1 ( 1)
#define PIN_B2 ( 2)
#define PIN_B3 ( 3)
#define PIN_B4 ( 4)
#define PIN_B5 ( 5)
#define PIN_PB0 ( 0)
#define PIN_PB1 ( 1)
#define PIN_PB2 ( 2)
#define PIN_PB3 ( 3)
#define PIN_PB4 ( 4)
#define PIN_PB5 ( 5)
ビルド用設定ファイルを編集します
$ pio init -b attiny85
$ vi platformio.ini
[env:attiny85]
platform = atmelavr
board = attiny85
framework = arduino
upload_protocol = custom
upload_port = /dev/ttyUSB0
upload_speed = 19200
board_build.f_cpu = 8000000L
upload_flags =
-C
$PROJECT_PACKAGES_DIR/framework-arduino-avr-attiny/avrdude.conf
-p
$BOARD_MCU
-P
$UPLOAD_PORT
-b
$UPLOAD_SPEED
-c
stk500v1
upload_command = avrdude $UPLOAD_FLAGS -U flash:w:$SOURCE:i
●ソースコード
#include <SoftwareSerial.h>
#define JoyStick_LX A1 // 2 LEFT LEFT/RIGHT
#define JoyStick_LY A3 // 3 LEFT UP/DOWN
#define JoyStick_RX A2 // 4 RIGHT LEFT/RIGHT
#define JoyStick_RY A0 // 5 RIGHT UP/DOWN (RESET)
#define PIN_TX PB0
#define PIN_RX PB1
SoftwareSerial mySerial(PIN_RX, PIN_TX);
void setup()
{
mySerial.begin(9600);
}
void loop()
{
uint8_t i;
uint16_t Lx, Ly, Rx,Ry;
uint8_t Lxh, Lxl, Lyh, Lyl, Rxh, Rxl, Ryh, Ryl;
Lx = analogRead(JoyStick_LX);
Ly = 1023 - analogRead(JoyStick_LY);
Rx = analogRead(JoyStick_RX);
Ry = 1023 - analogRead(JoyStick_RY);
Lxh = (Lx>>5)|0x00;
Lxl = (Lx&0x1F)|0x20;
Lyh = (Ly>>5)|0x40;
Lyl = (Ly&0x1F)|0x60;
Rxh = (Rx>>5)|0x80;
Rxl = (Rx&0x1F)|0xA0;
Ryh = (Ry>>5)|0xC0;
Ryl = (Ry&0x1F)|0xE0;
mySerial.write(Lxh);
mySerial.write(Lxl);
mySerial.write(Lyh);
mySerial.write(Lyl);
mySerial.write(Rxh);
mySerial.write(Rxl);
mySerial.write(Ryh);
mySerial.write(Ryl);
}
コードの解説
ATTiny85は4個のアナログ入力端子を持ち、解像度は10ビット(0~1023)です。
非同期式シリアル通信なので、受信側がどのタイミングで受信してもデータが区別できるように工夫しています。
ジョイスティック基板をブレッドボードに取り付ける際に時計回りに90℃回転させているので、取得した値を補正しています
Lx = analogRead(JoyStick_LX);
Ly = 1023 - analogRead(JoyStick_LY);
Rx = analogRead(JoyStick_RX);
Ry = 1023 - analogRead(JoyStick_RY);
10ビットの解像度なので5ビットに二等分して、余っている先頭3ビットをデータ識別用に使用します。
| Joystick | Order | ID | bit |
| Rudder(yaw) | High Byte: | 000 | Lx:98765 |
| Low Byte : | 001 | Lx:43210 |
| Elevator(pitch) | High Byte: | 010 | Ly:98765 |
| Low Byte : | 011 | Ly:43210 |
| Aileron(roll) | High Byte: | 100 | Rx:98765 |
| Low Byte : | 101 | Rx:43210 |
| Throttle | High Byte: | 110 | Ry:98765 |
| Low Byte : | 111 | Ry:43210 |
$ pio run -t upload -e attiny85
PLATFORM: Atmel AVR (5.1.0) > Generic ATtiny85
HARDWARE: ATTINY85 8MHz, 512B RAM, 8KB Flash
PACKAGES:
- framework-arduino-avr-attiny @ 1.5.2
- tool-avrdude @ 1.60300.200527 (6.3.0)
- toolchain-atmelavr @ 1.70300.191015 (7.3.0)
Dependency Graph
|-- SoftwareSerial @ 1.0.0
RAM: [== ] 24.2% (used 124 bytes from 512 bytes)
Flash: [== ] 23.1% (used 1890 bytes from 8192 bytes)
avrdude: safemode: Fuses OK (E:FF, H:DF, L:E2)
avrdude done. Thank you.
このチップのヒューズビットを確認してみると下記のようになっていました。
$ ~/.platformio/packages/tool-avrdude/avrdude -C ~/.platformio/packages/framework-arduino-avr-attiny/avrdude.conf -p attiny85 -P /dev/ttyUSB0 -b 19200 -c avrisp
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################ | 100% 0.02s
avrdude: Device signature = 0x1e930b (probably t85)
avrdude: safemode: Fuses OK (E:FF, H:DF, L:E2)
avrdude done. Thank you.
ATtiny85は工場出荷時クロックの8分周が有効になっています、L:E2 になっていない場合は、フューズビットを変更して無効にします。
$ ~/.platformio/packages/tool-avrdude/avrdude -C ~/.platformio/packages/framework-arduino-avr-attiny/avrdude.conf -p attiny85 -P /dev/ttyUSB0 -b 19200 -c avrisp -U lfuse:w:0xe2:m
●動作確認
受信側の動作確認プログラムです。
データ識別子をもとに5ビットのデータを繋ぎ合わせて、ジョイスティックの操作値を求めています。
uint16_t Lx, Ly, Rx, Ry;
void setup()
{
Serial1.begin(9600);
Serial.begin(115200);
Lx = 0;
Ly = 0;
Rx = 0;
Ry = 0;
}
void loop()
{
uint16_t ival;
uint16_t sLx, sLy, sRx, sRy;
while (Serial1.available()) {
ival = Serial1.read();
switch(ival&0xE0) {
case 0x00: // 0b000xxxxx
sLx = ((ival & 0x1F)<<5) | 0x8000;
break;
case 0x20: // 0b001xxxxx
if (sLx & 0x8000) Lx = (sLx | (ival & 0x1F)) & 0x03FF;
sLx = 0x0;
break;
case 0x40: // 0b010xxxxx
sLy = ((ival & 0x1F)<<5) | 0x8000;
break;
case 0x60: // 0b011xxxxx
if (sLy & 0x8000) Ly = (sLy | (ival & 0x1F)) & 0x03FF;
sLy = 0x0;
break;
case 0x80: // 0b100xxxxx
sRx = ((ival & 0x1F)<<5) | 0x8000;
break;
case 0xA0: // 0b101xxxxx
if (sRx & 0x8000) Rx = (sRx | (ival & 0x1F)) & 0x03FF;
sRx = 0x0;
break;
case 0xC0: // 0b110xxxxx
sRy = ((ival & 0x1F)<<5) | 0x8000;
break;
case 0xE0: // 0b111xxxxx
if (sRy & 0x8000) Ry = (sRy | (ival & 0x1F)) & 0x03FF;
sRy = 0x0;
break;
}
}
Serial.printf("%04d %04d %04d %04d\n",Lx,Ly,Rx,Ry);
delay(1000);
}

$ pio device monitor -p /dev/ttyACM0 -b 115200

ジョイスティック無操作の状態でも10ビットの中央値512からズレが生じていることがわかります。
この中央値補正はジョイスティック側ではなく、受信側のマイコンで行うことにします。

ジョイスティックは十字方向のみではなく、斜め方向にも稼働可能なので同時に4方向の値を取得することができます。
●マスタ側仕様
コントローラのレバーをニュートラルにした状態でマスタ側の電源を入れます。
コントローラの位置情報を一定回数取得して平均値を算出します。
続いてコントローラ左側レバーのラダーを右に、エレベータを上に、つまりレバーを真上から時計回り90度の位置までぐりぐりします。
合わせて同様に、右側レバーのエルロンを右に、スロットルを上に操作します。
スロットルはニュートラルをゼロ、上方向を加速に使用し、下方向は操作の初期設定決定に使用します。
2つのレバーをニュートラルに戻します。
続けてスロットルのレバーを下方向に動かすと各機能の最大値を表示し、最小値の入力に移ります。
コントローラ左側レバーのラダーを左に、エレベータを下に、つまりレバーを真左から反時計回りに90度の範囲でぐりぐりします。
合わせて同様に、右側レバーのエルロンを左に操作します。
2つのレバーをニュートラルに戻します。
スロットルのレバーを下方向に動かすとスロットルを除く各機能の最小値を表示します。
スロットルの最小値はニュートラル時の平均値を用います。
最大値、最小値を再入力する場合は、スロットルを下方向に動かします。
決定の場合は、スロットルを上方向に動かします。
ラダーは左右60度、エレベータは上下60度、エルロンは左右180度、スロットルは10段階に設定するので、
平均値と最大、最小値を用いて度数、段階に換算させるための係数を算出します。
レバーを動かしてラダー、エレベータ、エルロンを任意の位置に動かしたのちにスロットルを下方向に動かすと、
操作する度数が表示されます。
その表示値で実行する場合は、スロットルを上方向に動かし、ドローンに送信します。
訂正する場合は下方向に動かし再設定します。
|
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)
|