//======================================================== // Example7_BMP_Buff // 複数のBMPファイルを予め画像Buffに読み込んで切り替え表示させる //======================================================== // v01 SD初期化設定。  OLED = VSPI, SD = HSPI // 下記のPIN配置で、SDとOLEDの初期設定正常動作 // v02 Setup最後のBreak部分を解除。 // MonaLisa64x64.txt ファイルから、テキスト形式の0Xffデータを読み込んで // 画像表示成功。 // // 問題:ESP32に書き込み時に、全ての回路を接続し、USBから全電源供給で //    書き込みするとFetalErrとなる。 //    A fatal error occurred: Timed out waiting for packet content //    しかし、SDボードの電源を切り離すと正常書き込み終了。 // pim12を切り離せば電源そのままでOK // v03 SD関連の初期化部分の整理確認。SDデータ部分の読み出し確認。 // v04 SDデータを最後まで読み出して配列に格納する。(RGB24->RGB16) // 4096x2のデータ格納確認。(RGB24->RGB16) // v05 配列のデータをOLEDへ送信して画像表示まで。動作確認。 // v06 余分な命令を削除。全てのファイルを読み込んで連続表示。 // v07 Setupに前処理を、LOOPに繰り返しOLED表示を分ける // memcpy(IC_Buff, Image_Buff, sizeof(Image_Buff)); // 画像データの配列をコピーしてそれをOLED関数へ渡す // // // // // // // //----------------------------------------------------------------------- // // SD_ReadWrite03 を参照 // // https://github.com/sparkfun/SparkFun_RGB_OLED_64x64_Arduino_Library // v01 ブレッドボード上のESP32とSDを使用する。(TFT_LCDは未使用) // 処理過程はSerial通信で確認する。 // SDカードオープン成功。 // v02 SDの内容をダンプして確認する。OK // v03 SDの読み出しデータを処理関数に渡す // v04 OLED表示解除し、複数のファイルに対応する。 // // //--------------------------------------------------------- // // v01 注意 //======================================================================== // SD card read write test by ESP32 2020-10-22 // // PIN接続は以下の通り(VSPI)==>> HSPIに変更 // SDの電源は5V供給(I/Oは3.3Vで入出力される) // I/Oのプルアップなどは一切不要。(WEBにあるような10KのPullUpは不要) // (重要)R/Wするファイル名は、先頭に / を付けないとREADがERRになる。 // TFT LCDと同時使用の場合は、TFTをHSPIにし、SDをVSPIにすると動作確認すみ。 // Ver 03 // VSPIのクロックは、規定値では400KHzだった。(ロジアナで測定) // これをクロックアップテスト。 // //======================================================================== // SPIのESP32PIN接続(*印ピンは任意で設定可能) //           VSPI      HSPI // OLED SD // CS 5 15 // *RESET 33 32 'NU' // *DC 27 33 'NU' // MOSI 23 13 // MISO 19 'NU' 12 // CLK 18 14 // // //======================================================================== //---------------------------- // SD関連セットアップ //---------------------------- #include #include //SPIClass hspi(HSPI); File myFile; //---------------------------- // OLEDをVSPIに接続 //---------------------------- #include "SparkFun_RGB_OLED_64x64.h" // Click here to get the library: http://librarymanager/All#SparkFun_RGB_OLED_64x64 #define DRIVER_SPI SPI #define CS_PIN 5 #define DC_PIN 27 #define RST_PIN 33 RGB_OLED_64x64 myOLED; // Declare OLED object #define WORKING_BUFFER_LENGTH 2*64 uint8_t working_buffer[WORKING_BUFFER_LENGTH]; uint8_t Image_Buff[5][64 * 64 * 2] = {0}; // 64x64ドットのイメージバッファ10枚分初期化 uint8_t IC_Buff[5][64 * 64 * 2]= {0}; String File_Name[5] = {"Boy.bmp", "Flower.bmp", "", "", ""};// 読み込むBMPファイル名のエリアを初期化 //------------------------ // SD をHSPIに設定 //------------------------ #define SD_SS 15 #define SD_CLK 14 #define SD_MISO 12 #define SD_MOSI 13 SPIClass spiSD(HSPI); //----------------- // Global変数 //----------------- int i, j; int Max_F_No = 0; uint16_t I_size = 4096 * 2; void setup() { //---------------------------------------------------------------------- // ESP32起動確認 //---------------------------------------------------------------------- delay(3000);// 起動まで3秒待つ //---- Boot Up Check ---- pinMode(0, OUTPUT);// Monitor LED点滅 for ( i = 0 ; i < 5 ; i ++) { delay(200); digitalWrite(0, HIGH);// delay(100); digitalWrite(0, LOW); } //------------------------ // Serial設定 //------------------------ Serial.begin(115200); // Choose the fastest serial connection you can! while (!Serial) {}; //----------------------------------------- //以下OLEDの初期化 //----------------------------------------- DRIVER_SPI.begin(); myOLED.begin(DC_PIN, RST_PIN, CS_PIN, DRIVER_SPI, 8000000); // Use 8 MHz SPI on Arduino Uno instead of the default/maximum (10 MHz) myOLED.clearDisplay(); myOLED.setCursor(0, 0); myOLED.println("BMP Display"); myOLED.println("Ver 06"); //-------------------------- // SDの初期設定とFileオープン //-------------------------- //---- 初期化メッセージ --------- Serial.println(); Serial.println("------ Ex7 BMP v06 ------"); Serial.println("Serial Ready"); Serial.print("Initializing SD card..."); spiSD.begin(SD_CLK, SD_MISO, SD_MOSI, SD_SS); if (!SD.begin(SD_SS, spiSD, 8000000)) { //CSピン状態確認 Serial.println("initialization failed!");// SD開始できなければERR while (1); } Serial.println("SD Card Ready to read"); //----------------------- // Fine名の配列から読み出す //----------------------- for ( i = 0 ; i < 10 ; i ++ ) { if ( File_Name[i] == "") { Max_F_No = i; Serial.println(Max_F_No);//登録した画像ファイル数を表示 break; } myFile = SD.open("/" + File_Name[i]); // 画像のテキストデータ if (myFile) { Serial.println(File_Name[i]); Serial.println("File is opened"); } else { // if the file didn't open, print an error: Serial.println(File_Name[i]); Serial.println("error opening file"); while (1) { // ERRなら中断 } } //----------------------- // debug SDデータ読み出し //----------------------- Serial.println("SD Reading."); delay(1000); //-------------------------------------------------- // BMPファイルを読み出しOLEDへ転送 //-------------------------------------------------- Read_BMP_File(i);// 読み出すFileの配列番号を引数としてSDのBMPデータを読み出して配列へセット //------------------- // 現ファイルをCLose //------------------- myFile.close(); } } //================================================================ // LOOP処理 //================================================================ void loop() { //=========================================================== // 配列のBMPデータを繰り返しOLEDに表示する //=========================================================== //---------------------------- // OLEDディスプレイ設定 //---------------------------- myOLED.clearDisplay(); myOLED.setRowAddress(OLED_64x64_START_ROW, OLED_64x64_START_ROW + 0x40 - 1); myOLED.setColumnAddress(OLED_64x64_START_COL, OLED_64x64_START_COL + 0x40 - 1); myOLED.enableWriteRAM(); //------------------------------------- // OLEDへ配列のデータを転送 // これをしないと、OLED表示関数に引き渡した // 配列データの中身は破壊されるので注意 //------------------------------------- memcpy(IC_Buff, Image_Buff, sizeof(Image_Buff));// 画像データの配列をコピーしてそれをOLED関数へ渡す for ( j = 0 ; j < Max_F_No ; j ++ ) { //------------------------- // 配列データをOLEDへ転送 //------------------------- myOLED.setCSlow(); myOLED.write_bytes(IC_Buff[j], true, I_size); myOLED.setCShigh(); //------------------------ // 1画面ディスプレイ表示終了 //------------------------ //delay(100);//画像表示遅延用 } } //========================================================================================== // 以下、追加関数 //========================================================================================== //--------------------------------------------- // 指定された配列File_NameにあるBMPファイルを開き // 配列Image_Buffにセットする //--------------------------------------------- void Read_BMP_File(int F_No) { #define Dot_No 4096 // 64x64 int Dot_Cnt = 0;// BMPファイルのドット用バイト(H、L)数カウント(64x64x2) int Image_Cnt = 0;// BMP画像ファイルの番号 int BMP_Ptr = 0;// BMPファイルのReadPointer char Read_B; int Start_Add = 0; int Ret = 0; int i; //---- 読み込んだRGBの3バイトを2バイトに圧縮する為の仮変数 ---- uint16_t RGB24[3]; uint8_t RGB16[2]; uint16_t Temp = 0; //-------------------------------- // 指定されたBMPファイルを配列に読み込む //-------------------------------- //---- Header 確認 ---- Read_B = myFile.read();//1文字目を読み出す = B //Serial.print(Read_B); Read_B = myFile.read();//2文字目を読み出す = M //Serial.println(Read_B); //---- データ先頭アドレス取得(4 bytes) ---- myFile.seek(0x000a); Read_B = myFile.read(); Start_Add = Read_B;// データ開始アドレスをセット //Serial.println(Read_B, HEX);// 0x36 Read_B = myFile.read(); //Serial.println(Read_B, HEX);// 0 Read_B = myFile.read(); //Serial.println(Read_B, HEX);// 0 Read_B = myFile.read(); //Serial.println(Read_B, HEX);// 0 myFile.seek(Start_Add);// データ開始アドレスまで進む while (myFile.available()) { RGB24[0] = myFile.read();// 3バイト読み込む RGB24[1] = myFile.read(); RGB24[2] = myFile.read(); //Temp = ((RGB24[0] & 0xF8) << 8) | ((RGB24[1] & 0xFC) << 3) | (RGB24[2] >> 3); //Temp = ((RGB24[0] & 0xF8) << 8) | ((RGB24[2] & 0xFC) << 3) | (RGB24[1] >> 3); //Temp = ((RGB24[1] & 0xF8) << 8) | ((RGB24[0] & 0xFC) << 3) | (RGB24[2] >> 3); //Temp = ((RGB24[1] & 0xF8) << 8) | ((RGB24[2] & 0xFC) << 3) | (RGB24[0] >> 3); //Temp = ((RGB24[2] & 0xF8) << 8) | ((RGB24[0] & 0xFC) << 3) | (RGB24[1] >> 3); Temp = ((RGB24[2] & 0xF8) << 8) | ((RGB24[1] & 0xFC) << 3) | (RGB24[0] >> 3); RGB16[0] = Temp >> 8;// 上位8ビット Image_Buff[F_No][Dot_Cnt] = RGB16[0]; // 64x64ドットのイメージバッファ Dot_Cnt ++; RGB16[1] = Temp & 0x00ff;// 下位8ビット Image_Buff[F_No][Dot_Cnt] = RGB16[1]; // 64x64ドットのイメージバッファ Dot_Cnt ++; } }