Yahoo ニュース、天気予報、NTP時計ガジェットを ESP32 マルチタスク ( デュアルコア )で動かしてみた

記事公開日:2017年8月2日
最終修正日:2017年9月25日

スポンサーリンク

こんばんは。

いきなり余談ですが、つい昨日、2017/8/1 に GitHub の Arduino core for ESP32 が大幅修正されました。
ようやく WiFiClientSecure ライブラリがまともに動くようになりました。
そして、main.cpp のスタックサイズも 8192 となり、ESP32 ( ESP-WROOM-32 )のマルチタスク(デュアルコア)で SSLページの Web GET リクエストが問題無く動作するようになりました。

ただ、今、頻繁に更新されていますので、安定するまでしばらくダウンロードは待った方が良いかもしれません。

また、Serial.begin クラスが2重使用できなくなりましたので、当方自作の以下のライブラリも修正しました。

ESP32_SD_UTF8toSJIS  beta ver 1.21
ESP32_SD_ShinonomeFNT  beta ver 1.21

さて、本題に戻りまして、今回は前回の記事の続きです。
以前紹介した以下の記事で、ESP32 ( ESP-WROOM-32 ) ガジェットをマルチタスク(デュアルコア)で動かしてみたいと思います。

ESP32 と 有機EL SSD1331 で Yahoo News 、 天気予報 、 NTP 時計 Wi-FI ガジェットを作ってみた

では、早速以下の動画をご覧ください。

いかがでしょうか。
後ろに見えているのは、Arduino IDE のシリアルモニターです。

時計表示のスクロールや、Yahoo! Japan RSS ニュースのスクロールも停止せずに、別の CPU で動かしている SSL ページの GETリクエストが出来ていますね。

しかも、前回と異なるのは、ニュース記事と天気予報と NTP時刻取得など、Web から3つの情報を GET していることです。

電子工作レベルでこんな感じで安定して SSL ページをGET できるなんて、夢のようですね。
Arduino core for ESP32 も大幅更新されたため、ガッツリ安定動作です。

前回の記事では、有機EL ( OLED )ディスプレイのSPI通信をマルチタスクの core 0 で動作させて、Web の SSL ページ記事への GET リクエストはメインループの core 1 で動作させていました。
記事取得は1つでした。

今回のポイントは、ニュース記事と天気予報の2つの SSLページ GET と、UDP を使った NTPサーバー 時刻取得など、複数の記事取得をマルチタスクで行ったことです。

Arduino core for ESP32 の WiFiUdp ライブラリと、Arduino 標準の TimeLib ライブラリを使う場合は、うまく CPU core を分けてやらないと、HSPI接続 の OLED が一時停止してしまいます。

では、今回はその方法を紹介します。

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

最新版 Arduino core for ESP32 のインストール

先にも述べましたが、2017/8/1 以降、GitHub の Arduino core for ESP32 が大幅アップデートされました。
WiFiClientSecure ライブラリも正常に動くようになりましたので、最新版をインストールしてください。
インストール方法は以下のページを参照してください。

※get.exe を実行するだけではダメです。ZIPファイルを新たにダウンロードして再インストールしてください

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

使用するもの

前回の記事と同様です。

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

●ESPr Developer 32 ( スイッチサイエンス製)
当ブログおすすめボードです。

ESPr_Developer32_01

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

●ESP32-DevKitC ( Espressif 製)
本家 Espressif社の開発ボードです。

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

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

micro SDHC カード

サンハヤト SAD-101 ニューブレッドボード

ESPr Developer 32 でも使えるお勧めブレッドボードです。

固定抵抗10kΩ程度×2

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

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

使うもの、接続、ライブラリのインストール等

以下の記事を参考にして、最新版ライブラリのインストール、フォントのインストールを済ませておいてください。

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

それぞれのバージョンは以下の通りです。

【自作ライブラリ】

ESP32_SD_SSD1331_Gadgets  ( beta ver 1.1 )
ESP32_SD_ShinonomeFNT  ( beta ver 1.21 )
ESP32_SD_UTF8toSJIS  ( beta ver 1.21 )
ESP32_SSD1331 ( beta ver 1.3 )
ESP32_WebGet ( beta ver 1.1 )

【Arduino 標準ライブラリ】

Time ライブラリ ( ver 1.5 )

天気予報自作フォントのインストールは以下の記事を参照してください。

ESP32 と 有機EL SSD1331 で Yahoo News 、 天気予報 、 NTP 時計 Wi-FI ガジェットを作ってみた

また、フォントを修正したい場合は以下の記事を参照してください。

天気予報を自作フォントで表示してみた ( ESP32 , OLED SSD1331 )

スケッチの入力

では、以下のスケッチを入力してください。
前回の記事と重複しているところは省きます。

#include "ESP32_SD_SSD1331_Gadgets.h" //beta ver 1.1
#include "ESP32_SD_ShinonomeFNT.h" //beta ver 1.21
#include "ESP32_SD_UTF8toSJIS.h" //beta ver 1.21

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* MyFont_file = "/font/MyFont.fnt"; //自作フォントファイル名を定義
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 news_sj_txt[1024]; //Shift_JIS コード文字列を格納
uint16_t news_sj_length; //Shift_JIS コード文字列長

//-----ニュース記事文字列スクロール変数の初期化--------
uint16_t Scrolle_speed = 10; //文字列スクロールインターバル時間

//-----NTP時刻GET設定---------
uint32_t NTP_LastTime = 0;

//-----Yahoo記事取得引数初期化-------------------------
uint64_t NewsGetLastTime = 0;
uint64_t WeatherGetLastTime = 0;
bool News_first_get = true;
bool Weather_first_get = true;
bool News_get = false;
bool Weather_get = false;
String weather_str;

portTickType xLastWakeWebGetTime1; //マルチタスク時間カウント

//*****************セットアップ******************************
void setup() {
  _EWG.EWG_AP_Connect(ssid, password); //Wi-Fi ルーターと接続
  delay(1000);

  _ssd1331.SSD1331_Init(); //OLED SSD1331 初期化

  _SFR.SD_Shinonome_Init3F(UTF8SJIS_file, Shino_Half_Font_file, Shino_Zen_Font_file); //ライブラリ初期化。3ファイル同時に開く

  ESSG.Gadgets_MyFont_Init(MyFont_file); //自作フォント初期化
  delay(10);

  _EWG.EWG_NTP_TimeLib_init(9, "time.windows.com"); //NTPサーバー取得初期化
  _EWG.NTP_OtherServerSelect(9); //NTPサーバーと接続できなかった場合、他のNTPサーバーと接続できるか試す関数

  TaskHandle_t th; //マルチタスクハンドル定義
  xTaskCreatePinnedToCore(Task1, "Task1", 4096, NULL, 5, &th, 0); //マルチタスク実行

  xLastWakeWebGetTime1 = xTaskGetTickCount(); //マルチタスク時間カウント代入

  NewsGetLastTime = millis();
  WeatherGetLastTime = millis();
}
//************* メインループ ****************************************
void loop() {
  YahooNewsGET(0, 180000, 0, 7, 0); //180秒毎に天気取得
  YahooWeatherGET(48, 180000); //180秒毎に天気取得
  _EWG.NTP_Get_Interval(180000); //180秒毎にNTPサーバーから時刻取得
}
//************* マルチタスク ****************************************
void Task1(void *pvParameters){
  while(1){
    ESSG.Scroll_1_line(0, 0, 0, 7, 0, Scrolle_speed, news_sj_txt, news_sj_length, &News_get);
    ESSG.ShinonomeClock_YMD(0, 16, 3, 3, 3); //東雲フォント年月日表示
    ESSG.MyFontClock_Weekday(80, 16, 7, 7, 3); //自作フォント曜日表示
    ESSG.Shinonome_Sec_Clock(80, 32, 'H', 'V', 0, 0, 15, 7, 0, 1); //東雲フォント秒表示
    ESSG.MyFont_HM_Clock(0, 32, 'H', 'V', 'H', 'V', 0, 0, 1, 1, 50, 7, 0, 1); //自作フォント時分表示

    if(Weather_get){ //サーバーから天気予報取得できたら、OLED表示を更新
      ESSG.YahooJ_Weather_TodayTomorrow(48, weather_str);
      Weather_get = false;
    }
  }
}
//************** Yahoo RSS ニュースガジェット ************************
void YahooNewsGET(uint8_t y0, uint32_t get_interval, uint8_t Red, uint8_t Green, uint8_t Blue){
  if((News_first_get == true) || ((millis() - NewsGetLastTime) > get_interval)){
    char web_get_time[6];
    sprintf(web_get_time, "%02d:%02d", hour(), minute()); //ゼロを空白で埋める場合は%2dとする
    String news_str = "◆ " + String(web_get_time) + " ";

    char root_ca[2048];
    ESSG.Root_CA_SDcard_Read(Yahoo_rootca_file, root_ca); //SDカードに保存してあるルート証明書取得

    news_str += _EWG.EWG_https_Web_Get(root_ca, "news.yahoo.co.jp", "/pickup/rss.xml", '\n', "</rss>", "<title>", "</title>", "◆ ");
    Serial.print("News Get = "); Serial.println( news_str );
    Serial.flush(); //シリアル出力が終わるまで待つ
    news_sj_length = u8ts.UTF8_to_SJIS(news_str, news_sj_txt);
    NewsGetLastTime = millis();
    News_first_get = false;
    News_get = true;
  }
}
//************** Yahoo RSS 天気予報ガジェット *************************
void YahooWeatherGET(uint8_t y0, uint32_t get_interval){
  if((Weather_first_get == true) || ((millis() - WeatherGetLastTime) > get_interval)){

    char root_ca[2048];
    ESSG.Root_CA_SDcard_Read(Yahoo_rootca_file, root_ca); //SDカードに保存してあるルート証明書取得
    //東京の天気予報
    weather_str = _EWG.EWG_https_Web_Get(root_ca, "rss-weather.yahoo.co.jp", "/rss/days/46.xml",  '>', "</rss", "】 ", " - ", "|");
    Serial.print("Weather forecast = "); Serial.println(weather_str);
    Serial.flush(); //シリアル出力が終わるまで待つ
    WeatherGetLastTime = millis();
    Weather_get = true;
    Weather_first_get = false;
  }
}

【解説】

●1-3行:
先にも述べた通り、2017/8/1から Arduino core for ESP32 が大幅アップデートされました。
それにより、Serial.beginクラスも2重使用できなくなりましたので、以下のライブラリは最新の beta ver 1.21 を使用してください。

ESP32_SD_ShinonomeFNT  ( beta ver 1.21 )
ESP32_SD_UTF8toSJIS  ( beta ver 1.21 )

このライブラリは ESP32_SD_SSD1331_Gadgets でインクルードされていて、無くても良いのですが、あえてここで明示的にインクルードしておきます。

●12行:
micro SD カードに保存してある、Yahoo! Japan RSS サイトの SSL ルート証明書ファイル名です。

●34行:
ニュース記事スクロールインターバル時間はミリセコンド単位で決めます。
10ms くらいがちょうど良いと思います。

●48行:
ESP32 に搭載してある、FreeRTOS の経過時間をカウントするものです。
Tick という単位でカウントしています。

●52行:
自作の ESP32_Web_Get ライブラリのクラスで、ここでWi-Fiルータと接続しています。
このクラス内で、Serial.begin(115200); を使用しています。

●57行:
ここでフォントファイルを3つ開いています。
ESP32 ( ESP-WROOM-32 )では、1タスク内で同時に開けるファイル数は4つまでです。

●59行:
ここで自作フォントファイルを開いていますので、同時に開くファイル合計は4つになります。
後は、Yahoo! Japan RSS のルート証明書を開く必要がありますが、これはデュアルコアの別タスクになります。

●62-63行:
ここで、NTPサーバーから時刻を取得しています。
もし、time.windows.com から取得できなかった場合、他の NTP サーバーから時刻を取得するようにしました。
Arduino 標準の Time ライブラリでは、時刻セットにsetSyncProvider 関数をよく使いますが、これを使うと、自動で定期的にタイムをセットする時に、core 0 のループが一時中断してしまいます。
これの原因は突き止めておらず、良く分からないのですが、setSyncProvider関数を使わずに、setTime関数を使って NTP時刻をセットすれば、ユーザーで自由にタスクを選べます。
これは、77行でセットしています。

●65-66行:
ESP32 でマルチタスク(デュアルコア)で動かす、FreeRTOS 関数です。
80-93行の関数がメインループとは別のCPU で実行されます。
このタスクは core 0 、メインloop は core 1 です。
要するに、有機EL ( OLED )表示の SPI制御は core 0 で、Web記事 GET や NTP サーバー時刻取得は core 1 です。

●68行:
ここで、FreeRTOS の起動からの時間(Tickカウント)を代入します。

●74-78行:
メインloop 内では、WiFiClientSecure ライブラリで、Web記事を GET したり、WiFiUdp ライブラリで NTPサーバーから時刻を取得したりする関数を置きます。

●80-93行:
ここでは、マルチタスク(デュアルコア)の core 0 のループです。
82-86行は自作ライブラリESP32_SD_SSD1331_Gadgets からの関数群です。
カラーは赤、緑、青の三原色を混ぜて作ります。
256 色で指定します。
赤色 ( 0-7 )
緑色 ( 0-7 )
青色 ( 0-3 )

詳しい説明は省きますが、値をいろいろ変えてみて試してください。

Scroll_1_line(Y座標 , 番号 , 赤 , 緑 , 青 , インターバル , S-jisコード)

ShinonomeClock_YMD( X座標 , Y座標 , 赤 , 緑 , 青 )

MyFontClock_Weekday( X座標 , Y座標 , 赤 , 緑 , 青 )

Shinonome_Sec_Clock( X座標 , Y座標 , ‘V’ or ‘H’ , ‘V’ or ’H’ , 0 or 1 , 0 or 1 , 速さ ,  赤 , 緑 , 青 )

MyFont_HM_Clock( X座標 , Y座標 , ‘V’ or ‘H’ , ‘V’ or ’H’ , ‘V’ or ‘H’ , ‘V’ or ’H’ , 0 or 1 , 0 or 1 , 0 or 1 , 0 or 1 ,速さ ,  赤 , 緑 , 青 )

その他、以下の記事も参照してみてください。

ESP32 と 有機EL SSD1331 で Yahoo News 、 天気予報 、 NTP 時計 Wi-FI ガジェットを作ってみた

また、88-91行で、Yahoo! Japan RSS の天気予報から文字列抽出したものを、自作フォントに変換して OLED ディスプレイに表示させています。

●95-112行:
Yahoo! Japan RSS サイトからトップニューストピックスを取得する関数です。
97-99行で、取得時刻を文字列に変換して、頭の位置に表示させます。

101-102行で micro SD カードに保存されたルート証明書を取得します。

104行で SSL の Webページに記事をGET しに行きます。
ホストサーバー URL や、ターゲット URL を変えれば、自分の欲しい記事を取得できると思います。

107行で、UTF-8 文字列を Shift_JIS コードに変換しています。
それを、マルチタスクの 82行目に代入しています。

●114-127行:
ここでは、Yahoo! Japan RSS サイトの天気予報から文字列を取得しています。
120行目のホスト URL や、ターゲットURL を変えれば、自分の好きな地域の天気予報を取得できます。
ここでは、東京の天気予報になります。

天気予報の地域選択は以下のサイトから選んで、ターゲット URL を書き換えてください。

https://weather.yahoo.co.jp/weather/rss/

コンパイル書き込み実行

では、コンパイル書き込み実行させてみてください。

最初に紹介した動画のように、有機EL ( OLED )ディスプレイの表示が停止せずに、裏の CPU でWeb記事をGET できていればOKです。

シリアルモニターにはこのように表示されます。

ESP32_MultiTask_Gadget01

まとめ

これで、IoT としての必須条件である、Web記事取得と、NTP時刻取得をしながら、別のCPUで動作を止めずに動かすことができるようになりました。
これは、電子工作としては革命的ですよね。

それにしても、今回の GitHub の Arduino  core for ESP32 大幅アップデートによって、ESP32 ( ESP-WROOM-32 )の WiFi動作の不安がかなり解消されたことが、大いに助けになりました。
GitHub の issue で投げかけていた質問を読んでくれたのかどうか分かりませんが、開発チームの @me-no-dev さんや、@copercini さんには感謝したいです。
ありがとうございました。
m(_ _)m

今回はここまでです。

ではまた・・・。

mgo-tec電子工作 関連コンテンツ ( 広告含む )

スポンサーリンク

Amazon.co.jp 当ブログのおすすめ








投稿者:

mgo-tec

Arduino , ESP32 ( ESP-WROOM-32 ) , ESP8266 ( ESP-WROOM-02 )等を使って、主にスマホと連携した電子工作やプログラミング記事を書いてます。ライブラリも作ったりしてます。趣味、独学でやってますので、動作保証はしません。
電子回路やプログラミングの専門家ではありません。
畑違いの仕事をしてます。
でも、少しだけ電気の知識が必要な仕事なので、電気工事士や工事担任者等の資格は持ってます。

「Yahoo ニュース、天気予報、NTP時計ガジェットを ESP32 マルチタスク ( デュアルコア )で動かしてみた」への2件のフィードバック

  1. 記事参考してArduino core for ESP32 と自作ライブラリをアップデートしての(8月4日)マルチタスク ( デュアルコア )動作確認しました。
    ESP32を aitendo ESP-WROOM-32基板での単体使用、動作良好に動作してます。
    マルチタスクで無いスケッチもアップデート後は問題なく動作してます。
    動作時の電流値ですが、マルチタスクで約245mA、以前のスケッチで
    約220mAほどです、電光掲示板的にはどちらも申し分有りませんね。
    デュアルコアでの動作が電流値に出てるのかな、参考になる情報いつも
    拝見してます今後とも宜しくお願いします。

    1. 太田さん

      いつも当ブログをご覧いただき、そして実践してただき、感謝感謝です。
      m(_ _)m

      良好に動いていて安心しました。
      そうですか・・・、マルチタスクで25mA 程アップですか・・・。
      私はまだ計測していないのですが、思っていたよりそれほど消費していませんね。
      これがDeep Sleep で動いてくれればうれしいですね。
      今後の課題です。

      また、何かありましたらコメント頂けると助かります。
      ありがとうございました。
      m(_ _)m

コメントを残す

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

*画像の文字を入力してください。(スパム防止の為)