Web News記事自動取得 OLED ( 有機EL )ミニ電光掲示板に16×16フリー日本語フォント( 東雲 ) を使う

記事公開日:2016年6月2日
最終修正日:2016年7月13日

スポンサーリンク

こんばんは。

今回は前回の記事で紹介したフリーの16×16ドット日本語漢字フォント、東雲(しののめ)を使って、極小OLED (有機EL) SSD1306 に文字がスクロールする電光掲示板を表示させてみました。
以前の記事
ESP-WROOM-02 と 極小OLED (有機EL) で Yahooニュース電光掲示板とNTP時計を表示させてみた
で紹介したものでは、8×8ドットの美咲フォントが余りにも小さい文字だったので、それを大きくするために倍角にして表示させていましたが、やはり複雑な漢字は判読し辛かったのです。
今回は、東雲フォントを使ったので、判読バッチリ!!です。
ただ、処理速度が4倍かかるので、スクロール速度はあまり速くできませんでした。
こちらの動画をご覧ください。

いかがでしょうか?
OLEDの設定変更は全てAndroid(4.2.2)スマートフォンのブラウザGoogle Chromeで行ってます。AndroidとGoogle Chromeが推奨環境です。(できるだけ最新のものを使ってください。)
自作ライブラリEasyWebSocketを使ってリアルタイムWi-Fi制御してます。
時計はNTPサーバーから5分毎に自動修正してます。
電源はコンビニで買った単三型携帯充電器で、エネループを使ってみました。
満充電状態から使用して14時間持ちました。リチウムイオンならばもっと持つと思います。
最速スクロールはここまでが限界ですが、十分だと思います。
どちらかの行のスクロールを遅くすると片方のスクロールが早くなる感じです。
16ドットのスクロールですから、この前の倍角8ドットよりはスムースな感じですね。
文字が鮮明に読み取れるので、結構離れていても容易に判読できます。
ただ、スクロールをスムースにするために文字列を一気に全ての文字をドットに変換してバッファに記憶させるので、Web記事取得から表示までに18秒くらいかかってしまいます。
もっと高速に表示させる方法が分かる方がいらっしゃったら是非方法を教えていただきたいです。
以前の記事と同じく、Yahoo.co.jp の RSSサイトからニュースのトップタイトル記事だけを取得してます。天気予報や芸能記事、コンピューター系記事と記事を選ぶことができます。

初めて当ブログを見る方の為に念のため説明しておきます。
使っているものは
ESPr Developer ( ESP-WROOM-02 開発ボード )(スイッチサイエンス製)と極小OLED ( 有機EL ) SSD1306 だけです。

Amazon.co.jp

外付け漢字ROMやSDカードなどは一切使用しておりません。
その他はブレッドボードやジャンパーワイヤー、Androidスマートフォンです。
あとはプログラム書き込みにWindowsPC、Wi-Fi環境くらいでしょうか・・・。
これだけの最少部品点数でここまでできるのはスゴいですよね。
改めてESP8266のポテンシャルの大きさに感動します。

では、順番に解説していきたいと思います。

1.Arduino IDEの設定

この記事のコメント投稿でKさんから有益な情報をいただきました。
Arduno IDE 1.6.9 で問題なく動作確認が取れました。
以下のOTA機能を使わず、COMポート(USB)で問題なくSPIFFSファイルアップロードができました。
以下の記事はIDE 1.6.8を使用の場合で説明します。(2016/6/10)

まず、前回の記事の4節目まで事前に済ませておいてください。

1-1 EasyWebSocketライブラリ1.37のインストール

ライブラリインストールで、当方自作のEasyWebSocketライブラリを新たにインストールを追加してください。
現在のバージョンは1.37です。
GitHubのこちらのページにありますので、ZIPファイルをダウンロードしていただき、ZIPから自動インストールか、解凍して、EasyWebSocket_BETA1.3-masterフォルダのさらにその中のEasyWebSocket_BETA1.3-masterフォルダをArduinoのlibrariesフォルダにコピーしてください。インストールの方法はこちらの記事を参照してください。
インストール終了後、必ずIDEを再起動してください。
EasyWebSocketのプログラミング方法はこちらのページを参照してください。

1-2 Timeライブラリのインストール

Arduino.ccページのこちらにあります。→http://playground.arduino.cc/code/time
このページを開いて下図のようなところをクリックすると
ws_Yahoo_message05

下図のように表示されますので、Githubリンクをクリックしてください。

ws_Yahoo_message06

そうしたら下図のようなところをクリックするとZIPファイルのダウンロードが開始されます。
WS_Shinonome01

それを解凍するとTime-masterフォルダがありますので、更にその中のTime-masterフォルダをIDEのlibrariesフォルダにフォルダごとコピーしてください。
又は、IDEのライブラリ自動インストール機能を使ってZIPファイルからインストールしてください。
その場合、ドキュメントフォルダのArduino/librariesフォルダにインストールされます。

1-3 spiffs_01.txtファイルをdataフォルダにコピーして、OTAでフラッシュにSPIFFSファイルアップロードする

前回の記事 の6-3節まで済ませてください。
6-3節で新たに追加でdataフォルダにコピーして欲しいファイルがあります。
先ほどのEasyWebSocketインストール方法記事にあるようにサンプルスケッチの中のdataフォルダに spiffs_01.txt というファイルがあります。
このファイルをテキストエディタで開いて下さい。
メモ帳でも結構ですが、メモ帳だとあまり正しく表示されません。
ですが、編集できなくはないです。
メモ帳だとこんな感じになります。
この ws://192.168.0.14 というところのIPアドレスをご自分のルーターで割り当てたESP-WROOM-02のIPアドレスに書き換えてください。
WS_Shinonome02
書き換えたら、名前を付けて保存のところで必ずUTF-8形式で保存してください。
WS_Shinonome03

これを6-3節で作ったdataフォルダにコピーしておいてください。
これは、スマホブラウザとのWebSocket通信を行うためのHTMLヘッダファイルです。
つまり、BasicOTAサンプルスケッチのdataフォルダに以下のファイルがあれば良いです。

spiffs_01.txt (HTMLヘッダ)  6KB
shnm8x16r.bdf
 (半角東雲フォント) 29KB
shnmk16.bdf (全角ゴシック東雲フォント) 1,110KB
Utf8Sjis.tbl (私の自作、UTF8→Shift_JISコード変換テーブル) 236KB

これが済んだら、前回の記事の6-5節まで済ませてOTAでESP-WROOM-02のフラッシュにアップロードしてください。

2.スケッチの入力および解説

以下のスケッチをコピーして新規スケッチに貼り付けて、SSIDとパスワードをご自分の環境に書き換えて、名前を付けて保存してください。

/* WebSocketリアルタイムコントロール 有機EL(OLED) 16x16東雲フォント電光掲示板サンプルスケッチ
 * Web記事取得、時計機能あり。 ESP-WROOM-02(ESP8266) および 有機EL SSD1306専用
 * Dual licensed under The MIT License or LGPL v2.1
 * Copyright (c) 2016 MGO-tec 
 * License reference URL --> https://opensource.org/licenses/mit-license.php
 * 
 * Includes ESP8266WiFi.h -->LGPL v2.1 license.
 * ESP8266WiFi.h - esp8266 Wifi support.
 * Based on WiFi.h from Arduino WiFi shield library.
 * Copyright (c) 2011-2014 Arduino.  All right reserved.
 * Modified by Ivan Grokhotkov, December 2014
 * 
 * Includes Hash.h -->LGPL v2.1 license.
 * Copyright (c) 2015 Markus Sattler. All rights reserved.
 * License reference URL --> https://opensource.org/licenses/LGPL-2.1
 */
#include <EasyWebSocket.h>
#include <ESP8266WiFi.h>
#include <Hash.h>
#include <Wire.h>
#include <TimeLib.h> //timeライブラリver1.4の場合
#include <WiFiUdp.h>
#include <UTF8toSJIS.h>
#include <OLED_SSD1306.h>
#include <ShinonomeFONTread.h>

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

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

const uint8_t OLED_Adress = 0x3C; //OLED address 製品に記載の数値は7bitなので、8bitに変換して1bit右へずらした値(78>>3c)

EasyWebSocket ews;
UTF8toSJIS u8ts;
OLED_SSD1306 oled;
ShinonomeFONTread SFR;

String html_str1, html_str2, html_str3, html_str4, html_str5, html_str6, html_str7;

uint16_t PingSendTime = 30000; //スマホへPingを30秒毎に送信

String ret_str="", scl_txt="";

uint8_t scl_cnt = 0, scl_cnt2 = 0;
uint8_t fnt_cnt = 0, fnt_cnt2 = 0;
bool FntReadOK = true, FntReadOK2 = true;

uint8_t tmp_buf1[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, tmp_buf2[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

uint8_t SnnmDotOut[16][16], SnnmDotOut2[16][16];
uint8_t SnnmDotCnv[16][16], SnnmDotCnv2[16][16];
uint8_t Next_buf[16][16], Next_buf2[16][16];

uint8_t font_buf[512][16], font_buf2[512][16];
uint8_t test_tmp_buf1[16], test_tmp_buf2[16], dummy_font_buf[16];
uint8_t test_tmp_buf21[16],test_tmp_buf22[16], dummy_font_buf2[16];

uint8_t sj_txt[512], sj_txt2[512];
uint16_t sj_cnt = 0, sj_cnt2 = 0;
uint16_t sj_length, sj_length2;
uint32_t SclTime, SclTime2;
uint16_t SclSpeed = 50, SclSpeed2 = 30;
boolean Scl_Stop = false;
uint8_t Direction = 0;
int16_t Angle = 0;
boolean sjis_txt_in = false, sjis_txt_in2 = false;
boolean BW_reverse = false, BW_reverse2 = false;

//-------NTPサーバー定義----------------
IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov; //(129, 6, 15, 28)time.nist.gov NTP server
const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets
const int timeZone = 9;     // Tokyo
WiFiUDP Udp;
unsigned int localPort = 8888;  // local port to listen for UDP packets
time_t prevDisplay = 0; // when the digital clock was displayed
uint32_t LastTime = 0;

//-------時刻表示定義-------------------
String time_str, ymd_str, dummy_ymd_str;
uint8_t time_sj_txt[25], ymd_sj_txt[25];
uint16_t time_sj_length, ymd_sj_length;
const char* week_jp[7] = {"日","月","火","水","木","金","土"};
//-----Web取得定義-----------------------------------------------
uint8_t web_get = 0, web_get2 = 0;
uint32_t Web_time = 0;
boolean first_get = false;

//***********セットアップ***************************************************
void setup() 
{
  uint16_t cp,i,j;
  Wire.begin(); // I2C initialise the connection
  Wire.setClock(400000L); //クロックはMax 400kHz

  oled.Ini_OLED_SSD1306(OLED_Adress, 127); //contrast 0-255 default 127
  delay(300);
  //セットアップで全角を一旦表示させることが重要。半角だとなぜかSPIFFSファイル読み込みエラーになってしまうため。
  u8ts.UTF8_to_SJIS_str_cnv(UTF8SJIS_file, "WAIT・・・・", sj_txt, &sj_length);
  
  i=0;
  while(i<sj_length){
    cp=SFR.SjisToShinonome16FontRead(ZenkakuFontFile, HalfFontFile, 0, 0, sj_txt[i], sj_txt[i+1], font_buf[i], font_buf[i+1]);
    i=i+cp; //cpは全角ならば2, 半角ならば2を返る。
  }
  for(i=0; i<16; i++){
    oled.Dot_8X16_Rotation(90, font_buf[i], test_tmp_buf1, test_tmp_buf2);
    oled.OLED_8x16_Display_Out(OLED_Adress, 120-8*i, 2, test_tmp_buf1, test_tmp_buf2);
  }
  for(i=0; i<16; i++) { //初期化しておく
    for(j=0; j<16; j++){
      font_buf[i][j] = 0;
      SnnmDotOut[i][j] = 0; SnnmDotCnv[i][j] = 0;
      SnnmDotOut[i][j] = 0; SnnmDotOut2[i][j] = 0;
      SnnmDotCnv[i][j] = 0; SnnmDotCnv2[i][j] = 0;
      Next_buf[i][j] = 0;   Next_buf2[i][j] = 0;
    }
  }
  
  html_str1 = "<body style='background:#ddddff; color:#000;'>\r\n";
  html_str1 += ews.EWS_TextBox_Send("txt1", "1行目任意テキスト送信、半角カタカナもOK!","送信");
  html_str1 += "<br>\r\n";
  html_str1 += ews.EWS_TextBox_Send("Txt2", "2行目任意text送信、半角カタカナもOK!","送信");
  html_str1 += "<br><br>\r\n";
  html_str2 = "Scrolle Speed 1\r\n";
  html_str2 += ews.EWS_Canvas_Slider_T("Speed",200,40,"#777777","#77aaff");
  html_str2 += "<br><br>\r\n";
  html_str2 += "Scrolle Speed 2\r\n";
  html_str2 += ews.EWS_Canvas_Slider_T("speed2",200,40,"#777777","#77aaff");
  html_str3 = "<br><br>\r\n";
  html_str3 += ews.EWS_On_Momentary_Button("_SclStop", "Scrole Stop", 100,25,15,"#ffffff","#777777");
  html_str3 += "<br><br>1行目白黒反転 \r\n";
  html_str4 = ews.EWS_On_Momentary_Button("(rev", "Normal", 70,25,15,"#000000","#ffffff");
  html_str4 += "<span>  </span>\r\n";
  html_str4 += ews.EWS_On_Momentary_Button(")rev", "Reverse", 70,25,15,"#ffffff","#0000ff");
  html_str4 += "<br>2行目白黒反転 \r\n";
  html_str4 += ews.EWS_On_Momentary_Button("[rev", "Normal", 70,25,15,"#000000","#ffffff");
  html_str4 += "<span>  </span>\r\n";
  html_str4 += ews.EWS_On_Momentary_Button("]rev", "Reverse", 70,25,15,"#ffffff","#0000ff");
  html_str4 += "<br><br>\r\n";
  html_str5 = "<div style='width:330px; height:140px; text-align:center; padding:10px; background:#ccccff; border:#0000ff solid 1px;'>\r\n";
  html_str5 += ews.EWS_On_Momentary_Button("webON", "Web GET ON", 110,25,15,"#000000","#ff77ff");
  html_str5 += "※ここボタンを押すとWebSocketは切断されます。再操作する場合はWS-Reconnectボタンを押してください<br>1行目 \r\n";
  html_str5 += ews.EWS_On_Momentary_Button("News", "Top NEWS", 100,25,15,"#000000","#ffffff");
  html_str5 += "<span>  </span>\r\n";
  html_str5 += ews.EWS_On_Momentary_Button("Cnews", "PC NEWS", 110,25,15,"#000000","#ffffff");
  html_str5 += "<br><br>2行目 \r\n";
  html_str5 += ews.EWS_On_Momentary_Button("ENews", "芸能News", 110,25,15,"#000000","#ffffff");
  html_str5 += "<span>  </span>\r\n";
  html_str5 += ews.EWS_On_Momentary_Button("Weather", "Weather", 110,25,15,"#000000","#ffffff");
  html_str5 += "</div><br><br>\r\n";
  html_str6 = ews.EWS_Status_Text(20,"RED");
  html_str6 += "<br>\r\n";
  html_str6 += "<br><br>\r\n";
  html_str6 += ews.EWS_WebSocket_Reconnection_Button("WS-Reconnect", 200, 40, 17);
  html_str6 += "<br><br>\r\n";  
  html_str6 += ews.EWS_Close_Button("WS CLOSE",150,40,17);
  html_str6 += ews.EWS_Window_ReLoad_Button("ReLoad",150,40,17);
  html_str6 += "</body></html>\r\n";
  html_str7 = "";
  
  ews.AP_Connect(ssid, password);

  //NTPサーバーから時刻を取得
  Udp.begin(localPort);
  setSyncProvider(getNtpTime);
  delay(1000);
  
  SclTime = millis();
  LastTime = millis();
  prevDisplay = now();
}
//**************メインループ*************************************************
void loop() {
  //WebSocket ハンドシェイク関数
  ews.EWS_HandShake(html_str1, html_str2, html_str3, html_str4, html_str5, html_str6, html_str7);
  
  uint8_t br;
  uint16_t i;
  uint8_t cp;

  ret_str = ews.EWS_ESP8266CharReceive(PingSendTime); //ブラウザからのWebSocketデータ受信

  if(ret_str != "_close"){
    if(ret_str != "\0"){
      if(ret_str != "Ping"){
        if(ret_str[0] == 't' || ret_str[0] == 'T' ){
          scl_txt = ret_str.substring(ret_str.indexOf('|')+1, ret_str.length()-1);
          scl_txt += String(" ") + String("\0");
          switch(ret_str[0]){
            case 't':
              u8ts.UTF8_to_SJIS_str_cnv(UTF8SJIS_file, scl_txt, sj_txt, &sj_length);
              i=0;
              while(i<sj_length){
                cp=SFR.SjisToShinonome16FontRead(ZenkakuFontFile, HalfFontFile, 0, 0, sj_txt[i], sj_txt[i+1], font_buf[i], font_buf[i+1]);
                i=i+cp; //cpは全角ならば2, 半角ならば2を返る。
              }
              for(i=0; i<16; i++) dummy_font_buf[i] = font_buf[0][i];
              fnt_cnt = 0; scl_cnt = 0; sj_cnt = 0; web_get = 0;
              FntReadOK = true; sjis_txt_in = true; Scl_Stop == false;
              FntReadOK2 = false; sjis_txt_in2 = false;
              break;
            case 'T':
              u8ts.UTF8_to_SJIS_str_cnv(UTF8SJIS_file, scl_txt, sj_txt2, &sj_length2);
              i=0;
              while(i<sj_length2){
                cp=SFR.SjisToShinonome16FontRead(ZenkakuFontFile, HalfFontFile, 0, 0, sj_txt2[i], sj_txt2[i+1], font_buf2[i], font_buf2[i+1]);
                i=i+cp; //cpは全角ならば2, 半角ならば2を返る。
              }
              for(i=0; i<16; i++) dummy_font_buf2[i] = font_buf2[0][i];
              fnt_cnt2 = 0; scl_cnt2 = 0; sj_cnt2 = 0; web_get = 0;
              FntReadOK2 = true; sjis_txt_in2 = true; Scl_Stop == false;
              FntReadOK = false; sjis_txt_in = false;
              break;
          } 
          Serial.println();
          for (int iiii=0; iiii<sj_length; iiii++) Serial.write(sj_txt[iiii]);
          Serial.println();
        }else{
          switch(ret_str[4]){
            case 'S':
              SclSpeed = (ret_str[0]-0x30)*100 + (ret_str[1]-0x30)*10 + (ret_str[2]-0x30);
              SclSpeed = 200 - (floor(0.25 * SclSpeed) + 150);
              Scl_Stop = false;
              break;
            case 's':
              SclSpeed2 = (ret_str[0]-0x30)*100 + (ret_str[1]-0x30)*10 + (ret_str[2]-0x30);
              SclSpeed2 = 200 - (floor(0.25 * SclSpeed2) + 150);
              Scl_Stop = false;
              break;
            case '_':
              Scl_Stop = true;
              break;
            case '(':
              BW_reverse = false;
              break;
            case ')':
              BW_reverse = true;
              break;
            case '[':
              BW_reverse2 = false;
              break;
            case ']':
              BW_reverse2 = true;
              break;
            case 'w':
              web_get = 1; web_get2 = 1; first_get = true;
              break;
            case 'N':
              web_get = 1;
              sjis_txt_in = false; first_get = true;
              break;
            case 'C':
              web_get = 2;
              sjis_txt_in = false; first_get = true;
              break;
            case 'E':
              web_get2 = 1;
              sjis_txt_in2 = false; first_get = true;
              break;
            case 'W':
              web_get2 = 2;
              sjis_txt_in2 = false; first_get = true;
              break;
          }
        }
        ret_str = "";
      }else{
        ret_str = "";
      }
    }
    
    if(sjis_txt_in == true || sjis_txt_in2 == true){ //OLED1行目電光掲示板スクロール
      if(millis() - SclTime > SclSpeed){
        if(sj_cnt >= sj_length){
          sj_cnt = 0;
          for(i=0; i<16; i++) dummy_font_buf[i] = font_buf[sj_cnt][i];
          oled.OLED8x16_White_Reversal(BW_reverse, dummy_font_buf, dummy_font_buf);
        }
        if(Scl_Stop == false){
          for(i=0; i<16; i++){
            oled.Dot_8X16_Rotation(90, SnnmDotOut[i], SnnmDotCnv[0], SnnmDotCnv[1]);
            oled.OLED_8x16_Display_Out(OLED_Adress, i*8, 6, SnnmDotCnv[0], SnnmDotCnv[1]);
          }
          oled.Scroller_8x16Dot_Replace(Direction, Next_buf[0], SnnmDotOut[0], dummy_font_buf);
          for(i=0; i<15; i++) oled.Scroller_8x16Dot_Replace(Direction, Next_buf[i+1], SnnmDotOut[i+1], Next_buf[i]);
          scl_cnt++;
        }
        if(scl_cnt == 8){
          scl_cnt = 0;
          sj_cnt++;
          for(i=0; i<16; i++) dummy_font_buf[i] = font_buf[sj_cnt][i];
          oled.OLED8x16_White_Reversal(BW_reverse, dummy_font_buf, dummy_font_buf);
        }
        SclTime = millis();
      }

      if(millis() - SclTime2 > SclSpeed2){ //OLED2行目電光掲示板スクロール
        if(sj_cnt2 >= sj_length2){
          sj_cnt2 = 0;
          for(i=0; i<16; i++) dummy_font_buf2[i] = font_buf2[sj_cnt2][i];
          oled.OLED8x16_White_Reversal(BW_reverse2, dummy_font_buf2, dummy_font_buf2);
        }
        if(Scl_Stop == false){
          for(i=0; i<16; i++){
            oled.Dot_8X16_Rotation(90, SnnmDotOut2[i], SnnmDotCnv2[0], SnnmDotCnv2[1]);
            oled.OLED_8x16_Display_Out(OLED_Adress, i*8, 4, SnnmDotCnv2[0], SnnmDotCnv2[1]);
          }
          oled.Scroller_8x16Dot_Replace(Direction, Next_buf2[0], SnnmDotOut2[0], dummy_font_buf2);
          for(i=0; i<15; i++) oled.Scroller_8x16Dot_Replace(Direction, Next_buf2[i+1], SnnmDotOut2[i+1], Next_buf2[i]);
          scl_cnt2++;
        }
        if(scl_cnt2 == 8){
          scl_cnt2 = 0;
          sj_cnt2++;
          for(i=0; i<16; i++) dummy_font_buf2[i] = font_buf2[sj_cnt2][i];
          oled.OLED8x16_White_Reversal(BW_reverse2, dummy_font_buf2, dummy_font_buf2);
        }
        SclTime2 = millis();
      }
    }
  }else if(ret_str == "_close"){
    ret_str = "";  scl_txt = "";
  }

  if(now() != prevDisplay){ //ここから時刻表示設定
    char month_chr[3], day_chr[3], h_chr[3], m_chr[3], s_chr[3];
    sprintf(h_chr, "%2d", hour());//ゼロを空白で埋める場合は%2dとすれば良い
    sprintf(m_chr, "%02d", minute());
    sprintf(s_chr, "%02d", second());
    sprintf(month_chr, "%2d", month());
    sprintf(day_chr, "%02d", day());
    time_str = String(h_chr) + ':' + String(m_chr) + ':' + String(s_chr);
    ymd_str = String(year()) + '/' + String(month_chr) + '/' + String(day_chr) + "(" + String(week_jp[weekday()-1]) + ")";
    uint8_t time_dot[8][16], ymd_dot[16][16];   
    u8ts.UTF8_to_SJIS_str_cnv(UTF8SJIS_file, time_str, time_sj_txt, &time_sj_length);
    if(Direction != 0) Direction = 0;
    i=0;
    while(i<time_sj_length){
      cp = SFR.SjisToShinonome16FontRead(ZenkakuFontFile, HalfFontFile, 0, 0, time_sj_txt[i], time_sj_txt[i+1], time_dot[i], time_dot[i+1]);
      i = i + cp; //cpは全角ならば2, 半角ならば2を返る
    }
    if(dummy_ymd_str != ymd_str){
      u8ts.UTF8_to_SJIS_str_cnv(UTF8SJIS_file, ymd_str, ymd_sj_txt, &ymd_sj_length);
      if(Direction != 0) Direction = 0;
      i=0;
      while(i<ymd_sj_length){
        cp = SFR.SjisToShinonome16FontRead(ZenkakuFontFile, HalfFontFile, 0, 0, ymd_sj_txt[i], ymd_sj_txt[i+1], ymd_dot[i], ymd_dot[i+1]);
        i = i + cp; //cpは全角ならば2, 半角ならば2を返る。
      }
    }
    for(i=0; i<8; i++){
      oled.Dot_8X16_Rotation(90, time_dot[i], SnnmDotCnv2[0], SnnmDotCnv2[1]);
      oled.OLED_8x16_Display_Out(OLED_Adress, 88-i*8, 0, SnnmDotCnv2[0], SnnmDotCnv2[1]);
    } 
    if(dummy_ymd_str != ymd_str){
      for(i=0; i<16; i++){
        oled.Dot_8X16_Rotation(90, ymd_dot[i], SnnmDotCnv2[0], SnnmDotCnv2[1]);
        oled.OLED_8x16_Display_Out(OLED_Adress, 120-i*8, 2, SnnmDotCnv2[0], SnnmDotCnv2[1]);
      }
      dummy_ymd_str = ymd_str;
    }
    prevDisplay = now();
  }

  if(web_get == 0){
    if(millis()-LastTime >= 300000L){//5分毎にNTPサーバーからタイム取得
      setSyncProvider(getNtpTime);
      Serial.println(time_str);
      LastTime = millis();
    }
  }else{
    if(millis()-LastTime >= 240000L){ //Web記事取得時でもNTPサーバからタイムを補正しておく
      setSyncProvider(getNtpTime);
      LastTime = millis();
    }
  }

  if(web_get > 0 || web_get2 > 0){ //Web記事取得
    if(first_get == true || millis()-Web_time > 600000L){ //Web記事を10分毎に取得
      char* news1_1_host = "news.yahoo.co.jp";
      String news1_1_target_ip = "/pickup/rss.xml"; // トップニュースタイトルページ
      char* news1_2_host = "news.yahoo.co.jp";
      String news1_2_target_ip = "/pickup/computer/rss.xml"; //コンピューター系ニュースページ
      String news_str = "";
      char Web_h[3], Web_m[3];
      sprintf(Web_h, "%02d", hour());//ゼロを空白で埋める場合は%2dとする
      sprintf(Web_m, "%02d", minute());
      news_str = String("◆ ") + String(Web_h) + ":" + String(Web_m) + " ";
      switch(web_get){
        case 1:
          news_str += ews.EWS_Web_Get(news1_1_host, news1_1_target_ip, '\n', "</rss>", "<title>", "</title>", "◆ ");
          break;
        case 2:
          news_str += ews.EWS_Web_Get(news1_2_host, news1_2_target_ip, '\n', "</rss>", "<title>", "</title>", "◆ ");
          break;
      }
      Serial.print("\r\nWebGet1=");
      news_str.replace("&amp;","&"); //XMLソースの場合、&が正しく表示されないので、全角に置き換える
      u8ts.UTF8_to_SJIS_str_cnv(UTF8SJIS_file, news_str, sj_txt, &sj_length);
      news_str ="";
      i=0;
      while(i<sj_length){
        cp=SFR.SjisToShinonome16FontRead(ZenkakuFontFile, HalfFontFile, 0, 0, sj_txt[i], sj_txt[i+1], font_buf[i], font_buf[i+1]);
        i=i+cp; //cpは全角ならば2, 半角ならば2を返る
      }
      for(i=0; i<16; i++) dummy_font_buf[i] = font_buf[0][i];
      for(int iy=0; iy<sj_length; iy++){
        Serial.write(sj_txt[iy]);
      }
      Serial.println();     
      fnt_cnt = 0; scl_cnt = 0; sj_cnt = 0;
      sjis_txt_in = true;  FntReadOK = true;
      //2つめの記事取得
      char* news2_1_host = "news.yahoo.co.jp";
      String news2_1_target_ip = "/pickup/entertainment/rss.xml"; // 芸能トップニュースタイトルページ
      char* news2_2_host = "rss.weather.yahoo.co.jp";
      String news2_2_target_ip = "/rss/days/4620.xml"; //小田原の天気予報ページ
      String news2_str = "";
      news2_str = String("◆ ") + String(Web_h) + ":" + String(Web_m) + " ";
      switch(web_get2){
        case 1:
          news2_str += ews.EWS_Web_Get(news2_1_host, news2_1_target_ip, '\n', "</rss>", "<title>", "</title>", "◆ ");
          break;
        case 2:
          news2_str += ews.EWS_Web_Get(news2_2_host, news2_2_target_ip, '>', "</rss>", "【", " - ", "【");
          break;
      }
      Serial.print("\r\nWebGet2=");
      news2_str.replace("&amp;","&");
      u8ts.UTF8_to_SJIS_str_cnv(UTF8SJIS_file, news2_str, sj_txt2, &sj_length2);
      news2_str ="";
      i=0;
      while(i<sj_length2){
        cp=SFR.SjisToShinonome16FontRead(ZenkakuFontFile, HalfFontFile, 0, 0, sj_txt2[i], sj_txt2[i+1], font_buf2[i], font_buf2[i+1]);
        i=i+cp; //cpは全角ならば2, 半角ならば2を返る
      }
      for(i=0; i<16; i++) dummy_font_buf2[i] = font_buf2[0][i];
      for(int iy=0; iy<sj_length2; iy++){
        Serial.write(sj_txt2[iy]);
      }
      Serial.println();
      fnt_cnt2 = 0; scl_cnt2 = 0; sj_cnt2 = 0;
      sjis_txt_in2 = true;  FntReadOK2 = true;
      Web_time = millis();
      first_get = false;
    }
  }
}
//*************************NTP Time**************************************
time_t getNtpTime()
{
  while (Udp.parsePacket() > 0) ; // discard any previously received packets
  Serial.println("Transmit NTP Request");
  sendNTPpacket(timeServer);
  uint32_t beginWait = millis();
  while (millis() - beginWait < 1500) {
    int size = Udp.parsePacket();
    if (size >= NTP_PACKET_SIZE) {
      Serial.println("Receive NTP Response");
      Udp.read(packetBuffer, NTP_PACKET_SIZE);  // read packet into the buffer
      unsigned long secsSince1900;
      // convert four bytes starting at location 40 to a long integer
      secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
      secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
      secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
      secsSince1900 |= (unsigned long)packetBuffer[43];
      return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
    }
  }
  Serial.println("No NTP Response :-(");
  return 0; // return 0 if unable to get the time
}
//*************************NTP Time**************************************
void sendNTPpacket(IPAddress &address)
{// send an NTP request to the time server at the given address
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;
  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:                 
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(packetBuffer, NTP_PACKET_SIZE);
  Udp.endPacket();
}

ライセンスはMITですが、ESP8266 core for Arduinoライブラリも使っているので、LGPLver2.1とのデュアルライセンスとしておきます。
無保証で配布、改変は自由ですが、ライセンス表記はしてください。
LGPLver2.1についてはここでは述べませんのでネットで検索してみてください。

それでは、このスケッチについてザッと説明していきます。

●17-25行目:
ここで様々なライブラリをインクルードしてます。Arduino IDE上では19行のHash.hだけが黒色文字で、その他はすべて赤色文字になっていると思います。そうなっていなければ、ライブラリがインストールされておりませんので、インストールし直してみてください。

●27-28行:
ここでご自分のルーターのSSIDおよびパスワードに書き換えてください。

●30-32行:
UTF-8→Shift_JIS変換テーブル、東雲全角フォント、半角フォントのファイル名をここで指定します。

●36-39行:
自作ライブラリのクラス名をここで指定します。

●57行:
Web記事を取得した最大文字数に合わせて配列の最大値を決めます。漢字は8×16ドットが2個必要ですので、文字数の倍の数値を取っておきます。 多めに確保しておいた方が良いです。

●61行:
スマホからWebSocket通信で送られてきたUTF-8テキストをライブラリでShift_JISに変換したバイトを格納する配列です。漢字1文字は2バイトです。

●72-80行:
NTPサーバー時刻取得についての定義で、これはArduinoIDEのサンプルスケッチそのままです。

●99行:
これは、OLED_SSD1306ライブラリのver1.5で新たに登場した初期化関数です。
コントラストの調整ができます。

●102行:
セットアップ時にWAIT・・・という文字を表示させるために、この文字をShift_JISコードに変換します。

●104-108行:
Shift_JISコードバッファ配列から東雲フォントのドットを自作ライブラリで抽出し、font_buf配列へ格納します。

●109-112行:
font_buf配列からここで一気にOLEDへ文字列を吐き出して表示させます。

●113-121行:
ここで一旦配列を初期化しておかないと、OLEDが正しく表示されない場合があります。

●123-163行:
ESP-WROOM-02からスマホブラウザへ送信するHTMLタグのBody要素の文字列です。
ヘッダ部分はspiffs_01.txtファイルで定義してます。
これの使い方についてはこちらの記事を参照してください。

●165行:
ルーター(アクセスポイント)へここで接続します。

●179行:
自作ライブラリ、EasyWebSocketの関数で、常にループしながらスマホからのアクセスをチェックしてます。
WebSocket通信をスマホ側から切断しても、再接続が簡単にできるようになってます。

●185行:
スマホブラウザからWebSocket通信で送られてくるテキストデータを抽出する関数です。
PingSendTimeで定義した秒数でスマホにPingを送信して、Pongが返って来なければESP-WROOM-02側でコネクション切断するようになってます。

●193-218行:
スマホのブラウザのテキストボックスから送信された場合、その文字列の[0]番目の文字だけで判断して、OLEDに文字列を表示させます。’t’ ならば1行目の文字スクロール、’T’ ならば2行目の文字スクロールという感じです。

●223-268行:
ブラウザからテキストボックス以外のボタンやスライダーが操作された場合、[4]番目の文字で判断して制御を決めます。
スクロールスピードを決めるSclSpeedは0だと高速、200だと超低速になります。
ブラウザのCanvas要素のスライダーが200pix幅なので、ブラウザからは0~200という数値が送信されてくるのです。
ただ、200~50という数値はスクロール速度があまりに遅いので、50~0という範囲に収めるように数式を定義してます。

●276-324行:
テキストボックスやWeb記事取得したら文字列を1ドットずつ文字をスクロールしていきます。
SclSpeed=0が最速です。
281行で文字ドットを白黒反転させています。
285行では前回の記事で述べたように、90度文字を回転させてます。
288,289行ではOLED_SSD1306ライブラリver1.5から登場した関数です。
東雲フォントは16×16ドットですが、8×16ドット毎に制御した方が全角と半角を処理しやすいのです。これが毎回呼び出されて1ドットづつ書き換えていきます。
本来ならば、1文字の半分(8ドット分)スクロールし終えたら次の文字ドットを読み込んでいった方がメモリを食わないのですが、スクロール速度が遅くなるので、405-410行で記事を取得したらドットバッファ配列に記憶させてます。そのせいで、記事取得から文字スクロールまで18秒くらいかかってしまいます。もっと効率の良い方法が分かる方がいらっしゃったら是非教えていただきたいですね。

●329-367行:
NTPサーバーで定時修正されたESP-WROOM-02内部時刻をここで取り出して文字列に変換してOLEDに表示してます。

●369-380行:
5分毎にNTPサーバーから時刻を取得し、ESP-WROOM-02の内部時計を修正してます。
また、Web記事を取得した場合、記事を自動で10分毎に取得するため、ダブらないように4分毎に時刻を取得するようにしてます。

●382-451行:
Web記事を取得するプログラムです。
384-387行でYahoo.co.jpのRSSサイトを指定してます。
395行はWeb記事から必要な文字列を抽出する関数で、使い方はこちらのページを参照してください。

●454-498行:
NTPサーバからの時刻取得関数です。これはArduino IDEサンプルスケッチそのまま流用してます。

3.コンパイル書き込みおよび実行

では、このスケッチをシリアルUSBでコンパイル書き込みしてください。
書込み終了したら、シリアルモニターを起動するか、またはArduino IDEをすべて閉じてください。
シリアルモニターを起動していない状態でIDEを立ち上げていると動作しない場合があります。
稀にOLEDの初期化が上手くいっていない場合もあります。
その場合はUSBを抜き差ししてリセットしてください。

動画にあるように「WAIT・・・・」と表示された後に時刻が表示されたらスマホをWi-Fi接続してブラウザのURL欄にESP-WROOM-02のIPアドレスを入力してください。
すると以下の画面が出ますので、下のところに「WS.CONNECTED」と赤字で表示されるまでお待ちください。
ws_OLED_SSD1306_05
あとは、動画にあるように操作してみてください。
Web記事取得ボタンを押したらWebSocket通信は切断されますので、操作したければ「WS-Reconnect」ボタンを押してください。
直ぐに再接続できると思います。
一旦切断される理由は、以前の記事でも述べましたが、WebSocket通信プロトコルとHTTP GETプロトコルが異なる為です。

以上です。
前回の記事同様、OTAアップロードなどがありややこしくてスイマセン。
文章も分かりにくかったかもしれません。
ザザッと記事を書いたので、その辺はご容赦を・・・。
不明な点がありましたらコメント等でお問い合わせいただければできる限りお答えしたいと思っています。
ではまた・・・。

2016/6/8アップした記事で、FRISKケースに収めてみました。
Frisk37

スポンサーリンク

Amazon.co.jp広告




投稿者:

mgo-tec

Arduino, ESP8266, ESP-WROOM-02 等を使って、主にスマホと連携した電子工作やプログラミング記事を書いてます。ライブラリも作ったりしてます。趣味、独学でやってます。

「Web News記事自動取得 OLED ( 有機EL )ミニ電光掲示板に16×16フリー日本語フォント( 東雲 ) を使う」への11件のフィードバック

  1. 初めてコメントさせて頂きます。
    最近は昔を想い出しながら(ん十年前はアセンブラやC言語をバリバリ使っておりました…が)、RaspberryPiやArduinoを楽しんでおります。
    新たなノウハウを求めネットを彷徨っていたところ、貴殿の情報に辿り着いた次第です。
    毎回、斬新なアイデアとプログラミング手法に触発されておりますが、ほぼおんぶにだっこ状態でございます。
    ESP8266へのフォントデータのアップロードが上手く出来ず(Wifi経由でポートは出来るのですが…)に腐っておりましたが、IDEのversionを1.6.9に上げてみたところ、なんとCOMポートからのアップロードが出来た次第です。
    取り急ぎ、ご報告と感謝の気持ちをお伝えしたくコメントさせて頂きます。
    今後の記事も楽しみにしております。

    1. 栗原さん

      とーーっても有益なコメントありがとうございます!!!
      私の環境でも、ArduinoIDE1.6.9 にアップデートしたら、USB経由でフォントデータのSPIFFSファイルシステムアップロードができました!!!
      アップロード速度は最速の921600にして、約1分50秒くらいかかりました。
      WiFi OTA は便利で速いのですが、余分なメモリを食うのと、BasicOTAサンプルスケッチをいちいちコンパイルしなければいけなかったので不満だったのです。
      IDE1.6.9の安定性も疑問だったので試してなかったのですが、これでいろいろと解放されました。
      近いうちに記事を修正していこうと思います。
      ありがとうございました m_ _m

    2. IDE 1.6.9 改めてこちらで別の個体のESP-WROOM-02開発ボードで 4M(3M SPIFFS)でアップロードしてみたところ、できませんでした。
      どうやら個体差があるのかな??? と思ってます。
      ということで、シリアルUSBアップロードエラーになったら結局はOTAが一番確実ということが分かりました。
      こちらの記事を参照してみてください。
      https://www.mgo-tec.com/blog-entry-4m3m-spiffs-serial-trouble-01.html

  2. とても楽しく拝見させていただいています。
    早速、部品を集めて作成させていただきました。
    既にESP-WROOM-02は購入していたものの、何を作るか決めかねて
    しまい込んでいました。
    すごく面白いものを見つけた!という思いで作らせていただきました。
    100均のフィギュアケースに入れてみました。

    いいものができたので、欲が出てしまい、プログラムを改造しています。
    自分は時間が主で見たかったので、このOLEDでの例では
    一番上にして、黄色なので目立つようにして
    記事を真ん中へ、日付を一番下にしてみました。
    ==============
      12:34:00
    Yahoo!ニュース◆
    【Yahoo!天気】
    2016/11/26(土)
    ==============
    更に改造したいのですが、よくわからずに途方にくれています。
    アドバイスいただけると幸いです。
    1.日付を全角にしたい。
    2.記事をx2サイズにしたい。(32×32フォント?)
      ※1行で良い、大きく表示したい。

    とても有益な情報をいつもありがとうございます。
    しばらくは楽しめそうです。

    1. 伊藤さん

      とてもうれしいコメントありがとうございます。
      こういう声をいただけると、苦労したことが報われた気がします。
      こちらこそ、作って頂き感謝いたします。
      m(_ _)m

      改造の件ですが、コメント中で紹介するにはちょっと大変です。
      現段階ではザッと紹介するだけで、ご容赦ください。

      >1.日付を全角にしたい。
      これは、プログラムにかなりの工夫が必要です。
      全角数字のゼロはUTF-8コードでEFBC90です。
      その3バイト目の1ずつ足していけば、9までの数値を表現できます。
      Stringクラスの使い方が肝です。
      例えば、
      String H_str = “0”;
      H_str[2] = H_str[2] + 2;
      とすれば、”2” という文字になります。
      ただ、時刻の場合、十の位と一の位を分割して数値を作ることになるので、その計算式を工夫せねばなりません。
      それができれば、1行16バイトのString文字列ができると思います。
      そして、東雲フォントのforループのiを8から16に変更しておく必要があります。
      また、time_dot[8][16]; → time_dot[16][16]; に変更する必要があります。

      >2.記事をx2サイズにしたい。(32×32フォント?)
      >  ※1行で良い、大きく表示したい。
      これは、ちょっと難しいですね。
      これを実現すると、I2C通信ディスプレイでは速度が遅すぎて、まともに文字がスクロールしないと思います。
      SPI通信のOLEDに変える必要があります。
      そうすると、ライブラリまで変更する必要があり、別途開発研究しなければなりません。
      また、このSSD1306は8bit単位のドットで1列をディスプレイしているので、行を跨ぐドットの拡張は結構大変です。
      以下の記事のSSD1351のように、1ドット単位でSPI通信のディスプレイならば倍角文字スクロールは可能だと思いますが、
      それでも、速度が劇的に低下してしまうでしょう。
      https://www.mgo-tec.com/blog-entry-adafruit-oled-ssd1351-lib01.html

      ということで、今はここまでしかアドバイスできませんが、また何か不明な点がありましたらコメント頂けると幸いです。

  3. 初めまして。いつも楽しく拝見させていただいております。
    EasyWebSocketでWebブラウザに表示される画面と、
    OLEDの曜日のみが文字化けしてしまいます。
    原因がお判りになるようであればお教えいただけませんでしょうか。
    Win10 Chrome
    http://i.imgur.com/boPSz0B.png
    iPhone
    http://i.imgur.com/agqqTF0.png
    EasyWebSocketは1.48を使用しています。
    ArduinoIDEは1.6.13を使用しています。
    お手数をおかけいたしますがよろしくお願いいたします。

    1. まるやまさん

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

      おそらく、OSとブラウザの文字入力の文字コードエンコードが原因と思われます。
      Arduino IDE の文字入力は UTF-8 でなければなりません。
      Windows 10 日本語対応で、文字入力がMicrosoft IME ならば普通にインストールすれば、Arduino IDE の文字コードはUTF-8 になっているはずです。

      試しに、ESPr Developer に以下のスケッチをコンパイルして、シリアルモニターを115200 bps で表示させてみてください。

      void setup() {
        delay(1000);
        
        Serial.begin(115200);
        Serial.println();
        
        char c[10] = "あ";
        for(int i=0; i<3; i++){
          Serial.print(c[i], HEX);
        }
        
        Serial.println();
        Serial.write(c);
        
        Serial.println();
        Serial.write(0x82);
        Serial.write(0xA0);
        Serial.println();
      }
      
      void loop() {
      }
      

      これで、シリアルモニターの最初の1行の文字化けは無視して、次に以下のように表示されていれば良いです。
      E38182
      縺�

      これと別の数値や文字で表示されたら、OSの標準入力の文字コードが異なる可能性があります。
      また、これがブラウザの文字エンコードによっては違う風に表示される可能性がありますので、画像でお知らせいただけると確実に判別できます。

      それと、Windows10 の場合で、文字入力がMicrosoft IMEの場合、Arduino IDE のシリアルモニターはShift_JISコード表示になっています。
      (これが実は不思議なんですが・・・。)

      ですから、
      Serial.write(0x82);
      Serial.write(0xA0);
      を出力すると、「あ」と表示されるはずです。
      お手数ですが、確認してみてください。

      また、UTF8toSJIS、ShinonomeFONTread、OLED_SSD1306 それぞれのライブラリのバージョンを教えてください。
      当方では以下で動作確認取れています。(2016/12/26時点)

      UTF8toSJIS beta ver 1.41
      OLED_SSD1306 beta ver 1.5
      ShinonomeFONTread beta ver 1.33
      EasyWebSocket_SPIFFS beta ver 1.48
      Arduino IDE 1.6.13
      ESP8266ボード stable 2.3.0
      IDE文字入力: Windows10 Microsoft IME
      ブラウザ:
      Android 4.2.2 ~ Android 6.0.1 Google Chrome
      Windows10 Google Chrome
      iOS 10.2 Safari

      以上、ご確認くださいませ。

  4. mgo-tec様
    詳細なご回答ありがとうございます。
    恐らく私の環境に起因する問題なのですね。

    まず、例示して頂きましたスケッチの実行結果を画像でご報告いたします。
    http://i.imgur.com/0XOFvLw.png
    mgo-tec様のコメントは、Chromeでこのように表示されていました。
    http://i.imgur.com/eMFBEo0.png

    また新たに分かったこととして、.inoを保存してArduinoIDEを終了して
    再度.inoを開いてすぐにコンパイル・書き込みをすると文字化けが発生せず、
    一度でも編集してしまうと文字化けが発生します。
    この場合でも保存してArduinoIDEを再起動して書き込めば文字化けしません。
    どうやら、私の環境では編集することによってスケッチのエンコードが崩れてしまうようです。
    AruduinoIDEか、「OSの標準入力の文字コード」に問題がありそうですね。
    私はWindows10を使用しています。OSの文字コードがどこで設定されているのか探してみます。

    各ライブラリのバージョンは以下の通りで、mgo-tec様がお示しになったものと同一でした。
    UTF8toSJIS beta ver 1.41
    OLED_SSD1306 beta ver1.5
    ShinonomeFONTread beta ver 1.33
    EasyWebSocket_SPIFFS BETA ver 1.48
    Arduino IDE 1.6.13
    ESP8266ボード stable 2.3.0
    IDE文字入力: Windows10 Microsoft IME
    ブラウザ:
    Windows10 Google Chrome バージョン 55.0.2883.87 m
    iOS 10.2 Safari

    1. まるやまさん

      写真の投稿、ありがとうございます。m(_ _)m

      コメント投稿のブラウザ表示は正しかったです。
      E38182
      縺�

      が出ておらず、
      82A00


      という風に出力されたということですね。なるほど・・・。
      これは、Arduino IDE に入力された文字がShift_JISコードになっていますね。
      2行目は文字化けするはずですが、そのまま出力されているということは、
      Arduino IDE 入力がShift_JIS で、シリアルモニターも同じShift_JISということです。
      ですから、当然、編集してしまうと文字化けしてしまいます。
      日本語ではなく、ASCII文字は問題ないと思います。
      Microsoft IME の設定をUTF-8入力に変えれば良いと思いますが、Windows10でのその方法が私も分かりません。
      調べて、分かり次第お知らせしたいと思います。
      なるほど・・・、環境によってはArduino IDE がShift_JISになってしまうとは、知りませんでした。
      失礼いたしました。

  5. mgo-tec様
    ご回答恐れ入ります。ありがとうございます。
    デフォルト設定から何か違う点はないか?と探してみましたところ、
    私は書き込み時にスケッチを自動保存しない設定にしておりました。
    http://i.imgur.com/DhXYZOK.png
    デフォルトでは自動保存される設定になっておりますので、書き込みの都度スケッチが保存されます。
    デフォルト設定に戻しましたところ、ご提示いただいたサンプルスケッチも「縺�」と表示され、
    こちらの記事本体のスケッチも問題なく動作いたしました。
    お騒がせして申し訳ございません。
    仮説ですが、Arduino IDEは保存時にエンコードの変更を行うのかもしれません。

    1. まるやまさん

      とりあえず、解決して良かったですね。
      私の方は「検証または書き込みを行う前にスケッチを保存する」のチェックを外してやってみましたが、症状は出ませんでした。
      やはり、パソコンの環境ですかね・・・。
      もし、同じような症状が出た方はお知らせいただきたいですね。
      原因を知りたいです。

      でも、まぁ、正常に動いたのなら良かったです。
      また何かありましたらコメントくださいませ。
      情報ありがとうございました。m(_ _)m

コメントを残す

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


*