de IBY

めざせ知識の無駄遣い

インクジェットプリンターで動画を再生する with STM32

作るきっかけ

2021年のある日,10年物のインクジェットプリンターが壊れました.何をしても紙を吸い上げてくれません.寿命であるのは明らかなのでこれ自体は仕方ないと思っていましたが,部品が大量にあるこの機械をすぐに捨てるのはなんか勿体ないよなぁという感じでした.

その時,正月ごろにマジョカアイリスハックなる解析が行われていたことを思い出しました. github.com (詳細は割愛しますが,正体不明のLCDの信号を解析して汎用の液晶として使えるようにするという試みでした.)

このプリンターにはLCDが搭載されていたので,同じように解析して使えるようにすると面白いのではと考えました.一方で,大きなプリンターのうち操作パネルの液晶部分だけでなく本体も何か工夫したいと考えており,映像には音声が付き物なので,あの左右に移動するヘッドを音声の周波数で振動させれば音が出るのではという発想に至りました.そういうわけで,ピンアサインも全く分からない状態からの無意味な試みが始まりました.

装置全体図

なんやかんやあって全体はこんな構成となりました.

全体のブロック図

デジタル回路やFPGAは入門書以上の知識が無いため選択肢として考えず,動きがわかるほどの映像を制御する高速信号が出せるMCUとしてSTM32F446を採用しました.動画再生の先行例(昔話題になった秋月300円液晶を使っています)でSTM32を使っていたので,それに倣ったという面もあります. power-of-tech.hatenablog.com

映像編

まずは映像信号の解析から始めました.LCDに繋がっている端子にオシロのプローブを当ててひたすら信号を観察します.その結果,このプリンターに接続されているLCDは「EN, CLK, データ1, データ2, データ3」の5線(+電源線)で動いているようでした.続いて,オシロのトリガ時間を変えたりして映像が出力されるまでの各データの変化を時系列に記録して,マイコンで再現できるようにします.どうやらこの液晶は 321(1列非描画区画)×240 の画素を持っているようで,4:3の動画を簡単に再生できそうです.

データを記録していたノートの一部.LCDに入力される信号の遷移と信号同士の間隔などが漏れなく書かれています.よく取るモチベあったな,マジで….

描画に必要なデータを収集したら,STM32でその信号を再現します.STM32にはDMAというCPUの処理内容に依らず一定周期で信号を出力できる機能が備わっているため,これのPWMを利用して一定周期のクロックや信号を出力しています.参考

構造は先行例とほぼ同じリングバッファシステムとしました.SDIOを使ってSDカードから描画データを読み込み,各リングバッファに値を書き込んだ後,DMAがそのバッファをもとに信号を出力するという感じです.SDIOを使うことでSPIよりも高速に読み取れているはずです.

また,映像信号とLCD自体の制御信号で信号の幅が異なっており,DMAが出力する信号自体を大きく書き換えるのが難しかったので,制御信号用のDMAと映像信号用のDMAを別々に用意し,TC4053で切り替えるようにしました.

高速信号を扱うということで,可能な限り配線長を短くする+液晶本体から出るフレキケーブルを繋ぐためにブレッドボードから基板に回路を落とし込み,さらにインバータを使ったバッファを挟みました.中華製の74HC04だと瞬く間に信号が鈍ってしまった一方で,東芝製のICを使うと信号が正しく出力されました.やっぱり差があるんだね.基板はALLPCBで送料込み$20でした.部品はほとんど秋月です.フレキケーブルやコネクタは日米商事で買いました.

シールドっぽくしてみました.趣味で基板作る勢,シルクで遊びがち.

音声編

音声はアンプを通して増幅され,DCモーターに直接ぶち込まれています.モーター内部のコイルの励磁でモーターや軸の先にあるプリンターのヘッドが振動し,それをプリンター全体で共振させて音を出している感じでしょうか.

MCUから制御できる音声再生装置にDFPlayer miniを採用しました.Amazonにあるセカンドソースを買ったので秋月より安く手に入りました.

公式サイトArduino用の実行スクリプトが公開されているので,これをSTM32用にリファクタリングしました.

増幅回路は『定本 トランジスタ回路の設計』第5章の回路を参考にメジャーなプッシュプルの回路を作りました.電圧を約10倍に増幅させます.

大学の基板加工機で作りました.いつもお世話になっております.

ソフトウェア編

320×240サイズに合わせた映像を連番BMPに変換させて,BMPから読んだ画像データをSTM32が出力しやすい形式に変換し,SDカード内に置いたバイナリにappendする作業をフレーム数だけ行います.今回はモノクロデータのみ考えているため1画素を1ビットで表現可能なことから,画像1枚あたりのデータは(320+1)×240 = 9630バイトというコンパクトなサイズに収められました.それでも3分ちょっとのファイルで50MBになりましたが.動画の圧縮技術の凄さを感じさせる作業でした.

1枚のBMPを読んで変換するプログラムをC++で作成し,それをすべてのBMPに実行させるようにシェルスクリプトを書きました.映像の2値化+連番出力はAviutlを使用しました.

音声については動画から音声のみ取り出して,DFPlayer mini用のSDカードに入れるだけです.

実演

映像ベンチマークとして定評のある Bad Apple!! feat. nomico の影絵PVを再生してみました.24fpsで綺麗に再生されています.マイコンの処理速度の都合でこれ以上fpsを上げることはできないのですが,十分動いて見えるのでOKでしょう!音声はスピーカーを使っていない以上低音質になってしまいますが,聞き取ることができる程度の音声が聞こえてきました.(動画内ではモーター付近にマイクを近づけて録音しています)

ロゴのEPSONを加工してFR8QVにしてみました.フランスのコールサインっぽいですが,実在しない(はず).

おわりに

マイコンで液晶を扱うということを今まで積極的にやってこなかったので,信号解析やその制御など非常に多くのことを学ぶことが出来ました.改良点としてモノクロの映像をカラーにするというのが考えられますが,画素に必要な情報が24倍(8bit×3)になることを考えると今回の構成で十分なfpsを出すことは難しいでしょう.個人的には,マジョカアイリスハックの真似事ができたのでもう十分かな~という気持ち.

STM32を使うのは初めてでしたが,これを通じて基本的なスキルは身についたように思えます.STM32には使われていない機能がたくさんあるので,それらを使えるような面白い工作が出来ればと思います.

そして,EP-802Aをハックしたいという方,映像信号をお伝えできるのでご一報ください 笑

ここまでお読みいただきありがとうございました.