LoginSignup
5
3

More than 3 years have passed since last update.

ESP-01でOLED時計(Soft I2C)

Posted at

はじめに

ESP-01はESP8266を搭載したWiFiモジュールです。
image.png

Arduinoでの開発環境もあり、Arduinoの資産を活用した開発も簡単におこなえます。IOはGPIO0-3の4本あり、GIPO1とGPIO3はデフォルトでTX, RXに割り当てられています。

ここではNTPで時刻同期し現在時刻をOLEDにて表示してみます。完全無調整の時計となります。

ネット上ではAdafruitのライブラリを使用した作例が多いのですがフォントが固定の様子で時計としては不都合。 ThingPulse /
esp8266-oled-ssd1306
というライブラリを使用しました。フォントも自由に変更可能です。

image.png
デバッグ中の様子

必要なもの

ESP-01

image.png
ESP-01はAliExpressにて1-2USD程度で購入できます。(技的は知りません)

プログラマFT232

image.png
ESP-01は3.3VのためFT232を使用すると便利です。1.5USD程度で購入可能です。

OLED

image.png
I2Cの0.96"OLEDモジュールです。128x64のOLEDでも問題なく使用できます。

その他

Arudino開発環境、抵抗4.7kΩx2、配線、ハンダごてなど。

開発環境

ESP-01をArduinoで開発する環境はググってください。
その上でThingPulse /
esp8266-oled-ssd1306
というライブラリをインストールしてください。

プログラム環境

image.png
プログラム時にはVCC, RST, CH_PH, GPIO2をVCCに、GPIO0をGNDにする必要があります。
実行時にはGIPO0をVCCにします。
実行時にGIPO0, GPIO2をVCCにする必要があるので,IOとして使用するにはGPIO0, GPIO2を4.7kΩ程度の抵抗でプルアップしておきます。(プルアップしないと実行できません)

配線

VCC, RST, CH_PHに3.3Vを。
GNDに0Vを。
GPIO0をプルアップしつつ、OLEDのSDAへ
GPIO2をプルアップしつつ、OLEDのSCLへ

プログラム

ESP_01_TEST.cpp
//////////////////////////////////////////////////////////////
//
//  ESP01 Desktop clock
//  2020/02/02
//
///////////////////////////////////////////////////////////////
//
// Libraries needed:
//  SSD1306.h & SSD1306Wire.h:  https://github.com/squix78/esp8266-oled-ssd1306
//  ESP8266WiFi.h & WifiUDP.h: https://github.com/ekstrand/ESP8266wifi
//
// 128x64 OLED pinout:
// GND goes to ground
// Vin goes to 3.3V
// Data to I2C SDA (GPIO 0)
// Clk to I2C SCL (GPIO 2)


// To create font, use below site
// http://oleddisplay.squix.ch/#/home

#include <ESP8266WiFi.h>
#include <Wire.h>
#include <SSD1306.h>
#include <SSD1306Wire.h>

#include <time.h>     // for time(), localtime()


// Wi-Fi設定
#define WIFI_SSID   "WIFI_SSID"
#define WIFI_PASSWORD "WIFI_PASSWORD"


// NTP設定
#define TIMEZONE_JPN  (3600 * 9)  // JST is UTC+9hours
#define DAYLIGHTOFFSET_JPN  (0)   // No summer time
#define NTP_SERVER1   "ntp.nict.jpntp.nict.jp"  // NTP
#define NTP_SERVER2   "ntp.jst.mfeed.ad.jp"   // sub NTP


// Create a display object
SSD1306  display(0x3c, 0, 2, GEOMETRY_128_32); // OLED Setting 128x64 = GEOMETRY_128_64


void setup ()
{
  Serial.begin(9600); // Serial for debug

  // Soft I2C setting
  Wire.pins(0, 2);  // Start the OLED with GPIO 0 and 2 on ESP-01
  Wire.begin(0, 2); // 0=sda, 2=scl

  // OLED initialing
  display.init();
  display.flipScreenVertically();
  display.setBrightness( 16 ); // 0: low brightness, 254 : high

  // Connect to wifi
  Serial.println("");
  Serial.print("Connecting to ");
  Serial.print(WIFI_SSID);
  display.drawString(0, 10, "Connecting to Wifi...");
  display.display();

  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }


  Serial.println("");
  Serial.print("Connected to WiFi at ");
  Serial.print(WiFi.localIP());
  Serial.println("");
  display.drawString(0, 24, "Connected.");
  display.display();


  // Synchronize to NTP
  configTime( TIMEZONE_JPN, DAYLIGHTOFFSET_JPN, NTP_SERVER1, NTP_SERVER2 );

  Serial.println("NTP READY");
}

void loop()
{
  if (WiFi.status() == WL_CONNECTED) //Check WiFi connection status
  {
    // String table for day and month
    static const char *pszWDay[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
    static const char *pszMonth[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

    // Get current time & date
    time_t timeNow = time(NULL);
    struct tm* tmNow = localtime(&timeNow);

    // DATE
    char szDate[32];
    sprintf( szDate, "%04d/%02d/%02d(%s)",
             tmNow->tm_year + 1900,
             tmNow->tm_mon + 1,
             tmNow->tm_mday,
             pszWDay[tmNow->tm_wday] );

    // TIME
    char szTime[32];
    sprintf( szTime, "%02d:%02d",
             tmNow->tm_hour,
             tmNow->tm_min
             );

    // Output via serial
    Serial.println("");
    Serial.print("Local date: ");
    Serial.print(szDate);
    Serial.println("");
    Serial.print("Local time: ");
    Serial.print(szTime);

    // Display on OLED
    display.clear();
    // TIME
    display.setFont(Lato_Heavy_30);
    display.drawString( 5, 0, szTime);
    // Date
    display.setFont(ArialMT_Plain_16);
    sprintf( szDate, "%02d", tmNow->tm_mday);
    display.drawString( 96, 0, szDate); // day of Month
    display.drawString( 96, 16, pszMonth[tmNow->tm_mon]); // Month
    display.display();
  }
  else // attempt to connect to wifi again if disconnected
  {
    display.clear();
    display.drawString(0, 10, "Connecting to Wifi...");
    display.display();
    WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
    display.drawString(0, 10, "Connected.");
    display.display();
    delay(1000);
  }

  delay(1000);
}

display.setFont(Lato_Heavy_30);
でエラーになるはずです。下記でフォントを作成して置き換えてください。

Font作成

こちらでフォントを作成できます。生成したコードをOLEDDisplayFonts.hに貼り付けて使用してください。

完成

image.png
image.png
image.png
ヘッダーコネクタがかさばってますがコンパクトではあると思います。低背のコネクタを使用すれば厚さ1.5cmくらいにはなるかと。

image.png

ケースに入れて完成です。少し斜めってますね。

おわりに

ESP-WROOM-02でOLEDを使用するアプリケーションは沢山見付かるのですが、ESP-01では随分と苦労しましたので忘備録として記事にします。
現在ニキシー時計を作成しており、ESP-01はNTP同期のRTC程度に使用するつもりでしたが、プログラム容量、動作速度もありで、母艦のAtMega328は不要じゃないかと思いはじめています。このサイズと価格パワフルさでESP-01に惚れました。

20200202

5
3
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
5
3