姿勢制御機能付き球体Lチカを作ろう ②
LEDディスプレイ
①からの続きtajmahal0707.hatenablog.com
キューブ型LED型ディスプレイ試作
上記のadafruitのLEDディスプレイ。
基本は文字を表示することを主眼においています。
私の目的は画像ですから、やはりもうちょっと解像度が欲しいのと、フレームが邪魔で見づらい。
そこで自作してみます。
5050(左側)は、1辺が44.5mm、LED間隔は5.5mmピッチ。8x8で64LEDが6面の合計384LED。
2020のものは1辺が27.5mm, LED間隔は3mmピッチ。LED数は9x9で81LEDが6面の合計486LED。
この基板を起こしてLED実装してみました。
テストだ! えい!
自作9x9のRGB LED基板に実装。brightness変えても明るさが変化しない。。
— yakatano (@Yakatano) 2023年1月15日
Ws2812-2020 ってFastLEDのbrightness関数使えないんだっけ。。。それともWS2812Bじゃないとダメとか? pic.twitter.com/mdk7qTngL8
コンデンサは裏側に配置するようにして、前面はツメツメのLED実装としてみました。なかなかいい感じ。
これを立方体にするために構成を考えてみます。
ちなみに今回はLEDにWS2812(NEOPIXEL)を使用しています。前回のPOV neonはAPA102系(DOTSTAR)で配線の数が少ないのですが、POVのように高速で表示を切り替える必要がないため、このような節約も可能となっています。
homemadegarbage.com
Neopixelのリフレッシュレートが400Hz
Dotstarのリフレッシュレートが1.9kHz
POVでなければneopixelのリフレッシュレートで十分と考えています。
次はこれを立方体に構成する方法を考えます。
キューブ型LED型ディスプレイ構成
この基板を立方体に配置するための構成を考えます。フレームを入れてしまうのであれば、これでも良いことになってしまうので、なるべくフレームは見えなくしたい。
そこで完全に基板だけで立方体が作れるようにしました。
こんなふうに。
最後に3枚x3枚をマグネットで固定しようと思ったわけです。
マグネットを電極にして、信号のやり取りができないか、、、、と。
ハンダに砂鉄を混ぜてみたり、磁石をはんだ付けしようとしたり。。。。いろいろ格闘したのですが、なかなかうまく行きません。
実験:磁石に付く電極を作りたくて、はんだペーストに鉄粉混ぜてみた。→結論:ハンダと鉄粉が分離してしまう。ほんの少しだけ磁石に付く感じ。。鉄板をハンダ付けかな。 pic.twitter.com/0PpaY9t95m
— yakatano (@Yakatano) 2023年1月16日
結果、思った以上にうまく行かず、この計画は頓挫します(ここまで書いて頓挫かいw)
じゃあ、なんで書いたかって? せっかく作ったのにお蔵入りするのが可愛そうで供養したかったからですw
正12面体試作
- そもそもキューブだと球体というには少々無理がある。。。
- LED数が400満たないので、少々絵を出すには足りないのでは。。。。。
ということで、もっと面数を増やして球体に近づけ、なおかつLEDを増やし解像度を上げていこうとなったのでした。cube(正6面体)でやるにしてもフレーム設計して、基板や電池の収まる配置を1から考えないといけないならもっと理想に近い形を実装したい。。。ということですね。
ja.wikipedia.org
多面体には正四面体、正六面体、正八面体、正十二面体、正二十面体の五種類があります。
[https://ja.wikipedia.org/wiki/%E6%AD%A3%E5%A4%9A%E9%9D%A2%E4%BD%93:title=]
また、なぜ正多面体じゃないといけないんだ?という話もあります。これはごもっともで、サッカーボール多面体(切頂20面体)でも良いはずです。こちらの方が球に近い。
ja.wikipedia.org
これは純粋に金銭的効率の問題ですw
5角形と6角形の2種の基板をおこすならば、同じくらい球に近い正多面体があれば、そちらで注文すべきだと思いませんか? 私は思います。
というわけで正多面体の選定。
正4面体、正6面体は根本的に今回採用できない。正8面体もちょっと球と呼ぶには寂しい。となると12面体か、20面体、ということになります。
で、正20面体だったら切頂20面体でよくね?となりませんか?
となると切頂20面体 vs 正12面体。
正12面体の最適球配置
正12面体でLEDを配置する場合を考えます。想定したものはLED600個。五角形一枚あたり50個のLEDのを配置する計算です。
球表面上に最密でボールを充填する問題を考えます。球の表面なので2Dの充填問題となります。
sgk2005.blog.fc2.com
ja.wolframalpha.com
球表面に球体を充填する問題設定は探してもあまり見つかりませんので、自分で色々試行錯誤してみました。理論的に6角形の最密充填は任意のn個の点について計算することはできません。基本六角形で充填し、ところどころ5角形になるイメージです。
いろいろと調べてみると解析的に求められる方法は少なく、いくつか試してみました。
問題を定義してみると、下のようになります。
- 直径80mmのコア球表面に600個のボールを充填
- 充填球の直径は最適になるように変更可能
一般化螺旋集合
擬似的ですが解析的に求める手段として「一般化螺旋集合」を用いた方法があります。
blog.panicblanket.com
このあたりを参考にUnity上で螺旋配置するプログラムを書きました。
www.youtube.com
なかなか良さげなのですが、ちょっとランダム味が足りない。
どうゆうことかというと、コア球体表面に配置したボールに規則性がある(特に北極南極などの極点)とヒトの眼には目立ってしまい、回転していることが見破られやすくなってしまうのです。どこが極点なのかわからないのが理想。
そこで探索的な手法でも充填問題を考えます。
探索的球充填
一番シンプルなアイデアです。
Unityを使ってシミュレーションを実行します。剛体のコア球表面に剛体のボールを600個配置して、お互いがぶつかりながら細密になるように配置したものを逐次的に計算する、というものです。
コア球に重力を設定し、すべてのボールがコア球表面・隣のボールとも接触している状態を作り、それができない場合にはコア球とボールの半径を調節してちょうどよい状態を作ります。
www.youtube.com
こうすることで、ところどころ隙間はありますが回転させても極点がわからないランダム配置を作ることができました。
voronoi球体の設計
上記の方法から球面上に擬似的に均等配置された球上の点をもとに球表面をボロノイ分割します。
研究レベルだとこのようなものもあるようです。
多面体を用いた球面上の点配置の解析とその応用
具体的にはこのようにオブジェクトをボロノイ分割するような手順はいくつかあり、これを使って分割していきます。
www.thingiverse.com
作業はblenderで行います。
たとえばこんなの
note.com
このあたりも参考にしました。
www.youtube.com
出来上がったものがこれ
わかりますかね?ほとんどが6角形を形成しているところに一部だけ5角形になっています。面白いのは5角形を形成する部分だけ取り出してみると比較的均等になっていることがわかります。探索的にやったのに面白い。
これをベースに正12面体の一面ごとに5角形の形で12分割していきます。
左は正6面体に適用したもの。右が正12面体に適用したものです。
正6面体だとやはり周辺部でかなり傾斜がきつくなっており、中心との光路差も大きくなってしまうことがわかります。だからやっぱり正12面体かな。
正12面体基板
正12面体基板はこのように設計しました。
球体の時と同じ手法で五角形に最密充填で50個の球を配置します。これを配線してPCBGOGOに発注をかけたものがこちら
ここの基板上の丸(直径5mm)からコア球表面の穴まで繋げて、球体全体に映像を提示できるように考えています。(間に合わなければ、最終的には外側のコア球がなくてもなかなか面白いガジェットにはなりそうですw)
③につづく
姿勢制御機能付き球体Lチカを作ろう ①
はじめに
2015年から球体ディスプレイを作成しています.
もともとのアイデアは2015年のハッカソンから始まって現在まで開発を進める中,MakerFaireTokyo(以下MFT)2022でも展示させていただいてきています.
www.youtube.com
MFT2022は同じ球体ディスプレイ仲間の やまたい さんとの共同出品でした。
シャフトがまた折れたりとトラブルありましたが、動くようになりました!#mftokyo2022 #makerfairetokyo2022 pic.twitter.com/wRCrStxysU
— yakatano (@Yakatano) 2022年9月4日
このときに作っていた球体ディスプレイはPOV(Persistent Of Vision)という原理で動作していたものです。
en.wikipedia.org
原理はこの動画のように
www.youtube.com
ブレード状のLEDを回転させながら点滅させることで残像効果を使って映像を出力できるものです。
このブレードを
www.youtube.com
曲面に配置して回転させることで球面状に映像を出力できるようにしました。
この方法は、LEDを少なくすることで消費電力を抑えながら回転させることで解像度を上げることができることが利点です。このPOV neonは50個のLEDを一回転を120分割して映像を出力することで、50個のLEDだけで50x120=6000pixel分の画像を表示することができるのです。その一方で、モーターの制御や高速回転するLEDを正確に高速に制御する技術が必要です。
2022年はPOV neon finalと位置づけてPOV形式のneonデバイスの開発を進めてきました。
tajmahal0707.hatenablog.com
上でも示したようにフルカラーで映像を呈示できるようになり、かなり楽しい工作になりました。
しかし、neonとして機能が実装できていないものがあります。 それが
姿勢センサによるディスプレイの天地制御
です。こんな感じ
これでコンタクトジャグリングやったら面白いだろうなと前から思っていたんだけど,値段を調べてみたら結構高い.https://t.co/VvRSHx8QM7
— TESSY (@ytessy) 2023年2月11日
www.youtube.com
(。。。。。ちなみにこれ3万以上するんですよ。。。落としたら一発アウトだし)
液体に浮いたコンパスなどもコレですね。
今回実装したいのは、このように外殻のボールを回転させても中の模様(コンパスやら地球儀やら)が動かない機能のことです。(これって名前なんていうんでしょうね。。。知っている人いたら教えてください。)この機能を電子回路で実現できないか、というチャレンジになります。
姿勢センサを用いた天地判定
ソフトウェア
実はソフトウェア部分はすでに完成しています。
tajmahal0707.hatenablog.com
前記事を要約すると、
センサより獲得できる quaternion を として、球面上の点 をquat分回転した球面上の点のの座標を 、をテクスチャ上にマッピングした座標値を 定義します。
まず、
で を球面上で原点周りに回転させ、その位置をuv座標にマッピングする式は以下のようになる。
ここで や など重そうな計算が出てきます。すべてのLEDの回転に対して一つづつ計算していくと馬鹿にならない計算量になってしまい、演算が間に合わなくなってしまいそうです。
近似計算
neonはマイコンにESP32を採用しており、このESP32はディアルコアで浮動小数点演算を行うコプロセッサがあるためfloatの計算は速いようです...
といいつつ,探していたらこんな記事も見つけてしまいましたが..
esp32にFPU(浮動小数点演算装置)はあるけど有用性は微妙っぽい。残念w
t.co— mはげ (@Tw_Mhage) 2017年5月6日
しかし最近はS3も出て演算能力が上がり、高速化が期待できます。試してみましょう。
lang-ship.com
過去には わたこさんのwebページ でもESP32の演算能力について分析されています。
watako-lab.com
以下に検証に使った簡単なプログラムを置きます。
github.com
試験に使ったESP32-S3はXIAOのものを使用
www.sengoku.co.jp
arctanの近似
やっぱりarctan 重いですね。
そこでまずはarctanの計算について近似計算と関数演算とをESP32上で比較します.
比較対象はmath.hのatan2と以下のサイトにあった近似計算(_atan2)です.今回は4次の近似式を使います。
garchiving.com
を20万分割して20万回atan2を演算した結果をmicrosecで計測します。
もっと厳密に計算したほうが良いでしょうが、概要を捉えるのにはこれくらいで十分かな、と。
結果は_atan2が勝利。atan2 が1回あたり2.09 usecなのに対して、_atan2 では0.00001 usec。かなり差が付きましたがどちらも早い感じ?
sqrt の近似
同じようにsqrtもやってみます。
このような近似式があります。ここでは4次収束のものを使用(_sqrt)。
www.finetune.co.jp
前にESP32-S2(M5stack)でやったときには差があまり出なかったのに、今回は結構出た?
sqrt (math.sqrt)の計算が1回あたり15 usec。
_sqrt(近似計算)の計算が1回あたり4.4 usec となりました。
これも使ってもいいかも。
まとめ
このように近似計算を行うことで姿勢の変化に対してテクスチャの座標をマイコンレベルでも高速に変換することができるようになってきます。POV neonだと6000回の演算が10fpsくらいの速度で更新する必要があります。
そこで今回はちょっとLED数を減らして実験をすることに。
今回はこの機能の実装をメインに考えているので、POVではなくLEDディスプレイベースのこれを参考にしてみました。
learn.adafruit.com
これだと8x8のLEDアレイをcubicに配置(6面)なので、64x6=384 LEDとなり演算的にはかなり楽になりそうです。
球体POV neon final
はじめに
2015年から球体デバイスを作成しています.
もともとのアイデアは2015年のハッカソンから始まって,MakerFaireTokyo(以下MFT)でも展示させていただいています.
初代は
下はそこからパターンをきれいに表示させることができるようにLEDの数を増やしたもの
と,ここまで来るとLEDの消費電力など限界が見えてきたにも関わらず,ある欲求が首をもたげてきます.
これで絵を表示したい!
....という話は
こちらで語っていますので,こちらではPOVに移行してからのお話を...
今回の球体POV
2018年から球体デバイスをPOV化した取り組みを行ってきており,現在第3世代が進行中です.
今年はfinalの年と位置づけて,完結を目指しています.
POV=バーサライタとは一列に並べたLEDを高速に移動させ,残像現象を利用して映像を表示するディスプレイです.映像を呈示するのに大量のLEDを用意する必要がなく小型・低消費電力化できる点や,回転体(今回の球もそう)であれば立体的な映像表現が可能になる点が利点となります.
第2世代(2019)では
ここまでできていましたが,いくつかの問題点が未解決なのでした.
特に重要なのが次の2点.
- LEDがフルカラーで表示することができなかった
- 姿勢センサが機能していなかった
俺,ここを解決して完結するんだ...(死亡フラグ)
そしてこの課題解決に加えて,
- M5Stack基板 → オリジナル基板への変更
- それに伴う構造部分の再デザイン
という大きな設計変更を行っていきます.
全体デザイン
球体ディスプレイ「neon」は直径10cmとかなり小型のディスプレイです.
このサイズはこのプロジェクトの元々のモチベーション「映えるジャグリングデバイス」が出発点となっていることから由来しています.
私はジャグリングの中でも「コンタクトジャグリング」という種類のジャグリングを練習しており,このボールがディスプレイだったらステキだ,と思ったのが開発のきっかけです(このあとジャグリングよりも電子工作にのめり込んでいったのですが...)
このボールにいろいろな映像が表示され,なおかつ転がしても映像が回転しなかったらどうでしょう?
ステキだと思いませんか?
このボールの直径が基本10cmなのです(もちろんサイズ違いもあります).
そのため
- 手の上に乗るサイズ(10cm)
- ボールとして転がすことができる構造(ボールの外側には何も無い状態)
- 回転しても全面がディスプレイになるレイアウト
が「neon」ではとても重要な要素となるのです.
そのために基板・バッテリー・モーター・センサなどのユニットはすべて回転するLEDよりも内側に収納する必要があります.
基本構造の模式図を以下に示します.
以後の用語は上の表記を用いて説明します.
この図で言うと,回転するのは,④ベアリング,⑥LED基板,⑦スリップリングが回転し,それ以外は静止しているレイアウトになります.
最終版「neon」のコア部分はこのようになっています.
いろいろ装飾が入っていますが,おいおい説明していきます.
回転部分の設計
回転部分は上のようになっており,
厚さ5mm(内径90mm)透明の外殻の内側にLEDが配置されるリング状の基板(外径84mm,内径77mm)があり,回転軸には上部にモーターモジュールが配置されてます.回転部分はモーターの回転を受けるギヤがついており,外殻とコアを繋ぐシャフト内には外部からの給電用電源線が通っています.
この部分が唯一映像が表示されない部分であり大きな欠点ではありますが,片持ち梁で回転体の根元を支えることで反対側では隙間なく映像を表示することができるようになっています.
下部にはスリップリングという部品が配置されています.
今回のように回転体にLEDが配置されている場合,そちらへの給電・信号を伝達する必要があり,そのようなバーサライタの方式にはいろいろなタイプがあります.
「neon」はこのページいうところの3の手法を採用しています.
理由は,球体の中に閉じ込めて転がしたりすることの特性上,回転体の重量が大きくなるとジャイロ効果によって本体の転がり回転をバーサライタの回転が邪魔することで,まっすぐ転がらなくなってしまうためです.
実はそのために外殻の厚みをわざと厚く取っています.外殻とコアの重量を重くすることで全体に対する回転体の重量比を圧倒的に小さくします.そうすることで回転体のジャイロ効果を相対的に無視するような方針を取っているのです.
しかしこのスリップリングには欠点もあり,
- 耐久性が低い
- 回転に伴うノイズの発生
- 高回転に使える製品が少ない,高価
- すぐ欠品する...
私の採用しているスリップリングは下記のaliexpressで$15くらいで購入した製品ですがすでに欠品で画像のみ残っていました(もう購入履歴のリンクも無くなっていました...)
今回はこのスリップリングを採用しますが,今後のために代用品を探しておかないといけません.
現時点で1000rpmに耐えて,超小型のスリップリングには下記のものがあります.
MMC118は250rpmまでですが,高耐久・軍用のMMC1189は1000rpmまで使えます.しかし値段が......
ということで引き続きwatchは続けます.
最近いろいろな方がスリップリング採用していて,普通のスリップリングを1000rpmあたりで使用してもノイズは出ないようです.
もちろん耐久性は下がってしまうのでしょうが...
シャフト
シャフトは強度に直結するので,3Dプリンタではなく金属(真鍮もしくはアルミ)で作成したくて旋盤で加工しています.
個人での開発において,この真鍮やアルミの金属加工はとても敷居が高かったです.私自身は機械工学科出身なので授業で旋盤を経験していたりしたのですが,そもそも旋盤を個人が扱える場所がほとんど無い状態です.
以前はTechShop Tokyoで旋盤が扱えたのですが,どんどん閉鎖していっています.
今もまだ探しているので,良い場所があったらアドバイスいただけると嬉しいです.
外部との接続部分も難しいところで第一世代の当時からずっと悩み続けていました.
第一世代はオーディオ用の4極ジャックを使ってUSB microの配線をコアに導入してそのままM5stackに接続していました.
これはこれでも良かった(4chなのでUSB2.0の信号がそのまま導入できるため,そのままarduinoIDEなどでコンパイルしたものをM5stackに転送できた)のですが,プラグがズレたり何よりシャフト径8mmに対してジャックの外径も8mmとなってしまい,うまく収まらないのが課題でした.シャフトに内ネジ切ってジャックのネジをはめ込んで固定しようと思ったのですが,そうすると外殻とのネジ深さが減ってしまい,強度的に問題があったのです.
そこで今回は外部との接続は電源2極のみのマグネット型にしました.
今回採用したものはこちら
調べた限り雌側コネクタの径が最も小さい(4.9mm)商品だと思います.上の2.5mmピンジャックがφ6だったので,8mmのシャフトを想定すると肉厚が1mm程度(そこからさらにネジ溝を切るのでもっと肉厚は薄くなる)
これがシャフト内にφ4.9のコネクタが設置できて内径に余裕ができたので,シャフト肉厚が増えることから強度も上げることができます.
なにより磁石で「パチン」と留まる感じがキモチイイw
コア
コアには,
- メイン基板・モジュール基板
- LiPoバッテリー,電源管理基板
- モーター
- 回転量を計測するホール素子
が収納され,シャフト・スリップリング同軸に配置する構造体の役割を持ちます.
各基板サイズが37x25mmとなっており,これを内部に収納できるようコアの直径を55mmに設定しました.
コアの内部にピッタリ
電池も中に収納します.
コア径は55mmですが,そこから回転体の回転量を計測するためのホール素子と磁石を設置します.
第2世代はコア部分が円筒で,端が回転体ギリギリのところにあったので,ホール素子を回転体ギリギリの位置に設置できたのですが,今回はかなり空間に余裕があり,ホール素子を取り付ける部分が課題になっています.
そのためにコアの外側に飾りを取り付けています.
コアと飾りを分けている理由は,バーサライタの重要な特徴の一つは透過性なのです.画像が生成される面の後ろが透けているのが映像の浮遊感を産むので,コアはより小さいほうが画像面の後ろ側が見えると考え,なるべく後ろの透過量を増やしているのです.
とはいえ,透過した先がテクスチャのある飾りであれば透過した感じを観察者は感じてもらえるのでは,ということでツルッとした面ではなく,凸凹のある飾りをいれてみました.
最終的にどちらが良いか判断して,形状を決めようと思っています.
これらの構造物は3Dプリンタで出力しています.
レジンはSK本舗さんの水洗いレジンの銀灰です.
今回の「neon」の構造には関係ありませんが,見る角度によって銀色になるお気に入りのレジンです.
プリンタはELEGOO Mars3です.造形精度はかなり良く気に入っていますが,購入してから立て続けに故障しまして,2度もELEGOO社からパーツを送ってもらった結果,現在快調に動くようになっています.
初回トラブルはタッチパネルが押せなくなり,2度目はCPUとZ軸センサが逝ってしまったらしく,ゼロ点まで下げたときに「メリメリ」とゼロ以下まで下げようとするので,慌てて電源OFFな感じでした.
それでも写真と状態を説明したらどちらも無償で速攻で代替パーツを送ってくれたので,サービスが良いのか故障慣れしてるのかわかりませんが,治ったので良しとします.
FDM方式も所有していますが,サイズと造形性能の関係でSLAの方を使っています.
外殻
さて実はSLA方式の3Dプリンタを導入した最大の動機は,この外殻の作成です.
第一世代,第二世代とも外殻の作成には本当に苦労しました.型をFDMで作りそこに透明レジンを流し込む方法やアクリルを削る方法も考えましたが,結局できてもかなりシンプルな形状になってしまうため諦めていましたし,Maker Faire に展示したときも外殻から出して展示していました.
いろいろ設計したものをDMM.makeに透明アクリルで3Dプリントを依頼しようとしましたが,そのときの見積もりで3Dプリンタが買えてしまうことが判明して,自分で作ろうと決意したのでした.
そのあたりの奮闘記は以下のリンクで
このときは実験用でFDMによる出力でした.
今回はついに本番です.
じゃーーーーん
印刷範囲ギリギリですがちゃんと出力できました.打ち出し直後はほんとにキレイ.
そうそう.実は以前AnycubicのPhoton-Sを所有していたのですが,そのときに印刷範囲がギリギリ足らずに設計そのものを100mm→90mmに変更して設計したのですが,よく考えてみたらmars3なら印刷範囲足りるし解像度も上がってキレイなんじゃね? となって買い替えまでしたのでした.
両面打ち出したものがこちら
ところが,実はこれ嫁さんが落としてしまい,割れてしまいました.
使用したのはSK本舗の水洗い透明レジンでしたが,やっぱり高靱性かタフレジン使わなければいけなさそうです.
高靱性で透明なレジンとしてはこのへんかな〜〜
②に続く
第3世代 POV neon ③
はじめに
前回の続き
今回はソフトウェアの話です.
第2世代では主にハードウェアの実装がメインで,ソフトウェアは必要最低限のものでした.
このように単色,単一画像を表示し続ける...
これはこれで良いのですが,最終目標は
①スマホ側から信号(例えば音楽など)に合わせて画像・パターンを切替える
②できれば動画として表示したい
③ジャイロセンサを用いて,ボールが傾いても画像が傾かない
①②については,ハードウェア的にスマホと通信する機能は実装済み,動画として大量のデータを読み込むためにESP32ボードにはSDカードを実装しています.
そして,今までも構想にはあったけれど実装してこなかった③についての考察は,
ここで行いました.
processing上でのシミュレーション結果です.
ちなみに動画中の球体は,回転する120x45 dotsのLEDの位置に小さな球を配置し,それぞれのLEDの座標とジャイロセンサの情報を元に上記ブログのプログラムから地球儀のテクスチャを用いて各LEDの画素値を取得します.
動画中ちょっと見にくいのですが,世界地図の上に細かい線が引いてあり,ジャイロの動きに合わせて更新されているのがわかるかと思います.これはボールの経線を表しており,リアルタイムに更新されているのがわかります.
しかしいくらESP32がデュアルプロセッサとはいえ,これらの計算には大量のatan2とsqrt, sin, cosが登場します.ここを近似計算にすることによって計算負荷を下げ,他の通信系や画像処理にリソースを回したいところです.
ちなみにこの動画での結果が早いのは,これらの計算をPC(Macbook Pro)で行っているからです.ESP32ではまだ試していませんが,もっと遅くなってしまうことが当然予想されます.
逆にPCとwifi通信して角度情報を送っているため,タイムラグが発生しているのがわかります.
ESP32の浮動小数点処理
基本的には先人がいろいろ検討をしており,それを参考にしているので今更感はありますが,m5stack(ESP32)を使う人には参考になるのでは,と思います.
何より自分用のメモ.
ESP32はディアルコアで浮動小数点演算を行うコプロセッサがあり,floatの計算は速いようです...
といいつつ,探していたらこんな記事も見つけてしまいましたが..
esp32にFPU(浮動小数点演算装置)はあるけど有用性は微妙っぽい。残念whttps://t.co/wmb1V8JwgT
— mはげ (@Tw_Mhage) 2017年5月6日
しかし最近はこうゆうものも出たらしいので,
浮動小数点演算の勢力図はまだ変わっていくのかもしれませんね.
期待したいです。
各処理の速度演算については,
このサイトなど くわしく検証されています.
今回は標準関数によるatan2, sqrt, cosの3つの計算を近似計算に置き換えたものと置き換えなかったものとで比較しました.
計算に使用したソースコードは以下においてあります.
atan2
まずはata2の計算をESP32上で比較します.
使用するマイコンはM5stack-grey.
Arduino IDE上でコーディングし,比較対象はmath.hのatan2と以下のサイトにあった近似計算です.
参考ページの手法は,およそ±0.01° 以内の誤差で収まるようなので,このアルゴリズムでも4次近似式を使用します.
M5stackはマルチコアですが,片方はUIや通常のloop関数を扱っているので,計算部分は別スレッドで行いました.
標準関数であるatan2()と,近似計算を行う_atan2()とを交互に20万回計算し,かかった時間をμ秒で計測します.
atan2に入力するx, yはテキトーに決めて,値を放り込みました.
その結果
atan2()で2669332μ秒程度.1計算あたり約13.3μ秒.
近似式_atan2()は7.44μ秒以下...2倍行かないくらい.
上のブログは因数分解していたりなるべく整数になるような工夫が入っているので,まあ妥当な精度でしょうか...
sqrt
つづいてsqrt計算.
このブログを参考にニュートン法による漸化式を適用して,10万回計算したときのμ秒を計測します.
標準関数sqrtで412234μ秒.1回あたり4.1μ秒.
近似計算_sqrtで1420166μ秒.1回あたり14.2μ秒....
あれあれあれ...
標準関数は専用の計算プロセッサがあったりするのかな..これは標準関数を使った方が良さそうですね.
cos
つづいて三角関数.
近似方法としてはたとえば
などにテイラー展開やミニマックス近似などの方法が載っていますが,今回は参照テーブルを使うことにします.
360度を10,000分割し,その値をテーブルに格納します.
そのテーブルを使って,入力値となるcosの値を参照する近似方法です.同様に10万回計算したときにかかった時間をμ秒単位で計測.
標準関数cosでは131849μ秒.1回あたり1.3μ秒.
参照テーブルcosでは90135μ秒.1回あたり0.9μ秒.1.5倍くらい高速化しているか.
とまあ,こんな感じでESP32ベースでの計算高速化を検討してみました.
まとめ
ジャイロ(IMU)による情報からテクスチャを回転させることでボールが回転しても画像は変化しないプログラムを書きました.
ESP32のようなマイコンでこのような重い処理を行うには,かなり処理を高速化しないといけないので,ESP32プロセッサで近似計算による高速化がどれくらい効果的かを検討しました.
結果的には,atan2,cosなどの三角関数計算においては,ある程度効果が見られそうで活用しようと思います.
しかし,sqrtの計算は標準関数の方が速いので無理せずおまかせしようと思いますw
現在はまだボールのハードウェアを作成している最中なので未検証ですが,はやくソフトウェアのフェーズに入って実装したいですね.
第3世代 POV neon ②
はじめに
前置きが長くなってしまったので分けました.
①はこちら
第3世代POV neon
はじめに
第3世代POVは,精度,性能,機能と大幅に向上することにしました.
大きな変更点は,
- 第2世代で大きく問題となったフルカラーLED問題.
- 外装の再設計
- M5stack → ESP32独自基板
- ソフトウェア
MFT2021までにどこまで実現できるかな?? (審査受かってればだけれどなw)
フルカラーLED問題
第2世代POVで使用したLEDはAPA102-2020.
フルカラーLEDの定番,DOTSTARの製品ですが,上で述べたようにPOVで使うにはリフレッシュレートが足りないことが確認されています.
では,他にリフレッシュレートを上げることができる超小型フルカラーLEDは存在するのか?
いろいろ探した結果,見つけました.
Fast digital rgb pixel 2020 led chip HD107sroselighting.wordpress.com
なんとPWM rate 27kHz!!,データ更新レートは40MHz!!
これならいけそうだ!
HD107s-2020 が届いた!
— yakatano (@Yakatano) 2019年11月26日
GUGENに間に合うかな? pic.twitter.com/qm4ky7nUeh
HD107Sの電源波形
— mike (@mikekoma) 2020年9月4日
VCCに1Ωかまして観測。
GlobalBrightness=0x1E
Data=0x808080
Refresh rate=32KHz
公称値26KHz以上ってなっているので、一応OKぽい。 pic.twitter.com/cB3db13abW
しかも配置もNEOPIXELやDOTSTARと同じピンアサインなので,使い方も慣れていてGood.
ただしこの界隈,パチモノが多いというか...
商品ページの写真を比べてみましたが、載っているのはSK9822-2020の様に見えます。
— あおいさや (@La_zlo) 2019年9月4日
実物はいかがでしょう?https://t.co/rKVywt40WR pic.twitter.com/UHsS4Agy1G
こちらが、APA102-2020の写真。
— あおいさや (@La_zlo) 2019年9月4日
バリエーションが多いけど、どれとも違う。https://t.co/wuKXNhyeVF pic.twitter.com/E9YsIGLIQ7
同じような見た目で性能が変わる,なんてのがザラ...
地獄のようなハンダゴテを超えた後に変なもの掴まされてただのゴミと化すのは流石に辛い...
Rose Lightingさんというところが元のようなのですが
APA102互換の次世代LEDだそうです。2020サイズでも28kHzのリフレッシュレートが出るらしい! これなら既存基板で置き換え可能だ! https://t.co/Rvi1QaLcbd
— yakatano (@Yakatano) 2019年10月28日
でも1000個単位でしか売ってないっぽい。。。 誰か共同購入しません?w
— yakatano (@Yakatano) 2019年10月28日
1000個単位でしか売っていないようなのです....
それでもなんとか手に入れて,現在実装待機中です.
外装の再設計
第3世代POVは,外装も大きく変えます.
とはいえ基本的な設計思想は第1世代から変わりませんが,ちょっとづつ改良を加えていきます.
まだ,最終に向けてデザイン変更あるかもしれませんが,現状こんな感じ.
中央のキューブの中で回転軸の支柱を囲むように基板と電池が収まる予定です.
第2世代から変更した点
シャフト部分
第1世代は3Dプリンタ製 → 強度不足
第2世代は既製品(ステンレススペーサー)の流用
第3世代では専用に設計したシャフトを旋盤で削り出します.
素材は加工しやすい真鍮.両端にネジを切ることによって短い接合部でも強度と剛性を保つことができると考えました.
しかし,大きな問題が....そもそも旋盤加工を行う場所なんてあるのか? 設備は?
私自身,大学が機械工学科だったので旋盤作業自体は行ったことがありますが,個人で旋盤作業を行うことのできる施設が無い...
白羽の矢を立てたのはTechshopTokyo.
残念ながら2020年2月に閉鎖してしまいました..
しかし,その直前に入会して講習受けて旋盤してきました.入会したのは2020年の12月くらい....
え? もちろんその時にはTechshopが閉鎖するなんて知りませんでしたよ.ええ.講習代? もちろん支払いましたよ.
今も設計変更が入って新しく作り直さないといけないのに,今後どこで作業すりゃあいいんだ....orz
外殻部分
いままでの外殻は半球状のものを組み合わせましたが,第3世代では野球のボールのような構造のデザインに変更予定.
今回のMFTに間に合うかはわかりませんが,このような構造の外殻を作っています.
ただ,私の持っているAnycubic Photon-Sではサイズがぎりぎり足りないため,どうしようかなあと悩み中.
基板収納部分
いままではM5Stackを流用していたので,中央の基板収納部分のサイズはm5stackの基板サイズ50x50mmを超えることはできませんでした.
しかし,第3世代は専用基板を設計することにしたために,サイズの自由度が増えます.専用基板を設計することにした理由は以下の3点
- M5stackのサイズ制限からの開放.
- 精度向上のために中央の回転軸を固定するため
- M5stackの不要な機能の除去とIMU(ジャイロセンサ)の性能向上
①については,ボールの直径がφ100mm確定であることからM5stackを採用することは中央部分の空間を圧迫し,設計の自由度を下げてしまうため
②については,中央にm5stackが収納されるため,回転軸が途中で途切れてしまい,3Dプリンタ程度の設計精度だとやはり軸にズレが生じてしまうことから回転精度が低くなってしまうことを懸念したため
③については,M5stackはライブラリも充実しているし,よくできている製品だと思っていますが,今回の目的に対していくつかの機能は不要でいくつかの機能は性能不足,という点もあり第3世代は頑張って基板を起こしてみることにしました.
具体的には,M5stack のIMUはMPU9250もしくはMPU6886+BMM150による9軸センサですが,boshのBNO055がかなり性能が良さげなのです.
実際使ってみるとキャリブレーションもほとんど必要なく精度良く計測できているようで今回採用しています.
問題点としては,値段が高いことと,基板に実装しようとするとQFNでもない特殊な規格のようで一人でホットプレートリフローするにはかなり難しい点です.
今回はESP32をベースに,このIMUを組み込んだ基板を作成しよう,ということにしました.
基板設計
新しくM5stack相当の機能を持った基板を起こします.ピンアサインの基本的な構成はM5stackとなるべく共通になるように設定します
基板は設置スペースの都合で2枚に分離,さらに電源も別にしています.
上図のESP32基板(上段)には,
・U1:ESP32本体
・J1:SDカード( SPI経由での読み書き,ピンアサインはM5stack準拠)
・J2:PCと通信を行うためのUARTシリアル通信
・J7:2枚めの拡張ボードとの接続を行うためのコネクタ
拡張ボード基板(下段)には,
・U2:Motion Sensor(BNO055)
・U3:Motor Driver(DRV8355)
・U4:RTC(PCF8563TS)
・J5:フルカラーLED(HD107S-2020)とのSPI通信用コネクタ
・J6:4ch汎用GPIOコネクタ(うち一つは回転検出用ホール素子に使用)
・J8:3.3V,5V電源入力コネクタ
という構成です.
ESP32ボードは汎用性を持たせるために最低限の接続しかしておらず,拡張ボードとはJ7コネクタを介してI2C,HSPI,DACx2,GPIOx4の接続ができるように設計しました.
拡張ボート側を見ると分かる通りまだまだ余裕がありそうなので,今後他にもいろいろと積めると期待しています.
上のESP32ボード側は大したハンダ作業ではないので今回はホットプレートリフローを初体験してみました.
対して拡張ボードの方は,上述したとおりBNO055のピン配置は素人の私ではリフローする勇気はなく,こちらも初めて中国に実装も依頼しました.
いままで基板の作成はFusionPCBを利用していましたが実装が高いと感じていたので,今回はPCBwayさんに基板作成と実装を依頼してみました.
基板サイズは40x26mm,基板は10枚作成しそのうち5枚に実装を依頼しました.
基板作成・実装合わせて$200くらい.ざっくり1枚$40くらいでしょうか.部品代込みなのでこんなものでしょうかね...(BNO055が2000円くらいするのでかなり安い方?)
依頼して一ヶ月かからなかったくらいでしょうか.無事に届きました.
左がホットプレートリフローしたESP32基板(裏にSDカードスロット有り)
右が拡張ボードです.
ESP32ボード下側のコネクタにUARTシリアル変換を差し込んでPCからプログラムを書き込むことになります.
動作確認も無事に終わり,すべてのモジュールの動作を確認しました.
そして,分離した電源回路
左が電源回路で,
右が電源のオンオフを行うためのスイッチ回路です
電源回路は,
・U1:LiPo Battery Charger(MCP73831)
・U2:3.3V DCDC(LT1615)
・U3:5V DCDC(LT1615)
・U4:電源IC(XC6192)
という構成になります.
U1はLiPoを充電しつつ電源を供給できる構成としてMCP73831を採用.ここからはLiPo出力の3.7Vが出力されるので,分岐して各DCDCへ.
U2はESP32を駆動するのに必要な3.3Vを安定供給できるようDCDCを,U3はモータやフルカラーLEDを駆動するための5Vを安定供給することを目的に配置.
今後も汎用性を持たせたいので各DCDCの入り口にはジャンパーを配置して5V出力のみ,3.3V出力のみと切り替えることも可能です.
そして電源IC. POV neonは最終的にボールの中に収まることを想定しているので,電源ON/OFFの操作を行うことが難しい.
ボールから外部へのアクセスはwifi,BLE以外(これは通電していることが前提なので電源ボタンには使えない)には4chのオーディオピンコネクタしか存在しないので.このオーディオピンから供給される電源線を使ってON/OFFしたいと考えて採用しました.
4chのうち,2ch分はUSBからの5V入力とGNDとなり,残りの2chのうち1本を使って電源の管理を行おうというものです.
電源ICというのは,ボタン長押しで電源ONなどいくつかの機能的な電源管理を行うICのようで,本当はbattery chargerのような機能を持ったものもあるのですが,今回はスイッチ機能のみ採用しました.
奥にあるのがスイッチボックスとなります.向かって右側にUSB端子がありこちらから給電し,左側からケーブルが伸びて4chマイクロプラグを介してneonに接続されます.
第2世代ではここからそのままPCに接続してシリアル通信を行うことができましたが,今回はそれは廃止.
基板のシリアルコネクタからUSBシリアル通信を行うことで,基板の省スペース化を実現しています.
さいごに
現在は,これらすべてのパーツを組み合わせて最終工程に持っていくフェーズに入っています.
ソフトウェアの改良は③で紹介しようかなと思っていますが,現状の設計状況を3Dプリンタで出力した結果がこちら
モーターとスリップリングを仮組みして精度を確認しています.
シャフトもまだ金属ではなく3Dプリンタで打ち出したもので試し中
シャフト末端のマイクロプラグはなかなか小さいものが見つからず,最終的には自分で削ることになりそうです.
③のソフトウェア編に続く
第3世代 POV neon ①
はじめに
球体POV(Persistent Of Vision)というものを作成しています.
タイトルの通り,球体POVとしてはこれで3世代目に入っています.
もともとのアイデアは2015年のハッカソンから始まって,MakerFaireTokyo(以下MFT)でも展示させていただいています.
初代は
このようにPOVではなく,LEDを配置(右上のものはLED32個)してスマートフォンからの命令で複数のボールのパターンを制御するものでした.
下はそこからパターンをきれいに表示させることができるようにLEDの数を増やしたもの
と,ここまで来るとLEDの消費電力など限界が見えてきたにも関わらず,ある欲求が首をもたげてきます.
これで絵を表示したい!
....という話は
こちらで語っていますので,こちらではPOVに移行してからのお話を...
POV neonの歴史
第1世代
第1世代は 2018年のMFTにてお披露目しました.
この世代はLEDに入手しやすいNEOPIXEL(APA102-5050)を使用しています.LEDの大きさが5mm x 5mmなのでどうしても解像度が上げられず,LEDを数も17個に留まっています.
解像度を上げるために半ドットずらして反対側にも配置して33LEDにまで高解像度化していますが,せいぜい国旗あたりまでの解像力でした.
第2世代
第2世代は 2019年のMFTにてお披露目しました.
MFTでは画像を表示するところまではいけませんでしたが,その後画像を表示できるように...
第2世代ではLEDをDOTSTAR(APA102-2020)という2mm x 2mmの超小型フルカラーLEDに交換し,片側45LEDという高精細を実現することができました.
この第2世代はMFTに来ていただいた方々にも興味を持っていただけて,モチベーションになっています.
MFTでは間に合いませんでしたが,動画の後半のように地球儀を表示できているところをお見せでき,画像を表示できる能力を手に入れることができました.
ただ,せっかくLEDがフルカラーなのに地球儀は赤一色であることにお気づきの方もいらっしゃるでしょう.
このあたりHomemadeGabageさんらと相談しながらいろいろと検証しています
そのため,上の動画の前半をご覧になっても分かる通りパターンが流れてしまっていることがわかります.
そう.DOTSTARでも2020のサイズではPOVとして動作するには遅いのです.そのあたりの詳細はここで議論しています
要するに,DOTSTARはLED自体の更新レートは19kHzあるのですが,それはLEDをが100%輝度(0xFF)の場合のみで,フルカラーでLEDををコントロールする場合,RGBの各値を0xFFより小さくしますよね.その明るさコントロールをPWMで行っているため,更新レートが400Hzに低下してしまうのです.
現在のPOV neonが一回転の速度が12Hz程度(1秒に12回転).一回転を分解能120(3度刻み)で表示しているので,更新レートは1.5kHz程度.当然間に合わないわけです.
このあたりの考察はHomeMadeGabageさんのここを参照
こんなわけで第2世代で画像を表示する場合には単色8色しか使えないのでした.
APA102-2020は色輝度が600HzほどのPWMで制御されるのでPOVで使用すると絵が途切れる。しかしグローバル輝度は電流制御だったので、色輝度を最大(600HzのPWMのデューティ100%)にしてグローバル輝度で調光すれば絵は途切れないのだ。
— HomeMadeGarbage (@H0meMadeGarbage) 2019年9月5日
しかし色は8色しか出ない。。。
0x000000, 0x0000FF,‥,0xFFFFFF https://t.co/pwstlNP11E
これを解決するために第3世代が爆誕することになります.
そしてこれを機に,今までマイコンはM5Stackを流用していましたがここも基板から起こすことにしました.
そのため2年がかりの更新となってしまいました(MFT2020は落選しちゃったんですけれどねえ)
ぐはっ
— yakatano (@Yakatano) 2020年7月10日
MFT2020落ちた! pic.twitter.com/CkgK4E3eJc
第2世代のこのあたりまでの経緯については,Make:Japanさんに記事にもしてもらいました.嬉しい.
②に続く
野球のシーム(縫い目)のようなボールを作る②
はじめに
球体POVというものを作成しています.
その中で,今は外殻に相当するボール部分を制作しています.
なかなかいいところまでは行ったのですが,肉厚が足りないのか,くびれが強いためか,かなり無理矢理嵌めなければならなかったので緩んで隙間ができてしまいカタカタ鳴るくらいユルユルになってしまっていたのでした.
今回はこの問題を解決するために,接合部分に凸凹の嵌合部をblenderベースで作ってみたので紹介します.
blenderでプログラマブルに任意の軌跡のパイプを作りたい人には参考になるのではないかな,と思っています.
やりたいこと
前回のブログではB値の設定を変更(B=0.5→B=0.35)してもうちょっと調整しようというところでおわっていたのですが,その調整して打ち出したものがこちらになります
途中から色が変わっているのはフィラメントがなくなって継ぎ足したからですw
でもこれだとかなりカチっと嵌ってくれます.
前回はB値が大きかったためくびれが大きくて嵌めるときにかなり無理矢理行かないといけなかったのですが, 今回はザクッと差し込むことができました.
懸案だったボール内へのデバイス収納問題も,B=0.5のときは無理そうでしたが今回(B=0.35)では無事収納できました.
(とはいえ,実は対のパーツを組み込むことができないことが発覚して,未だ未解決になってしまっているのですが....)
しかーーーーーし
最初はしっかり嵌っていたのですが,しばらくすると緩んできてしまいます.
というより,印刷時に付いているサポート材(一番上の写真にボールの上下についている円柱のような部分)が付いているときはパーツを閉じる効果が強くて嵌め合い時の力も強かったのですが,このサポート材を取り外したら閉じる力が弱くなってしまったようなのです.
前回よりはマシなのですが,やっぱりこれじゃあ心配だ.
そこで嵌合部に凸凹を付けてしっかりと嵌るように作ることにします.
要するに作りたいものはこんなもの
各パーツに対して,一方はUNIONで
他方はdifferenceで
このような凹凸をつけてあげれば重ねたときにパチっと嵌るのではないか,と期待したわけです.
Blenderでの作業
前のプログラムを変更して作ります.
Blenderで自由形状のパイプを作るにはパスを作って,そのパスに沿って形状をbevelする必要があります.前回のPolygonを作るコードは下にあります.
参考にしたのはこのあたり
使うのはcurve operatorです
pythonプログラムで前回作ったpolygonのvertex値をつないでパスを作ります.
まずは原点にbezierのオブジェクトを置きます.
bpy.ops.curve.primitive_bezier_circle_add(location=(0, 0, 0))
このときに作られるベジェのオブジェクトはedit modeにするとわかりますが,制御点が4つしかありません.これから軌跡に沿ってvertexを追加していくので今回は最初の4点は下のコマンドで消してしまいます.
bpy.ops.curve.delete(type='VERT')
それが終わると前回と同じ方法でちょうどパーツの中間になる値(今回は半径50mmで肉厚5mmの球のため,パスの半径(SEAM_RADIUS)は0.475ということになります)
角度に応じた軌跡上の点(x1, y1, z1)を計算したらその座標を追加してパスを伸ばしていきます.
bpy.ops.curve.vertex_add(location=(x1,y1,z1))
角度を0〜360まで回すとパスは一周して完了です.閉じる処理も必要ですがそれは手作業でやっちゃいました.
同時に角度が0のときの位置(開始点:xx1)にパイプの形状を決める円を配置します.
bpy.ops.curve.primitive_bezier_circle_add(location=xx1)
ちなみに開始点は,一度座標値をプリントしてそれをコピペしただけですw
配置した円は,向き・大きさを手動で整えておきます.
xx2まで出したのはxx2-xx1のベクトルがパイプ断面の法線になると思ったのですが,開始点はそのまま垂直なので使いませんでした.
えい,実行
パスを選択して,プロパティからcurveを選ぶと右のようなプロパティが出てきます.
「bevel object」という項目に先程作った開始点にある断面形状(今回は円)を選んでやると上のようなパイプを作ることができるのでした.
これを前回作成したボールパーツに対してそれぞれboolean演算してやることで,各パーツに凹と凸を付けることができるのでした.
ただし,このままだとbezier curveがカーブオブジェクトのまま(図中の赤丸で囲った部分)なので,「object」「convert to」「Mesh from curve」を使ってカーブオブジェクトをメッシュに変換します.
こうすることでbooleanで凹凸をつけることができるようになります.
これを3Dプリンタにもっていき,印刷開始!
じゃん.
上が凸で下が凹.
ちゃんと凹みを表現できています.
実際に組んでみると
こんな感じ!!
一部白いのは,今回もフィラメント不足で継ぎ足しましたw
左にあるボールはこのブログの最初に印刷した嵌合部なしのもの.右の透明が今回打ち出した嵌合部アリのボール.噛み合いが全然ちがいます.
これは流石にぴったり.ほとんどズレません.フィラメントの消費量は殆ど変わらないのにこれくらい造形がしっかりしてくるのは面白いですね.
工夫すればするほど良いものになっていく.
本番は光造形で打ち出すため素材が違うので嵌合部がどれくらい行くかはわかりませんが,なかなか満足の行くものができました.
でも,まあそれよりもこのボールの中にちゃんと本体が収納できるようにしないと光造形までたどり着くことはできないんですけれどね.....