「スコープに宣言がありません」と怒られたらプロトタイプ宣言してみよう
Arduinoでスケッチが長くなってきたら
機能ごとにファイルを分割したりしますよね。
で、コンパイルすると宣言がないと怒られたわけです。
でも
タブを切り替えるとちゃんとある。
実際のスケッチは関数名が長いので、打ち間違えていないか一文字ずつ指差し確認。
でも一致しているように見える。
テキストエディタにコピペして並べてみてもやっぱり同じだ。
おっかしいなぁ.....。
プロトタイプ宣言
見つからないって言うんだから、見つかるようにプロトタイプ宣言してみようか。
(Arduinoはコンパイル時に自動でやってくれるから本来は要らない。)
あっ.......
別のタブの別の関数で、ネストのカッコ閉じを失敗していました。
カッコを直したら
プロトタイプ宣言を削除しても無事コンパイルが通るようになりました。
まとめ
正しく宣言がされているにも関わらずコンパイラに「宣言がない」と怒られたら、その関数をプロトタイプ宣言してみよう。
すると、真の原因が見つかるかもしれない。
おもちゃの修理を頼まれた(アンパンマン掃除機編)
「余計に壊れて復元不能になっても知らないからね!」を条件に、小物の修理を引き受けていたらだんだん 面倒 厄介なモノも持ち込まれるようになってきました。
https://www.amazon.co.jp/dp/B00HFID516/
切れたホースをつなげ
せめてもうちょっと真ん中らへんで切れてくれれば、ビニルテープぐるぐる巻きとかやりようがあるのですが。
ホースの両端はグリップに合わせて成型されており、汎用品を切って使っているのではなく専用品のようです。
接続用のパーツをモデリング
まずは蛇腹ホース。
グリップの中の空間もざっくり採寸。
蛇腹ホースは円筒ボディーをかぶせる。
2つのパーツをロフトで連結。
先端は挿し込みやすいようにテーパをつけて、蛇腹側は結束バンドを巻くための突起をつける。
蛇腹ボディーを引き算して断面をみるとこんな感じ。
挿し込みが固そうなので割り込みを入れておく。
2つに割って完成。
造形
同じものを2個作ります。
組立て
ホースを挟んで
押し込む!
爪も折れることなく入りました。すっぽ抜けないか心配でしたが、かなり固くはまっています。
あとは結束バンド巻いて完成です。
反対側が切れた
直ったと思ったら、ホースの反対側が切れました。
ビニールテープぐるぐるではなくクリアの収縮チューブを使いました。
しかし、かなり蛇腹ホースの劣化が進んでいるようです。またすぐ違うところが切れるでしょう。
おまけ
「おもちゃの音が出なくなった」系の故障は、スピーカーの交換で今のとこ復活しています。(N=3)
https://www.amazon.co.jp/dp/B01I9FBIOE/
スピーカーの抵抗を測定し、断線してそうなら交換。
5年分ぐらい届いたよ!
3Dプリンタでの造形物を三脚に付けたい
3Dプリンタで作ったケースをカメラ用三脚に付けたい
だけどネジ穴をモデリングしてもすぐ潰れてしまいそうです。
ということで思い付いた一案。
カメラネジアダプターをねじ込む
三脚を取り付ける位置に直径 9mm の孔をモデリングしておき、C面も2~3mmぐらい付けておきます。
そこにカメラネジアダプターをねじ込む。
- 出版社/メーカー: ハクバ
- メディア: Camera
- この商品を含むブログを見る
モデリング
NEMA17 ステッピングモーターを三脚に取り付けて
その上で小さなテーブルをぐるんぐるんさせよう。
造形
カメラネジアダプターの取り付け
マイナスドライバーでねじ込んでいきます。
なんとか入った。
まっすぐねじ込むのが難しい
軸をまっすぐに保つのが難しく斜めに入ってしまいます。
めいっぱいねじ込んであれば気にならないけど、ちょっとネジをゆるめて浮かせるとわかります。
幅 10mm の大きめのマイナスドライバーでも、カメラアダプターの溝にギリギリかかる程度でツルっと先端が滑り、PLAの硬さも相まって手こずりました。
本来はネジ穴の大きさを変えるためのパーツですので、タップタイトのように使うには向いていなかったようです。
これだけネジ山が高いとハンダゴテで熱溶着も無理がありそうです。きっと三脚に適合するインチタイプのインサートナットもあると思うのですが、見つけられませんでした。
まとめ
三脚に取り付けたところ、思ったより安定していました。
先端がこんな形状のドライバーがあったら、アダプターの軸を垂直に保ちつつしっかり回せそうです。
3Dプリントした造形物にビットインサートの熱溶着を試す
3Dプリンタで作ったパーツをネジで固定したい
今回は知人が親子でダンボールキッチンを作っていたので、ガスコンロをもうちょっとかっこよくできるかも?と、ツマミとゴトクを贈呈しました。
こちらは完成時。テーブルの高さ 40cm、幅60cmぐらい。
3Dプリントしたパーツの組立てでネジを使う場面は、大抵はネジボスを立ててそこにタップタイトのネジで固定でしょうか。今回は強度に不安があったのでビットインサートの熱溶着を試してみました。
モデリング
ツマミ
上から順に、ツマミ、台座、留め具です。台座を段ボールにボンドで貼って、ツマミを取り付けたら裏から留め具をネジで固定。ツマミはちゃんと90度回って止まる予定。
ゴトク
黄色がゴトクで赤が留め具です。
ボンドや両面テープでの接着だけだとすぐ剥がれてしまいそうな気がしたので、段ボールに穴をあけて裏から留め具でも固定します。
ビットインサートの熱溶着
3Dプリントしたものをタップタイトネジで固定しても、すぐに割れて外れてしまいそうな気がします。そこで、ビットインサートを熱溶着してコネジで固定します。
今回使ったビットインサートはこちら。
国産 黄銅 ビットインサート フランジ型 M3xD1=4.5xL2=5.0 60ヶ入 HFB-3001
- 出版社/メーカー: ウィルコ
- メディア:
- この商品を含むブログを見る
Φ4.5mm の下穴をあけておき(ビットインサートの径より少し小さい)
ビットインサートをあてがって
300℃のハンダゴテでぐぐっと押し込む。熱せられたビットインサートがプラを溶かしながら埋まっていく。
3Dプリントの素材は PLA なので、300℃では温度が高すぎたようです。
白光FX600 なら下は200℃まで下げられるので、めいっぱい下げると良いかもしれません。
うまく付いたように見えましたが
裏から見るとはみ出ちゃってる!しかも溶けたPLAのくずが中に入り込んでしまいネジが入りにくい。
裏から留め具を付けるとこんな感じです。
ツマミもゴトクと同様にビットインサートを熱溶着してボンドと留め具で取り付けます。
牛乳パックを積み上げて骨組みを作り、段ボールで壁をつくり、その上に壁紙のようなシートを貼っているそうです。流し台も内側にアルミテープを貼ってピカピカ。廃材で作った割にオシャレに仕上がっています。
まとめ
3Dプリンタで作った物をネジで組み立てるのは、タップタイトネジでは強度や割れの心配があったが、インサートナットの使用で使い勝手は良くなる。
インサートナットの内側にハンダが付くとネジが入らなくなるので、コテ先は未使用品が良い。コテ購入時に付属していた円錐形のコテ先が未使用のまま残っていたので今回はそれを使用。
インサートナットを差し込む方向がネジとは逆方向からだと、インサートナットの中に溶けたプラのくずが入り込んでしまいネジが入りにくくなってしまった。インサートナットはネジと同じ方向から差し込むのが良さそう。
ツマミ側はネジと同じ方向からインサートナットを入れたのでネジの入りはスムーズで問題なかった。
プラの素材がPLAだったので、ハンダゴテの温度が300℃は高すぎた。すぼっと軽く入ってしまい、やや傾いてしまっている。
ツマミを回しきったときのクリック感が欲しくなる。
お子様にも気にいってもらえたようで何よりです。
ガーバーのファイル名をまとめて変える
KiCadから出力したガーバーを
Elecrow とか FusionPCB に送るためにファイル名を変えるとき、1個ずつファイル名を変えてませんか?
batで自動化している人もいるようですが
Windows標準の機能でまとめて変えることができます。
一番上のファイルを選択し、
Shift を押しながら一番下のファイルを選択。
このとき Ctrl + A でまとめて選択するとうまくいきません。
F2キーを押し
揃えたいファイル名を入力
そのまま Enter すると、
拡張子より前は全部同じファイル名になりました。
ファイルを選択するときに Ctrl + A で選択すると
F2キーでファイル名を変更しようとしたとき、一番上のファイルを変更する状態になります。すると、そこは既に変更後に設定したいファイル名なので、あらためて同じファイル名を入力しても何も変更されません。もとのファイル名と違う名前にすればまとめて変更されます。
まとめ
ドリルと基板外形の拡張子変更は、2個だけなので手動で変更しましょう......
ミニマルな自作キーボード
自作キーボードが流行って2年ぐらい経つでしょうか。私もちょっとだけ、かじってみようと思います。
きっかけ
ある知人のノートPCがカンマとピリオドがキー入力を受け付けなくなり、ショップに修理を頼んだら見積もりが2万越えだったようです。
安いデスクトップ用のキーボードつないでしのぐことにしたようですが、実際に使っているところを見るとかなり邪魔そうです。
そうだ、効かなくなったカンマとピリオドだけのキーボードなら邪魔にならないかも。
回路図
ProMicroにスイッチをキー入力用2個とリセット用1個つけただけです。キーボード用ではなく手元にあった汎用のタクトスイッチを使いました。
スイッチマトリックスではないのでダイオードは要らないし、プルアップ抵抗もINPUT_PULLUP
で内部プルアップさせ部品点数は思ったより少ない。
12セグメント基板で余ったフルカラーLED の WS2812B も4個付けてあります。
基板アートワーク
A面
B面
今回使うスイッチは裏側にガイドボスの出っ張りがあるのですが、KiCad に初期導入されている12mmのタクトスイッチのフットプリントはガイドボスが入る孔がありません。
そのまま使うと残念なことに。というか、KiCad でフットプリントの3D 表示させたらまさにそういう状態に配置されてて笑う。
海外メーカーの安いスイッチはガイドボスが無い物もあるのでそれを使うのも有りですが、パネルを取り付けるので位置をしっかり出したかったのと、試しに買ってみたらパッチンパッチン安っぽいクリック音がうるさかったのでやめました。
ガイドボタン用の孔を追加したフットプリントを作ります。
基板サイズが基板屋さんの指定する最小サイズより小さいので面付けして発注します。
パネル
基板むき出しだと使いにくいので上面と下面だけアクリル板のパネルを取り付けます。基板CADが吐き出したDXF に重ねるようにパネル外形と孔を描いていきます。
細かい寸法を入れていったら、微妙にズレているではないですか。
上パネルは上下が非対称、下パネルは左右が非対称。しかもぱっと見ただけではわからない微妙なズレ。組み立てるときに逆向きに取り付けて「なんか精度悪くね?」となるやつです。
基板の外形はミリのグリッドに乗せ、部品の配置はミル(インチ系)のグリッドに乗せたので、スイッチを中央に置いたつもりが微妙にズレたようです。
コネクタやICなどの部品はインチ系が多いので、部品を配置するときはグリッドをミルにすることが多いのですが、パネルに関係する部品はミリ系で配置しないといけなかったですね。
ズレていても良いのですが、その場合は組立て時に上下左右裏表が判りやすいよう目印をつけておきたかったです。この場合だと、1か所だけカドのRをC面にするとかでしょうか。
気付いたのが発注後だったので、このまま作ります。
10cm×10cmの正方形から2セット取れます。発注単位が5枚なので10台分。思ったよりたくさん取れました。基板も面付けして40台分あるのですが..... 配っても邪魔になるだけですね。
入荷
組立て
ProMicro の泣き所、「表面実装の Micro USB がもげる」の対策として、コネクタを上から押さえるだけの基板を作り、ピンヘッダに重ねてハンダ付けしています。どの程度強度アップしてるか試してないけど、無いよりマシかな?
スイッチとキートップ
Arduinoスケッチ
#include "Keyboard.h" #include <Adafruit_NeoPixel.h> #define NUM_KEY 2 // 使用するキーの数 #define PIN_PIXELS A0 // WS2812B を接続するピン #define NUM_PIXELS 4 // WS2812B の数 Adafruit_NeoPixel pixels(NUM_PIXELS, PIN_PIXELS, NEO_GRB + NEO_KHZ800); const uint8_t PIN_KEY[NUM_KEY] = {2, 3}; // キーを接続したピン番号 const char FUNC_KEY[NUM_KEY] = {',', '.'}; // キーに割り当てる文字 const unsigned int INSENS = 5; // チャタリング対策の不感時間[ms] /* キーを押すごとに変化するLEDの色 */ const uint32_t rgb[] = {0x7F0000, 0x007F00, 0x00007F, 0x3F3F00, 0x3F003F, 0x003F3F, 0x3F3F3F}; void setup() { for (uint8_t pos = 0; pos < NUM_KEY; pos++) { pinMode(PIN_KEY[pos], INPUT_PULLUP); } Keyboard.begin(); pixels.begin(); pixels.clear(); write_pixels_switch(); pixels.show(); } void loop() { key_scan(); } void key_scan() { static boolean prev_key[NUM_KEY]; static unsigned long prev_press_time[NUM_KEY]; // 前回キーを押した時間(チャタリング対策用) static unsigned long prev_release_time[NUM_KEY]; // 前回キーを離した時間(チャタリング対策用) /* キーの状態を順番にスキャン */ for (uint8_t pos = 0; pos < NUM_KEY; pos++) { boolean key = digitalRead(PIN_KEY[pos]); unsigned long time = millis(); /* キーを押したとき */ if (prev_key[pos] == HIGH && key == LOW) { if (time - prev_press_time[pos] > INSENS && time - prev_release_time[pos] > INSENS) { Keyboard.press(FUNC_KEY[pos]); prev_press_time[pos] = time; write_pixels_switch(); pixels.show(); } } /* キーを離したとき */ if (prev_key[pos] == LOW && key == HIGH && time - prev_press_time[pos] > INSENS) { Keyboard.release(FUNC_KEY[pos]); prev_release_time[pos] = time; pixels.show(); } prev_key[pos] = key; } } /* LED の色を切り替える */ void write_pixels_switch() { static uint8_t rgb_pos = 0; for (int i = 0; i < NUM_PIXELS; i++) { pixels.setPixelColor(i, rgb[rgb_pos]); } rgb_pos = (rgb_pos + 1) % (sizeof(rgb) / sizeof(rgb[0])); }
今回キーは2個しかありませんが、マトリックスにしない限りキーが増えても最小限の修正で済むように作りました。
#define NUM_KEY 2 // 使用するキーの数 const uint8_t PIN_KEY[NUM_KEY] = {2, 3}; // キーを接続したピン番号 const char FUNC_KEY[NUM_KEY] = {',', '.'}; // キーに割り当てる文字
試してないですが、ここの3行を書き換えるだけでキーを増やしたり割り当てを変えたりできるはずです。
無駄に光るよ
キーを押すごとに色が変わる。なんとも鬱陶しい。
使用感
- 汎用スイッチはタッチ感が良くないので特殊キーには良いかもしれないが文字キーには向かない。
- ノートPCのキー入力が効かなくなったせいで、句読点を「まる」「てん」から漢字変換して入力するのよりは使いやすくはなる。
- シフトを押しながら押せば、ちゃんと 「<」や「>」が入力できた。
- マクロ用として使うなら良いかもしれない。
- キーにマウスクリックの機能をアサインしようとしたが、
#include "Keyboard.h"
と#include "Mouse.h"
は同時に使えないらしく動かなかった。
部品代
品目 | 金額 | メモ |
---|---|---|
ProMicro | 約1000円 | 1個 1台分 |
基板 | 約600円 | 4枚取り×10枚で40台 |
パネル | 約700円 | 10台分 |
基板とパネルの送料 | 約2000円 | |
LED (WS2812B) | 約50円 | 4個 1台分 |
スイッチ | 約200円 | 2個 1台分 |
キートップ,キーカバー | 約60円 | 2組 1台分 |
六角スペーサー | 約1000円 | 8本 1台分 |
反省点
- もっと小さくしたかった。特に厚み。(現在 27mm)
- 上下のパネルが 5mm厚なので、薄くしても良さそう。
- パネルの向きがやはり組み立てる時に迷う。完全に対称にするか、目印を付けたかった。
- しかし、試しに逆向きに取り付けてみたところ、特に違和感なかった。
- 基板に ProMicro の取り付け向きをシルクで表示するのを忘れた。
- 基板にM3のネジ孔がスペース的に入らなかったので M2.6 で設計したが、M2.6 は安価な六角スペーサーが見つからず高く付いた。M2でも良かったかもしれない。
- キーボード用スイッチを使わず汎用スイッチを使ったので、キートップと透明のキーカバーの間に紙を挟むだけでキートップの印刷を自由に作れる。
まとめ
製作のきっかけとなった知人の反応
「そういえばスラッシュのキーも壊れてたんだっけ。」
12セグメント カナフォントをハード化する
写真で見ると文字が白とびしちゃうので露出補正で暗くしていますが、実際は明るい部屋でも綺麗に表示されます。
3ヶ月前ぐらいに見かけたとあるツイート
突然脳がなんかを受信して、こんな12セグメントのカタカナのフォントを思いつきました
— ByNEET (@ByNEET) 2019年1月7日
読めるか読めないかギリギリのライン。 pic.twitter.com/WN5AAEAu7z
やってみよう
回路図
当初、8ビットシフトレジスタ 74HC595 を2個使い、各セグメントを2個のLEDで点灯するよう回路図とアートワークを作ったのですが、どうせこれカラー表示したくなるよね、ということで WS2812B に変更。
基板1枚に WS2812B を24個(各セグメント2個×12セグメント)。数珠つなぎになった信号線の両端にコネクタを配置し、基板同士を連結できるようにします。
基板アートワーク
基板外形
基板が安く作れる最大寸法 100mm×100mm に収めます。
A面
B面
部品が15°単位で傾いているのでグリッドをかなり細かくしないと思い通りのところに置けません。
基板入荷
A面
B面
この12セグメントの表示形式に名前は付いていないようなので、基板名は SnowCrystal としました。
部品実装
スペーサー
各セグメントの形状を出すためのスリット兼LEDの光を均一にするスペーサーです。
高さは 10mm, 15mm, 20mm の3種類を試したところ、15mmが良さそうでした。
3Dプリンタで出力。基板に重ねてネジどめ。
Arduino で点灯させる
スケッチの一部
#define NUM_DIG 5 // 接続した文字数 #define NUM_SEG 12 // ディジットあたりのセグメント数 #define NUM_PPS 2 // 各セグメントに使用するWS2812Bの数 Pixels Per Segment #include <Adafruit_NeoPixel.h> Adafruit_NeoPixel pix = Adafruit_NeoPixel(NUM_PPS * NUM_SEG * NUM_DIG, PIN_PIX, NEO_GRB + NEO_KHZ800);
dig番の文字の seg番のセグメントを rgb色 にセット
void set_seg(uint8_t dig, uint8_t seg, uint32_t rgb) { for (uint8_t i = 0; i < NUM_PPS; i++) { pix.setPixelColor(NUM_PPS * NUM_SEG * dig + NUM_PPS * seg + i, rgb); } }
dig番の文字に patternの文字を rgb色 にセット
void set_dig(uint8_t dig, uint16_t pattern, uint32_t rgb) { for (uint8_t seg = 0; seg < NUM_SEG / 2; seg++) { set_seg(dig, seg, pattern >> (13 - seg) & 1 ? rgb : 0); } for (uint8_t seg = NUM_SEG / 2; seg < NUM_SEG; seg++) { set_seg(dig, seg, pattern >> (11 - seg) & 1 ? rgb : 0); } }
フォントを作る
const PROGMEM uint16_t font_map[256] = { 0, // 0 0, // 1 /* 中略 */ 0, // 46 0, // 47 B000111 << 8 | B100100, // 48 0 B000001 << 8 | B100100, // 49 1 B101101 << 8 | B010010, // 50 2 B101101 << 8 | B011000, // 51 3 B000010 << 8 | B100110, // 52 4 B101100 << 8 | B101000, // 53 5 B101111 << 8 | B001010, // 54 6 B000011 << 8 | B100100, // 55 7 B101101 << 8 | B011011, // 56 8 B111101 << 8 | B010001, // 57 9 /* 中略 */ 0, // 175 0, // 176 B100001 << 8 | B110100, // 177 ア B000000 << 8 | B010110, // 178 イ B011010 << 8 | B110001, // 179 ウ B001100 << 8 | B010101, // 180 エ B000000 << 8 | B110111, // 181 オ B010000 << 8 | B110110, // 182 カ B100001 << 8 | B101110, // 183 キ B100001 << 8 | B010010, // 184 ク B000011 << 8 | B001101, // 185 ケ B000100 << 8 | B000101, // 186 コ B000010 << 8 | B110110, // 187 サ B101100 << 8 | B000001, // 188 シ B000001 << 8 | B101100, // 189 ス B001000 << 8 | B110110, // 190 セ B011000 << 8 | B000001, // 191 ソ 0, // 192 0, // 193 /* 中略 */ 0, // 254 0, // 255 };
1バイトカナ文字(半角カナ)を Serial.println()
すると戻りは3バイトなので、下位1バイトを使って font_map
の配列からパターンを取り出す
uint16_t font(byte ascii) { return pgm_read_word(&font_map[ascii]); }
byte code = 'ア'
としたときに、「ア」の下位1バイトだけ取り出して変数 code に代入してくれれば良いのですが、narrowing conversion
のエラーが出るPCとコンパイルが通るPCがあります。キャスト面倒だから通して欲しいんだけど何が違うんだろう?
紙を被せて完成
2mmの白いアクリルでは、滲んでピンボケみたいになってしまいました。
アクリルをコピー用紙に変えたらシャキッと表示できました。
まとめ
while 文の無限ループが含まれているのでスケッチの全文公開はやめとこ(笑)
フォントのパターンは、こちらのブログで紹介されているものを再現しています。
12セグメントカタカナフォント|ニートが頑張るブログ