PICマイコンで作るPhotoフレーム
<PICで作るデジタルフォトフレーム>
SPI接続の480x320ピクセルのTFT LCDの安いものが無いかと探していると、中華製で760円で売りに出ているのを発見。1500円以上購入すると送料無料とのことで、ついでに320x240のLCDと半田吸い取り網線2巻をまとめて1520円でゲット。
2024年に作成した320x240ピクセルのLCDにSDカードに保存したBMP画像を表示する基板をジャンク箱から探し出し、今回購入した480x320ピクセルのLCDへ改造する事にしました。
上がTS1931Wという品番の480x320ピクセルのLCDです。使っているLCDドライバーICはST7796S。PICとのインターフェースはパラレルとシリアルを選択できますが、デフォルトは4線式SPIに設定されていました。
ドライバーICの変更に伴い、ソースファイルを手直しする事1日。 簡単にBMP画像を表示出来るようになりました。
左のスクリーンコピーがヘッダーファイルとソースファイルの全てです。 ファイル名は2024年に試作した時と同じ名前になっていますが、ソースファイルの一部が変更されています。
これらの全てのファイルはzipファイルでダウンロードできます。
SDカードにセーブされるBMPファイルは、縦型で水平方向のピクセルは320ピタリでなければなりません。縦方向は480ピクセルですが、こちらは480以上有っても480を超えたラインは切り捨てられます。画像描写はBMP画像の下から上へスィープしますので、画像の上部が切り取られる事になります。 目安としては最大490ピクセルくらいです。
また、SDカード内のBMPファイルのファイル名はFAT32のロングファイル名を使う事ができますが、PIC側が日本語対応していないので、英文に限られます。 SDカード内のファイル名はDIRキーでLCD上に表示できますが、この時の表示はMS-DOSの8+3式の大文字の表示に限られます。ファイル名が8文字を超える場合、8文字目が数字になってファイルの識別をおこないますので、ロングファイル名がOKと言っても、SDカード内のファイル名も8文字以内に制限していた方が無難です。
下の写真はデバッグ中のバラック回路と480x320ピクセルで表示したLCDです。 フォトフレームとして使える様にケースを探す事にします。
TFT LCDにBMPファイルを表示する基本機能が出来上がりましたので、次は、これをケースに収納し、曲りなりにも、写真を飾れるようにします。 しかし、市販されている1万円を超えるような仕上がりには程遠く、写真を飾ると言うより、プログラムのデバッグを楽しむというレベルにしかならないようです。
まず、ケースですが、ダイソーのブリキの箱で、以前周波数カウンターを送信機の中に内蔵するとき、高周波の妨害を防ぐ為のシールドBOX用に買ってあったのですが、サイズが大きすぎて、未使用となっていたのを流用します。このLCDを収納するにはちょうど良さそうです。
元になるJPEG画像を撮影したのは、キャノン、SONYのコンパクトデジカメ各1台、PENTAXの一眼レフデジカメ2台、計4台のカメラからですが、この4台の縦横のピクセル数と、縦横のピクセル比が全て違います。今回のフォトフレームの縦横のピクセル数は480x320限定であり、PCでBMPファイルのサイズを320x480ピクセルサイズにサイズ変更するのが、以外と大変でした。 そこで、BMPファイルのピクセルサイズは、短い方のピクセル数を320に指定する必要がありますが、長い方のピクセル数はカメラの縦横比のままのピクセル数でも、画像の中心をほぼ維持した上で、LCDサイズよりはみ出す部分があっても、LCDサイズより小さな画像も画面のほぼ中央に持ってくるような処理も追加しました。 PCで簡単に出来る、画像の縮小や拡大はPICではほぼ無理なので、高望みしない事にします。
電源は5V出力のACアダプターを使用しますが、電源ON時、前回まで表示していた画像を継続表示するよう、ラストメモリー機能付きにしました。 最初、記憶して置くのは、ファイルインデックスにしたのですが、SDカードの中のファイルをPCで追加、削除した場合、違ったファイルを読み出してくる場合があり、ファイルネームを記憶させる事に変更しました。
使用できるSDカードはSD HCのみです。 DIRで呼び出せるファイル数は最大30までです。SDカード内にファイルを追加する場合、30以内になるよう不要のファイルを削除必要です。
このPICのRAMサイズの場合、最終的には最大512枚までメモリーを確保しました。
しばらくは、使い勝手の改善のためにデバッグが続きそうです。
LCDドライバーIC ST7796SのLCD向きは縦長オンリーで、通常横長の写真が多い中、作成するBMP画像は常に縦長の状態でSDカードへ記録する必要があります。 また、ファイル名の表示も縦長しかできません。 だから安かったのかな。
現在表示出来るBMP画像の総数は最大64枚ですが、確認は28枚しかやっていません。
PICのBMP画像表示プログラム BMP_display_480x320_091.cをダウンロード
SDカードアクセスプログラム SD_main_091.cをダウンロード
上の2点のみは、zipファイルに含まれるプログラムより更新されています。ファイルの中でGIFという文字が沢山出てきますが、これは本来BMPに変更しなければならなかったのですが、それを上記ふたつのファイルで行うと、コンパイルエラーが続出し、修正を諦めました。 多分、ソースプログラムだけでなく、ヘッダーファイルの中にもGIFの文字があるのでしょう。
2026年8月4日
このフォトフレームはこれで完成ではなく、スライドショーが可能になるまでやります。
一応、スライドショーが可能になり、かつ扱えるBMPファイルの数も512までとなりました。
以前のバージョンでは28枚以上の画像をSDカードに記録していなかったので、68枚まで増やし確認すると、ハングアップしました。原因は配列メモリーの設定ミスでした。 気にしていたGIFの文字を全てBMPに変えました。
MPLAB Xの中のファイルもいくつか修正がはいりましたので、ファイルリストを左に示します。
以前のコンパイル状態から、修正が有ったファイルのみ名前を変更してあります。 名前が変更になったファイルは個別にダウンロードできるようにします。
スライドショーのON/OFFは新たに追加したスライドSWで切り替えます。スライド間隔の最小時間を当初15秒に設定したのですが、画像の描画速度が遅く、描画完了と同時に次の画像描画の動作になりますので、ゆっくりみられません。従い、最小時間間隔は20秒とし、30,45,60,90秒、2,3,4,5,7,10,15,20分と選択できるようにしました。DIRキーとUP/DOWNキーで選択できます。 画像の表示順序はSDカードに記録された順序のままで、変更はできません。
電源OFFのときラストメモリー機能がありますので、次に立ち上げた時は、その画像を最初に表示します。 windowsの中で使われている文字コードは2バイトなので、PICの中で扱う文字は1バイトに変換していますが、SDカード内のファイルを検索する場合、また、2バイトコードに変換する必要があります。この変換はキャスト変換を使っていますので、プログラムの中にある、変換関数は使っていません。変換関数は初期のころ、デバッグ用に作成したものが、そのまま残っているものです。
以下のファイルをダウンロードできます。
BMP_display_480x320_092.cをダウンロード
BMP_display_system_092.hをダウンロード
上はスライドショーモードで画面が切り替わる途中のショットです。
さらに243枚までBMP画像を追加し、かつ、360x480の画像も50枚以上入れましたが、画像表示の乱れはありませんでした。という事は横方向(短い方)のピクセル数が320でなくても、正常に表示できる条件があるという事です。 短い方のピクセル数が320以外の、色々なサイズのBMPファイルを作り確認しましたが、OKとNGの条件が判らず、1週間くらい悩みました。そして判った原因はBMPファイルの4バイト境界とパッディングでした。 BMP画像を表示するとき、空読みを追加して解決しました。(赤色の言葉で検索すると、その意味を説明するサイトがいっぱい表示されます)
void Bmpdisplay(int grx, int gry, int col, int row,uint16_t *file) {
us char c1,c2,cr,cg,cb,cd,d;
int pad,xmax;
int G_col=col-1;
int G_row=row-1;
int x,y,xofset,yofset,xsweepend,ysweepend;
lcd_CMD(0x36);
lcd_DATA(0b11011000);
xofset = 0;grx = 0;
yofset = 0;gry = 0;
set_col_range(0,319);
set_row_range(0,479);
pad = (col * 3)%4;
if (pad != 0){pad = 4-pad;}
xmax = G_col;
if (col > 320){
xofset = (col - 320)/2;
}
if (row > 480){
yofset = (row - 480)/2;
}
if (col < 320){grx = (320-col)/2;
write_line(0,0,grx,479,8);//Xs,Ys,Xe,Ye,Color
write_line(319-grx,0,319,479,8);//Xs,Ys,Xe,Ye,Color
// set_col_range(grx,(grx + G_col));
}
if (row < 480){gry = (480-row)/2;
write_line(0,0,319,gry,8);//Xs,Ys,Xe,Ye,Color
write_line(0,479-gry,319,479,8);//Xs,Ys,Xe,Ye,Color
set_row_range(gry,(gry + G_row));
}
if (col < 320){set_col_range(grx,(grx + G_col));}
xsweepend = xofset + 319;ysweepend = yofset + 479;
lcd_CMD(0x2C);//色データ書き込み
for (y=0;y<=G_row;y++) {
for (x=0;x<=xmax;x++) {
cb=FILEIO_GetChar(file);
cg=FILEIO_GetChar(file);
cr=FILEIO_GetChar(file);
if (((x >= xofset) && (x <= xsweepend)) && ((y >= yofset) && (y <= ysweepend))){
lcd_DATA(cr);
lcd_DATA(cg);
lcd_DATA(cb);
}
if (x == xmax){
for (d = 1;d<=pad;d++){
cd=FILEIO_GetChar(file);
}
}
}
}
}
赤色の部分がBMPdisplay関数の中に追加したプログラム行になります。 縦方向の320ピクセルを任意のピクセルにしてもOKという事は、原画を任意のピクセルでトリミング出来るという事ですから、原画にある余計な背景を消したり、原画ではかなり小さく写っている被写体を画面一杯に拡大する事ができます。 その時、縦横比を厳密に意識しなくても良いという事は編集がものすごく楽です。
ファイル数が243枚ともなると、探すのに手間がかかります。そこで、DIRを続けて押すと、20枚づつ早送り出来る機能と最後のファイル名を選択した状態でさらにダウンを押すと、最初の画像に帰り、最初の画像を選択中にUPキーを押すと、最後のDIR表示ページへ飛ぶように変更しました。
1画面の描画時間を約4秒短縮できたので、スライドショーの画面切り替え最小時間を15秒に戻しました。 また、扱えるBMPファイル数も最大800枚としました。
以下のソースのみ入れ替えると実現できます。
BMP_display_480x320_101.cをダウンロード













