ESP32 マルチタスク(デュアルコア)で、電光掲示板スクロールを止めずに、別のCPUで Web GET できました

記事公開日:2017年7月31日
Arduino core for ESP32 が大幅アップデートされました。
それに伴い、自作ライブラリもアップデートしましたので、最新版をダウンロードしてください。
(2017/8/2)

こんばんは。

前々回の記事で、ESP32 ( ESP-WROOM-32 ) のデュアルコア(マルチタスク)を実験してみましたが、今回は、ディスプレイに文字を電光掲示板スクロールしながら、それを止めずに、もう一つの CPUコア で Web 記事をGET してみます。

以下の動画をご覧ください。

いかがでしょうか?
バックに見えているものは、Arduino IDE のシリアルモニターです。
Web記事に GETリクエストを送って、返ってきた文字列を抽出した様子を出力しています。

見事に電光掲示板風文字スクロールが停止せずに裏で Web 記事がGET できていますよね。

パソコンなどの高性能CPU では当たり前のことですが、これが電子工作レベルのマイコンでできてしまうことがスバラシイですね。

では、この方法を説明したいと思います。

この記事および自作ソースコードの公開について、Yahoo! Japan さんにお問い合わせして、趣味や研究範囲と判断でき、問題無いとの回答を得ております。
(2017/8/11)

スポンサーリンク

使うもの

ESP-WROOM-32 ( ESP32 ) 開発ボード

お勧めの開発ボードは以下の2種類です。

ESPr Developer 32 ( スイッチサイエンス製)

Amazon.co.jp
ESPr Developer 32
スイッチサイエンス(Switch Science)

ソフトスタート機能やFTDI社製のUSBシリアル変換を使っているお勧めボードです。
ピンヘッダは別売りです。
このボードのレビューは以下の記事を参考にしてください。

ESPr Developer 32 ( スイッチサイエンス製 ) を使ってみました

ESP32-DevKitC ( Espressif 製)
本家 Espressif社の開発ボードです。
秋月電子通商さんでも売っていますが、Amazon.co.jpさんでは以下のところで販売してます。

※2018/01/30時点で、Amazon.co.jp では Espressif system純正の ESP32-DevKitC は販売されていません。秋月電子通商さんか、マルツパーツさんで購入してください。

フルカラー有機EL ( OLED ) SSD1331 モジュール

Amazon.co.jp さんでは、以下の中国販売店で売っています。
到着までに1週間~10日くらいは覚悟しておいてください。
品質は今のところ問題ないようです。

Amazon.co.jp

秋月電子通商さんでは、Pmod OLEDrgb という商品で売っています。
ちょっと高いのですが、問題無く使えます。

esp32_blynk2_08.jpg


Pmod OLEDrgb Pmod96×64有機ELディスプレイ

SparkFun マイクロSDカードスロット・ピッチ変換基板

以下のシンプルな変換基盤です。
ピンヘッダは別売りです。

Amazon.co.jp

micro SDHC カード

以下のカードは動作確認取れています。

Amazon.co.jp

ブレッドボード

超お勧めはサンハヤトさんの SAD-101 です。

Amazon.co.jp

固定抵抗10kΩ程度×2

micro SDカードスロットのプルアップ用です。

ジャンパワイヤー、WiFi環境、パソコン、USBケーブル等

接続する

Pmod の接続方法は以下の記事を参照してください。

ESPr Developer 32 ( スイッチサイエンス製 ) を使ってみました

ESP32-DevKitCの場合はこんな感じです。
OLED SSD1331 は HSPI接続、micro SDHC カードスロットは VSPI接続です。

hspi_vspi_20.jpg


Arduino core for ESP32 をインストールしておく

事前に以下の記事を参照して、Arduino IDE に Arduino core for ESP32 をインストールしておいてください。
Arduino IDE バージョンは 1.8.3 を使用してください。

Arduino core for the ESP32 のインストール方法

フォントファイル、変換テーブルのダウンロード

16×16日本語フォントや、UTF-8→Shift_JIS変換テーブルファイルが必要です。
フォント類はGitHub の以下のページにあります。

https://github.com/mgo-tec/SDcard_sample_filses

ZIPファイルをダウンロードして、解凍してください。
font フォルダの中の以下の3つのファイルが必要です。

Utf8Sjis.tbl

UTF-8 から Shift_JIS へ変換するためのテーブルファイルです。

私の自作のバイナリファイルで、ライセンスは MIT です。
著作権表記してあれば、自由に使うことができます。

shnmk16.bdf

16×16 東雲フォント(全角)
東雲フォントについては以下の記事を参照してください。
ライセンスは Public Domain です。

ESP32 で 日本語漢字フォント をカラー OLED に表示させ、4行同時スクロール ( SSD1331 使用)

shnm8x16.bdf

8×16 東雲フォント(半角)

オリジナルファイル名の ”r” を削除して、8文字にしたものです。

自作ライブラリをインストール

Arduino core for ESP32 が大幅アップデートされました。
それに伴い、自作ライブラリもアップデートしましたので、最新版をダウンロードしてください。
(2017/8/2)

私の自作した、以下の ESP32 用ライブラリを Arduino IDE にインストールしてください。
最近では関数を追加したり、細かい修正したりして、バージョンが上がっています。
最新版をダウンロードしてください。

GitHub からダウンロードした ZIP ファイルライブラリを Arduino IDE にインストールする方法は以下のページを参照してください。
ただ、インストールする前に、以前インストールした古いライブラリはフォルダごと削除してからインストールしてください

GitHubにある ZIP形式ライブラリ のインストール方法 ( Arduino IDE )

ESP32_SD_UTF8toSJIS

現在のバージョンは beta ver 1.21 です。
GitHubの以下のページにあります。

https://github.com/mgo-tec/ESP32_SD_UTF8toSJIS

これは、UTF-8コード文字列をShift_JISコードに変換するライブラリです。

ESP32_SD_ShinonomeFNT

現在のバージョンは beta ver 1.21 です。
GitHubの以下のページにあります。

https://github.com/mgo-tec/ESP32_SD_ShinonomeFNT

これは、Shift_JISコードや、UTF-8文字コードから、16×16ドットの東雲フォントに変換するライブラリです。

ESP32_SSD1331

現在のバージョンは beta ver 1.3 です。
GitHubの以下のページにあります。

https://github.com/mgo-tec/ESP32_SSD1331

これは、有機EL ( OLED ) SSD1331 モジュールを SPI通信で制御するライブラリです。

ESP32_WebGet

現在のバージョンは beta ver 1.1 です。
GitHubの以下のページにあります。

https://github.com/mgo-tec/ESP32_WebGet

これは、Web上の記事から文字列を抽出したり、NTPサーバーから時刻を取得するライブラリです。

ESP32_SD_SSD1331_Gadgets

現在のバージョンは beta ver 1.1 です。
GitHubの以下のページにあります。

https://github.com/mgo-tec/ESP32_SD_SSD1331_Gadgets

上記のライブラリを一まとめにして制御するライブラリです。

TimeLib ライブラリのダウンロード

Arduino 標準 Time ライブラリは 2017/7/31 時点で ver 1.5 です。

これのインストール方法は以下のページを参照してください。

https://www.mgo-tec.com/blog-entry-1616shinonome-ws-oled-news.html

micro SDHC カードにフォントやルート証明書を保存しておく

パソコンとSDカードライタを使って、上記でダウンロードしたフォントファイルや、Yahoo! Japan RSS サイトのルート証明書を予め micro SDHC カードに保存しておきます。

フォントやテーブルファイルの保存

micro SDHC カードに /font/ というフォルダを作成して、そこに保存しておいてください。

micro SDHC カードを標準サイズの SD カードスロットに入れるためには、アダプターが必要になります。
上記で紹介した micro SDHC カードならば大抵付属していますが、仕様が変更されている場合がありますので、よく確認してから購入してください。

micro SDカードのフォーマットについては以下の記事を参照してください。

micro SD 、micro SDHC カードの初期化(フォーマット)方法

ルート証明書の保存

Yahoo! Japan RSS サイトのルート証明書を micro SDHC カードに保存しておきます。

ルート証明書の取得方法は以下の記事を参照してください。

Arduino – ESP32 WiFiClientSecure ライブラリで、安定して https ( SSL )記事をGETする方法

その記事では、ルート証明書をスケッチ上に載せていましたが、今回はmicro SDHCカードから読み込むようにします。

micro SDHC カードに /root_ca/ というフォルダを作成して、そこにルート証明書を保存しておいてください。
ファイル名はここでは yahoo.cer としておいてください。

WiFiClientSecure ライブラリを修正しておく

Arduino core for ESP32 の WiFiClientSecure ライブラリは、そのまま標準でWeb へGETリクエストして使用すると、数10回~200回以内でフリーズ(ハングアップ)して、動かなくなります。
これの修正方法はかなり面倒なのですが、頑張って修正しておくことをお勧めします。
以下の記事を参照して、修正してみてください。

2017/8/2に修正されました。libmbedtls.a と main.cpp のスタックサイズも修正されてます。

Arduino – ESP32 WiFiClientSecure ライブラリのハングアップ問題がついに解決!

スケッチの入力

では、Arduino IDE に以下のスケッチを入力してみてください。
ライブラリ化したことによって、かなりシンプルになって、100行を切りました。

ESP32 ( ESP-WROOM-32 ) のデュアルコア(マルチタスク)動作方法については、以下の記事も合わせて参照してください。

Arduino – ESP32 のマルチタスク ( Dual Core ) を試す

因みにこのプログラムは無保証です。
いかなるトラブルも当方では責任負えませんので、予めご了承ください。

#include "ESP32_SD_SSD1331_Gadgets.h"

const char* ssid = "xxxx"; //ご自分のルーターのSSIDに書き換えてください。
const char* password = "xxxx"; //ご自分のルーターのパスワードに書き換えてください。

const char* UTF8SJIS_file = "/font/Utf8Sjis.tbl"; //UTF8 Shift_JIS 変換テーブルファイル名を記載しておく
const char* Shino_Zen_Font_file = "/font/shnmk16.bdf"; //全角フォントファイル名を定義
const char* Shino_Half_Font_file = "/font/shnm8x16.bdf"; //半角フォントファイル名を定義

const char* Yahoo_rootca_file = "/root_ca/yahoo.cer"; //Yahoo! Japan RSS ルート証明書ファイル

const uint8_t CS_SD = 5; //SD card CS ( Chip Select )

const uint8_t SCLK_OLED =  14; //SCLK
const uint8_t MOSI_OLED =  13; //MOSI (Master Output Slave Input)
const uint8_t MISO_OLED =  12; //これは実際は使っていない。MISO (Master Input Slave Output)
const uint8_t CS_OLED = 15;
const uint8_t DC_OLED =  16; //OLED DC(Data/Command)
const uint8_t RST_OLED =  4; //OLED Reset

ESP32_SD_SSD1331_Gadgets ESSG;
ESP32_SD_UTF8toSJIS u8ts;
ESP32_SSD1331 _ssd1331(SCLK_OLED, MISO_OLED, MOSI_OLED, CS_OLED, DC_OLED, RST_OLED);
ESP32_SD_ShinonomeFNT _SFR(CS_SD, 24000000);
ESP32_WebGet _EWG;

uint8_t sj_txt[1024] = {}; //Shift_JIS コード文字列を格納
uint16_t sj_length; //Shift_JIS コード文字列長

int32_t NewsGetLastTime = -60000; //起動時にWebGETするために、マイナスにしておく
bool WebGet = false;
//************* セットアップ **************************
void setup() {
  Serial.begin(115200);
  _EWG.EWG_AP_Connect(ssid, password); //Wi-Fi ルーターと接続
  delay(1000);
  _ssd1331.SSD1331_Init(); //OLED SSD1331 初期化
  if(!_SFR.SD_Shinonome_Init3F(UTF8SJIS_file, Shino_Half_Font_file, Shino_Zen_Font_file)){
    return;
  }

  TaskHandle_t th; //マルチタスクハンドル定義
  xTaskCreatePinnedToCore(Task1, "Task1", 4096, NULL, 5, &th, 0); //マルチタスク起動
}
//************* メインループ **************************
void loop() {
  if((millis() - NewsGetLastTime) > 60000){ //60秒毎にYahoo! RSS 記事取得
    char root_ca[2048];
    ESSG.Root_CA_SDcard_Read(Yahoo_rootca_file, root_ca); //ルート証明書取得
    String news_str = _EWG.EWG_https_Web_Get(root_ca, "news.yahoo.co.jp", "/pickup/rss.xml", '\n', "</rss>", "<title>", "</title>", "◆ ");
    sj_length = u8ts.UTF8_to_SJIS(news_str, sj_txt); //UTF-8文字コードをShift_JISに変換
    Serial.println(news_str);
    Serial.flush();
    WebGet = true;
    NewsGetLastTime = millis();    
  }
}
//************* マルチタスク **************************
void Task1(void *pvParameters){
  //OLED SSD1331 ディスプレイの文字スクロールを別タスクで実行
  while(1){
    ESSG.Scroll_1_line(0, 0, 0, 7, 0, 10, sj_txt, sj_length, &WebGet);
  }
}

【解説】

●1行目:
自作ESP32_SD_SSD1331_Gadgetsライブラリのインクルードです。
このライブラリの中に、ESP32_SD_ShinonomeFNT や、ESP32_SSD1331、ESP32_WebGet などのライブラリが予めインクルードされています。

●3-4行目:
ご自分のWi-Fi ルーター環境に合わせて、SSID や パスワードを書き換えてください。

●6-8行目:
micro SDHC カードに保存されたフォントファイル名の定義です。

●10行目:
micro SDHC カードに保存されたYahoo! Japan RSS ニュースサイトのルート証明書ファイル名定義です。

●12-19行目:
micro SD カードスロットや、OLED SSD1331 モジュールの GPIO ピンアサイン設定です。
micro SD カードスロットは VSPI 接続、OLED SSD1331 モジュールは HSPI 接続です。
VSPI や HSPI については以下の記事を参照してください。

ESP32 の SPI_MODE が修正。HSPI , VSPI , 複数SPIデバイス制御 , SPI高速化などについて

●21-25行:
ここで、それぞれの自作ライブラリのクラス名を定義しています。

●27行:
Yahoo! Japan RSS ニューストピックストップ記事の文字サイズは概ね 1024文字以下です。

●30行:
Yahoo! Japan RSS サイトからニュースを GET する場合に、60秒毎に設定すると、電源投入後の初回時に GET してくれないので、ここでマイナス数値にしておくと、47行を通過して、GETしてくれます。

●31行:
これは、Webから記事をGETしたら true に変わる変数です。

●38-40:行:
micro SD カードから読み込みできない場合は false を返してきて、プログラムが動作しないようにしています。

●42行:
ここで、ESP32 ( ESP-WROOM-32 )をデュアルコア(マルチタスク)で動作させるためのハンドル名を定義します。

●43行:
ここで、59-64行のタスクを ESP32 の core 0 で動作させます。
タスクのスタックメモリサイズは 4096 で、タスク優先順位はメインループより高い 5 としています。
要するに、ディスプレイで文字列を電光掲示板スクロールさせる動作の方を優先しているわけです。

●46-57行:
ここで注意していただきたいのは、マルチタスク(デュアルコア)動作の場合、メインループ関数内で WiFiClientSecure ライブラリを使って Web から記事を GET しているということです。
私が今まで実験したところによると、WiFiClientSecure ライブラリ関数を別のタスクで実行させるとうまく動作しませんでした。
メインループ内の core 1 ならば問題無く動作するので、OLED ディスプレイの電光掲示板文字スクロールの方を別タスクにしました。

47行目で60秒毎に記事を取得していますが、この間隔はこれ以上短くし過ぎないようにしてください。
余りにも短いと相手サーバーに迷惑をかけてしまいますので要注意です。

48行でルート証明書を格納する char型配列を宣言していますが、メモリ節約のためにもここで宣言した方が良いです。
そうすれば、if文を出る時にメモリが解放されます。

49行目でmicro SDHC カード内に保存してあるルート証明書を読み込んで WiFiClientSecureライブラリにセットする関数を使っています。
今回からESP32_SD_SSD1331_Gadgetsライブラリに新たに登場です。
これを使えばスケッチ上のメモリを節約できます。

●50行:
ここで、Yahoo! Japan RSS ニュースを GET しています。
自作の EWG_https_Web_Get関数を修正して、ルート証明書を引数に盛り込みました。
そして、この関数は少々修正して、安定的に動作するようにしています。
これについては以下の記事を参照してください。

Arduino – ESP32 WiFiClientSecure ライブラリで、安定して https ( SSL )記事をGETする方法

●51行:
ここで、String 文字列のUTF-8文字コードをShift_JIS に変換しています。
UTF-8文字コードよりもShift_JISコードの方がバイト数は少なく済みます。

●54行:
Web Getできたら、true が代入され、これが62行に反映されます。

●59-63行;
ここが ESP32 のマルチタスク(デュアルコア)動作の core 0 ループです。
62行目で今回初登場した自作ライブラリ関数です。
これ1行で OLED SSD1331 モジュールに日本語文字列を電光掲示板スクロールさせることができます。

Scroll_1_line(垂直位置, 行番号, RED, GREEN, BLUE, interval, sj_txt, sj_length, &WebGet)

 

垂直位置は0-48 で決めます。

行番号は、その行に 0-4 の値で番号をつけます。

色は 256色カラーで決めます。
赤色 ( 0-7 )
緑色 ( 0-7 )
青色 ( 0-3 )

interval はスクロールスピード調整をします。

sj_txt に 文字列の Shift_JISコードを代入します。

sj_length はShift_JIS文字列サイズを代入します。

&WebGet は、記事をGet したら true という値を渡してあげれば、文字列スクロールを最初の文字から始めることができます。
これは Web記事とは関係なく、ただ単に文字列を最初の文字からスクロールさせたい場合に true という値の入った変数のポインタアドレスを渡してあげれば良いです。
そして、最初の文字列からスクロール始めたら、その変数は false になります。

以上、スケッチの解説でした。
今回はライブラリを統合したため、かなりシンプルになりました。
将来的にはもっとシンプル化したいと思っています。

ただ、まだプログラムが甘いところがありまして、マルチタスクだと初回動作時にきれいに表示してくれません。
今後の課題です。

コンパイル実行

ではこのスケッチをコンパイル実行してみてください。
最初に紹介した動画のようになっていればOKです。

ESP32 ( ESP-WROOM-32 )のデュアルコア(マルチタスク)を使えば、電光掲示板スクロールが止まらずに、イイ感じで裏で記事をGET できますよね。

ブレッドボード電子工作レベルでここまで出来てしまう時代に突入したんだなぁと、つくづく感心してしまいます。

これでマルチタスクプログラムの応用がいろいろできるようになってきましたね。

まとめ

以上、いかがでしたでしょうか。

ESP32 のマルチタスク(デュアルコア)を使う場合に気を付けなければいけない事は、WiFiClientSecure などの WiFi制御ライブラリはメインloop関数内で使用し、SPI 通信や、micro SDカードスロット制御は core 0 で動かすことが可能ということが分かりました。

今後は同じ core 番号でも vTaskDelay 等をうまく使えば時間差タスクみたいなこともできそうな気がします。

では、今回はここまでです。

次回は複数の記事GET に挑戦しようと思います。

ではまた・・・。

スポンサーリンク


Amazon.co.jp 当ブログのおすすめ
Amazon.co.jp
M5Stack Basic
スイッチサイエンス
Amazon.co.jp
ESPr Developer 32
スイッチサイエンス(Switch Science)
Amazon.co.jp
Amazon.co.jp

「ESP32 マルチタスク(デュアルコア)で、電光掲示板スクロールを止めずに、別のCPUで Web GET できました」への2件のフィードバック

  1. いつも記事を見させてもらっています。
    突然のコメントで申し訳ありません。お聞きしたいことがあります。
    WROOM32にてWiFiの各IPを固定した際に
    アクセスポイントへの接続ができたりできなかったりします。
    これは私だけの症状でしょうか?
    具体的にはデバッカにてSTA_GOT_IPのイベントが発生した状態で止まってしまいます。
    しかも常にではなく3割くらいの確立で発生します。
    ご回答のほうよろしくお願いします。

    1. まっちゃん さん

      当ブログをご覧いただき、ありがとうございます。

      もう試されているかと思いますが、念のため申し上げます。

      2017/5/23 頃、GitHub の Arduino core for ESP32 の WiFi.begin クラスが修正されて、WiFi が繋がりにくい、もしくは殆どつながらないバグが修正されました。
      最新版をインストールされても接続されないのでしょうか?

      因みに、Arduino core for ESP32 をアップデートする場合は、一旦 C:\Users\User-Name\Documents\Arduino\hardware\espressif\esp32フォルダ内を全て削除して、新たにコピーし直し、それから get.exe を右クリック(Windowsの場合)して、「管理者として実行」をクリックしてインストールする必要があります。

      私の場合、git でアップデートしていませんので分かりませんが、それでも良いかと思います。
      get.exe だけ実行してもアップデートされないようです。

      あと、私の場合は IP を固定しておらず、自動割り当てにしていますので、固定した場合の挙動は正直分かりません。
      自動割り当ての場合は問題無く殆ど一発で接続できています。

コメントを残す

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください