シューティングにはまってアケコン作った話

この記事は FUN AdventCalendar 2021の13日目の記事になります。

adventar.org

 

昨日はこたさんによる こたのちきちきお一人ハッカソン でした。(です?現在進行形?頑張ってください...)(追記:今見たら終了してました、お疲れさまでした。)

ちなみに私は一日アプリ開発の方に票を入れました。若干の申し訳なさも感じつつ、マジでお疲れ様です。

 

 

自己紹介+はじめに

 

こんにちは、kazu8823と申します(twitter:@kazujdDR8823)

知能システムコース2年、好きな言語はC・C#、好きなゲームは音楽ゲーム(弐寺DDRドラマニ)です。

 

こんなことや、

 

そんなことや、

 

あんなことや、

 

こんなことを、

しています。

 

よろしくお願いします。

 

 

早速本題に入っていきます。

 

先ほど好きなゲームは音楽ゲームだと書いたのですが、実は最近あまりモチベがなく、しばらくプレイしてません。

しかし、代わりに(?)とあるジャンルにはまっています。

 

そう、シューティングです!!!!

 

主に遊んでいるのは、

怒首領蜂大復活

store.steampowered.com

 

虫姫さま

store.steampowered.com

 

斑鳩

store.steampowered.com

 

などです。(シューティング楽しいよ!!!!!やろう!!!!!!)

 

 

そんな私が普段シューティングをプレイするときは、キーボードで操作しています。

 

もちろんキーボード操作だからと言って、何か問題があるなんてことはありません。

 

超楽しい。まじで

 

 

ですが、少しづつある思いが芽生えてきました。

 

 

.....欲しい

.....欲しい

.....欲しい

 

.....欲しい

 

.....欲しい

 

.....欲しい

 

 

.....欲しい

 

 

 

 

 

 

 

 

 

アケコン欲しい!!!!!!!

 

(Q. アケコンって何? A. こういうの)

item.rakuten.co.jp

 

 

 

 

 

 

 

 

そうだ!!!!!!!

 

 

 

 

 

 

 

 

作ろう!!!!!!

 

 

 

 

 

 

 

 

注意

 

先に言っておきますが、この記事長いです。

 

たった今ブラウザバックしたくなった人が気持ちよくブラウザバックできるように、先に結論から言っちゃいますね。

 

 

 

 

 

 

 

 

 

既製品を買え!!

 

(この記事のオチ、ここから下は駄文)

 

 

 

 

 

作りたいもの

 

アケコンの製作に入る前に、どのようなアケコンを作るかを決めましょう。

 

今回は

・ボタン+レバーは静音

  通常のやつうるさいから。ただ通常より値段が高い。

 

・8方向レバー+8ボタン+スタート・セレクト等に4ボタン

 

見た目は気にしない!!!!

  (気にすることができるほどの加工技術無い)

 

基盤はPICを使って自作

  PICが好きだから

  (Q. PICとは? A. マイコンの一種)

  (Q. マイコンとは? A. これ見て https://wa3.i-3-i.info/word15753.html)

 

・天板はアルミ+硬質塩ビ

  硬さを求めてアルミ+冬冷たいから表面は塩ビ、の2層構造

 

・天板以外は木

  加工性・入手性良し+割と強度ある

 

・なるべく改造しやすいように作る

  ボタンの端子に直で半田付けとかはしない

 

見た目は気にしない!!!!

  (大事なことなので二回言いました)

 

 

 

それでは実際の製作に入っていきましょう

 

 

 

 

 

基盤など

(小難しい話が続くので、流し読み推奨)

 

 

使用するマイコンについて

最初はp18f14k50を使おうと思っていたのですが、

akizukidenshi.com

(↑まじオススメ、USB周りの配線とか全部されてるから、ブレッドボードに指すだけで開発できて超楽)

 

14k50はUSBを使うと、GPIO(入出力に使える端子)が12(+1)本しかありません。

 

今回はレバー(=4ボタン)+8ボタン+4ボタン=16ボタンのため、ピン数が足りないです。

 

ということでピン数が多いp18f2550に変更しました。

akizukidenshi.com

 

2550には、(秋月で観測する限り)USBコネクタ付きのボードはなかったため、マイコン・USB周りの部品(水晶発振子、コンデンサ等)を全部そろえて、配線する必要があります。

 

 

ということで回路図はこんな感じです。

f:id:kazujdDR8823:20211205021423p:plain

 

 

スイッチと基盤は、5ピンコネクタ(GND共通、4ボタン分)でつなぐことにします。

 

 

 

主な部品表です

部品名 値段 個数 用途など
PIC18F2550 500 1 マイコン
水晶発振器20MHz 30 1 クロックの生成
積層セラミックコンデンサ15pF 10 2 水晶発振子の負荷容量
セラコン0.1μF 15 1 パスコン
セラコン0.22μF 20 1 VUSB端子につなぐ
セラコン1μF 20 1 USB端子側につけてノイズ軽減
ミニB-USBコネクタDIP化キット 200 1 USB端子
抵抗10kΩ(購入は100単位) 1 8 プルアップ抵抗
XHコネクタ ベース5P 15 4 ボタンと基盤をつなぐ端子
丸ピンICソケット 28P 70 1 マイコンを直でつけないために使用
ユニバーサル基盤 100 1 基盤

 

合計1043円(全部秋月)

 

 

はんだ付け

ということで、実際に基盤を作っていきます

 

まずは部品配置などの設計をします。

 

f:id:kazujdDR8823:20211207004735j:plain

ユニバーサル基盤上で作る場合、基盤の寸法図を印刷して使うと便利でオススメです。

(ただこの写真の紙は半透明にするの忘れたからクソやりにくい)

 

実際に書いたものがこちらです。

f:id:kazujdDR8823:20211207004731j:plain

汚いけど自分がわかればOK!!!!!!!!!!

 

 

 

次ははんだ付け!

 

(とりあえず動画撮ってみたやつ)

 

作業時間:約2時間

f:id:kazujdDR8823:20211207005038j:plainf:id:kazujdDR8823:20211207005057j:plain

 

ということでこんな感じです。

 

ここら辺そんなに書くことないからサクサク行きます

 

 

プログラム

次はマイコンに書き込むプログラムです。

 

 

 

が、結構長いため、別の記事に分割しました。

kazu8823.hatenablog.jp

 

↑の記事はPICがある程度わかっている人向けかつ、割とまじめに書いたやつ、そして長いので、

アケコン作るつもりはない

・PIC?なにそれ?おいしいの?

arduinoで作らせてよ

・この記事長い

という人は読むことをオススメしません。時間の無駄だぞ、よく考えろ。

 

 

 

 

 

 

 

 

 

 

 

ということでプログラムを書きこんだマイコンがこちらになります!!!!!!!!!

(料理番組のように)

f:id:kazujdDR8823:20211207010836j:plain

 

 

 

 

 

ボタン・レバー周り

次にメインと言ってもいいボタンやレバーなどの入力装置周りについてです。

全部三和電子製でそろえています。

 

 

まずは購入した部品です

 

楽天(三和電子ストア)

部品名 値段 個数 用途など
JLF-TPRG-8BYT-SK- 5808 1 静音レバー
OBSFE-30- (4個入り) 1452 2 静音ボタン メインボタン用
OBSFE-24-K 363 4 静音ボタン スタートセレクト等用
JLF-H 583 1 レバーにつなぐ線
LB-35- 187 1 レバーボール
AT-187 (100個入り) 1210 1 ボタンに線を取り付ける用の金具

 

秋月

部品名 値段 個数 用途など
耐熱電子ワイヤー 2m×7色 AWG24 480 1
XHコネクタ ハウジング 5P 10 4 ボタンからの線を基盤につなげるためのコネクタ
XHコネクタ ハウジング用コンタクト(100個入り) 200 1 コネクタ用の金具

 

合計 12864円

 

結構な値段になってしまいましたが、静音のパーツにしているのが主な原因です。

静音じゃないレバーは大体3000円弱、ボタンは1個250円ほどで買えます。

 

 

楽天から届いた時の画像

f:id:kazujdDR8823:20211210230459j:plain

 

レバーやボタンの取り付けは一番最後の作業になるため、先にハーネス作りをします。

(Q. ハーネスとは? A. 線何本かまとめたやつみたいな)

 

 

イメージしにくいと思うので、完成品を先に載せます

f:id:kazujdDR8823:20211210230810j:plain

 

こんなやつです。

 

 

 

はい、わかりにくいですね。

まあ、「なんか線まとめてるんだなぁ」程度の認識でなんも問題ないです。

 

 

とりあえず先ほどの画像の説明をします。

f:id:kazujdDR8823:20211210230810j:plain

・上の部分にあるのが、基盤に刺さるコネクタ

・下の線の先にあるのがリセプタクルという、金属の端子に差し込めるようになるパーツです。

・下の黒以外の線をそれぞれボタンの片方に、黒い線をもう片方にさします。

 

f:id:kazujdDR8823:20211210231613j:plain

そうするとこうなり、GND側(-側)を共通にして端子数を減らしています。

 

 

 

ってことで製作!!!!

 

 

 

作業時間:1時間ちょい

 

(さっきのはんだ付け動画もですが400倍です)

 

 

f:id:kazujdDR8823:20211210234038j:plain

ってことで完成!!!!!!!

 

(ちなみにこの日、後述する木工作業と基板作成をやったあとに作業したため、超きつかった)

 

 

 

 

筐体作成

 

それでは、今までに作ったものたちを納める箱を作ります。

 

 

最初に書いた内容とかぶるところもありますが、筐体は以下のような仕様です

 

・天板はアルミ塩ビ版の二層構造。アルミは強度用。ただアルミだけだと表面冷たいから塩ビも上に。二層構造だから間に紙とか挟める、ってか挟む。

 

・それ以外の部分は木

 

・メンテとかしやすいようにするために、磁石でパカパカ開けれるようにする

 

 

 

まずは購入した部品です

 

部品名 値段 個数 用途など
MDF板300x450x12 470 1
アルミ板200x300x2 1045 1 天板
硬質塩ビ板200x300x2 437 1 天板
超低頭小ねじ(4個入り) 129 1 レバー固定用
六角ナット 5 4 レバー固定用
ワッシャー 4 4 レバー固定用
丸木ねじ(たくさん入ってるやつ) 110 1 天板固定用
超低頭タッピング(たくさんはいってるやつ) 162 1 いろいろ固定用
マグネットキャッチ 173 2 パカパカ開けれるようにするためのやつ

 

合計2735円(全部ホーマック)

 

 

購入した商品の説明+補足

 

アルミ板+塩ビ板+MDF板

f:id:kazujdDR8823:20211211002412j:plain

 

ホーマックに売ってたアルミ板が300x200だったため、カットしなくて済むように筐体も300x200としました。

 

・取り付けるボタンが(確か)板厚MAX3.9ミリまでなので、アルミを2ミリ・塩ビを1ミリにしました。

 

・MDF板はもともと300x450でしたが、ホーマックの木材カットサービスを使って、300x200,60,60,60,60 にしてもらいました。ホーマックマジ神。

 

 

 

 

 

マグネットキャッチ

f:id:kazujdDR8823:20211211004106j:plain

 

・磁石の力でピタッと閉まる棚とかに使われてるアレ

 

 

「でしょうね」って動きする

 

 

 

 

 

ねじ類

f:id:kazujdDR8823:20211211004556j:plain

 

左:天板固定用

右:基盤固定用だったけど、マグネットキャッチ付属のねじが長すぎて木材貫通しそうだったから、基盤だけじゃなくそこにも一部使用

 

 

 

 

 

レバー固定用ねじ等

f:id:kazujdDR8823:20211211004915j:plain

 

左からナット、ワッシャー、ねじ

 

 

一番右の超低頭ねじがマジで頭部分が薄くてびっくりしました。1ミリ無い....

 

f:id:kazujdDR8823:20211211005008j:plain

 

 

 

 

それでは実際の作業に入ります

 

サクサク行きますよ~~~

 

 

 

木材加工

 

切る

f:id:kazujdDR8823:20211211005913j:plain

 

切った

f:id:kazujdDR8823:20211211005823j:plain

 

つける

f:id:kazujdDR8823:20211211005852j:plainf:id:kazujdDR8823:20211211010011j:plain



つけた

f:id:kazujdDR8823:20211211010049j:plain

 

金属

f:id:kazujdDR8823:20211211010221j:plain


磁石

f:id:kazujdDR8823:20211211010250j:plain

 

 

完成~~~~~!!!!!!!

f:id:kazujdDR8823:20211211010321j:plain

 

 

 

 

 

(あんまり書くことない...)

 

 

 

 

天板加工

 

アケコンを作る上で超重要と言ってもいい天板部分です。

 

先に完成品からご覧ください!!!

 

f:id:kazujdDR8823:20211212170310j:plain

左からアルミ・間に挟む紙・硬質塩ビ板

 

 

いやあぁ、いいですねぇ。綺麗ですねぇ。

 

 

 

 

 

 

だって全部自分でやってないからねえ

 

 

 

はい、ということで、天板部分は知り合いの方にお願いしました。

 

アルミ板に30mmの穴開ける工具持ってないんですよね...そのためアルミ板と塩ビ版の穴あけは、機械加工が得意な知り合いの方に、

間に挟む紙は、ミリ単位でイラストを描けるソフト持ってないので、イラレ持ってる知り合いの方に、お願いしました。

 

そんなわけで天板部分に関しては人の力借りまくりました。

 

 

余談ですが、ボタンははめ込み式のためねじが必要ないのに対し、レバーはねじで固定するため、そのまま取り付けようとするとねじの頭が表面に出てしまいます。

 

そのため、

f:id:kazujdDR8823:20211212171849p:plain

こんな感じに塩ビには大きめに穴をあけて、表面にあまり出ないようにしようとしていたのですが、

 

f:id:kazujdDR8823:20211212171951p:plain

何とこんな感じに加工してくださいました。神かよ

 

 

間に挟む紙については、サイズが300x200とA4よりちょっと大きいです。しかし自宅にあるプリンターは最大A4のため、もらったデータをUSBに入れてセブンイレブンのプリンターに駆け込みました。セブンイレブンさんありがとうございます。

 

 

 

天板の加工をしてくださった方と、こんな感じで頼みますって手書きイメージ送った通りにデータに変換してくれた方に、この場を借りてお礼を申し上げます。

 

 

 

 

 

つまり天板は、他力本願ゾーンです

 

 

イェイ

 

 

組み立て

全部の部品がそろったので実際の組み立て作業に入ります。

 

1.レバー取り付け

f:id:kazujdDR8823:20211212172118j:plainf:id:kazujdDR8823:20211212172212j:plain

アルミ板にレバーを取り付けます。

ちなみにレバーボールも取り付けていますが、この後塩ビ板を取り付けなきゃいけないため、順番間違っています。せっかちだね。

 

 

2.塩ビ板&デザイン紙取り付け

f:id:kazujdDR8823:20211212172349j:plain

アルミの上に、紙・塩ビ板の順番で重ねて、今度こそレバーボールを取り付けます。

 

 

3.木箱へ取り付け

f:id:kazujdDR8823:20211212172504j:plain

すごくわかりづらいのですが、木箱にねじで取り付けてます。

 

 

4.ボタンはめ込み

f:id:kazujdDR8823:20211212172536j:plainf:id:kazujdDR8823:20211212172553j:plain

ボタンをはめ込みます。っぽくなってきた。

 

 

5.線取り付け

f:id:kazujdDR8823:20211212172700j:plain

線を挿します。全体的に線がちょっと長かった。

 

 

6.完成!!!!!!

f:id:kazujdDR8823:20211212172800j:plain

(なんか感動する)

 

 

 

テストプレイ

それでは実際に使用している様子をご覧ください。

 

 

シューティング

めっちゃしくってるけど、ギリギリ1CCできたしOK

 

 

アクション

かちゃかちゃやるのたのしい(小並感)

 

 

jump king

アケコンでやるもんじゃねえ、レバー重い

 

 

 

自作についてまじめに考える

 

アケコン自作について、いろいろと振り返ってみます。

 

まずは金銭面から

 

秋月 1763
楽天(三和電子) 12144
ホーマック 2735
合計 16642

 

うん、高い。

 

同じ値段なら↓とか買った方が500%いい

www.amazon.co.jp

 

正直思ったより高くなりました。

 

 

 

続いて、メリット・デメリット等

 

メリット

・楽しい - 唯一にして最大の魅力。モノを作るのが楽しめる人なら超楽しい。

 

 

デメリット

・時間 - 作業時間だけでも10時間は超えてそう。設計考えてる時間とかいろいろ含めたら倍以上に...

 

・お金 - 材料費だけじゃなく、工具代などがかかる。かかった費用として書いているのは材料費のみだが、作る上で工具を買い足しているので結構お金がかかった。

 

・失敗のリスク - 必ずしも成功するとは限らないものにかけられる値段ではない気がする。

 

 

 

これらを踏まえて

 

私個人としては、自作したいという強い意志がない限りは既製品を購入した方がいいと思います。正直デメリットがでかすぎる....

 

ただ、もし「作りたい!!!」って人がいるのであれば、割とオススメできます。

ネットに情報がゴロゴロ転がっている上に、完成すれば普通にコントローラーとして使えるので、達成感が味わいやすい気がします。ってかなんかあったら聞いてくれ!組み込み楽しいよ!!!!!!

 

 

終わりに

こんなに長い記事を最後まで読んでいただき、本当にありがとうございます。

 

去年「組み込みが好きです」って言っときながら組み込みじゃなかったので、今年はかけて満足しています。(ただし財布の中身がやばい...)

 

質問も受け付けますので、もしアケコン自作したい人などがおられましたら、私のtwitterにでもお願いします。

 

 

adventar.org

明日はよっすーさんによる「デザイン系の話かハッカソン周りの話をします」です!

(デザインできる人マジで尊敬します...)

お楽しみに!!!

 

 

 

 

(ちなみに、私はPart2の17日にも登録していますので、もしよろしければそちらもご覧ください。ゲーム紹介の予定です。今頑張って書いてます...)

adventar.org

 

 

PIC18f2550をジョイスティックにする

この記事は、

kazu8823.hatenablog.jp

の補足記事です。

 

ある程度PICに慣れている方向けの説明となっています。ご了承ください。

 

また、私の環境はMPLAB X IDE v5.45 + XC8 v2.32です。

 

 

 

 

それでは、PICマイコンに書き込むプログラムを作っていきます

 

 

 

 

環境など

 

使用マイコン PIC18f2550 

akizukidenshi.com

 

理由

・ピン数が多い(28ピン、20ピンだとちょっと足りない)

・p18系しか使ったことなかった

秋月に売ってたから(超重要!!)

 

 

データシート(日本語版なさそう)

https://ww1.microchip.com/downloads/en/DeviceDoc/39632e.pdf

 

 

 

ブレッドボードでテスト

 

主な部品表です

部品名 値段 個数 用途など
PIC18F2550 500 1 マイコン
水晶発振器20MHz 30 1 クロックの生成
積層セラミックコンデンサ15pF 10 2 水晶発振子の負荷容量
セラコン0.1μF 15 1 パスコン
セラコン0.22μF 20 1 VUSB端子につなぐ
セラコン1μF 20 1 USB端子側につけてノイズ軽減
ミニB-USBコネクタDIP化キット 200 1 USB端子

 

 

f:id:kazujdDR8823:20211201022615j:plain

最小構成

f:id:kazujdDR8823:20211201022700j:plain

PICkit用の線追加

 

f:id:kazujdDR8823:20211212175230p:plain

PICkit用の端子無しですが、最小構成はこんな感じです。左下のコンデンサパスコンなので、マイコンに近い位置に配置してください。

 

細かい話ですが、USBで接続したときの電源の取得方法で回路が変わります。これはバスパワーの場合の回路図になっています。

 

Microchip Libraries for Applications (MLA) のダウンロード

MLAとは、Microchipから公開されている、USBやLANなどといったものを使うためのサンプルコード集みたいなやつです(って認識でいました)。

 

 

ここからダウンロード

https://www.microchip.com/en-us/development-tools-tools-and-software/libraries-code-examples-and-more/microchip-libraries-for-applications#

 

皆さんの環境に合わせたものをダウンロードしてください。

 

f:id:kazujdDR8823:20211201211315p:plain

MLAのダウンロード

インストーラーがダウンロードされる(容量は意外と大きい、300MBほど)

f:id:kazujdDR8823:20211201211936p:plain

Next

 

f:id:kazujdDR8823:20211201211951p:plain

accept からの next

 

f:id:kazujdDR8823:20211201212013p:plain

フォルダ指定してね~ってやつ

とりあえずC直下においています。今後、パスを書く際はC直下に置かれている前提で書きます。

 

f:id:kazujdDR8823:20211201212100p:plain

入れるやつ選択してね~ってやつ

他のやつは使わないのでUSBだけを選択しました。

 

 

f:id:kazujdDR8823:20211201212119p:plain

とりあえずnext

 

f:id:kazujdDR8823:20211201212132p:plain

Nextでインストール開始

 

f:id:kazujdDR8823:20211201212236p:plain

インストール完了後この画面になります。finishで終了

 

 

 

それでは今インストールしたライブラリをMPLABで開いてみましょう。

f:id:kazujdDR8823:20211201212540p:plain

C直下にインストールした場合は

C:\microchip\mla\v2018_11_26\apps\usb\device\hid_joystick\firmware\picdem_fs_usb.x

を開いてください。

 

開くとこうなります。

f:id:kazujdDR8823:20211201212735p:plain

 

ここで赤丸で囲んだ部分を見てください。

f:id:kazujdDR8823:20211212180447p:plain

 

 

 

 

f:id:kazujdDR8823:20211201212916p:plain

バイス違うじゃん(今回は18f2550)

 

ということで

 

 

プロジェクトの作成

今回使用しているPIC18F2550用のライブラリはMLAに入っていません。

しかし、ピン数が増えているだけのPIC18F4550のライブラリが入っているため、それを使用していきます。

 

まずはサンプルプロジェクトをコピーしてみましょう。

 

と言いたいのですが、このMLAは様々なデバイスに対応しているため、共通化できる部分はめちゃくちゃ共通化されています。

その結果、プロジェクトをコピーしようにも、いろいろなところに散らばっているファイルをかき集めなければなりません。

 

少し面倒くさいですが、やっていきましょう。

 

 

まずは新規プロジェクトを作成してください。

 

何点か注意点があり、

 

バイスはPIC18F2550

f:id:kazujdDR8823:20211201213023p:plain

 

コンパイラはXC8

f:id:kazujdDR8823:20211201213041p:plain

 

プロジェクトの名前などは任意でOKです。

f:id:kazujdDR8823:20211212181133p:plain



 

それでは次に、MLAから必要なファイルを、今作ったプロジェクトのフォルダに入れていきます。

 

C:\microchip\mla\v2018_11_26\apps\usb\device\hid_joystick\firmware\picdem_fs_usb.x

から

fixed_address_memory.h

io_mapping.h

system.c

system.h

 

C:\microchip\mla\v2018_11_26\apps\usb\device\hid_joystick\firmware\demo_src

から

app_device_joystick.c

app_device_joystick.h

app_led_usb_status.c

app_led_usb_status.h

main.c

usb_config.h

usb_descriptors.c

usb_events.c

 

C:\microchip\mla\v2018_11_26\framework\usb\inc

から

usb.h

usb_ch9.h

usb_common.h

usb_device.h

usb_device_hid.h

usb_hal.h

usb_hal_pic18.h

 

C:\microchip\mla\v2018_11_26\framework\usb\src

から

usb_device.c

usb_dvice_hid.c

usb_device_local.h

 

C:\microchip\mla\v2018_11_26\bsp\picdem_fs_usb

から

buttons.c

buttons.h

leds.c

leds.h

 

 

すべて入れるとこのようになります。

f:id:kazujdDR8823:20211212181415p:plain



ファイル数多かったのでヘッダファイルはフォルダに入れました

f:id:kazujdDR8823:20211212181458p:plain

完成

 

 

それでは次に、今入れたファイルをプロジェクトに追加していきます。

 

Projectウィンドウから、Add Existing itemで追加

f:id:kazujdDR8823:20211201215050p:plain

f:id:kazujdDR8823:20211201215102p:plain

 

ちなみにこの時点でビルドをかけるとエラーが起きますので、気にしないでください。

f:id:kazujdDR8823:20211212191649p:plain



 

 

また、ヘッダファイルなどを別フォルダにした場合include directoriesの設定を忘れずにしましょう。

f:id:kazujdDR8823:20211201215349p:plain

 

 

続いて、ビルドを通すためにいくつか変更を加えます。

先ほど4550は2550にピン数を増やしただけと書きましたが、もろにその部分でエラーが起きています。

leds.cを開くとこのような部分があるはずです

f:id:kazujdDR8823:20211201220130p:plain

2550には存在しないポートDを使用しているためエラーが起きていました。

 

ということでDをAに変更しておきましょう

 

#define LED_D1_LAT LATDbits.LATD0

#define LED_D1_LAT LATAbits.LATA0

 

 

これで一応ビルドが通るはずです。

 

 

 

 

次にコンフィギュレーションビットの設定をしていきます。

コンフィギュレーションビットの説明はコンパイラをインストールしたフォルダの中にPDFがありますので、そちらを参考にしましょう。

 

ちなみに私の場合このディレクトリにありました。

C:\Program Files\Microchip\xc8\v2.32\docs\chips\18f2550.html

 

 

 

コンフィギュレーションビットはsystem.cに書かれています

f:id:kazujdDR8823:20211201221001p:plain

 

 

2点だけ説明します。

 

1.PLLDIV

f:id:kazujdDR8823:20211201222408p:plain

PLLDIV = 5にします。(変更なし)

今回は20MHzの水晶発振子をつないでいるため5のままで大丈夫です。それ以外の周波数の発振子を使う場合は変更してください。

 

 

f:id:kazujdDR8823:20211201221156p:plain

クロックダイアグラム(データシートより)

クロックダイアグラムを見るとこのようになっており、現在の構成では、

 

20MHz→1/5に分周→4MHz→PLL→96MHz→1/2に分周→クロックとして利用

 

となっています。つける水晶発振子の周波数や、CPUクロックを変更する場合は、コンフィギュレーションビットやレジスタを変更しなければならないので気を付けてください。

 

2.MCLRE

リセットピン用の設定です。今回の回路ではリセットボタンは実装しないためOFFにしておきましょう。

MCLRE = OFF 

 

 

 

書き込み時の注意

ここまで来たら実際に書き込むのですが、p18f2550において書き込みに失敗することが多いらしいです

akizukidenshi.com

実際に私もこの状況に遭遇したのですが、PICkitからの電源供給を3.375Vにしたところ書き込めました。

 

実際につないでみよう

PICにプログラムを書き込み、PICkitを外しUSBケーブルを付けます

PICkitを付けたままUSBを付けると、電源関係が確かアレするのでアレです(よくわかってないけどダメなのはわかる)

 

コントロールパネル→ハードウェアとサウンド→デバイスとプリンター

で見てみると、PCから認識されています。

f:id:kazujdDR8823:20211212191815p:plain



Joystick Demo を右クリックで選択しゲームコントローラーの設定を開きます。

f:id:kazujdDR8823:20211201223656p:plain

 

Joystick Demo を選択し、プロパティを開きます。

f:id:kazujdDR8823:20211201223716p:plain

 

 

なんかあらぶっていますがOKです。

 

 

それではプログラムを少し見ていきましょう。

実際にコントローラーの入力を設定している部分は、app_device_joystick.cのAPP_DeviceJoystickTasks関数にあります。

 

f:id:kazujdDR8823:20211201224931p:plain

 

f:id:kazujdDR8823:20211212183447p:plain

 

if文の条件式にある、BUTTON_USB_DEVICE_HID_JOYSTICKとはRB4のことです(io_mapping.h, buttons.h, buttons.cなど参照)

 

ということで、RB4にスイッチを取り付け(とりあえずプルダウン)ると

f:id:kazujdDR8823:20211207011554j:plain

 

あらぶらなくなります

 

 

もう少し詳しく見ていきます。

 

 

f:id:kazujdDR8823:20211212183718p:plain

この部分が、実際に入力を設定している部分です。

 

joystick_inputは上で宣言されており

f:id:kazujdDR8823:20211201231312p:plain

INPUT_CONTROLS型の変数です。

 

INPUT_CONTROLSとは、同じファイルの上の方に書いてあり

f:id:kazujdDR8823:20211201231459p:plain

構造体の共用体(?)ですね(なんて説明していいのかわからん)

 

ただここら辺はあんまり理解しなくともかけるので、なんとなくこんなのがあるんだな~程度でOKです。

 

 

ピン配置を決める

アケコン用にプログラムを作る前に、ピン配置を決めます

 

ポートA(0~3)→レバー

ポートB→メインボタン

ポートC(0,1,2,6)→スタート・セレクトとか

 

ということにしました。

 

ポートBだけ内蔵プルアップがあるので使い、ポートAとCは自力でプルアップします。

 

 

プログラムを書く

 

アケコン向けにプログラムを書く前に、すでに設定されてるピン設定を無効化します。

 

system.cにあるSYSTEM_Initialize関数のED_Enable関数、BUTTON_Enable関数呼び出しをコメントアウトします。

f:id:kazujdDR8823:20211201232751p:plain

 

 

usb_events.cにある、APP_LEDUpdateUSBStatus関数呼び出し3つをコメントアウトします。

f:id:kazujdDR8823:20211201233809p:plain

 

次に

app_led_usb_status.c

leds.c

buttons.c

の3ファイルをプロジェクトから外します。(右クリックからRemove From Project)

 

app_device_joystick.cの、167行目あたりのBUTTON_isPressed~~~みたいなところをとりあえずtrueにしておきます(ここはあとからすべて変えるのでとりあえずtrueでOK)

f:id:kazujdDR8823:20211201234053p:plain

 

この変更をするととりあえずビルドが通るはずです。

(使ってないヘッダファイルとか残ってるけど気にしない...)

 

 

 

と、ここまではすでにある設定の削除でした。

ここからは新しいアケコン向けの設定を書いていきます。

 

 

 

いろいろ設定するために新しくヘッダファイルを作成します。(my_header.h)

f:id:kazujdDR8823:20211212184846p:plain

/* 
 * File:   my_header.h
 * Author: kazu8823
 *
 * Created on 2021/12/01, 23:16
 */

#ifndef MY_HEADER_H
#define    MY_HEADER_H

#ifdef __cplusplus
extern "C" {
#endif
    
// 追加部分ここから********************************************    
// レバー
#define LEVER_UP !PORTAbits.RA0
#define LEVER_DOWN !PORTAbits.RA1
#define LEVER_RIGHT !PORTAbits.RA2
#define LEVER_LEFT !PORTAbits.RA3
    
#define LEVER (~PORTA & 0x0f)

// メインボタン
#define BUTTON1 !PORTBbits.RB0
#define BUTTON2 !PORTBbits.RB1
#define BUTTON3 !PORTBbits.RB2
#define BUTTON4 !PORTBbits.RB3
#define BUTTON5 !PORTBbits.RB4
#define BUTTON6 !PORTBbits.RB5
#define BUTTON7 !PORTBbits.RB6
#define BUTTON8 !PORTBbits.RB7
    
// スタートセレクト等
#define SUB_BUTTON1 !PORTCbits.RC0
#define SUB_BUTTON2 !PORTCbits.RC1
#define SUB_BUTTON3 !PORTCbits.RC2
#define SUB_BUTTON4 !PORTCbits.RC6


// ここまで****************************************************

#ifdef __cplusplus
}
#endif

#endif  /* MY_HEADER_H */



 

回路がプルアップのため、ON=0, OFF=1になってしまいます。そのため、!を付けてON=1, OFF=0にしています。(好み)

 

今度はそれをmain.cから呼び出します。

f:id:kazujdDR8823:20211201235324p:plain

 

次に、main関数の前にinit関数を作って設定をしましょう。

f:id:kazujdDR8823:20211202005510p:plain

// 設定など
void init(){
    // 入出力設定 0で出力 1で入力
    TRISA = 0x0f;   // 0~3までを入力 
    TRISB = 0xff;   // 全部入力
    TRISC = 0x47;   // 0,1,2,6を入力
    
    INTCON2bits.RBPU = 0;   // ポートBの内蔵プルアップを有効にする(0で有効 1で無効)
    ADCON1bits.PCFG = 0b1111;   // AD変換を無効化(全ピンデジタルに)
}

 

 

main関数の最初で、今作成したinit関数を呼び出します

f:id:kazujdDR8823:20211202001211p:plain



 

app_device_joystick.cからも自作ヘッダをインクルードします

f:id:kazujdDR8823:20211202000335p:plain

 

 

同じくapp_device_joystick.cに、レバーの入力と出力の関係を表す配列を作っておきます。

f:id:kazujdDR8823:20211212185239p:plain

unsigned char lever_con[] = {
  0x8, 0x2, 0x6, 0x2, 0x4, 0x3, 0x5, 0x3, 0x0, 0x1, 0x7, 0x1, 0x8, 0x2, 0x6, 0x2
};

 

 

 

最後にAPP_DeviceJoystickTasks関数をこのようにします

f:id:kazujdDR8823:20211212185529p:plain

(最後の閉じカッコ途切れています、すいません...)

 

void APP_DeviceJoystickTasks(void)
{  
    /* If the USB device isn't configured yet, we can't really do anything
     * else since we don't have a host to talk to.  So jump back to the
     * top of the while loop. */
    if( USBGetDeviceState() < CONFIGURED_STATE )
    {
        /* Jump back to the top of the while loop. */
        return;
    }

    /* If we are currently suspended, then we need to see if we need to
     * issue a remote wakeup.  In either case, we shouldn't process any
     * keyboard commands since we aren't currently communicating to the host
     * thus just continue back to the start of the while loop. */
    if( USBIsDeviceSuspended() == true )
    {
        /* Jump back to the top of the while loop. */
        return;
    }

    //If the last transmission is complete
    if(!HIDTxHandleBusy(lastTransmission))
    {
        // ボタン
        joystick_input.members.buttons.square = BUTTON1;
        joystick_input.members.buttons.x = BUTTON3;
        joystick_input.members.buttons.o = BUTTON4;
        joystick_input.members.buttons.triangle = BUTTON2;
        joystick_input.members.buttons.L1 = BUTTON6;
        joystick_input.members.buttons.R1 = BUTTON5;
        joystick_input.members.buttons.L2 = BUTTON8;
        joystick_input.members.buttons.R2 = BUTTON7;
        joystick_input.members.buttons.select = SUB_BUTTON2;
        joystick_input.members.buttons.start = SUB_BUTTON1;
        joystick_input.members.buttons.left_stick = SUB_BUTTON3;
        joystick_input.members.buttons.right_stick = SUB_BUTTON4;
        joystick_input.members.buttons.home = 0;
        
        // レバー
        joystick_input.members.hat_switch.hat_switch = lever_con[LEVER];
        
        // アナログスティック(無効)
        joystick_input.members.analog_stick.X = 0x80;
        joystick_input.members.analog_stick.Y = 0x80;
        joystick_input.members.analog_stick.Z = 0x80;
        joystick_input.members.analog_stick.Rz = 0x80;
        
        lastTransmission = HIDTxPacket(JOYSTICK_EP, (uint8_t*)&joystick_input, sizeof(joystick_input));
    }
    
}//end ProcessIO

 

 

 

 

テスト

ここまで出来たら実際にプログラムを書き込みましょう。

 

また、テストができるようにブレッドボードにスイッチを取り付けます。

 

回路図はこんな感じです。コネクタでかいていますが、普通のジャンパー線でつなぎました。

f:id:kazujdDR8823:20211205021423p:plain

 

 

そしてボタン16つけたブレッドボードがこちら!!

f:id:kazujdDR8823:20211207011744j:plain

 

 

 

結果

古いタクトスイッチを使っているため、入力がちょっと不安定です...

 

 

 

ということで完成です!!!!!

 

すごく駆け足で説明したため、わかりにくい部分もあったと思います。

何か質問等ありましたら、私のツイッター(@kazujdDR8823)にでもお願いします。

 

ここまでご覧いただきありがとうございました。

 

Wiiリモコンっていいよね!って話

 

始めまして、kazu8823と申します。(twitter:@kazujdDR8823)

 

この記事はFUN Advent Calendar 2020 Part2 9日目の記事です。

FUN Part2 Advent Calendar 2020 - Adventar

 

昨日は はくすけ さんの「†┏┛墓┗┓†」でした!

あの墓マジで見てみたいんですけど、置いてあるカフェの場所知っている方いれば是非教えてもらいたいです...

 

 

 

本題に入る前に...

始めましての人がほとんどだと思うので、自己紹介します。

 

音ゲーマーです

 

弐寺DDRドラマニをメイン機種としているBEMANI好きのオタクです。

 

...と冗談はさておき...

未来大生としての自己紹介をすると、

知シスかICT(情シス)に進むか悩んでいる1年です。

好きな言語はC#、好きな分野は組み込み、特にPICマイコンをよく使っています。

 

こんなことや、

 

そんなことや、

 

あんなことや、 

 

こんなことを、

しています。

 

よろしくお願いします。

 

 

 

それでは、本題に入ります。

先ほど自己紹介の中で組み込みが好きだと書いたのですが、私が思うに組み込みの大きな魅力の一つに、多彩な入力があると思います。

入力回路から作らなければいけませんが、作りさえすればいろいろな入力部品を使用することができます。アナログ値を取れるというのがものすごくでかい気がしてます。

(めっちゃ楽しいよ、みんなやろうよ組み込み!)

 

 

と、このように組み込みを推す発言を書いていますが、本題は組み込みではないです。

ここまでで何が言いたいかと言いますと、

入力って面白いよ!

って話です。

しかし、組み込みって正直難しいと思います。単純なものを作ろうにも、必要な知識が他に比べて多いです。しかも、何らかの入力機器をPCにつないで何かするとなると、さらに難しくなります。

 

それでも、アナログ値が返ってくる入力部品が使いたい!って人はいると思います。いるよね?

 

 

 

そんなあなたにオススメしたい機器があります!

 

簡単にPCに接続できて!!!

入手性もよくて!!!!

多彩な入力がある機器!!!!!

 

 

そう!!!!!!!

それは!!!!!!!!

 

 

 

Wii リモコンです!!!!!!!!!!

 

 

 

 

この記事について(注意)

この記事は、私が後先のことを何も考えずその時のノリと勢いで書いています。そのせいで、ものすごく長ったらしい記事になってしまっています。

もしWiiリモコンを実際にPCに接続して使ってみたい人は、全体的に読んでいただけるとありがたいのですが、そのつもりがない方は、

WiiリモコンをPCに接続してみよう!!

・WiimoteLibについて

・WiimoteLibの使い方

の3つを読み飛ばすことをおススメします。

 

Wii リモコンについて

Wiiリモコンとは、任天堂のゲーム機「Wii」及び「Wii U」において使用できる、標準のコントローラーです。

Wiiリモコンは、Wii本体とBluetooth通信でつながっています。そのため、非公式の使用方法として、PCとつないで使用することができます。もちろん、ただつなぐだけで使うことはできませんが、簡単に使用できるようにするためのライブラリが、有志の手によって作成されています。

今回はその中でも「WiimoteLib」というライブラリを後ほど紹介します。

 

Wiiリモコンには様々な装置が備わっています。

・ボタン(A,B,1,2,十字,-,+,home,電源ボタン)

・バイブレーション

・LED×4

・ポインタ(詳しくは後述)

・スピーカ

・3軸加速度センサ

・3軸ジャイロセンサ(Wiiリモコンプラス、もしくはWiiモーションプラスのみ)

・ユーザメモリ(Miiなどの保存に用いる)

などの装置がWiiリモコンには入っています。

 

こんだけたくさん入って3800円ってやばくない???マジでやばいよ

 

 

ポインタについて

Wiiにはセンサーバーという機器が付属していて、それにリモコンを向けることによって、センサーバーがリモコンの指している向きを認識し、ゲーム上でポインタを使うことができます。

 

 

と、思われているかもしれませんが、実は違います!

分解してみるとわかるのですが、センサーバーの中身はただの赤外線LEDです。

カメラ等でセンサーバーを撮ってみると、両端の部分が光っています。

 

  f:id:kazujdDR8823:20201208214818p:plain

上が赤外線が映るカメラ(iPhone8 内カメ)

下が赤外線が映らないカメラ(iPhone8 外カメ)

 

それじゃあどのようにして、ポインタの動作を実現しているかと言いますと、

Wiiリモコンの先っぽにある黒い部分にはCMOSセンサ(カメラみたいなもの)があり、そのCMOSセンサで、センサーバーの赤外線LEDの位置を検知し、そこからWiiリモコンがセンサーバーに対してどのような角度にあるかを割り出します。

 

  f:id:kazujdDR8823:20201208214936j:plain

 

この記事に、詳しい説明や画像が載っているので、気になる方はぜひ見てみてください!

xtech.nikkei.com

 

 ちなみに、CMOSセンサから入力された画像データは、「赤外線が強い、上位4つの点の座標」という数値の形式でWii本体とやり取りされます。(だったはず、違ったらすいません...)

  

余談ですが、SwitchのJoy-Con(R)に搭載されているモーションIRカメラも似たようなものなのですが、こちらは画像データそのままをやり取りしているっぽいので、Wiiリモコンよりもっと多彩なことができます。

 

 

 

WiiリモコンをPCに接続してみよう!!

 注意! 

この先の内容すべてに言えることなのですが、私の持っている環境がwindowsのみなため、maclinuxでの方法については書くことができません。ご了承ください。

使用する環境は Win + Visual Studio + C# です

また、Visual Studio を少し使える(プロジェクトを作ってビルドするまでくらい)人向けの内容となっています。 

 

 

 超注意!!

今回使うライブラリ「WiimoteLib」はWiiリモコンプラスに対応していません。そのため、古いWiiリモコンしか使えませんのでご注意ください。

 

  f:id:kazujdDR8823:20201208215148p:plain

左が古いWiiリモコン、右が新しいWiiリモコンプラス

     f:id:kazujdDR8823:20201208215234j:plain

リモコン下部に、「Wii MotionPlus INSIDE」の文字があるものが、新しいWiiリモコン

文字がないWiiリモコンしかWiimoteLibでは使えません。

 

 

 

それでは、WiiリモコンとPCを接続していくのですが、Wiiリモコンについてのところで説明したように、WiiリモコンBluetoothで通信を行うため、Windows標準の機能で簡単に接続することができます。

 

 

 

と思いきや、めっちゃめんどいです。

まず普通に繋ごうとしても繋がらないのと、もし繋がったとしても再度接続しなおすたびに、デバイスマネージャーからデバイスのアンインストールをしなきゃいけなくなるなど、めっちゃ大変です。

そんなわけで、「wiipermpair2」というソフトを使用します。

tyche.pu-toyama.ac.jp

 

このソフトを使用することで、簡単に接続できるのと、毎回毎回デバイスマネージャーを開かなくてよくなります。

詳しいインストール方法や使い方などはこのサイトを参照してください。C#の環境が必要です。

一応簡単にこのソフトを導入するまでの流れを説明すると、

 

wiipermpair2のソースコードをダウンロード

 ↓

Visual Studio でビルド(C#)

 ↓

生成されたexeを起動

(プロジェクトフォルダ/wiipermpair2/bin/Release/wiipermpair2.exe)

 ↓

Wiiリモコンの赤いボタンを押す

 ↓

一覧に何か表示されたらもう一度赤いボタンを押し、プログラムの「pairing」のボタンを押してしばらく待つ。

 ↓

「disconnect」の表示がでればOK

 

また、Wiiリモコンとの接続をやめるときは、PC側のBluetoothをOFFにすることで簡単に切断できます。確実に切断することができるので、この方法をオススメします

 

って感じです。もし何かあれば私(@kazujdDR8823)に連絡してくれれば対応できるかもしれません。(期待はしないでください...笑)

 

 

WiimoteLibについて

WiiリモコンをPCに接続するだけでは、思うように使用することはできません。そこで、簡単にWiiリモコンと通信できるようにするための「WiimoteLib」というライブラリを使用します。(WiimoteとはフランスでのWiiリモコンの名称らしいです)

 

github.com

 

使用方法

(Visual Studio がインストール済み&C#の環境も構築済みとします)

1. 上のリンクのリポジトリからダウンロードします

2. WiimoteLib-master/WiimoteCS/Wiimote.sinを開く

3. ビルドします

 ビルドすることにより、WiimoteLib.dllというファイルが生成されます。

 この時に、Wiiリモコンを接続していなかった場合

 

    f:id:kazujdDR8823:20201208035135p:plain

 

 このように怒られますが、気にしないでOKです。

 一応確認のために、Wiiリモコンをつないでからもう一度ビルドしてみましょう。

 

 Wiiリモコンをつないでからビルドした場合、

 

  f:id:kazujdDR8823:20201208154531p:plain

 

 このような画面が出てきます。ボタンを押したりWiiリモコンを振ったりすると、画面上の値などが変わっていきます。

 Outputsの欄にチェックをつけると、対応したLEDを光らせたり、バイブレーションをONにできたりします。

 

 もし、接続したはずなのにエラーが出てくる場合、接続の手段をもう一度やり直してみましょう。

 

4. 新しくC#のプロジェクトを作る(私はフォームアプリケーションで制作していますが、WPFでも大丈夫だと思います。というか今はWPFのいいんだよね?移行するのめんどい...)

 

  f:id:kazujdDR8823:20201208035527p:plain

 

5. 作成したプロジェクトに先ほど作ったWiimoteLibのdllファイルを参照させます。

 

  f:id:kazujdDR8823:20201208040229p:plain

 

 画像のように、上のメニューバーの「プロジェクト」→「参照の追加」を押します。

 

 

  f:id:kazujdDR8823:20201208040517p:plain

 

 その後、出てきたウィンドウの右下の「参照」を押し、先ほど作成した「WiimoteLib.dll」を追加します。

 場所は

  wiimoteLibのプロジェクトフォルダ(WiimoteCS)/WiimoteLib/bin/Debug/WiimoteLib.dll

 です。

 

  f:id:kazujdDR8823:20201208040905p:plain

 

 画像のように「WiimoteLib.dll」の左側にチェックマークが入っていればOKです!

 

これで、WiimoteLibを使用する準備は整いました!

 

 

 

 WiimoteLibの使い方

使い方に入る前に、参考にさせていただいたサイトを貼っておきます。

 

C#ではなくVBでの実装ですが、やってることは同じなのでいろいろと参考にさせていただきました。

bibo.capture.jp

  

 

 

それでは実際にWiiリモコンを使用してみましょう!

 

  f:id:kazujdDR8823:20201208160247p:plain

 

フォームアプリケーションだった場合このようなソースコード(Form1.cs)が生成されると思います。

これに追加する形で書いていきましょう!

 

下準備

まず接続(button1)と切断(button2)を行うボタンを作ります。

  

  f:id:kazujdDR8823:20201208161152p:plain

 

そして、Form1.csにこのように書きます。

 

using System;
using System.Windows.Forms;
using WiimoteLib;

namespace Wiimote_kazu8823 {
    public partial class Form1 : Form {

        Wiimote wiimote = new Wiimote();            // インスタンスの作成
        public WiimoteState wiimoteState = null;

        private delegate void UpdateWiimoteStateDelegate(WiimoteChangedEventArgs args);

        public Form1() {
            InitializeComponent();
        }

        // 接続ボタン
        private void button1_Click(object sender, EventArgs e) {
            try {
                wiimote.Connect();  // Wiiリモコンへの接続を行う
            } catch (WiimoteNotFoundException exception){
                MessageBox.Show("Wiiリモコンが見つかりません", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // Wiiリモコンとの通信モードを設定
            wiimote.SetReportType(InputReport.ButtonsAccel, true);

            wiimote.SetLEDs(0b1111);    // LEDの点灯

            wiimote.WiimoteChanged += Wiimote_WiimoteChanged;
        }

        // 切断ボタン
        private void button2_Click(object sender, EventArgs e) {
            wiimote.SetLEDs(0b0000);    // LEDの消灯
            wiimote.Disconnect();   // Wiiリモコンの切断を行う
        }

        private void Wiimote_WiimoteChanged(object sender, WiimoteChangedEventArgs e) {
            BeginInvoke(new UpdateWiimoteStateDelegate(UpdateWiimoteChanged), e);
        }

        public void UpdateWiimoteChanged(WiimoteChangedEventArgs args) {
            wiimoteState = args.WiimoteState;
        }
    }
}

 

これで実行してみると、接続ボタンを押すとLEDが光り、切断ボタンを押すとLEDが消えるプログラムができます。

 

 

これでWiiリモコンとの接続ができました!!!!!!

後は、一番下の関数(UpdateWiimoteChanged)にいろいろな処理を追加していくだけです!

 

バッテリー残量の表示

Wiiリモコンのバッテリー残量を表示してみましょう。

Form1にバッテリー残量を表示するラベル(label1)を追加します。

 

  f:id:kazujdDR8823:20201208170349p:plain

 

そして、UpdateWiimoteChangedをこのようにします。

 

public void UpdateWiimoteChanged(WiimoteChangedEventArgs args) {
    wiimoteState = args.WiimoteState;

    label1.Text = "battery : " + wiimoteState.Battery + "%";    // バッテリー残量の表示
}

 

これで実行すると、接続している間、Wiiリモコンのバッテリー残量が表示されます。

 

  f:id:kazujdDR8823:20201208170829p:plain

 

 

ボタンの状態の取得

Wiiリモコンにあるボタンの状態を取得してみましょう。

Form1にCheckBoxを追加します。

 

  f:id:kazujdDR8823:20201208171408p:plain

 

番号は

↑:1   ←:2   →:3   ↓:4   A:5   B:6   1(ボタン):7   2(ボタン):8

にしています。

 

そしてUpdateWiimoteChangedの末尾にこれを追加します。

 

// ボタン
checkBox1.Checked = wiimoteState.ButtonState.Up;
checkBox2.Checked = wiimoteState.ButtonState.Left;
checkBox3.Checked = wiimoteState.ButtonState.Right;
checkBox4.Checked = wiimoteState.ButtonState.Down;
checkBox5.Checked = wiimoteState.ButtonState.A;
checkBox6.Checked = wiimoteState.ButtonState.B;
checkBox7.Checked = wiimoteState.ButtonState.One;
checkBox8.Checked = wiimoteState.ButtonState.Two;

 

これで実行すると、ボタンに対応したcheckboxに表示されます。

 

 

加速度の取得

はい来ました、これですよ。加速度センサってすんごく楽しいんですよ。マジで。

これをやりたいがために、今回のテーマをWiiリモコンにしたといっても過言じゃないレベルです。

とりあえず、データを取得するところまでやってみましょう。

 

まずはForm1にtrackBarを3つ追加します。

(左側のラベルはわかりやすくするために付けているだけなのでなくても大丈夫です)

 

  f:id:kazujdDR8823:20201208172916p:plain

 

また、プロパティから

 Maximum を 255 に

 Minimum を 0 に

 SmallChange を 1 に

 Value を 127 に

しておきましょう

 

  f:id:kazujdDR8823:20201208173111p:plain

 

その後、UpdateWiimoteChangedの末尾に、以下を追加しましょう。

 

// 加速度センサ
trackBar1.Value = wiimoteState.AccelState.RawValues.X;
trackBar2.Value = wiimoteState.AccelState.RawValues.Y;
trackBar3.Value = wiimoteState.AccelState.RawValues.Z;

 

これで実行すると、Wiiリモコンの動きに合わせてtrackBarが動きます。

 

 

これだけで楽しいよね!!!!!!

これを伝えたいんだよ私は!!!!!!!

良くない??

だって自分の動きがそのまま取れるんだよ!!!!

楽しいっしょ!!!!!

 

 

 

 

すいません、取り乱しました。

 

CMOSセンサの取得

ポインタ関係です。

最初の方で述べたように、センサーバーにはただの赤外線LEDしかなく、Wiiリモコンに入っている赤外線を検出するCMOSセンサから、ポインタなどの処理をやっています。

 

なのでまずは、赤外線を発射するものを準備する必要があります。

もちろんセンサーバーを使ってもいいのですが、いちいちWiiの電源をつけるのはめんどくさいと思います。

なので赤外線LEDを少し離して2つ設置して、簡易センサーバーを作ることをおススメします。

 

調べるとセンサーバーを自作している人が結構います。

traceback.mydns.jp

 

ちなみに私は、ビュートローバーというプログラミング学習者向けロボットについている、ライントレース用の赤外線センサを利用しています。

 

f:id:kazujdDR8823:20201208220348j:plain

赤丸で囲んだ部分に赤外線LED(など)があります。

 

 

それでは値の取得をしてみましょう。

まずはわかりやすいようにPanelを追加します。

大きさは512×384にします。

CMOSセンサから取得できる座標データは1024×768なのですが、大きすぎるため半分にしました。

 

  f:id:kazujdDR8823:20201208180857p:plain

 

次に、今作ったPanelの中にButtonを2つ追加します。

Buttonである必要はありませんが、形を作りやすいという理由からButtonにしてます。

 

  f:id:kazujdDR8823:20201208181110p:plain

 

大きさやテキストは何でもいいのですが、分かりやすいように1(button3)と2(button4)にしてます。

またsizeは20,20にしました。

 

このようにPanelの中に置くと、座標がPanel基準となり、Panelの左上の座標からの相対座標で位置を指定できるようになります。(って認識なんですけどあってますよね?詳しい人教えてください...笑)

 

プログラムに関しては、UpdateWiimoteChangedの末尾に以下のコードを追加してください。

 

// 赤外線関係
button3.Visible = wiimoteState.IRState.IRSensors[0].Found;
button4.Visible = wiimoteState.IRState.IRSensors[1].Found;

if(wiimoteState.IRState.IRSensors[0].Found) {
    button3.Location = new System.Drawing.Point(wiimoteState.IRState.IRSensors[0].RawPosition.X / 2, wiimoteState.IRState.IRSensors[0].RawPosition.Y / 2);
}
if(wiimoteState.IRState.IRSensors[1].Found) {
    button4.Location = new System.Drawing.Point(wiimoteState.IRState.IRSensors[1].RawPosition.X / 2, wiimoteState.IRState.IRSensors[1].RawPosition.Y / 2);
}

 

それに加えて、Button1_click()内にあるwiimote.SetReportTypeを変更します。

 

// 接続ボタン
private void button1_Click(object sender, EventArgs e) {
    try {
        wiimote.Connect();  // Wiiリモコンへの接続を行う
    } catch (WiimoteNotFoundException exception){
        MessageBox.Show("Wiiリモコンが見つかりません", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return;
    }

    // Wiiリモコンとの通信モードを設定
    wiimote.SetReportType(InputReport.IRAccel, true);       // 変更部分

    wiimote.SetLEDs(0b1111);    // LEDの点灯

    wiimote.WiimoteChanged += Wiimote_WiimoteChanged;
}

 

InputReport.ButtonsAccel ではCMOSセンサ関係のデータは取得できないのですが、

InpurReport.IRAccel にすることで取得できるようになります。

 

このようにすることで、CMOSセンサの値を取得することができます。

 

 

また、今回のコードではwiiリモコン側から見た、赤外線LEDの座標をそのまま表示しているため、左右が反転しています。

左右を反転し、赤外線LEDの2点の座標を平均化することによって、Wiiにおいての挙動に近づけることができます。

 

まず中心を示すボタン(button5)を追加します。

  f:id:kazujdDR8823:20201208190211p:plain

 

 次にプログラムを↓

 

// 赤外線関係
var IR0Enable = wiimoteState.IRState.IRSensors[0].Found;
var IR1Enable = wiimoteState.IRState.IRSensors[1].Found;
var IR01Enable = IR0Enable && IR1Enable;

var IR0PositionX = 1023 - wiimoteState.IRState.IRSensors[0].RawPosition.X;
var IR0PositionY = wiimoteState.IRState.IRSensors[0].RawPosition.Y;
var IR1PositionX = 1023 - wiimoteState.IRState.IRSensors[1].RawPosition.X;
var IR1PositionY = wiimoteState.IRState.IRSensors[1].RawPosition.Y;

button3.Visible = IR0Enable;
button4.Visible = IR0Enable;
button5.Visible = IR01Enable;


if(IR0Enable) {
    button3.Location = new System.Drawing.Point(IR0PositionX / 2, IR0PositionY / 2);
}
if(IR1Enable) {
    button4.Location = new System.Drawing.Point(IR1PositionX / 2, IR1PositionY / 2);
}
if(IR01Enable) {
    button5.Location = new System.Drawing.Point((IR0PositionX + IR1PositionX) / 4, (IR0PositionY + IR1PositionY) / 4); 
}

先ほどの部分をこのように置き換えることでWiiのポインタのような挙動になります。

 

 

 

 

その他

これでWiiリモコンに関するものは一通り終わりました。

しかし、WiimoteLibで扱えるものはまだあります。

 

ヌンチャク

 

WiimoteLibは様々な周辺機器にも対応しています。

 

例えば、ヌンチャク

 

  f:id:kazujdDR8823:20201208220611j:plain

 

ヌンチャクには、

・ボタン×2 (c, z)

・アナログスティック

・3軸加速度センサ

が入っており、これらもWiimoteLibを使用することでPCから扱うことができます。

 

一つ注意として、ヌンチャク自体に通信をする機能は存在していません。

Wiiリモコンとつなげることによって、はじめて通信できるようになります。

 

使い方の前に、表示用として

Wiiリモコンの加速度と同じようにtrackBarを3つ

・アナログスティックの表示用にhScrollBarとvScrollBar

・CとZのボタンのためにcheckBoxを2つ

を用意しています。

また、hScrollBarとvScrollBarは

 Maximum を 255 に

 Minimum を 0 に

 SmallChange を 1 に

 Value を 127 に

しています。

 

  f:id:kazujdDR8823:20201208194411p:plain

 

使い方は、まずWiimtoeStateを宣言したように、NunchukStateというものを宣言します。

  

  f:id:kazujdDR8823:20201208192816p:plain

 

public NunchukState nunchukState;    // 追加

 

それに加えて、先ほどと同じようにButton1_click()内にあるwiimote.SetReportTypeを変更します。

 

// 接続ボタン
private void button1_Click(object sender, EventArgs e) {
    try {
        wiimote.Connect();  // Wiiリモコンへの接続を行う
    } catch (WiimoteNotFoundException exception){
        MessageBox.Show("Wiiリモコンが見つかりません", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return;
    }

    // Wiiリモコンとの通信モードを設定
    wiimote.SetReportType(InputReport.ExtensionAccel, true);       // 変更部分

    wiimote.SetLEDs(0b1111);    // LEDの点灯

    wiimote.WiimoteChanged += Wiimote_WiimoteChanged;
}

 

ExtensionAccelにすることで、ヌンチャクの状態を取得することができます。

 

そして、UpdateWiimoteChangedの末尾に以下を追加します。

 

// ヌンチャクの状態を取得
nunchukState = wiimoteState.NunchukState;

// 加速度センサ(ヌンチャク)
trackBar4.Value = nunchukState.AccelState.RawValues.X;
trackBar5.Value = nunchukState.AccelState.RawValues.Y;
trackBar6.Value = nunchukState.AccelState.RawValues.Z;

// アナログスティック
hScrollBar1.Value = nunchukState.RawJoystick.X;
vScrollBar1.Value = 255 - nunchukState.RawJoystick.Y;

// ボタン(ヌンチャク)
checkBox9.Checked = nunchukState.C;
checkBox10.Checked = nunchukState.Z;

 

 

これで、ヌンチャクのデータを取得することができます。

 

 

 

バランスWiiボード

WiimoteLibでは、Wiiリモコンに直接つなぐ機器だけでなく、バランスWiiボードも使うことができます。

取得できるデータは

・圧力センサ×4(4隅にある)

・体重

・重心(平面座標の形で取得できる)

です。

 

バランスボードに関しては、今のプログラムに追加する形だとちょっと大変(というかごちゃごちゃしすぎる)なので、参考になるウェブサイトを紹介させていただきます。

 

yamaokuno-usausa.hatenablog.com

 

ちなみに、バランスボードとPCの接続方法は、Wiiリモコンの時と同じ流れでOKです。

 

 

説明を端折る代わりに、以前作ったものなのですが、バランスボードとWiimoteLibを使うとこんなことができるよっていう例を紹介します。

 

(ところどころ音声が乱れています。すいません...) 

 

この動画では、体重移動をマウスの移動に変換し、それで壺おじをプレイしています。

もちろんですが、操作性はクソです。

もしやってみたい人がいましたら、連絡してください笑

 

ちなみにソースコードは人に見せられるものじゃないので、もし欲しい人がいれば教えてください。全力で書き直してから渡します...

 

 

 活用例

ここからは、センサの値を取得するだけでない活用例を紹介します。

また、ここにある例のほとんどは昔作ったものな為、ネタが古いことが多々あります。

ご了承ください。

 

 

マウス代わり

せっかくポインタ的なことができるので、マウスの代わりにWiiリモコンを使ってみましょう。

 

 

流れ的にWiimoteLibで書いたもののように感じるかもしれませんが、WiimoteLibを使っていません。

それどころか自分で書いたプログラムじゃないです...

これはWiinRemoteというソフトを用いて、Wiiリモコンをマウス代わりにしています。

WiinRemoteを使うと、加速度センサの値がグラフで表示されるのでものすごくわかりやすいです。

 

nostalgia.xii.jp

 

こちらのサイトの手順のうち、BluetoothによるPCとの接続に関する部分は、すでに接続できている場合必要ありません。

 

 

魔法みたいな感じなやつ(適当)

まずは動画をご覧ください。

 

 

Wiiリモコンを画面に向けると音が割れるプログラムです。 

 

何が起きているかを説明すると、PCのディスプレイの上に赤外線LEDが置いてあります。

Wiiリモコンを画面に向けると、その赤外線LEDの光がCMOSセンサに入ります。

ということで、普通に曲を流しつつ、赤外線LEDをCMOSセンサが検知している間だけ、割れている曲に切り替えています。

 

ちなみに画面に向けている間、手が震えていますが、その震えに意味はありません。

なんか魔法出してる感を出そうとしてこうなりました。わかりずらっ...

 

 

電動消しゴム

Wiiリモコンにはバイブレーション機能がついています。

このバイブレーション機能を有効活用してみました。

 

UpdateWiimoteChangedの末尾に以下のコードを追加しました。

 

if(wiimoteState.ButtonState.A) {
    wiimote.SetRumble(true);    // 振動スタート
}
if(wiimoteState.ButtonState.B) {
    wiimote.SetRumble(false);   // 振動ストップ
}

 

Aボタンで振動スタート、Bボタンでストップです。

 

このプログラムを活用することで、Wiiリモコンが遊ぶためじゃなく、電動消しゴムがない時の代わりにもなります!!!!!

すごくないですか?!!!!

文字も消せるWiiリモコンってすごいですよね!!!!!!!!

やばいよ!!!!!

マジで!!!!!!!

 

 

 

マウス代わり(2回目)

はい、先ほどはスイマセンデシタ...

どうしようもないクソ枠はさっきので終わりです。

次は(ネタではあるけど)ちゃんとしてます。

 

先ほどバランスボードのところで、体重移動をマウス移動に変換していました。

それに加えて、Wiiリモコンでクリックの操作をします。

クリックは単純にボタンに割り当てるのではなく、加速度センサを使い、一定以上の速度でリモコンを振ったときにクリックの扱いにしています。

 

それを用いてくまのプーさんのホームランダービー!をします。

(今年中で遊べなくなっちゃうの悲しいね...)

 

 

はい...

 

想像の100倍くらい難しいですよこれ...

 

マジで...

 

 

ということで、以上活用例でした。

 

 

まとめ

ものすごく長々と書きましたが、どうだったでしょうか?

もしこの記事を読んで、Wiiリモコンを使って遊ぶ方が増えてくれれば幸いです。

 

もちろん、何か質問などがあれば私に言っていただければ、精いっぱい対応しますので、みなさんもぜひWiiリモコンを使ってみてください!

 

また、今回はWiimoteLibを用いましたが、私は使ったことがないのですがこれ以外にもUnityやProcessing向けのライブラリも存在します。C#だけでない様々な環境でWiiリモコンを使うことができるので、皆さんに合ったもので開発してみてください!!

 

 

以上、kazu8823(twitter:@kazujdDR8823)による「Wiiリモコンっていいよね!って話」でした!!!

 

この記事はFUN Advent Calendar 2020 Part2 9日目の記事でした。

FUN Part2 Advent Calendar 2020 - Adventar

 

明日は 7 さんによる「なんか書きます」です!!お楽しみに!!!