作者: ken

ESP8266 開發板 with 0.91 inch OLED Display – WeMos TTGO

No Comments
TTGO 正面。有天線,microUSB conn,一顆 reset 按鈕,及一顆自訂按鍵。當然還有容易被忽略的 128×32 OLED 顯示器。參考批發價格 43 RMB(OLED 確實是不便宜)。

在前面的文章,我們就評估過一張 1.8 吋 SPI 介面的全彩顯示器。但您一定會發現使用 D1-mini,就已會被佔掉五支 GPIOs,因此剩下能運用的腳位就不多了。也因此 WeMos 又出了另一張開發板,稱為 TTGO,板上配置了一張 0.91 吋的 OLED 顯示器。而當前筆者將要運用的是單色顯示,故它是不是全彩的筆者就未查證了。此顯示器使用了 I2C 作為傳輸介面,這意謂著佔用掉的兩根 PIN 還可復用,沒錯吧 I2C Bus。再加上,此板並不使用 ESP8266MOD 模組,意謂著更多的 GPIOs 將會被釋放出來,運用度更高。當然相對面 de-modulation(假借,去模組化)就有可能劣於 ESP8266MOD 抗干擾。

本文將快速地驅動這張開發板。這在 Arduino 的世界裏並不是新鮮事。

20210503 補充:這張開發板可以直接對電池充電,不過電池本身須具保護板。另外這張板,容易變得無法 write flash 更新。建議嘗試使用改版的。
20230814 補充:U8g2 的 reset pin 指定為 -1。若板子沒有 reset pin 給接,則如此設之;若有,建議 pull-high/low(不確定)以避免浪費一支 GPIO。
TTGO 背面。有一顆 ESP8266EX,及其晶振,32Mbits(4MB) flash,及 SL 的 USB2UR,2-pin 電源。須注意的是,或許該看一下板子的電路圖,因為圖中的顯示器的 FPC 接腳仍然是那麼多 pin,筆者的認知是它應會接到驅動 IC SSD1306 但其未在板子上可見。因此筆者的猜測如下:1. 驅動 IC 與 OLED 包在一起,只是二者的腳位全須外繞。2. 並沒有 SSD1306。而是它被預期使用軟體模擬,並透過 I2C pins 來當成輸入。因筆者懶得找電路圖查看了(或許也看不懂XD)故就不再妄加斷言。
放大圖。筆者單靠肉眼是看不到的XD
數一下,有 11 pin GPIOs 可用,1 pin ADC,並有兩對電源接腳便利外接出去。不過 I2C 2 pin 和 UR 2 pin 可能需排除(若腳位不夠用再來查證:GPIO1 & 3 是 UR 的 txd0&rxd0,若使用了 GPIO1,則就無法從終端輸出資料),用時就先略過它們。另外筆者的 PRG button 似乎是空接的

20210511 補充 如附圖說明

請注意三支驅動腳位分別是 GPIO 4/16/5。這是另一個版本的 TTGO,不過腳位的排列與原 TTGO 並不相容,請特別注意。此外此版本能對電池充放電,但筆者認為前一個 TTGO 版本就有此功能了。再來,為何會換成白版本而不延用黑版本,就是因為黑版本買了三支三支都出現 flash 不能更新的問題。而白版,待測。另外 ADC 是 3.3V,二者皆同。
請注意,筆者有發現用上 SIL USB2UR chip,必須在 setup() 一開頭 delay 上至少 2 秒。

步驟

  • 安裝額外必要的函式庫,按關鍵字來搜尋程式庫:Adafruit SSD1306U8g2
  • 在網路上找尋可用的範例,筆者稍作修改並貼於下。From “Simple Stuff Matters”。這份範例的出處
搜尋或安裝 zip 或加載入程式庫算是基本操作,往後筆者就不再贅述演示了。
Adafruit ssd1306
U8g2

參考資料

教學影片,內容蠻詳盡的。筆者也聽不懂,請打開字幕多少有些幫助。點擊此

範例

說明:請將 wifi_ssid 及 wifi_password 改成您的 AP 的,否則無法連線程式會一直停頓在那連線。另外運行時請打開序例埠監控視窗,鮑率設成 115200,可觀看進度。若一直出現點點點就代表連線連不上請檢查連線。至於 OTA 是什麼筆者也不是很清楚,但它在此範例不影響什麼,只要求連線成功即可。
板子請選擇 “NodeMCU 0.9 (ESP-12 Module)”或其類似。

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////                                                                                                          ////
////  TTGO ESP8266 0.91 inch OLED demo w/ OTA                                                                 ////
////  requires U8g2 library                                                                                   ////
////  Select "NodeMCU 0.9 (ESP-12 Module)" board                                                              ////
////  More examples at http://simplestuffmatters.com                                                          ////
////  USB drivers: https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers  ////
////                                                                                                          ////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include <ESP8266WiFi.h>  //For ESP8266
#include <ESP8266mDNS.h>  //For OTA
#include <WiFiUdp.h>      //For OTA
#include <ArduinoOTA.h>   //For OTA
#include <Arduino.h>
#include <U8g2lib.h>      // make sure to add U8g2 library and restart Arduino IDE  
#include <SPI.h>
#include <Wire.h>

#define OLED_SDA  2
#define OLED_SCL 14
#define OLED_RST  4
U8G2_SSD1306_128X32_UNIVISION_F_SW_I2C u8g2(U8G2_R0, OLED_SCL, OLED_SDA , OLED_RST);
const char *text = "U8g2 OTA";  // scroll this text from right to left

//WIFI configuration
#define wifi_ssid "rewirte_this_word_to_your_ssid"
#define wifi_password "rewirte_this_word_to_your_ssids_password"
#define WiFi_hostname "ESP8266-TTGO"

//Necesary to make Arduino Software autodetect OTA device
WiFiServer TelnetServer(8266);

void setup_wifi() {
  delay(100);
  Serial.println("");
  Serial.print("Connecting to ");
  Serial.println(wifi_ssid);
  WiFi.hostname(WiFi_hostname);
  WiFi.begin(wifi_ssid, wifi_password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.print("   IP address: ");
  Serial.println(WiFi.localIP());

  Serial.print("Configuring OTA device...");
  TelnetServer.begin();   //Necesary to make Arduino Software autodetect OTA device  

  ArduinoOTA.onStart([]() {Serial.println("OTA starting...");});
  ArduinoOTA.onEnd([]() {Serial.println("OTA update finished!");Serial.println("Rebooting...");});
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {Serial.printf("OTA in progress: %u%%\r\n", (progress / (total / 100)));});  
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });
  ArduinoOTA.begin();
  Serial.println("Wifi OK, OTA Ready on telnet 8266.");
}


char str1[17];        // ******** intended for a wiggling string on display
byte dir1;            // ******** intended for a wiggling string on display

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

  strcpy(str1, text); // ******** intended for a wiggling string on display
}

// a null-terminated string already in an frmsz-size frm-frame with or without leading spaces will be wiggling in it.
// dir stores 0(forward) or 1(backward, non-zero) represents current direction which will be auto reversed.
void TextInFrameWiggle(byte &dir, byte frmsz, char *frm){
  
  for (int i=0, j=0; i<frmsz; i++){
    if (frm[i]!=' '){ // find the 1st non-space character incl. 0
      if (dir){ // backward
        if (i){
          do {frm[i-1]=frm[i];} while (frm[i++]);
          return;
        }
        else dir=0;
      }

      // forward
      j=i;
      while (frm[j++]);
      if (j-i==frmsz) return; // means no-leading-space string occupies entire frame
      if (j==frmsz){ // time to turnaround
        --i;
        dir=1;
        continue;
      }
      do {frm[j]=frm[j-1];} while (--j!=i);
      frm[j]=' ';
      return;
    }
  }
}


void loop() {
  ArduinoOTA.handle();
  u8g2.clearBuffer();          // clear the internal memory
  u8g2.setFont(u8g2_font_8x13B_mf); // choose a suitable font
  
  TextInFrameWiggle(dir1, 17, str1); // ******** intended for a wiggling string on display
  
  u8g2.drawStr(0,10,str1);  // write something to the internal memory
  IPAddress myip= WiFi.localIP();
  String sFullip = String(myip[0]) + "." + myip[1] + "." + myip[2] + "." + myip[3];
  u8g2.drawStr(0,28,sFullip.c_str());  // write something to the internal memory
    
  u8g2.sendBuffer();          // transfer internal memory to the display
  delay(1);  
}
PHP Code Snippets Powered By : XYZScripts.com