はじめに
テトリスをプレイできる小型ゲーム機をRaspiベースで開発した。
最終成果物はこちら。
アナログスティック+ボタン4個で操作するレトロ風ゲーム機。
開発全体の流れ、ソフト・基板・ケースの設計内容、学んだ事などを残す。電子工作に興味のある方、一気通貫での設計例を見たい方などの参考になればいいな~と。
組み込み系特有の用語・概念等は要所で外部リンクを貼るので、必要あれば参照下さい。
※長いので、興味ある箇所中心で読まれることを推奨。
ご質問等あれば可能な範囲で回答しますので、コメント下さい。
目次
開発のきっかけ
組み込み系ソフト開発者として就職し2年経つが、自分で手を動かす機会が少なく、実装能力や組み込みで重要なマイコンやハードの知識が十分得られていない感覚があった。
空いてる時間で遊びながら勉強したいな~と思案した結果、電子工作という答えに辿りつき、やってみることにした。テーマにゲーム機&テトリスを選んだのは単なる好み。
後述するが、結論としては非常に勉強になった。あとすごいたのしかったです。
ゲーム機全体設計
仕様検討
どういうゲームにするか?の仕様を大雑把に検討する。
初の電子工作という事で、難しすぎる事は避け普通のテトリスをそのまま実装する方向性で考え、以下の通り基本仕様を定めた。

※マジで何の変哲もないテトリス。テトリミノ=テトリスでいっぱい降ってくるアレ
システムとしての動作仕様も軽く検討。
ゆる〜い仕様だが、ソフト作る中で色々追加・変更したくなるのが目に見えていたのでこの程度に留めた。実際後から色々追加しつつ固まったのでヨシ!!
システム設計
ゲーム機のシステムとしての機能やハードウェア構成を決定する。
仕様検討の内容からわかる通り、このゲーム機に必要な操作は
- ゲームのスタート
- テトリミノを左右に動かす操作
- テトリミノを下に落下させる操作
- テトリミノを回転させる操作
くらいであり、十字キーとボタン1個もあればゲーム操作は完結する事が分かる。
あとは電源ON/OFFできれば十分
ただ、ボタン1個だと機能追加したい時に困りそうだったり、十字キーは普通過ぎて面白くないな~とか思い、その辺をアレンジする事にした。
そんな感じで割とノリで検討を進め、以下のようにシステムの大枠を決定
完成後の今思えば、音源出力はあっても良かったなと思う。気が向けば追加したい
主要部品選定
上記設計を元に、システムの主要部品を選定。
元々別のモノを使っており途中で変更した部品もあるが、最終採用品のみを紹介する。
選定理由等も軽く記載。ご参考まで。
| 部品名 | 選定品 | 選定理由・使用感等 |
|---|---|---|
| ① マイコンボード | Raspi-Pico H | 有名どころから適当に選定 |
| ② ディスプレイ | GME128128-01-IIC | 安価&高解像度のモノを探しコレに辿り着いた 比較的簡単に制御でき、発色も良い。「ジー」という音が常に鳴るのが少し気になる(許容はできる) 画面サイズは小さめ(約2.7cm×2.7cm) |
| ③ アナログスティック | ADA-2765 | 店舗で実物を見かけ、見た目良かったので採用 P○Pのアナロ△パッドみたい!! 可動範囲は狭めで繊細な操作には向かない |
| ④ タクトスイッチ |
SKHCBEA010 |
押ボタンとリセットボタン共用。見た目で選定 使い易く、サイズ感も結構いい感じ キャップは別売&付け替え可能 |
| ⑤ スライドスイッチ | CS-12AAP1 | 電源スイッチ用。見た目と操作性で選定 |
| ⑥ 電池ソケット | SN4-3PC | 適当なところで適当に購入。単4×3本用 |
ソフト設計
ハードの前提が整理されたので、ソフトを作っていく。
ちなみに動作確認用の環境はユニバーサル基板上に部品を半田付けして作成。
ソフト開発と並行で部品を継ぎ足していく感じで進めた。最終品は後ほど提示
※回路図が見たい方は後述の回路設計の項を参照
アーキテクチャ設計
今回、必要になる機能がそこそこ多くなる事がシステム設計の時点で見えていたので、最低限アーキテクチャを整理した上で各機能の設計を行う事にした。
実装が進む程変更するのがキツくなってくるので、最初の段階でちゃんと検討。
必要になる機能を関心事ベースでコンポーネントとして分離した上でそれらのグルーピングを考える。最終的に以下で整理された。
| グループ | コンポーネント | 関心事・責務 |
|---|---|---|
| Application | tetris | テトリスゲームロジック テトリスのゲーム仕様を実現する |
| Application | config | ソフトウェア設定定義 Application用のMiddle・Driverの設定を一括管理する |
| Middle | analogStick | アナログスティック制御 スティックのX軸・Y軸の座標値を取得する |
| Middle | SH1107(display) | ディスプレイ制御 ディスプレイ画面に任意の描画内容を表示させる GME128128-01-IICに搭載されるSH1107の制御専用 |
| Middle | button | ボタン制御 ボタンの押下状態・押した瞬間を取得する |
| Middle | debugcom | デバッグ通信制御 デバッグ用PCツールからのコマンドを受信する ※最終版ソフトでは無効化している |
| Driver | gpio | GPIO制御 マイコンのGPIOの出力変更と入力読出を行う マイコンのGPIOピンの機能割当と初期設定を行う |
| Driver | adc | ADC制御 マイコンのAD変換を実行し、変換後のAD値を取得する |
| Driver | I2C | I2C制御 マイコンのI2C機能を利用して通信を制御する |
| Driver | timer | タイマー制御 マイコンのタイマーを用いて時間の測定等を行う |
| Driver | interrupt | 割り込み制御 マイコンの割り込みの有効化や設定を行う マイコンの割り込み発生時に所定の機能を呼び出す |
| Common | lib | 汎用ライブラリ(算術計算lib、ビットマップlib等) |
| Common | include | 汎用インクルード |
コンポーネント図モドキによる全体構造図式化↓(※矢印の意味:依存元 → 依存先)

※configからの依存とlib,includeへの依存は省略。煩雑になる&重要ではないため
左側の3層構造がソフトのメインで、これはいわゆるレイヤードアーキテクチャにあたる。
各レイヤの位置付けは以下の通り
- Application:システム仕様を実現するレイヤ(テトリスのゲームロジックが主)
- Middle:マイコン操作により間接的に実現する機能のレイヤ(外部デバイス制御等)
- Driver:マイコンを直接操作するレイヤ(各機能のレジスタのRW等)
つまり、下のレイヤほどハードウェアに近い機能になっている。
この分け方は組み込み系ソフトウェアにおいては(たぶん)最もメジャーで、実際組み込み系でよくある事象をクリーンに解決しやすい。今回のシステムでの例を挙げると、
- 同じハードウェア構成でテトリス以外のゲームを追加したい:Application層に新ゲームのコンポーネントを1個追加してMiddle・Driver層はそのまま再利用すればよい
- 部品を別のモノに変えたい:Middle層に新部品制御用のコンポーネントを追加すればよい。Driver層の変更有無は部品の制御仕様次第だが、流用できる事が多い
- 仕様は基本変えずマイコンだけ全とっかえしたい:マイコンを直接制御する機能はDriver層に集約しているので、Driver層だけ全とっかえすれば良い
等の恩恵が得られやすい。要するにソフトの拡張性・再利用性・移植性などを一定水準で確保できる。
実際、元々I2CコンポーネントはSH1107コンポーネント向けに実装し、後からデバッグ通信機能を追加したという経緯がある。この時debugcomコンポーネントをMiddle層に追加した上で通信の実現はI2Cコンポーネントを再利用するだけで済み、最小限の変更に抑えられた。
尚、3層全てから参照される汎用機能についてはCommonグループとして分離している。これにより、(Application → Middle → Driver) → Common という方向での依存関係になり、ソフト全体の単方向依存が完全に保たれる。これは人間が混乱しないクリーンな構造を保つために必要だし、循環依存があるとバグやソフト変更の影響が周囲のコンポーネントに伝播したりと良い事が無いので大事。
設計•実装
前述のアーキの項で分割した各コンポーネントをそれぞれ設計・実装する。
全体で5Kステップくらいあるので、面白い所・需要ありそうな所を中心に説明する。
他はかいつまんで紹介。コードを読みたい場合はGithubからどうぞ↓
実装全体:https://github.com/D-grid375/Tetris_Boy
Driver層の設計(割愛)
Raspi-Picoには標準ライブラリが存在し、マイコンの各種ペリフェラルを簡単に利用できるAPIが予め用意されている。これは今回で言うDriver層の機能に相当するためそのまま使えば楽なのだが、元々マイコンの勉強をしたいという大目的があるため使わず自分で実装。
データシートと睨めっこしながら実装と動作確認を繰り返し、結構時間はかかったがソフトとハードの境界で何が起きているのか理解でき十分価値があった。でももうやりません
やってることはレジスタのRWメインで面白いロジックとかは特に無いので設計の話は割愛。殆どの人はライブラリを使うはずで需要も無いと思うので(あれば言って下さい)
Driver層実装:https://github.com/D-grid375/Tetris_Boy/tree/master/src/drv
Middle層の設計
マイコンとの入出力を担う外部部品の制御機能について、各部品ごとに概要を解説。
デバッグ通信機能は省略
Middle層実装:https://github.com/D-grid375/Tetris_Boy/tree/master/src/mid
アナログスティック制御機能の設計
今回使うアナログスティックの仕様・使い方の概要は以下の通り。
要するに、スティックのX軸•Y軸の位置によってX軸電圧•Y軸電圧が変動するという事。
例えば、ニュートラルポジションならX軸電圧=Y軸電圧=1.65V、斜め右上にスティックを動かせばX軸電圧=約0.8V・Y軸電圧=約2.4Vという具合。
なのでこの電圧値をAD変換し、取得したAD値をアプリケーション向けの座標値に変換して返すようにする。AD変換機能はDriver層のADCコンポーネントで実装済みなので、analog stickコンポーネントはこのAPIを叩くだけ。シーケンスを図式化すると↓
尚、今回はスティックは1個しか載せないが、別システムにコードを流用する可能性を考慮してオブジェクト指向っぽく実装した。スティックに関するパラメータは構造体で定義&スティックの数だけインスタンスを宣言するようにし、スティックの座標取得関数はインスタンスのポインタを引数にして叩くようにしている。
ボタン制御機能の設計
ボタンとして使うタクトスイッチの仕様と使い方は以下。
押下中だけHigh(3.3V)になるのでそれをマイコンのGPIOで読む。
プルダウン抵抗を繋げているため非押下時は常にLow(0V)で固定される。
GPIOのHigh/Lowを読む機能はDriver層で実装しているので、ボタンを押しているか/押していないかはそのAPIを叩くだけで判定できる。ただ、ボタンの処理でよく使う「ボタンを押した瞬間だけ処理を行う」という機能はあくまでボタン制御としての機能なのでこちらで実装。方法は単純で、前回読出時の状態を常に保持しておき、今回読出時の状態と比較する事で押したタイミングを検出するだけ。
アナログスティックと同じく、任意個数のボタンをインスタンスで宣言して使えるようにしている。ボタンは5個載せるのでこの方法で無いといけない。
ディスプレイ制御機能の設計
今回採用したディスプレイモジュールの仕様は超大まかには以下。
マイコンとの接続・通信方法は省略。詳しく知りたい方はI2Cの通信規格を参照
※本システムではマイコンがマスター、ディスプレイがスレーブ
実際は前述のスイッチやアナログスティックと比べてそこそこ複雑な仕様。
全体仕様はディスプレイICのデータシートからどうぞ。
ディスプレイに描画する画面の情報は内部的にはビットマップデータで持つようにした。つまり、ディスプレイの白いドットは0、黒いドットは1と捉えてデータ化する。
簡単のため、小さいディスプレイでの例を挙げると以下の様に図式化できる
図の下側に書いてる通り、128×128のディスプレイでは64bit符号無し整数を2×128個の配列で持つ事になる。このビットマップの考え方は本システムの核になる部分なので、後述のゲームロジック設計の項でも別途説明する。
あとはこのビットマップを縦8ドット×横1ドット=8ビット(=1byte)ずつ送信すればよい。実際は描画データ送信の前にIC指定のコマンドを送信したりする必要があるが、データシートに従うだけで特に面白い話は無いので割愛。が、これだけだと実は問題がある。
というのはI2Cは通信速度が結構遅く、本ディスプレイは最大でも400KHzでの通信までしか対応していない。この数値からディスプレイ全体の描画にかかる時間を概算すると、
- 1bitの送信にかかる時間 = 1/400KHz = 2.5us
- 128×128bitの送信にかかる時間 = 2.5us×128×128 = 約46ms
となり、最大でも27FPSくらいしか出ない。ゲームで30FPSも出ないのは割と厳しい。
尚、上記式はI2CのACKやドット描画以外のコマンド送信分を考慮していないので、実際はもっと下がる。なので画面全体を毎回描画するのではなく、更新必要な差分を計算&その部分のみディスプレイに描画させるようにした。やる事は単純なので詳細は割愛。
最終的にはこの実装の上で100FPS固定で描画更新している。ちなみに、実はこのディスプレイモジュールは高速通信可能なSPIタイプもあり、そっちならこの工夫は不要だった。
SPIの方が高速なのは知った上で単にI2C触ってみたいという適当理由で選定していたので、完全に検討不足で手間が増えたというパターン。ハードが絡む設計は事前にちゃんとやっとかなあかんな~と学びになりましたとさ★彡
Application層の設計
テトリスのゲーム仕様を実現する機能を作る。
詳細を書くとキリが無いので、コアになるロジックを中心に説明。
Application層実装:https://github.com/D-grid375/Tetris_Boy/tree/master/src/app
テトリス・演算アルゴリズムの設計
テトリスというゲームではマス目で区切られたフィールドがあり、その中でテトリミノを動かしたり積んで遊ぶ。これを実現できるアルゴリズムが必要。
これにも前述のビットマップ方式を採用した(多分これ以外選択肢無い気がする)。
概要はこちら↓
ディスプレイ上では当然1ブロック=1ドットで描画する訳ではないが、ソフトで演算する際には1ブロック=1ドットとして扱う。また、この方法だとテトリミノの操作や各種判定処理も簡単に実現でき都合が良い。
例えば、テトリミノを右に移動する操作は、テトリミノの各ブロックを1つずつ右にずらすという操作になる。そしてこれはビットマップ上の1のビットをそれぞれ1つ右にずらす、という処理に相当し、右ビットシフト演算そのものになる。
このように、テトリミノの基本操作はビットシフト演算や代入演算で大体実現できる↓
- テトリミノを右に移動:ビットマップを右ビットシフト
- テトリミノを左に移動:ビットマップを左ビットシフト
- テトリミノを下に移動:ビットマップ[i行目] = ビットマップ[i-1行目]を繰り返す
- テトリミノを回転:回転状態が0°、90°、180°、270°のテトリミノビットマップを予め定義しておき、回転操作の度にビットマップ自体を差し替える(これだけちょい面倒)
ただ、これだけだと操作中のテトリミノを動かした時、既に地面に積まれているテトリミノも一緒に動かしてしまうので機能として成立しない。そこで、複数のビットマップを別々のレイヤーとして保持し、それを重ね合わせて最終的なビットマップを作る↓
これで、操作中のテトリミノを独立して動かす事が可能になった。テトリミノの操作だけでなく、他の処理も同様に複数のレイヤー間で適切な演算を行えば処理できる。
例えばゲームオーバー判定の実現には、まずゲームオーバー判定用レイヤーを用意し、「ここにブロック積まれたらゲームオーバー」という範囲を全部1固定で埋める。その上で、既に積まれたテトリミノのレイヤーとゲームオーバー判定用レイヤーでどちらも1になっているビットを抽出=ビットAND演算する。1つでもあればゲームオーバーと判定できる。
このようにして、テトリスのブロックが絡む演算はほぼ全てこのビットマップとレイヤーの考え方で実装している。
以上で、最も基本&重要な演算アルゴリズムを実現できた。
テトリス・UI機能の設計
ディスプレイに表示するUIデザインと、UI生成処理の設計。
見やすさ・見栄え等考えながら以下のように決定。

※最終版では黒背景になったが、この時点では白背景で設計していた
一般的なテトリスの画面を踏襲しつつ、ディスプレイの解像度に合わせて128ドット×128ドットにピッタリ収まるよう設計した。
尚、仕様検討段階では表示パラメータはSCOREのみだったが、UI検討中に色々パラメータを追加している。最終仕様は以下
- NEXT:次に降ってくるテトリミノ
- LEVEL:ゲームのレベル。レベルが上がるとテトリミノの落下速度が速くなる
- ROW:消去したブロック行の総数。これが一定値を超える毎にLEVELが上がる
- SCORE:合計得点。1度に複数のブロック行を消去すると高得点を獲得できる
これらを追加したのは、SCOREだけだと画面がスカスカでめちゃしょぼく見えたというのと、単純にゲームとしてあんま面白くないなと思ったため。
あとはこれをディスプレイに送信可能なデータ=128×128のビットマップとして組み立てるだけ。前述のレイヤーの考え方をまた使う↓
各レイヤーは全て128×128のビットマップ。ちなみに固定UI等の定数ビットマップについては、懐かしのペイントツールでドットをポチポチ打ち込んで作った(たのしい)。それを符号無し64ビット整数型の配列に変換するプログラム(AIにpythonで書かせた)に突っ込み、出力結果をソースコードに定数として埋め込んでいる。
ゲームオーバー時は専用の文字列を表示したりするが、これも同じ話で文字列を定数ビットマップで用意しておき、それをレイヤーに重ね合わせるだけ。
テトリス・制御フローの設計
あとはこれまで設計した機能を総動員し、制御フローを組み立ててゲームとして成立させる。ここは設計と実装を繰り返して検討し、最終的に以下で固まった。

※抽象化している箇所は色々あるが、大枠としては上図で網羅される
4つのステートでそれぞれ別のフローを走らせており、各フローは10ms周期でループされる。パッと見で分かる通り「ゲーム実行中ステート」がメイン。実際にテトリスのプレイ中は常時このステートにいるため、システム起動中の9割はここでプログラムが動いている。
メイン以外のステートは大したことはやっておらず、ゲーム開始待ちステートとゲームオーバーステートでは「ボタンを押してゲーム開始!」的な画面をずっと点滅表示させており、ボタン入力で次のステートに進む。ゲーム初期化ステートはゲーム開始直前に呼ばれ、変数等を全部初期化するだけ。
各ステート内の処理は入力・演算・出力で分類しており、責務は見ての通り。尚、データの流れとしても入力→演算→出力になっている。ボタンとスティックの入力値を元にゲームの演算が行われ、演算結果を元に描画データの生成とディスプレイへの出力が行われる、というイメージ。
フローへの機能追加等も割としやすく、最低限妥当&無難な設計にまとまったと思う。
動作確認
ソフトに対する動作確認の様子↓(勿論ここまでの過程で段階的に細かいテストはしている)
ちなみに配線は基板の裏面でやっている↓(※ゴミ配線のため目が腐らないよう注意)
この時点ではアナログスティックやボタンが別物だったりボタン数が少なかったりとハード面では最終版と差分があるが、ソフト的には殆ど最終版。
繰り返しテストプレイし、正常に動く事を確認できた所でソフト設計は完了。
基板設計
ここからはガチ素人からのスタートだったので、当然設計は甘いので予めご了承。
初めて基板作ってみたい!って方には割と参考になるかも?
ツール導入(Kicad)
色々調べたが、無償で使えるモノではKicadというツールほぼ一択と判断しこれに決定。
最後までずっとこれを使っていたが、神で草だった。正直このツールの使い方さえ覚えれば、高校物理レベルの知識があれば基板は作れると思う
※あくまで電子工作レベルの話です。実務レベルの基板を作るには当然プロのスキルが必要
回路設計
基本的にはユニバーサル基板上で行った配線をそのまま回路図に起こすだけ。
以下のみ新規追加
- 0Ω抵抗:デバッグ用。万が一実物を入手してから回路に修正•変更が必要になっても、コイツを外してジャンパーする事で楽に対応できるという保険
- TP(テストポイント):基板表面に配線の導通部分を露出させ、特定ポイントの電圧や電流をテスターで楽に測定できる
これらは職場で回路図を見たり実基板を触る中で有用性を理解していたので採用した。
そんなこんなで描いた回路図がこちら↓

※線の先に付いてる五角形みたいなマークは同名のマーク同士で繋がっている事を示す
ここでミスるとバイバイなので念入りにチェック。ただ、電気的に明らかな配線ミス(電源とGNDが短絡してるとか)はERC(エレクトリカルルールチェッカー)という機能が検出•警告してくれる。便利ダネェWWWWWWW
ちなみにツール上の操作としては、配線したいポイント同士をクリックして線を繋げるようなイメージ。色々いじってればすぐ理解できる程度には直感的。
パターン設計
パターン、つまりプリント基板のデザインを設計。大まかな流れは以下
- 基板上に部品を配置する
- 回路図に従って配線する
- GNDベタを張った上で諸々調整
回路図描くよりやる事が多い。まず部品配置だが、Kicadは回路図の内容を読み取ってPCBエディタに各部品のフットプリントを展開してくれる↓(フットプリントは半分程自作した)
基板に載せる部品がとりあえず全部エディタに出たという状態になった。
謎の青い線が大量に見えるがこれはラッツネストと言って、基板上の部品間を最短で接続するルートを意味する。つまりツールが回路図を元に部品間の接続を認識しており、「ココとココ結べや」と教えてくれているという事。すggggっげ!!!WWWWWW
次は部品を動かして配置するのだが、ここでラッツネストが役に立つ。
どういう事かと言うと、配線はその距離が短くなるよう引くというのが大原則で、ラッツネストがパッと見短くなるよう意識して配置を行うとこれを満たしやすいという話。
ゲーム機用基板という特性上ボタン等の配置はかなり縛られるが、可能な範囲で上記も考慮しつつ配置した結果がこれ↓
結構ムズかったが、パズルみたいでおもろ〜Wって感じだった。
ちなみに、電池ホルダーのみ重量やサイズの都合上裏面に配置している。
あとはこれを配線し、GNDベタを張りビアを打って諸々調整を加える。最終系が↓

※表面のみ。赤い線が配線、薄い赤のエリアがGNDベタ。裏面はほぼ全部GNDベタ
回路設計時と同様、電気的な問題が無いかをチェックしてくれるDRC(デザインルールチェッカー)という機能があり、それもパスしたので基板設計完了。
ツールのパワーのお陰でここまで出来た。
基板発注~入手・動作確認
発注はelecrowというサイトから行った。他にはJLCPCB等が有名か
上記はいずれも中国のサイトなのだがとにかく安い。今回は送料込みで3000~4000円くらいで発注できた(基板のサイズが小さければもっと安くできた)
発注から2週間ちょいで入手↓
黒ベースに白のシルクはなかなか映える。
これに部品を半田付けし、マイコンにソフトを書き込んで電源ON↓
発注前にアホ程チェックしたので8割位の確率で動くとは思っていたが、実際に動くと結構感動する。正直ユニバーサル基板でテトリス動いた時の千倍くらい達成感あった
ケース設計
基板設計と同じく素人スタートなのでご了承。
またパワフルなツールに依存して楽をさせてもらう。
ツール導入(Autodesk Fusion)
3Dデータ設計用のツールだが、今回はAutodesk Fusionを採用。
元々Blenderが多少触れるのでそのまま使おうかと思ったが、これはあくまでCGソフトなのでミリメートル単位での機構設計に向いているとは言えない(不可能では無いが低効率)。
なので別で3DCADを導入する事にし、その中で無料かつ高性能っぽく見えたFusionを採用。
無償版には機能制限アリ&商用利用は有償なのでそこだけ注意。
デザイン検討
元々デザインのコンセプトは頭にあり、「シンプル&レトロっぽく」でイメージしていた。具体例で言うとゲームボーイカラーとかが近い。
上記コンセプトをベースに検討したデザインがこちら
裏面は特に装飾等無く、ネジ締め用の六角ナット挿入口を空けるだけにした。
尚、ネジは隠そうと思えばできたがアクセントとしてあえて露出させている(これは実際映えて良かった)。
また、上記で設計した基板だとサイズや部品配置の関係でこのデザインを実現できなかったので、基板パターンを再設計した。結局パターンは半分以上変更になったが、2回目なのもあって1日で終えられた。
電池ホルダーに加えてマイコンボードも裏面に配置する事で縦幅を大きく縮小できた。
(実は、基板設計の時点ではケース設計までやるかは迷っており、そもそもケースに収める前提でパターンを引いていなかった。なのでケース作る時点で基板再設計はほぼ必須だった)
3Dモデル設計
Fusionで3Dプリント用のモデルを作る。上記デザインをベースにモデル設計しつつ、ケース内部の構造も並行して詰めた。大まかに以下の流れで設計
- 平面図(fusionではスケッチと呼称)を描く
- 平面図から各部位を押し出して立体構造を作成(ここで内部構造を定義)
- 立体構造に調整を加える(エッジを丸みを持たせる等)
まずはケース表面のデザインから平面図を起こす。
寸法を正確に指定する事だけ徹底する。あとは割と単純作業

※馬鹿みたくごちゃごちゃしてるが、あちこちに見える数値がそれぞれの寸法値
面白いのが、寸法値を変数化して指定できるという点。例えば、
- Φ_roundbutton = 14.50mm
- clearance_min = 0.50mm
と定義し、平面図上の寸法を"Φ_roundbutton + clearance_min"で定義すると15.00mmで反映されるという事。これにより共通寸法を使い回せるだけでなく、変数値を変更すれば平面図にも反映されるため後からの設計修正も楽ちん。ワオ!!!!!!WWWWWWW
この平面図から立体構造を生成する。作業イメージは以下GIFを参照
要は平面図の特定範囲を押し出す事でパーツや壁を成形する感じ。この際の押し出す寸法も当然前述の変数にて定義可能。小学校の図工みたいでたのC!!!WWWWWWW
ここまで来てようやく内部構造をちゃんと詰めた。↓のような断面図をいくつか描いて検討。
特に気を付けるべきなのが嵌合部位の寸法設定で、3Dプリント用素材では素材毎に最小クリアランスが指定されている(上図では紫箇所でクリアランスを検討している。ただし縦方向のみ考慮)。これを守らないと凸が凹に入らなくて組み立てが出来ねー的な事が起こり得る。
余裕を持って設定すれば当然安全だが、そうすると正確に固定させたい箇所がカパカパする可能性が上がるので塩梅が難しい。今回は多少大きめにクリアランスを設定し、カパカパしちゃったら適当な緩衝テープとかを挟んでケアする方針で設計。
検討の上で構造を確定後、調整を加え出来上がった3Dモデルがこちら。
ケースを横に開いた際の内部構造はこんな感じ。
図の青丸はボタンやアナログスティック裏の支え。これらの操作時は指から基板に圧力がかかるので、その力をケースで受け止め基板の割れを防止する。赤丸はケース自体のしなりや変形を防止するための支え。この構造はゲームのコントローラーを参考にしている。
ツールの断面解析機能等を使いモデルをめっちゃチェックし、ケース設計は完了。
発注〜入手•組み立て•完成
3DプリントはJLC3DPに発注。多分ここ一択?
基板発注はまたelecrowから。JLCPCBであればケースと一緒に発送させて送料減らせるからそっちの方が良かった気はする。
どちらも2週間くらいで入手。今回の3DプリントではSLAという最も加工精度の高い方式を採用した。素材はレジン。
想像以上に加工精度が高い。。しかも全然頑丈(レジンと聞くと頑丈なイメージが無かった)
裏側なので表面処理が甘い箇所があるが、表はちゃんとキレイ。
基板2枚あるが、左下が新基板、右下は旧基板(サイズ比較用)。だいぶ小さくなった
新基板の方にはケースが接触する箇所を全部シルクで示している。こうすれば基板を壊してリード線で直す時にどこを避けるべきか分かるし、緩衝テープを貼るべき場所も分かる。
基板に部品実装してケースと仮組みすると、やはり基板がカパカパしたので緩衝テープを張って対応。完成が近付いた事で欲が出てきたのでケースとボタンを適当にラッカーで塗装し、最終組み立てした結果がこちら
裏面(何度も遊んでたら塗装がめちゃ劣化した その内ウレタンで塗り直したい)

自分の理想イメージをほぼ満たすモノに仕上がり、満足。
これにてゲーム機完成。
感想
この取り組みでは組み込み系ソフトの学習を主目的に据えていたが、結果的にはかなりレベルアップできた実感があり非常に良かった。特に以下2つの作業の効果が高かった。
1.Driver層のセルフ実装:マイコンの各種機能を独自コードで制御・利用するには機能の仕組みを正確に理解していなければならず、その理解のためにはデータシートをある程度読み込まないといけない。この過程で知らない概念やロジックに大量にぶち当たり、1つずつ理解していかざるを得ない状況になったので嫌でも知識が付いた。要領の良い人はこんな事せずより効率的に学習できるだろうが、自分は頭の回転が遅め&とにかく具体・原理まで理解しないと気が済まない人間なのでこの方法がマッチしていたと思う。
2.基板設計全体:今回作った基板はあくまで工作レベルだが、それでも回路図・パターン図の読み方や電気に関すする常識や感覚がそれなりに付いたと実感している。業務でも割と回路図とかは読むが、単に読むのと自分で作るのではやはり頭への入り方が違っていた。あと、元々回路図やパターン図を読むのに若干拒否反応があったのだが、それが完全に無くなったのはめちゃくちゃ良かった(なんなら結構好きになってすらいる)。回路チームとのコミュニケーションも多少円滑になった気もしており、良い事ずくめだった。
ケース設計は組み込み系の勉強には1ミリもならないただの趣味になってたが、やって良かったと思う。これによって1つの作品として完成した感があり達成感が段違いだし、次もなんか作ろうというモチベーションが沸いた。あとすごい楽しかった。正直、ケースをラッカーで塗装してる時が全編通して一番たのしかったです
基板とケースの設計は恐らく何回か失敗してやり直すだろうと最初思っていたが、一度も失敗無く完成させられたのはラッキーだった(筐体用の基板再設計は置いといて)。それもこれもとにかくツールが強いためで、チャレンジしやすい環境なのだなと思った。外部発注も簡単&めちゃ安いし。
あと基板設計&ケース設計の一般論やツールの使い方は半分以上AIに聞いていた。背景知識0の分野でAIを多用すると情報の正しさの検証が難しくリスクもあるが、原理レベルまで掘り下げて質問責めする事でケアしたため、ちゃんと設計できたし結果的に深く理解できた。やはり環境が良い。現代に生まれといてよかった~WWW
終わりに
書いてる通り、環境が良いので興味があればとりあえずやってみる、が丸いと思います。
ご質問等あればコメント下さい。長い記事をお読み頂きありがとうございました。

























