2021年1月19日火曜日

LCDへCUI,GUIを出力する HDMIコピーを出力する方法【Raspberry Pi Zero】

 先日やっとRaspberry Pi Zero WHを手に入れまして、早速LCDを接続してミニPCを作ろうと思ったのですが、案外手こずったのでここに手順を記します。



ここではLCDにCUI(コマンドライン)を表示させる、GUI(デスクトップ)を表示させる方法と、HDMIディスプレイの複製をLCDに表示させる方法を紹介します。

0.目次

    1.準備するもの
    2.LCDにデスクトップを表示する編
    3.HDMI出力のコピーをLCDに表示する編

1. 準備するもの

・ラズパイzero (他のラズパイでもできるかもしれません)
・グラフィックLCD(今回はILI9341というコントローラ搭載のものを使用します)
    最近だとAmazonでも1000以下で入手することができます。
・Raspberry Pi OS(Raspbian)の入ったSD
・ディスプレイ(テレビ)+HDMI or SSH環境
    ここではディスプレイを用いて進めます。


2.LCDにデスクトップを表示する編

OSの導入などの手順は省きます。

OSのバージョンの差等によってうまくいく、行かないあるかもしれませんが、当環境はこの投稿時点の最新verです。


https://www.instructables.com/Rasberry-Pi-Zero-W-With-Arduino-TfT-ili9341/

これからの手順はほとんど上のサイトを参考にしています。

上のサイトでは若干いらないのでは?と思う部分があったので省略して、自分がいると思った部分だけ載せます。


Step.1

LCDとラズパイzeroを下の通り、ワイヤリングしていきます。

MOSIピンをGPIO 10 (SPI_MOSI)

MISOピンをGPIO 09 (SPI_MISO)

SCKピンをGPIO 11 (SPI_CLK)

CSピンを GPIO 08 (SPI_CE0_N)

DCピンをGPIO 24

ResetピンをGPIO 23

またLCDには3.3Vを供給します。

LCDのLEDピンには5Vと抵抗(1kくらい)で繋ぎます。


Step.2

ターミナルを起動し、下のコマンドでラズパイコンフィグを開きます.

sudo raspi-config

3 Interface Options -> P4 SPIよりSPIを有効化(enabled)します。

また、ここを参考に起動時にGUIが立ち上がらないようにしてください。


Step.3

次に下のコマンドを実行し、ファイルをnanoエディタで開きます。

自分はnanoが分かりやすいので使っていますが、他のでも大丈夫です。

エディタの使い方等は他のサイトを参照ください。

sudo nano /boot/config.txt

下にスクロールし、"dtparam=i2c_arm=on" , "dtparam=spi=on" の2文のコメントを外します。


最後に、ファイルの最後の部分に下の文を追記します。

dtparam=rotate=90
dtparam=speed=48000000
dtparam=xohms=100
dtparam=debug=4
gpu_mem=64

ここまで終わったらこのファイルを保存して閉じてください。

Step.4(重要)

次に下のコマンドで別のファイルを開きます。
sudo nano /boot/cmdline.txt

ファイルを開き、"root wait"の後に、スペースを挟んで下の一文を挿入します。

この文の後に改行はいれず、スペースだけにしてください。

fbcon=map:10 fbcon=font:ProFont6x11

これを挿入したらファイルを保存して閉じます


次に下のコマンドでファイルを開きます。

sudo nano /etc/modules

ファイルを開いたらファイルに下の5行を追加します。

spi-bcm2835
snd-bcm2835
i2c-bcm2708
flexfb
fbtft_device

ここでひとまず再起動します。

ここまでの手順をミスなく行えれていれば、下の図のように、LCDにカーネル読み込みが表示され、最終的にコマンドラインが表示されます。

(HDMIディスプレイには起動時のカーネル読み込みみたいな部分だけ表示されると思います。)


この画面でCUIの操作はできるのですが、"startx"を打ってGUIに以降するにはもう少し作業が必要です。ここでstartxを打つとフリーズします。

Step.5

下のコマンドでファイルを開きます。

sudo nano /usr/share/X11/xorg.conf.d/99-fbturbo.conf

ファイルを開くとどこかに"fb0"という表記があると思います。

ここを"fb1"に変更し、保存してファイルを閉じます。

"reboot"コマンドで再起動すると、このLCDでGUIを表示できるようになります。

この手順はGUIを起動するにあたって、ディスプレイを選択するようなもので、fb0にあたるのがHDMI,fb1にあたるのがこのLCDです。

なのでこのLCDでGUIを起動するにはfb1に変更する必要があり、逆に元の状態に戻す(ディスプレイで表示するように戻す)にはfb0にまた変更する必要があります。

ここで"startx"コマンドを入力し、デスクトップを表示してみた結果が下の画像です。


ここまでで、自分なりに少しまとめたいと思います。

最初、CUI画面をLCDで見るのではなく、HDMIで出力したくなった場合どこをどうすればいいのか分からなかったのですが、いろいろ試すとStep.4で追記した"fbcon=map:10"という部分が肝心なようで、これを追記することによってCUIがLCDに移行しているようです。


3.HDMI出力をLCDへコピーする編

ここで、先程の手順の状態のまま、HDMI出力をLCDへコピーすると、操作しなければならないコマンドラインがコピーの出力で見えなくなってしまいます。

なので、コマンドライン,CUIの表示をHDMI側に戻す必要があり、そのためには先述の通りStep.4で追記した"fbcon=map:10"を削除するのと、Step.5で述べたように"fb0"に変更します。

その上でStep.6へ進みます。

Step6.

以下の6コマンドを順に実行するだけです(要ネット環境)

sudo apt-get install cmake
sudo git clone https://github.com/tasanakorn/rpi-fbcp.git
mkdir build
cd build
cmake /home/pi/rpi-fbcp
make
sudo install fbcp /usr/local/bin/fbcp

すべてエラーなく完了したら、下のコマンドを実行してください。

fbcp &

すると、LCDにディスプレイのコピーが表示されると思います。

下の画像は実際に表示してみた画像です。

先程のデスクトップ画像より、HDMIをコピーしている分アイコンが小さいのがわかります。




2019年1月23日水曜日

320*240 中華カラーグラフィックLCDの使い方



Amazonで数百円程度で入手できる320*240のカラーGLCDの使い方をPIC32MX270f256bを例に軽く紹介していきます。
この記事はArduinoなどで制御してみたいと思っている方にはあまり参考にならないかと思います(既存のライブラリがあるから)。

この記事ではPIC32mxを例に使いますが、SPI1バイト書き込み関数&ディレイ関数さえ用意できれば、他のc言語環境(AVR-GCCやPIC16のXC8)へ簡単に移植できます。

・ピンアサイン
上の写真をみるとGLCDからは9つのピン(SDカード関連を除く)が出ており、上(1番)からVCC,GND,CS,RESET,RS,SDI(MOSI),SCK,LED,SDO(MISO)となっています。
各ピンの説明をしておくと、VCC,GNDは文字通り電源です。
CSはチップセレクトという名前のピンでCS=0ならglcdはSPI信号を受け取るというもので、SPIバスに同じGLCDを2つ繋いで異なる制御をしたいという場面でもない限りCSはgndに落としておいても動きます。
RESETは文字通りリセットするピンでアクティブローです(Lでリセット有効)。
RSは送信するデータの種別(コマンドか表示データか)を選択するもので、Lでコマンド,Hでデータとなります。
LEDは液晶のバックライトLEDのアノード側のピンになります。
その他(SDI,SDO,SCK)はSPI関係のピンになります。

・lcdの概要(表示までの簡単な流れ)
ここでglcdに色つき四角形を表示する流れをglcdの特徴の説明を混ぜながら説明していきます。
マイコンはまずLCDに対して初期化処理を行います。
これには後で説明するglcd_init()という関数を呼ぶだけで終了します。
これで初期化は終了したので次に四角形を表示するための処理をします。
四角形を表示するためにはまず、四角形の二点の座標をaddset(後で説明します)関数でセットします。
四角形の座標の取り方ですが、一つの点は原点(x=0,y=0)に近い点、もう一つはさっきの点の対角の点です。
addset関数にて二点の座標をセットしたら、次に四角形を構成する一点一点に色データを設定します。
このLCDでは1ピクセルに2バイト使い、色を表現するので1ピクセルあたり2バイト送信します。
2バイトの内訳はRGB565という方式になっていて、上位バイトのうちの上位5ビットで赤の濃さを決め、上位1バイトの下位3ビット+下位バイトの上位3ビットで緑の濃さを決め、下位バイトの下位ビットで青の濃さを決めています。
もし意味がわからない場合google等で調べてみてください。
またピクセルに色を設定する際の順序ですが、まずx軸正の方向へ順に設定していき端まで行けばyを+1して、またx軸正の方向へ順へ設定します。

なので例えば、addsetで(0,0)と(1,1)という四角形を指定した時、この四角形のピクセル数は4つで、各ピクセルの座標は(0,0),(1,0),(0,1),(1,1)となり、色の設定の順番は(0,0)→(1,0)→(0,1)→(1,1)となります。

・glcdにおける座標
このglcdにおける座標の取り方は上の画像の赤い矢印の様になっています。
なのでglcd右上が(0,0)、右下が(239,0)、左上が(0,319)、左下が(239,319)となっています。
これ座標系だと使いにくい時があるので、黒い矢印の座標系を使うようにした関数がいくつかあります(あとで紹介します)。

・プログラム
プログラムはここよりダウンロードしてください。

・各関数の機能説明

  • glcd_init() 
    • この関数はglcdを初期化するためのものです。

  • write_command(unsigned char cmd)
    • この関数はglcdにコマンドを送信します。

  • write_data(unsigned char data)
    • この関数はglcdに表示データを送信します。

  • glcd_clear(unsigned char R,unsigned char G,unsigned char B)
    • 引数で指定された色で画面をクリアします。このglcdはrgb565なのでR,Bには2^5以上の値、Gには2^6以上の値を設定しても無意味です。

  • addset(unsigned int x,unsigned int y,unsigned xx ,unsigned int yy)
    • 第一,第二引数のx,yで原点よりの四角形の座標を設定し、第三,第四引数のxx,yyで先の点の対角の点を設定します。
    • この関数の後、write_data()でピクセルのデータを送っていきます。

  • addset_t(unsigned int x,unsigned int y)
    • この関数は先程の画像の黒い矢印の座標系を引数に取ります。関数内でglcdの座標系(赤い矢印)に変換しています。
    • この関数を用いて画面を操作する際、1ピクセルごとにこの命令でアドレスセットをする必要があります。
    • 後で登場する"_t"がつく関数は黒い矢印の座標系をしようします。

  • glcd_chr(unsigned int x , unsigned int y, unsigned char moji) 
    • 指定された座標に第三引数の文字を表示します。
    • 文字の左上端が指定された座標になります。
    • 使用可能な文字は基本的にアスキー文字です。

  • glcd_str(unsigned char x , unsigned char y , char *str) 
    • 指定された座標から文字列を表示します。
    • 使用可能な文字は基本的にアスキー文字です。

  • glcd_chr_t 及び glcd_str_t
    • 先程紹介した2つの関数の黒い矢印座標系版です。



  • glcd_square(unsigned int x,unsigned int y,unsigned xx ,unsigned int yy,unsigned char dh,unsigned char dl)
    • (x,y)と(xx,yy)で表される四角形を表示します。
    • 色はglcd_clearのようにrgbしてではなく、2byteによる指定です。(面倒だった)

  • glcd_array(unsigned int x,unsigned int y,unsigned xx ,unsigned int yy,unsigned char *data)
    • glcd_squareはすべてのピクセルに同じデータを送っていたので単色ですが、この関数は引数の配列から順にデータを取っていきます。
    • 例えばa[]という配列にa[0]=0b11111000,a[1]=0,a[2]=0,a[3]0b11111と定義しglcd_array()に渡すと、1ピクセル目はa[0],a[1]が適用され赤に、2ピクセル目はa[2],a[3]が適用され青となります。

  • glcd_all(unsigned char *data)
    • glcd_array()の全画面版です。

  • glcd_all_p(unsigned char *data)
    • 圧縮されたデータが格納された配列用です。
    • また別の記事にて紹介したいと思います。


・移植について
このライブラリを他の環境で使用したい場合、まずgcolor.cとgcolor.hをプロジェクトに入れます。
一番変更に手間がかかる部分は多分write_command()とwrite_data()です。
ここには自分が使うマイコンに応じてSPIの1バイト書き込み処理を記述します。
次にglcd_init()内のdelay_ms関数を自分の環境に応じて変更してください。
その他注意する点はソースコードに書いてあります。

・回路図、PICの動作モード
右のコネクタがglcdを表しています。
またパスコン等は省いています。
PIC32MXはPLLで48MHz駆動にしています。

2018年5月31日木曜日

24bit BMP -> RGB565 変換ツール 組み込み向け

24bitBMPをRGB565形式でbinファイル、またはC言語配列形式でtxtに出力するツールを作りました。
またランレングス圧縮して出力する機能を備えています。


ダウンロードリンク

当ツールには下記のような7つのモードがあります。

1. 24bit BMPをRGB565に減色し、binファイルで出力します。
2. 24bit BMPをRGB565に減色し、圧縮してbinファイルで出力します。
3. 24bit BMPをRGB565に減色し、C言語の配列形式でtxtファイルに出力します
4. 24bit BMPをRGB565に減色,圧縮し、C言語の配列形式でtxtファイルに出力します。
5. binファイルをC言語配列形式で出力します。
6. binファイルを圧縮し、C言語配列形式で出力します。
7. binファイルを圧縮し、binファイルに出力します。


binファイルには画像の左上から右に向かってデータが格納されています。
圧縮の方式はランレングス圧縮です。
仕組みが簡単なので圧縮も簡単ですが、高精細な画像とかを圧縮するとかえってデータサイズが大きくなります。
背景が冗長な画像などには大きな効果があります。
本ツールの2,4,6,7モードでは圧縮率が表示されます。
圧縮率が0.5なら、圧縮によってデータサイズは50%になっています。

圧縮後のデータ形式は

{ 次の2byteで示される色が連続する数(1byte) , RGB565下位(1byte) , RGB565上位(1byte) }

のように出力され、画素数が255を超える場合は上記3byteブロックが複数にわたって出力されます。
例えば画素数が300ならば、データは

{ 0xFF(255個) , RGB565下位 , RGB565上位 , 0x2D(45個) , RGB565下位 , RGB565上位}

というふうになります。

以下の画像は実際にbmp画像を変換してみた例です。

出力形式,圧縮形式などの詳しい説明はreadme.txtに記載していますのでご覧ください。

2016年12月11日日曜日

PIC16F1939でHC-SR04を使う

PIC16F1939を使ってHC-SR04を使ってみました。
HC-SR04は超音波を使用した距離センサーで2cm~400cmまで対応しているそうです。
このセンサーはAmazonで200円程度(中国配送)で販売しているので気軽に使うことができます。
このセンサーを使用してみた感想ですが、近距離(~1mくらい)では誤差がプラマイ5cm以下位で結構良いと思いました。
しかし。自分の使い方が悪いのか、長距離(1.5m~2m以上)を測ろうとすると短距離の数値が出てきてしまいました。しかしたまに出る正しい数値の精度は良好です。



このセンサーの使い方を説明します。
このセンサーからは4ピン出ていて、Vcc,Echo,Trig,Gndです。VccとGndは電源(5v)です。
距離取得までの手順ですが、簡単に説明していくと、まずTrig端子に10μs以上のパルスを与えます。その後、しばらくするとEcho端子からパルスが出力されます。このパルスの長さが超音波が対象物まで往復するのに掛かった時間になります。

サンプルプログラム
PIC16F1939を使用したサンプルプログラムです。
このサンプルでは、HC-SR04以外にAQM1602Aというi2cLCDとタクトスイッチと10Kの抵抗を使用しています。
余談ですがAQM1602という液晶は秋月電子で売っているのですが、めちゃくちゃ便利なのでおすすめです。sc1602とかより断然いいです。
PICと各パーツとの接続は
RB5 --- HC-SR04のEcho
RD6 --- HC-SR04のTrig
RC3 --- AQM1602AのSCL
RC4 --- AQM1602AのSDA
RB0 --- タクトスイッチ
簡単な回路なので回路図は省略します。
PICと接続するスイッチはRB0を10Kの抵抗でプルアップしてください。なので、
スイッチを押したら0Vになるようにしてください。
あとPICのMCLRピンの抵抗もお忘れなく。

Echoパルスの時間の測り方っていろいろあると思うんですが、今回のプログラムでは、タイマー1のゲート機能を使用しました。今回のゲート機能の動作は、タイマー1ゲートピン(RB5)がHIの間のみタイマーをカウントするというものです。
今回、タイマーはFosc / 4を源として、1/4プリスケーラを使用しています。
あと今回のプログラムではセンサーから取得できる最大距離は557cmになっています。
これだと若干無駄な気がするので、プリスケーラを1/1にすれば最大距離は約139cmになってしまいますが、精度は上がると思います。プリスケーラを1/1するには
T1CONの値を0b00100101 から 0b00000101へ
a = ((0.03125 * counter * 4 * 4) / 29.4117) / 2 の部分を
a = ((0.03125 * counter * 4 ) / 29.4117) / 2 へ変更してください。
あと上のa=の式は距離を求めるものなのですが、0.03125は32Mhzの周期(単位μs)、
29.4117は音が1cm進むのに掛かる時間(単位μs)となっています。

サンプルプログラムの内容ですが、電源を入れると画面には何も表示されません。
スイッチを押すたびにlcdの1行目にタイマーの値が、2行目に対象物との距離(単位cm)が表示されます。あともしタイマーの値が32767(16bit int型最大値)を超えていると-表示になります。
ですがプログラム中には正常に動作しています。

質問、指摘等ありましたら是非コメントお願いします。
ありがとうございました。

2016年2月14日日曜日

イオン風 ビーフェルド-ブラウン効果の原理の実験

Amazonで安く販売されていた高電圧発生モジュールを使ってイオン風を発生させてみました。
イオン風は高電圧放電によってイオン化された空気の移動です。(wikpediaより)
ビーフェルド-ブラウン効果はこのイオン風で推力を得る現象だそうです。(Wikiより)

構成は片方の極に筒を繋ぎ、もう片方には尖った線をつないでいます。
筒はトイレットペーパーの芯を切ってアルミホイルを巻いてあります。

動画でイオン風でライターの炎が消えるのが確認できます。


2016年2月13日土曜日

ESP-WROOM-02をPICで使ってみた感想

PIC24F64ga002でESP-WROOM-02を使ってみました。
このESP-WROOM-02は秋月電子で単体で550円、変換基板付きでも1000円以下で買えます。これだけ手軽な値段でWifiモジュールが手に入るとは思っていなかったので初め見たときは衝撃でした。
無線が安価で使えるとマイコンの可能性、楽しみがさらに広がります。

自分はこのモジュールをATコマンドを使って制御しました。マイコンとの通信方法はUARTです。
このモジュールを使ってみた感想ですが、正直面倒くさいなと思いました。これまで自分はいろいろセンサー、モジュールを使ってきたのですが、それら全てマイコンからのモジュールへの指令、モジュールからの実行結果の表し方は数字でした。数字というのは例えばマイコンがモジュールへ『~~を実行しろ』というとき(0x0A)などの数字を送信し、モジュールがマイコンに『エラー発生』などを返すとき、エラーコードとして(0x01)を送るなどとして決まった通信方法でやりとりしていました。
しかし、このwifiモジュールでは命令、結果のやりとりは全て文字列です。
例えばWifiモジュールのバージョンを確認する際"AT+GMR"という文字列を送信します。まあこの辺はまだ普通ですが、モジュールからの結果がバラバラで面倒くさいのです。モジュールから結果が帰ってくるとき『OK』『ERROR』『SEND OK』『CLOSED』だの命令によって結果がばらばらです。命令ごとに対応する結果を決めなければいけないので面倒だと思いました。まあこう思うのも自分の経験不足でしょう。

しかし安価でWifiモジュールが手に入るのは革命だなと思いました、ぜひ買ってみてください。
また今度、PIC+このモジュール+温度センサーでTwitterへ自動投稿する物を作ってみたので紹介したいと思います。

2016年2月1日月曜日

PIC16 PWM周波数 PR2計算ソフト

PIC16でPWMを使うとき周波数やPR2の値をわざわざ電卓で計算していたのですが、面倒くさかったのでソフトを作りました。


使い方

まずここからダウンロードしてください。
ダウンロード
zipですので解凍したらNewPro.exeというのが出てくると思いますのでコマンドプロンプトで開いてください。

モードが二つ有り、1つ目はPR2、プリスケーラ値、PICのクロックからPWMの周波数を求める場合。
二つ目はPWMの周波数、PICのクロック、プリスケーラ値からPR2の値を求める場合。


注意

先ほどの2のモードで出たPR2の値は低くれば低いほどPWMの分解能が悪くなります。
また求めたPR2の値が255以上の場合はPICのPR2レジスタに入れても期待通りになりません(PR2は8bitの容量)。ですのでもし超えた場合はプリスケーラはクロックを変更してください。