「Raspberry Pi Pico」に「microSD(TF)カードリーダー」と「TFT液晶ディスプレイ」を搭載した「RP2040-GEEK」の使い方を詳しく紹介します。
「Pico」の基本的な使用方法や「ArduinoIDE」を使用した開発環境の準備等は以下のリンクで詳しく紹介しています。
1.RP2040-GEEKとは
2.外観、デモ画面
・外観
・デモ画面
3.基本仕様
4.端子配列、端子機能
5.動作確認に使用した配線図
6.ArduinIDEの初期設定
・インストール、初期設定
・ボード選択、シリアルポートの選択
・ライブラリの準備
7.サンプルプログラムで動作確認
・液晶表示の使い方
・入出力端子、アナログ入力の使い方
・microSD(TF)カードの使い方
・JPEG画像データの表示
8.本体の初期化方法
9.まとめ
1.RP2040-GEEKとは
「RP2040-GEEK」とは、中国の電子部品メーカーで「Raspberry Pi」や「Arduino」に関連した製品を多数展開している「WAVESHARE」製のシングルボードコンピューターです。
コントローラーには「Raspberry Pi Pico」と同じ「RP2040」が使用されており、使用方法も「Pico」と同じように使用することができます。
個別に各部品を揃えて配線するよりもコンパクトで安価に実現することができます。
使用できる端子は「Pico」と比べると少ない(計6点)ですが、3つのコネクタが搭載されており、全て入出力端子として使用でき、各種通信(UART、I2C)、アナログ入力にも割り付けて使用できます。
その他、USB(Type-A)搭載で直接パソコンに接続して開発が可能です。
専用のファームウェアを書き込めば「デバッグプローブ」としても使用可能で、コネクタ付配線も付属しています。
「Paspberry Pi Pico」の使い方や「Pico」をデバッグプローブとして使用する方法は以下のリンクで詳しく紹介しています。
処理速度が速くなりメモリは倍増した「Pico2」と同じ「RP2350」を搭載した「RP2350-GEEK」も発売されているので用途に応じて選定しましょう。
2.外観、デモ画面
外観や工場出荷時のデモ画面については以下のようになります。
・外観
梱包状態は上画像のように届きました。
箱は少し潰れて届きましたがいつものことです^^
中身は上画像のように本体と付属のコネクタ付き配線が入っています。
各コネクタ付配線は上画像のように接続して使用できます。
USB Type-Aが搭載されて、直接パソコンに接続して使用できますが、USBメモリーのように直接データを保存するのは難しいと思います。
側面にはJST製のSHコネクタが3箇所搭載されています。「Raspberry Pi Pico」と同じ機能の「BOOT」ボタンも側面にあります。
microSD(TF)カードのスロットも搭載されており、microSDカードを使用したプログラムの開発をすぐに行うことができます。
・デモ画面
工場出荷時のデモ画面は以下のような6つの画面が順番に繰り返し表示されます。
3.基本仕様
「RP2040-GEEK」の基本仕様は「Raspberry Pi Pico」と同じで、以下表のようになります。
使用できる端子は「Pico」より少なく合計6点となります。
項目 | 詳細 |
---|---|
コントローラ | RP2040 |
クロック | 最大133MHz (デュアルコア Arm Contrex M0+プロセッサ) |
Flash / SRAM | 2MB / 264kB |
電源電圧(USB) | DC5V±10% |
USB | USB Type-A |
入出力 | 多機能GPIO x 6 |
通信機能 | UART x 2 / I2C x 2 SPI x 2(液晶表示器とSDカードリーダーで使用) |
アナログ入力 | ADC(12bitアナログコンバータ) x 2 |
液晶表示器 | SPI1 1.14-inch 240×135(ST7789VW) Pixel 65K color IPS LCD display |
TF(microSD) カードリーダー | SPI0 SDIO interface |
寸法 | W61 x H25 x D9 (mm) |
4.端子配列、端子機能
端子配列について、出力端子は全てコネクタになっていて使用できるのは「6ピン」分だけです。
コネクタは3箇所あり「Raspberry Pi Pico」の「BOOTSEL」ボタンと同じ機能の「BOOT」ボタンも側面にあります。
端子機能の詳細は以下表のようになります。
コネクタ経由で使用できる端子「GP2〜5,28,29」は全て「入出力端子」として割り付けて使用することができます。
アナログ入力は「ADC2/3」の2点だけ使用可能で「Raspberry Pi Pico」で自由に使用できなかった「ADC3(GP29)」が自由に使用できます。
各種通信機能も割り付けて使用できますが「UART、I2C」ともに2系統ある通信の使用できるコネクタが決まっているため、上表で番号を確認して割り付けて使用してください。
5.動作確認に使用した配線図
今回の動作確認に使用した配線図は以下のようになります。
microSDカードの動作確認には別途microSDカードが必要です。(16GBで動作確認済)
「スイッチ」と「LED」「ボリューム」は入出力とアナログ入力の確認に必要です。
microSD(TF)カードの動作確認には「スイッチ」のみ使用します。
LEDやボリュームの使い方は以下のリンクで詳しく紹介しています。
6.ArduinIDEの初期設定
・インストール、初期設定
開発環境に使用する「ArduinoIDE」のインストール方法は以下のリンク先で詳しく紹介しています。
「AruduinoIDE」の使用方法、プログラムの書き込み方法は「Raspberry Pi Pico」と同じで以下のリンク先で詳しく紹介しています。
・ボード選択、シリアルポートの選択
「RP2040-GEEK」は「Raspberry Pi Pico」と同じように使用できるため「ボード」の選択は下画像のように「Raspberry Pi Pico」を選択してください。
シリアルポートの選択は、下画像のようにRP2040の互換ボードとして認識されるようなので、以下のように認識されているポートを選択してください。
・ライブラリの準備
「RP2040-GEEK」を使用するために最低限必要なライブラリは以下になります。
・Adafruit ST7735 and ST7789 Library:ST7789液晶ディスプレイ制御用
・SD:SDカード操作用
・JPEGDecoder:JPEG画像デコード用(JPEG画像を表示しないなら不要)
「ArduinoIDE」でライブラリをインストールする方法は以下のリンク先で詳しく紹介しています。
7.サンプルプログラムで動作確認
動作確認用のサンプルプログラムとして以下の4種類を準備しました。
・液晶表示の使い方
サンプルプログラムを実行すると、フォントを指定した文字表示や、座標、色の指定方法、線や図形の表示等、基本的な液晶表示の使い方が確認できます。
以下がサンプルプログラムを実行した画面になります。
色の指定は以下の「Adafruit_ST7789ライブラリ」に登録されている色か、16ビット(565)カラーで指定できます。
// 登録色一覧(16bit指定値)
ST77XX_BLACK // 黒(0x0000)
ST77XX_WHITE // 白(0xFFFF)
ST77XX_RED // 赤(0xF800)
ST77XX_GREEN // 緑(0x07E0)
ST77XX_BLUE // 青(0x001F)
ST77XX_CYAN // 水色(0x07FF)
ST77XX_MAGENTA // 紫(0xF81F)
ST77XX_YELLOW // 黄(0xFFE0)
ST77XX_ORANGE // 橙(0xFC00)
フォントは下画像のように「Adafruit_GFX_Library」内の「Fonts」フォルダ内にたくさんあります。
ファイル名がフォント名になるので、いろいろ読み込んで試してみてください。
液晶表示のサンプルプログラムは以下になります。
コピペで貼り付けて書き込んでください。コピーは下の黒塗り部右上のアイコンクリックでもできます。
#include <Adafruit_GFX.h> // Adafruitのグラフィックスライブラリ
#include <Adafruit_ST7789.h> // ST7789液晶ディスプレイ用のライブラリ
#include <SPI.h> // SPI通信を行うためのライブラリ
#define TFT_CS 9 // TFT液晶のCSピン
#define TFT_DC 8 // TFT液晶のDCピン
#define TFT_MOSI 11 // TFT液晶のMOSIピン
#define TFT_SCK 10 // TFT液晶のSCKピン
#define TFT_RST 12 // TFT液晶のRSTピン
// Adafruit_GFXのフォント読み込み(必要なものだけ有効にする。他にもたくさんあります)
// #include <Fonts/FreeMono12pt7b.h>
#include <Fonts/FreeSans12pt7b.h>
// #include <Fonts/FreeSerif12pt7b.h>
// #include <Fonts/FreeMonoBold12pt7b.h>
// #include <Fonts/FreeSansBold12pt7b.h>
// #include <Fonts/FreeSerifBold12pt7b.h>
#include <Fonts/FreeSansBold18pt7b.h>
Adafruit_ST7789 tft = Adafruit_ST7789(&SPI1, TFT_CS, TFT_DC, TFT_RST); // TFT液晶のインスタンス設定
// 初期設定 -----------------------------------------
void setup(void) {
Serial.begin(9600); // シリアル通信初期化
// SPI1初期設定(TFT液晶用)
SPI1.setSCK(TFT_SCK); // TFTのSCK (GP10)
SPI1.setTX(TFT_MOSI); // TFTのMOSI (GP11)
// 出力端子初期設定
pinMode(25, OUTPUT); // TFTバックライト用端子
digitalWrite(25, HIGH); // TFTバックライト点灯
// TFT液晶の初期設定
tft.init(135, 240); // TFT初期化(画面サイズ指定)
tft.fillScreen(0x2102); // 背景の塗りつぶし(16bitカラーで指定)
tft.setRotation(3); // 画面回転(0-3)
}
// メイン -----------------------------------------
void loop() {
// タイトル表示
tft.setTextSize(1); // 文字サイズ(1)
tft.setFont(&FreeSans12pt7b); // フォント
tft.setTextColor(ST77XX_GREEN); // 文字色(登録色で指定)
tft.setCursor(6, 20); // 表示開始位置左上角(X,Y)
tft.println("LCD"); // 表示内容
tft.setCursor(0, 45); // 表示開始位置左上角(X,Y)
tft.println("TEST"); // 表示内容
tft.setTextSize(2); // 文字サイズ(2)
tft.setTextColor(ST77XX_ORANGE); // 文字色
tft.setCursor(75, 40); // 表示開始位置左上角(X,Y)
tft.println("ST7789"); // 表示内容
tft.setTextSize(1); // 文字サイズ(1)
tft.setFont(&FreeSansBold18pt7b); // フォント
tft.setTextColor(0x02DF); // 文字色(16bitカラーで指定)
tft.setCursor(5, 83); // 表示開始位置左上角(X,Y)
tft.println("RP2040-GEEK"); // 表示内容
// 図形表示
tft.drawLine(0, 50, 240, 50, ST77XX_WHITE); // 線(始点終点指定)
tft.drawFastVLine(68, 0, 45, ST77XX_CYAN); // 線(指定座標から垂線)
tft.drawFastHLine(0, 90, 240, ST77XX_WHITE); // 線(指定座標から平行線)
tft.drawCircle(16, 113, 16, ST77XX_YELLOW); // 円
tft.fillCircle(52, 113, 16, ST77XX_RED); // 円(塗り潰し)
tft.drawTriangle(69, 130, 89, 95, 109, 130, ST77XX_BLUE); // 三角
tft.fillTriangle(114, 130, 134, 95, 154, 130, ST77XX_CYAN); // 三角(塗り潰し)
tft.drawRect(159, 95, 36, 36, ST77XX_GREEN); // 四角
tft.fillRect(200, 95, 36, 36, ST77XX_MAGENTA); // 四角(塗り潰し)
delay(500); // 遅延時間
}
・入出力端子、アナログ入力の使い方
サンプルプログラムを実行すると、基本的な入出力端子の動作確認とアナログ入力の使用方法を確認できます。入出力端子は全ての端子(GP〜)に割り付けて使用できます。
動作確認用の配線図は下画像のようになります。
以下が実際に動作確認している画像になります。
プログラムを実行すると液晶画面に2つのアナログ入力値と電圧換算値が表示されます。
ボリュームを操作すると各数値が変化するのが確認できます。
スイッチ1(赤)を押すとLED1(赤)が点灯して画面背景色が赤色になります。
スイッチ2(黄)を押すとLED2(黄)が点灯して画面背景色が黄色になります。
入出力、アナログ入力の動作確認をするサンプルプログラムは以下になります。
コピペで貼り付けて書き込んでください。コピーは下の黒塗り部右上のアイコンクリックでもできます。
#include <Adafruit_GFX.h> // Adafruitのグラフィックスライブラリ
#include <Adafruit_ST7789.h> // ST7789液晶ディスプレイ用のライブラリ
#include <SPI.h> // SPI通信を行うためのライブラリ
#define TFT_CS 9 // TFT液晶のCSピン
#define TFT_DC 8 // TFT液晶のDCピン
#define TFT_MOSI 11 // TFT液晶のMOSIピン
#define TFT_SCK 10 // TFT液晶のSCKピン
#define TFT_RST 12 // TFT液晶のRSTピン
// Adafruit_GFXのフォント読み込み
#include <Fonts/FreeSans12pt7b.h>
Adafruit_ST7789 tft = Adafruit_ST7789(&SPI1, TFT_CS, TFT_DC, TFT_RST); // TFT液晶表示用のインスタンス設定
// 初期設定 -----------------------------------------
void setup(void) {
Serial.begin(9600); // シリアル通信初期化
// SPI1初期設定(TFT液晶用)
SPI1.setSCK(TFT_SCK); // TFTのSCK (GP10)
SPI1.setTX(TFT_MOSI); // TFTのMOSI (GP11)
// 出力端子初期設定
pinMode(25, OUTPUT); // TFTバックライト用端子
digitalWrite(25, HIGH); // TFTバックライト点灯
pinMode(2, OUTPUT); // LED1用端子
pinMode(3, OUTPUT); // LED2用端子
digitalWrite(2, LOW); // LED1消灯
digitalWrite(3, LOW); // LED2消灯
// 入力端子初期設定
pinMode(4, INPUT_PULLUP); // スイッチ1用端子
pinMode(5, INPUT_PULLUP); // スイッチ2用端子
// アナログ入力初期設定
analogReadResolution(12); // 分解能12bit(0〜4095)
// TFT液晶の初期設定
tft.init(135, 240); // TFT初期化(画面サイズ指定)
tft.fillScreen(ST77XX_BLACK); // 背景の塗りつぶし
tft.setRotation(3); // 画面回転
tft.setFont(&FreeSans12pt7b); // フォント
}
// メイン -----------------------------------------
void loop() {
// スイッチ状態確認、LED点灯/消灯、画面色変更
if (digitalRead(4) == false) { // スイッチ1がONなら
tft.fillScreen(ST77XX_RED); // 背景の塗りつぶし
digitalWrite(2, HIGH); // LED1点灯
} else if (digitalRead(5) == false) { // スイッチ2がONなら
tft.fillScreen(ST77XX_YELLOW);// 背景の塗りつぶし
digitalWrite(3, HIGH); // LED2点灯
} else { // スイッチが押されてなければ
tft.fillScreen(ST77XX_BLACK); // 背景の塗りつぶし
digitalWrite(2, LOW); // LED1消灯
digitalWrite(3, LOW); // LED2消灯
}
// アナログ入力処理
float ad_val1; //アナログ入力2変換値(0~4095)格納用
float ad_volt1; //アナログ入力2電圧(0~3.3V)格納用
float ad_val2; //アナログ入力3変換値(0~4095)格納用
float ad_volt2; //アナログ入力3電圧(0~3.3V)格納用
ad_val1 = analogRead(28); //アナログ入力2変換値(0~4095)取得
ad_volt1 = (3.3 / 4096) * ad_val1; //アナログ入力2電圧(0~3.3V)換算
ad_val2 = analogRead(29); //アナログ入力3変換値(0~4095)取得
ad_volt2 = (3.3 / 4096) * ad_val2; //アナログ入力3電圧(0~3.3V)換算
// 液晶画面表示
tft.setCursor(0, 17); // カーソル位置
tft.setTextColor(ST77XX_WHITE); // 文字色
tft.println("I/O, ANALOG TEST"); // 文字表示
tft.setTextColor(ST77XX_GREEN); // 文字色
tft.printf("Value1 : %.0f\n",ad_val1); // 文字表示
tft.printf("Volt1 : %3.2fV\n",ad_volt1);
tft.setTextColor(ST77XX_ORANGE); // 文字色
tft.printf("Value2 : %.0f\n",ad_val2); // 文字表示
tft.printf("Volt2 : %3.2fV",ad_volt2);
delay(300);
}
・microSD(TF)カードの使い方
サンプルプログラムを実行すると、microSD(TF)カードにデータを保存したり、データを読み出して画面に表示させたり、保存したファイルを削除する動作が確認できます。
読み出しボタン長押しでデータを保存したファイルを削除できます。
以下が実際に動作確認している画像になります。
プログラムを実行すると上画像のような画面が表示されます。
スイッチ1を押すごとに上画像のように電源ONしてからの経過時間が表示され、microSDカードにプログラムで指定したファイル名(test.txt)で保存されます。
スイッチ2を押すと上画像のように保存されたデータを読み出して液晶画面に表示します。
スイッチ2を長押し(2秒以上)するとデータが保存されているファイルが削除されます。
最低限のエラーも下画像のように表示されます。
microSDカードが入っていない時のエラー
ファイルを削除しようとした時にファイルが見つからなかった時のエラー
microSD(TF)カードの読み書きを行うサンプルプログラムは以下になります。
コピペで貼り付けて書き込んでください。コピーは下の黒塗り部右上のアイコンクリックでもできます。
#include <Adafruit_GFX.h> // Adafruitのグラフィックスライブラリ
#include <Adafruit_ST7789.h> // ST7789液晶ディスプレイ用のライブラリ
#include <SPI.h> // SPI通信を行うためのライブラリ
#include <SD.h> // SDカード操作用のライブラリ
#define TFT_CS 9 // TFT液晶のCSピン
#define TFT_DC 8 // TFT液晶のDCピン
#define TFT_MOSI 11 // TFT液晶のMOSIピン
#define TFT_SCK 10 // TFT液晶のSCKピン
#define TFT_RST 12 // TFT液晶のRSTピン
#define SD_CS 23 // SD(TF)カードリーダのCSピン
#define SD_MISO 20 // SD(TF)カードリーダのMISOピン
#define SD_MOSI 19 // SD(TF)カードリーダのMOSIピン
#define SD_SCK 18 // SD(TF)カードリーダのSCKピン
#include <Fonts/FreeSans12pt7b.h> // Adafruit_GFXのフォント読み込み
#define SWITCH_PRESS_TIME 2000 // スイッチ2長押し時間(ms)
#define SD_FILENAME "/test.txt" // SD(TF)カードに保存するファイル名
Adafruit_ST7789 tft = Adafruit_ST7789(&SPI1, TFT_CS, TFT_DC, TFT_RST); // TFT液晶表示用のインスタンス設定
// 変数宣言
unsigned long lastPressedTime = 0; // スイッチ2の最後に押された時間保持用
bool swState1 = false; // スイッチ1状態保持用
bool swState2 = false; // スイッチ2状態保持用
// 初期設定 -----------------------------------------
void setup(void) {
Serial.begin(9600); // シリアル通信初期化
// SPI0初期設定(SDカード用)
SPI.setTX(SD_MOSI); // SD(TF)カードリーダのMOSI(GP19)
SPI.setRX(SD_MISO); // SD(TF)カードリーダのMISO(GP20)
SPI.setSCK(SD_SCK); // SD(TF)カードリーダのSCK(GP18)
// SPI1初期設定(TFT液晶用)
SPI1.setSCK(TFT_SCK); // TFTのSCK (GP10)
SPI1.setTX(TFT_MOSI); // TFTのMOSI (GP11)
// 出力端子初期設定
pinMode(25, OUTPUT); // TFTバックライト用端子
digitalWrite(25, HIGH); // TFTバックライト点灯
pinMode(2, OUTPUT); // LED1用端子
digitalWrite(2, LOW); // LED1消灯
pinMode(3, OUTPUT); // LED2用端子
digitalWrite(3, LOW); // LED2消灯
// 入力端子初期設定
pinMode(4, INPUT_PULLUP); // スイッチ1用端子
pinMode(5, INPUT_PULLUP); // スイッチ2用端子
// TFT液晶の初期設定
tft.init(135, 240); // TFT初期化(画面サイズ指定)
tft.fillScreen(ST77XX_BLACK); // 背景の塗りつぶし
tft.setRotation(3); // 画面回転
tft.setFont(&FreeSans12pt7b); // フォント
tft.setCursor(0, 18); // カーソル位置
// 初期表示画面
tft.println("- SD STRAGE TEST -"); // メッセージ表示
tft.drawFastHLine(0, 22, 240, ST77XX_WHITE); // 線(指定座標から平行線)
tft.println("SW1(GP4) : SAVE"); // スイッチ1をONでデータ保存
tft.println("SW2(GP5) : READ"); // スイッチ2をONでデータ読み出し
tft.println("SW2 Longpress"); // スイッチ2長押しでデータ(ファイル)削除
tft.println(" : DELETE");
// SDカードの初期化
if (!SD.begin(SD_CS)) {
Serial.println("SDカードの初期化に失敗しました");
dispMessage("SD card not found!", ST77XX_RED); // 液晶画面メッセージ表示関数呼び出し
return;
} else {
Serial.println("SDカードが初期化されました");
}
}
/*********************** 液晶画面メッセージ表示関数 **********************/
void dispMessage(const char* text, uint16_t collor) {
tft.fillScreen(collor); // 背景の塗りつぶし
tft.setCursor(0, 70); // カーソル位置
tft.print(text); // メッセージ表示
}
/************************* CSVデータ書き込み関数 ************************/
void writeSdData(const char* text) {
// SDカードのファイルを開く
File myFile = SD.open(SD_FILENAME, FILE_WRITE);
// データ書き込み
if (myFile) { // ファイルが開けたら
myFile.printf("%s : %d\n", text, millis()); // テキストとミリ秒をファイルに書き込み
myFile.close(); // ファイルを閉じる
} else { // ファイルが開けなければ
Serial.println("ファイルを開けませんでした");
dispMessage("Can't open file!", ST77XX_RED); // 液晶画面メッセージ表示関数呼び出し
}
// 書き込みデータ表示
tft.fillScreen(ST77XX_BLACK); // 背景の塗りつぶし
tft.setCursor(0, 70); // カーソル位置
tft.printf("%s : %lums\n", text, millis()); // テキストとミリ秒を画面に表示
Serial.printf("%s : %lums\n", text, millis()); // シリアル出力
}
/********************* SDカード データ読み込み関数 ********************/
void readSdData(const char* fileName) {
// SDカードのファイルを開く
File myFile = SD.open(fileName);
if (myFile) { // ファイルが開けたら
tft.fillScreen(ST77XX_BLACK); // 背景の塗りつぶし
tft.setCursor(0, 18); // カーソル位置
// データ読み込み表示
while (myFile.available()) { // ファイルにデータがあれば繰り返し
char data = myFile.read(); // データを1文字づつ読み込む
tft.print(data); // TFT出力
Serial.print(data); // シリアル出力
}
myFile.close(); // ファイルを閉じる
} else { // ファイルが開けなければ
Serial.println("ファイルが読み込めませんでした"); // シリアル出力
dispMessage("Can't read file!", ST77XX_RED); // 液晶画面メッセージ表示関数呼び出し
}
}
/********************* SDカード データ削除関数 ********************/
void deleteSdData(const char* fileName) {
if (SD.exists(fileName)) { // ファイルが存在すれば
// ファイルを削除
if (SD.remove(fileName)) { // ファイル削除が成功すれば
Serial.println("ファイルを削除しました");
} else { // ファイル削除に失敗したら
Serial.println("ファイルの削除に失敗しました");
dispMessage("Delete Failed!", ST77XX_RED); // 液晶画面メッセージ表示関数呼び出し
}
} else { // ファイルがなければ
Serial.println("ファイルが見つかりません");
dispMessage("file not found!", ST77XX_RED); // 液晶画面メッセージ表示関数呼び出し
}
}
// メイン -----------------------------------------
void loop() {
unsigned long nowTime = millis(); // 経過時間を現在時間として取得(ms)
// SDデータ書き込み処理
if (digitalRead(4) == false && swState1 == false) { // スイッチ1がONでスイッチ1状態がfalseなら
digitalWrite(2, HIGH); // LED1点灯
writeSdData("Time"); // 文字表示
swState1 = true; // スイッチ1状態をtrueへ
}
if (digitalRead(4) == true) { // スイッチ1がOFFなら
swState1 = false; // スイッチ1状態をfalseへ
digitalWrite(2, LOW); // LED2消灯
delay(50); // スイッチOFF待ち(チャタリング防止)
}
// SDデータ読み込み処理
if (digitalRead(5) == false && swState2 == false) { // スイッチ2がONでスイッチ2状態がfalseなら
// SDをデータ読み込んで内容を液晶画面に表示
readSdData(SD_FILENAME); // ファイル名を指定してSDデータ読み出し関数呼び出し
digitalWrite(3, HIGH); // LED2点灯
swState2 = true; // スイッチ2状態をtrueへ
}
// SDデータ削除処理
if (digitalRead(5) == false) { // スイッチ2がONなら
if (nowTime - lastPressedTime >= SWITCH_PRESS_TIME) { // スイッチ2が2秒以上長押しなら
lastPressedTime = nowTime; // 最後に押された時間を更新
// SDデータ削除
deleteSdData(SD_FILENAME); // ファイル名を指定してSDデータ削除関数呼び出し
dispMessage("Delete file!", ST77XX_BLUE); // 液晶画面メッセージ表示関数呼び出し
}
} else { // スイッチ2がOFFなら
swState2 = false; // スイッチ2状態をfalseへ
lastPressedTime = nowTime; // 最後に押された時間を更新
digitalWrite(3, LOW); // LED2消灯
delay(50); // スイッチOFF待ち(チャタリング防止)
}
}
・JPEG画像データの表示
サンプルプログラムを実行すると、microSD(TF)カードに保存されたJPEG画像を読み込んで、液晶画面に表示します。
「JPEGDecoder」ライブラリでは「16×16ピクセル」ごとに処理されるため、直接描画すると「16×16ピクセル」単位で描画されていきます。
サンプルプログラムでは「bitmap」配列に各データを取得してから、ビットマップ画像として一括表示させています。
以下が実際に動作確認している画像になります。
プログラムを実行すると、プログラムで指定したファイル名のJPEG画像データの情報が上画像のように表示されます。
※MCUはデコードの処理単位です。
しばらくすると、JPEG画像がデコード処理されて、上画像のようにビットマップ画像として一括表示されます。
ここで使用するJPEG画像サンプルは以下からダウンロードできます。
JPEG画像を表示するサンプルプログラムは以下になります。
コピペで貼り付けて書き込んでください。コピーは下の黒塗り部右上のアイコンクリックでもできます。
#include <Adafruit_GFX.h> // Adafruitのグラフィックスライブラリ
#include <Adafruit_ST7789.h> // ST7789液晶ディスプレイ用のライブラリ
#include <JPEGDecoder.h> // JPEG画像デコーダー用のライブラリ
#include <SPI.h> // SPI通信を行うためのライブラリ
#include <SD.h> // SDカード操作用のライブラリ
#define TFT_CS 9 // TFT液晶のCSピン
#define TFT_DC 8 // TFT液晶のDCピン
#define TFT_MOSI 11 // TFT液晶のMOSIピン
#define TFT_SCK 10 // TFT液晶のSCKピン
#define TFT_RST 12 // TFT液晶のRSTピン
#define SD_CS 23 // SD(TF)カードリーダのCSピン
#define SD_MISO 20 // SD(TF)カードリーダのMISOピン
#define SD_MOSI 19 // SD(TF)カードリーダのMOSIピン
#define SD_SCK 18 // SD(TF)カードリーダのSCKピン
#define FILENAME "/GEEK.jpg" // JPEG画像ファイル名
#include <Fonts/FreeSans12pt7b.h> // Adafruit_GFXのフォント読み込み
Adafruit_ST7789 tft = Adafruit_ST7789(&SPI1, TFT_CS, TFT_DC, TFT_RST); // 液晶表示処理のインスタンス初期化
JPEGDecoder jpegDec; // JPEGデコーダのインスタンス
//********************* JPEGデコード画面表示処理関数 *********************//
void jpegDraw(char* filename) {
uint16_t *pImg; // ピクセルデータ用のポインタ
int x, y, bx, by; // 位置座標格納用
// JPEGファイルをSDカードからデコード実行
JpegDec.decodeSdFile(filename);
uint16_t bitmap[JpegDec.width * JpegDec.height]; // デコード画像サイズを取得してビットマップデータ格納用バッファを準備
// 液晶表示、デコード画像情報(MCU [Minimum Coded Unit]:JPEG画像データの最小処理単位、ここでは16x16ピクセル)
tft.printf("Size : %d x %d\nMCU : %d x %d\n", JpegDec.width, JpegDec.height, JpegDec.MCUWidth, JpegDec.MCUHeight);
delay(3000); // 液晶画面への画像情報表示時間
// シリアル出力、その他のデコード画像情報
Serial.printf("Components: %d\nMCU / row: %d\nMCU / col: %d\nScan type: %d\n\n",
JpegDec.comps, // コンポーネント数、16ビットカラーRGB565のため1(24ビットカラーなら3)
JpegDec.MCUSPerRow, // x方向のMCU数(240 / 16 = 15)
JpegDec.MCUSPerCol, // y方向のMCUの数(135 / 16 = 8.4375 → 9)
JpegDec.scanType); // サンプリングやエンコーディング方式
// 画像データをピクセル単位で描画
while (JpegDec.read()) { // JPEGデータを読み込む
pImg = JpegDec.pImage; // 現在のピクセルデータのポインタを取得
// MCU高さ分ループ
for (by = 0; by < JpegDec.MCUHeight; by++) {
// MCU幅分ループ
for (bx = 0; bx < JpegDec.MCUWidth; bx++) {
// 現在のピクセルのx, y座標を計算
x = JpegDec.MCUx * JpegDec.MCUWidth + bx; // x座標
y = JpegDec.MCUy * JpegDec.MCUHeight + by; // y座標
// ピクセルが画像範囲内にあるかチェック
if (x < JpegDec.width && y < JpegDec.height) {
// tft.drawPixel(x, y, pImg[0]); // 有効にすると、MCU単位で液晶画面に描画されていく
bitmap[y * JpegDec.width + x] = pImg[0]; // 座標ごとにピクセルカラーを取得してビットマップ画像生成
}
// ポインタを次のピクセルデータへ進める
pImg += JpegDec.comps;
}
}
}
// 描画位置を指定してビットマップを描画
tft.drawRGBBitmap(0, 0, bitmap, JpegDec.width, JpegDec.height);
}
// 初期設定 -----------------------------------------
void setup(void) {
Serial.begin(9600); // シリアル通信初期化
// SPI0初期設定(SDカード用)
SPI.setTX(SD_MOSI); // SDカードリーダーのMOSI
SPI.setRX(SD_MISO); // SDカードリーダーのMISO
SPI.setSCK(SD_SCK); // SDカードリーダーのSCK
// SPI1初期設定(TFT液晶用)
SPI1.setSCK(TFT_SCK); // TFTのSCK (GP10)
SPI1.setTX(TFT_MOSI); // TFTのMOSI (GP11)
// 出力端子初期設定
pinMode(25, OUTPUT); // TFTバックライト用端子
digitalWrite(25, HIGH); // TFTバックライト点灯
// TFT液晶の初期設定
tft.init(135, 240); // TFT初期化(画面サイズ指定)
tft.fillScreen(ST77XX_BLACK); // 背景の塗りつぶし
tft.setRotation(3); // 画面回転(0-3)
tft.setTextSize(1); // 文字サイズ
tft.setFont(&FreeSans12pt7b); // フォント
// SDカードの初期化
if (!SD.begin(SD_CS)) {
Serial.println("SDカードの初期化に失敗しました");
return;
} else {
Serial.println("SDカードが初期化されました");
}
// SDカードからJPEG画像を開く
File jpegFile = SD.open(FILENAME); // ファイル名を指定して開く
// ファイルが開けたか確認
if (!jpegFile) { // ファイルが開けなければエラー処理
Serial.println("JPEGファイルを開けませんでした");
tft.fillScreen(ST77XX_RED); // 背景の塗りつぶし(赤)
tft.setCursor(40, 70); // カーソル位置
tft.print("Can't open file!"); // エラー表示
return;
}
// 開いたJPEG画像のデータ容量を取得
unsigned long fileSize = jpegFile.size();
// 処理前のJPEG画像情報表示
tft.setCursor(0, 30); // カーソル位置
tft.printf("%s\n%lu bytes\n", FILENAME, fileSize); // JPEG画像ファイル名とデータ容量表示
// JPEG画像デコード実行
jpegDraw(FILENAME); // JPEGデコード画面表示処理関数呼び出し
jpegFile.close(); // JPEGファイルを閉じる
}
// メイン ---------------------------------------------
void loop() {
// メインループでは何もしない
}
8.本体の初期化方法
「RP2040-GEEK」の動作がおかしくなったり、手順を最初からやり直したい等で初期状態に戻したい場合もあると思います。
そんな時のために「RP2040-GEEK」本体を初期化する方法も紹介します。
以下のサイトにアクセスして、本体初期化用のファイルをダウンロードします。
表示されたページのに、下画像矢印部のようなリンクがあるので「UF2 file」をクリックします。
クリックすると「flash_nuke.uf2」というファイルがダウンロードされます。
「RP2040-GEEK」本体の「BOOT」ボタンを押しながらパソコンと接続して認識されたフォルダに、このファイルをドラッグ&ドロップするだけで初期化は完了します。
9.まとめ
「RP2040-GEEK」の使い方を詳しく紹介しました。
「RP2040-GEEK」は「Raspberry Pi Pico」と同じコントローラ「RP2040」を搭載しており、「Pico」と同じように使用できます。
「microSD(TF)カードリーダー」と「TFT液晶ディスプレイ」を搭載しているため、これら利用したプログラムなら、個別に用意して配線する必要がなく、安価でコンパクトに実現できます。
使用できる端子は合計6点と限られますが、全て入出力端子として使用でき、アナログ入力やシリアル通信(UART、I2C)も充実しているため、通信で取得したデータを表示して記録するデータロガーに最適なデバイスと思いました。
今回は長くなったのでシリアル通信については触れていませんが、次回はシリアル通信でいろいろなデータを取得して記録するデータロガーの作り方を詳しく紹介したいと思います。
コメント