0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

SenseCAP IndicatorでESP32側からmicroSDのファイルを読む

Posted at

SenseCAP Indicatorという4インチタッチスクリーン液晶のESP32デバイスがあるんですね。
https://www.seeedstudio.com/SenseCAP-Indicator-D1-p-5643.html
Groveコネクタもあるし、microSDカードも挿せるので、でかいM5Stackみたいに使えないかな…と思って…買いました。
https://files.seeedstudio.com/products/SenseCAP/SenseCAP_Indicator/SenseCAP%20Indicator%20User%20Manual_2023.4.21.pdf
ところがこのマニュアルの回路図を見てほしいんですけど、microSDスロットがつながっているのはRP2040の方なんですよ。M5Stackの感覚で直接読むわけには行かないのでどうしようかと思って…RP2040でmicroSDから読んだデータをUARTでESP32の方に送信してみることにしました。

準備

Platform IOでESP32側の開発ができるようにする

公式にはESP-IDFを使う方法が書いてあるんですけど、
https://wiki.seeedstudio.com/SenseCAP_Indicator_How_To_Flash_The_Default_Firmware/#for-esp32-s3
使い慣れたPlatform IOを使いたかったのでここを参考にしました。
https://qiita.com/fukuebiz/items/de6007c651255dd2458b
例ではesp32s3box.jsonを書き換えていますが、一応SenseCap-Indicator.jsonみたいに別ファイルを作成してボードを追加しています。
LovyanGFXが使えれば画像の表示も簡単そうです。microSDカードから画像を読みこんで表示することにしました。

Arduino IDEでRP2040側の開発ができるようにする

こっちもPlatform IOでやりたかったのですが…よく分からなかったため…公式に設定方法が書いてあるArduino IDEの方を使うことにしました。
https://wiki.seeedstudio.com/SenseCAP_Indicator_How_To_Flash_The_Default_Firmware/#for-rp2040

UART通信

RP2040側

UART通信ってどの程度まで速度出せるんでしょうね?こちらを参考に921600を設定してます。
https://asukiaaa.blogspot.com/2023/02/esp32-c3-s3-builtin-usb-can-send-700kbps.html
ESP32側から一行単位でコマンドを受け取り、応答を返します。「SD_OPEN_READ:(ファイル名)」でファイルを開いて「SD_READ_LENGTH:(バイト数)」でファイルを読むとかそんな感じです。手を抜いたので読み込みのみだし、ファイルは1つしか同時に開けないし、ファイル名は13文字までです(「/filename.txt」みたいなSD直下の8.3ファイル名を想定しています)。

#include <Arduino.h>
#include <SPI.h>
#include <SD.h>

File currentFile;

void setup()
{
  Serial.begin(115200);

  const int chipSelect = 13;
      SPI1.setSCK(10);
      SPI1.setTX(11);
      SPI1.setRX(12);
      if (SD.begin(chipSelect, 1000000, SPI1))
      {
        Serial.println("SD_BEGIN:TRUE");
      }
      else
      {
        Serial.println("SD_BEGIN:FALSE");
      }
  
  // Begin Serial1 for UART communication with ESP32
  Serial1.setTX(16);
  Serial1.setRX(17);
  Serial1.begin(921600);
}

void loop()
{
  if (Serial1.available() > 0)
  { // Listening Serial1 to receive commands from ESP32S3
    String line = Serial1.readStringUntil('\n');

    if (line.startsWith("SD_EXISTS:"))
    {
      String fileName = line.substring(strlen("SD_EXISTS:"));
      if (fileName.length() < 14) {
        char fileChar[14];
        fileName.toCharArray(fileChar, fileName.length());
        if (SD.exists(fileChar))
        {
          Serial1.printf("SD_EXISTS:TRUE %s\n", fileChar);
        }
        else
        {
          Serial1.printf("SD_EXISTS:FALSE %s\n", fileChar);
        }
      }
      else
      {
        Serial1.printf("SD_EXISTS:FALSE LONG %s\n", fileName.c_str());
      }
    }
    
    else if (line.startsWith("SD_OPEN_READ:"))
    {
      String fileName = line.substring(strlen("SD_OPEN_READ:"));
      if (fileName.length() < 14) {
        char fileChar[14];
        fileName.toCharArray(fileChar, fileName.length());

        if (currentFile = SD.open(fileChar))
        {
          Serial1.println("SD_OPEN_READ:TRUE");
        }
        else
        {
          Serial1.println("SD_OPEN_READ:FALSE");
        }
      } else {
        Serial1.println("SD_OPEN_READ:FALSE LONG");
      }
    }
    else if (line.startsWith("SD_CLOSE:"))
    {
      if (currentFile)
      {
        currentFile.close();
        Serial1.println("SD_CLOSE:TRUE");
      }
      else
      {
        Serial1.println("SD_CLOSE:FALSE");
      }
    }
    else if (line.startsWith("SD_SIZE:"))
    {
      if (currentFile)
      {
        Serial1.printf("SD_SIZE:%d\n", currentFile.size());
      }
      else
      {
        Serial1.println("SD_SIZE:0");
      }
    }
    else if (line.startsWith("SD_READ_LENGTH:"))
    {
      String lenString = line.substring(strlen("SD_READ_LENGTH:"));
      size_t len = lenString.toInt();

      if (currentFile.size() - currentFile.position() < len) {
        len = currentFile.size() - currentFile.position();
      }
       
      Serial1.println("SD_READ_START:");

      char buffer[512];
      while (len > 0)
      {
        size_t readLen = 0;
        if (len > 512) {
          readLen = currentFile.readBytes(buffer, 512);
        } else {
          readLen = currentFile.readBytes(buffer, len);
        }
        Serial1.write(buffer, readLen);
        //byte aByte = currentFile.read();
        //len -= Serial1.write(aByte);
        len -= readLen;
      }
      
    }
    else if (line.startsWith("SD_READ_LINE:"))
    {
      String fileLine = currentFile.readStringUntil('\n');
      Serial1.println(fileLine);
    }
    else
    {
      Serial1.println(line);
    }
  }
}

ESP32側

本当はLovyanGFX周りのセッティングがありますが、それはこちらのまんまですので割愛します。
https://qiita.com/fukuebiz/items/de6007c651255dd2458b
Serial2を使ってRP2040側にコマンド文字列を送り、ファイルサイズを聞いてメモリを確保し、受信したJPEGをLovyanGFXで表示させます。本当はStreamとして直に渡せると思う。

void setup(void)
{
  Serial2.begin(921600, SERIAL_8N1, 20, 19);
}

void loadJpeg(String fileName)
{
  String command = "SD_OPEN_READ:" + fileName;
  Serial2.println(command);
  String response = Serial2.readStringUntil('\n');
  Serial.println(response);

  Serial2.println("SD_SIZE:");
  response = Serial2.readStringUntil('\n');
  Serial.println(response);

  String sizeString = response.substring(strlen("SD_SIZE:"));
  size_t fileSize = sizeString.toInt();
  size_t position = 0;

  byte *fileBuffer = (byte *)malloc(fileSize * sizeof(byte));
  if (!fileBuffer) {
    Serial.println("malloc failed");
    return;
  }

  Serial2.printf("SD_READ_LENGTH:%d\n", fileSize);
  response = Serial2.readStringUntil('\n');

  while (position < fileSize)
  {
    if (Serial2.available()) {
      size_t readLength =  Serial2.readBytes(fileBuffer + position, (fileSize - position));
      position += readLength;
      if (position == fileSize) break;
    }
  }
  display.drawJpg(fileBuffer, fileSize, 0, 0, 480, 480);
  Serial2.println("SD_CLOSE");
  free(fileBuffer);
}

できた

できた。480x480、96KBのJPEGで1秒くらい受信にかかっているようです。
IMG_3530.jpeg

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?